diff --git a/AUTHORS b/AUTHORS index 76ff47e9db6..fcd14d0b12c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -99,6 +99,11 @@ ScummVM Team Scott Thomas Jordi Vilalta Prat + Hugo: + Arnaud Boutonne + Oystein Eftevaag + Eugene Sandulenko + Kyra: Torbjorn Andersson - VQA Player Oystein Eftevaag @@ -106,6 +111,11 @@ ScummVM Team Gregory Montoir Johannes Schickel + Last Express: + Matthew Hoops + Jordi Vilalta Prat + Julien Templier + Lure: Paul Gilbert @@ -158,6 +168,9 @@ ScummVM Team Filippos Karapetis Joost Peters + Toon: + Sylvain Dupont + Touche: Gregory Montoir @@ -172,7 +185,7 @@ ScummVM Team Dreamcast: Marcus Comstedt - GP2X: + GPH Devices (GP2X, GP2XWiz & Caanoo): John Willis iPhone: @@ -190,6 +203,9 @@ ScummVM Team Nintendo DS: Neil Millstone + OpenPandora: + John Willis + PocketPC / WinCE: Nicolas Bacca - (retired) Kostas Nakos @@ -449,6 +465,9 @@ Special thanks to Patrick Combet - For the original Gobliiins ADL player Ivan Dubrov - For contributing the initial version of the Gobliiins engine + Henrik Engqvist - For generously providing hosting for our buildbot, SVN + repository, planet and doxygen sites as well as tons of + HD space DOSBox Team - For their awesome OPL2 and OPL3 emulator Till Kresslein - For design of modern ScummVM GUI Jezar - For his freeverb filter implementation @@ -482,3 +501,13 @@ Special thanks to John Young, Colin Smythe and especially Terry Pratchett himself for sharing the source code of Discworld I & II with us. + Emilio de Paz Aragon from Alcachofa Soft for sharing the source code of + Drascula: The Vampire Strikes Back with us and his generosity with + freewaring the game. + + David P. Gray from Gray Design Associate for sharing the source code of + the Hugo trilogy. + + Broken Sword 2.5 team for providing sources of their engine and their + great support. + diff --git a/Makefile b/Makefile index ad2f8fcf9f7..e8c8a172919 100644 --- a/Makefile +++ b/Makefile @@ -34,8 +34,14 @@ ifeq "$(HAVE_GCC)" "1" # being helpful. #CXXFLAGS+= -Wmissing-format-attribute - # Disable RTTI and exceptions, and enable checking of pointers returned by "new" - CXXFLAGS+= -fno-rtti -fno-exceptions -fcheck-new + # Disable RTTI and exceptions + CXXFLAGS+= -fno-rtti -fno-exceptions + +ifneq "$(HAVE_CLANG)" "1" + # enable checking of pointers returned by "new", but only when we do not + # build with clang + CXXFLAGS+= -fcheck-new +endif endif ifeq "$(HAVE_CLANG)" "1" diff --git a/Makefile.common b/Makefile.common index cf8626ce3c7..5abfc2e784c 100644 --- a/Makefile.common +++ b/Makefile.common @@ -230,7 +230,7 @@ dist-src: \ DIST_FILES_DOCS:=$(addprefix $(srcdir)/,AUTHORS COPYING COPYING.BSD COPYING.LGPL COPYRIGHT NEWS README) # Themes files -DIST_FILES_THEMES=scummmodern.zip +DIST_FILES_THEMES=scummmodern.zip scummclassic.zip ifdef USE_TRANSLATION DIST_FILES_THEMES+=translations.dat endif @@ -262,6 +262,9 @@ endif ifdef ENABLE_TEENAGENT DIST_FILES_ENGINEDATA+=teenagent.dat endif +ifdef ENABLE_TOON +DIST_FILES_ENGINEDATA+=toon.dat +endif DIST_FILES_ENGINEDATA:=$(addprefix $(srcdir)/dists/engine-data/,$(DIST_FILES_ENGINEDATA)) # pred.dic is currently only used for the AGI engine diff --git a/NEWS b/NEWS index 0e69339fd98..d988f9b17a4 100644 --- a/NEWS +++ b/NEWS @@ -1,11 +1,75 @@ For a more comprehensive changelog for the latest experimental SVN code, see: http://scummvm.svn.sourceforge.net/viewvc/scummvm/?view=log +1.3.0 (????-??-??) + New Games: + - Added support for Backyard Baseball. + - Added support for Backyard Baseball 2001. + + Drascula: + - Added German and French subtitles in the Von Braun cutscene (#3069981: + no subtitles in scene with "von Braun"). + - Improved French translation of the game. + + SCI: + - Improved support for non-English versions of games. + + SCUMM: + - Improved support for FM-TOWNS versions of games. + +1.2.1 (2010-??-??) + Groovie: + - Fixed a regression that made the Russian version of T7G crash. + +1.2.0 (2010-10-15) + New Games: + - Added support for Fascination. + + New Games (Sierra SCI0 - SCI1.1): + - Added support for Castle of Dr. Brain (EGA and VGA). + - Added support for Codename: ICEMAN. + - Added support for Conquests of Camelot. + - Added support for Conquests of the Longbow (EGA and VGA). + - Added support for EcoQuest: The Search for Cetus. + - Added support for EcoQuest 2: Lost Secret of the Rainforest. + - Added support for Freddy Pharkas: Frontier Pharmacist. + - Added support for Hoyle's Book of Games 1. + - Added support for Hoyle's Book of Games 2. + - Added support for Hoyle's Book of Games 3 (EGA and VGA). + - Added support for Hoyle Classic Card Games. + - Added support for Jones in the Fast Lane. + - Added support for King's Quest I (SCI remake). + - Added support for King's Quest IV (SCI version). + - Added support for King's Quest V (EGA and VGA). + - Added support for King's Quest VI (low and hi res). + - Added support for Laura Bow: The Colonel's Bequest. + - Added support for Laura Bow 2: The Dagger of Amon Ra. + - Added support for Leisure Suit Larry 1 (SCI remake) (EGA and VGA). + - Added support for Leisure Suit Larry 2. + - Added support for Leisure Suit Larry 3. + - Added support for Leisure Suit Larry 5 (EGA and VGA). + - Added support for Leisure Suit Larry 6 (low res). + - Added support for Mixed-up Fairy Tales. + - Added support for Mixed-up Mother Goose. + - Added support for Pepper's Adventures in Time. + - Added support for Police Quest I (SCI remake). + - Added support for Police Quest II. + - Added support for Police Quest III (EGA and VGA). + - Added support for Quest for Glory I/Hero's Quest. + - Added support for Quest for Glory I VGA remake. + - Added support for Quest for Glory II. + - Added support for Quest for Glory III. + - Added support for Slater & Charlie go camping. + - Added support for Space Quest I (SCI remake) (EGA and VGA). + - Added support for Space Quest III. + - Added support for Space Quest IV (EGA and VGA). + - Added support for Space Quest V. + - Added support for The Island of Dr. Brain. -1.2.0 (????-??-??) New Ports: - Added Android port. - Added Dingux port. - Added Caanoo port (based on the GP2XWiz port). + - Added OpenPandora port. General: - Removed the outdated PalmOS port. @@ -23,6 +87,11 @@ For a more comprehensive changelog for the latest experimental SVN code, see: - Added support of MIDI devices. - Added support for accurate Tandy sound emulation. Switched to it as default. + Broken Sword 2: + - Fixed missing speech in some cutscenes. + - Fixed a memory leak that would eventually cause the game to hang. + (#2976008 - BS2: Game lockup in British Museum) + Drascula: - Fixed number of GFX glitches. - Made many cutscenes smoother. @@ -37,6 +106,12 @@ For a more comprehensive changelog for the latest experimental SVN code, see: - Implemented formerly missing recreation of some in game items. - Added support for playing Kyrandia 3 with the original CD file layout. + LURE: + - Fixed bug where Goewin could get stuck in the Weregate. + - Fixed issue with Ratpouch repeatedly moving between two rooms. + - Fix for Goewin losing her schedule after Were-cave. + - Fix for player getting stuck in sewer exit room. + Parallaction: - Made part one of The Big Red Adventure completable. @@ -58,15 +133,16 @@ For a more comprehensive changelog for the latest experimental SVN code, see: GameCube port: - Added support for DVDs with the ISO9660 file system. - - GP2X port: - - Added support for dynamic engine plugins. -1.1.2 (????-??-??) - Broken Sword 2 - - Fixed missing speech in some cutscenes. - - Fixed a memory leak that would eventually cause the game to hang. - (#2976008 - BS2: Game lockup in British Museum) + GP2X port: + - Added support for dynamic engine plugins (experimental). + - Reworked control system and better touchscreen support. + + GP2XWiz/Caanoo port: + - Improved downscale code to minimise 'tearing' corruption. + - Reworked control system and better touchscreen support. + - Renamed backend from GP2XWIZ to GPH to better reflect + the supported devices. 1.1.1 (2010-05-02) New Ports: @@ -87,7 +163,7 @@ For a more comprehensive changelog for the latest experimental SVN code, see: - Fixed several memory leaks. - Corrected problems in the handling of followers when blocked from performing actions by closed doors between rooms. - - Solved issues with Goewin not always correctly following the player out of the caves + - Solved issues with Goewin not always correctly following the player out of the caves. Tinsel: - Fix video playback regression in Discworld 2. @@ -141,7 +217,7 @@ For a more comprehensive changelog for the latest experimental SVN code, see: The Secret of Monkey Island. (GSoC Task) - Fixed some other bugs related to game versions for the Amiga. - Added support for original save/load dialog in MM NES. - - Added support for savepoint passcodes for Sega CD MI1 via debugger command 'passcode' + - Added support for savepoint passcodes for Sega CD MI1 via debugger command 'passcode'. - Added support for Kanji rendering in Japanese version of Monkey Island Sega CD. 1.0.0 (2009-11-15) diff --git a/README b/README index 9c600554299..fd900ce3103 100644 --- a/README +++ b/README @@ -71,25 +71,37 @@ files. The clever part about this: ScummVM just replaces the executables shipped with the game, allowing you to play them on systems for which they were never designed! -Some of the adventures ScummVM supports include Adventure Soft's Simon -the Sorcerer 1 and 2; Revolution's Beneath A Steel Sky, Broken Sword I -and II; Flight of the Amazon Queen; Wyrmkeep's Inherit the Earth; Coktel -Vision's Gobliiins; Westwood Studios' The Legend of Kyrandia and games -based on LucasArts' SCUMM (Script Creation Utility for Maniac Mansion) -system such as Monkey Island, Day of the Tentacle, Sam and Max and more. -You can find a thorough list with details on which games are supported -and how well on the compatibility page. ScummVM is continually -improving, so check back often. +Originally it was designed to run LucasArts' SCUMM games, such as Maniac +Mansion, Monkey Island, Day of the Tentacle or Sam and Max. SCUMM stands +for 'Script Creation Utility for Maniac Mansion', which was the first +game for which LucasArts designed this system. And much later it gave +its name to ScummVM ('VM' meaning Virtual Machine). + +Over time support for a lot of non-SCUMM games has been added, and +ScummVM now also supports many of Sierra's AGI and SCI games (such as King's +Quest 1-6, Space Quest 1-5, ...), Discworld 1 and 2, Simon the Sorcerer 1 and +2, Beneath A Steel Sky, Lure of the Temptress, Broken Sword I and II, Flight of +the Amazon Queen, Gobliiins 1-3, The Legend of Kyrandia series, many of +Humongous Entertainment's children's SCUMM games (including Freddi Fish and +Putt Putt games) and many more. You can find a full list with details on which +adventures are supported and how well on the compatibility page. ScummVM is +continually improving, so check back often. Among the systems on which you can play those games are regular desktop computers (running Windows, Linux, Mac OS X, ...), game consoles (Dreamcast, Nintendo DS & Wii, PS2, PSP, ...), smartphones (Android, iPhone, PocketPC, Symbian ...) and more. -At this time ScummVM should be considered beta software, and is still -under heavy development. Be aware that whilst we attempt to make sure -that many games can be completed with few major bugs, crashes can -happen. +At this time ScummVM is still under heavy development. Be aware that +whilst we attempt to make sure that many games can be completed with few +major bugs, crashes can happen and we offer no warranty. That being said, +some of the games have been supported for a long time and should work +fine with any recent stable release. You can get a feeling of how well +each game is working in ScummVM by looking at the compatibility page. +Actually if you browse a bit around you might discover that ScummVM is +even being used commercially to re-release some of the supported games on +modern platforms. This shows that several companies are happy with the +quality of the software and how well it can run some of the games. If you enjoy ScummVM feel free to donate using the PayPal button on the ScummVM homepage. This will help us buy utilities needed to develop @@ -256,6 +268,8 @@ Other Games: Musketeer [touche] SCUMM Games by Humongous Entertainment: + Backyard Baseball [baseball] + Backyard Baseball 2001 [baseball2001] Backyard Football [football] Big Thinkers First Grade [thinker1] Big Thinkers Kindergarten [thinkerk] @@ -309,8 +323,6 @@ these at your own risk, and please do not file bug reports about them. If you want the latest updates on game compatibility, visit our web site and view the compatibility chart. - Backyard Baseball [baseball] - Backyard Baseball 2001 [baseball2001] Backyard Baseball 2003 [baseball2003] Backyard Football 2002 [football2002] Backyard Soccer [soccer] @@ -382,9 +394,9 @@ in the previous paragraph. 3.3) Maniac Mansion NES notes: ---- ------------------------- -Supported versions are English GB (E), French (F), German (G), Swedish -(SW) and English US (U). ScummVM requires just the PRG section to run -and not the whole ROM. +Supported versions are English GB (E), French (F), German (G), Italian (I), +Swedish (SW) and English US (U). ScummVM requires just the PRG section +to run and not the whole ROM. In order to get the game working, you will have to strip out the first 16 bytes from the ROM you are trying to work with. Any hex editor will @@ -392,7 +404,7 @@ work as long as you are able to copy/paste. After you open the ROM with the hex editor, copy everything from the second row (17th byte) to the end. After you do this, paste it to a new hex file. Name the new file "Maniac Mansion (XX).prg" while XX stands for the version you are -working with (E, F, G, SW, or U). The final size should be exactly +working with (E, F, G, I, SW, or U). The final size should be exactly 262144 bytes. If you add the game manually make sure that the platform is set to NES. diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index 0616713eab5..c8d19a57a5f 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -169,6 +169,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { // key pressed. A better fix would be for engines to stop // making invalid assumptions about ascii values. event.kbd.ascii = Common::KEYCODE_BACKSPACE; + _currentKeyDown.ascii = Common::KEYCODE_BACKSPACE; } break; diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp index 4857a385b71..5b3d2980017 100644 --- a/backends/fs/psp/psp-fs.cpp +++ b/backends/fs/psp/psp-fs.cpp @@ -248,18 +248,18 @@ AbstractFSNode *PSPFilesystemNode::getParent() const { Common::SeekableReadStream *PSPFilesystemNode::createReadStream() { const uint32 READ_BUFFER_SIZE = 1024; - + Common::SeekableReadStream *stream = PspIoStream::makeFromPath(getPath(), false); - - return new PspIoBufferedReadStream(stream, READ_BUFFER_SIZE, DisposeAfterUse::YES); + + return new Common::BufferedSeekableReadStream(stream, READ_BUFFER_SIZE, DisposeAfterUse::YES); } Common::WriteStream *PSPFilesystemNode::createWriteStream() { const uint32 WRITE_BUFFER_SIZE = 1024; - + Common::WriteStream *stream = PspIoStream::makeFromPath(getPath(), true); - - return new PspIoBufferedWriteStream(stream, WRITE_BUFFER_SIZE, DisposeAfterUse::YES); + + return new Common::BufferedWriteStream(stream, WRITE_BUFFER_SIZE, DisposeAfterUse::YES); } #endif //#ifdef __PSP__ diff --git a/backends/fs/psp/psp-stream.cpp b/backends/fs/psp/psp-stream.cpp index 3b0737ba63e..10b80a0639a 100644 --- a/backends/fs/psp/psp-stream.cpp +++ b/backends/fs/psp/psp-stream.cpp @@ -43,17 +43,17 @@ #ifdef DEBUG_BUFFERS void printBuffer(byte *ptr, uint32 len) { uint32 printLen = len <= 10 ? len : 10; - + for (int i = 0; i < printLen; i++) { - PSP_INFO_PRINT("%x ", ptr[i]); + PSP_INFO_PRINT("%x ", ptr[i]); } - + if (len > 10) { PSP_INFO_PRINT("... "); for (int i = len - 10; i < len; i++) PSP_INFO_PRINT("%x ", ptr[i]); } - + PSP_INFO_PRINT("\n"); } #endif @@ -62,7 +62,7 @@ void printBuffer(byte *ptr, uint32 len) { PspIoStream::PspIoStream(const Common::String &path, bool writeMode) : _handle(0), _path(path), _fileSize(0), _writeMode(writeMode), - _physicalPos(0), _pos(0), _eos(false), _error(false), + _physicalPos(0), _pos(0), _eos(false), _error(false), _errorSuspend(0), _errorSource(0), _errorPos(0), _errorHandle(0), _suspendCount(0) { DEBUG_ENTER_FUNC(); @@ -74,11 +74,11 @@ PspIoStream::~PspIoStream() { if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("suspended\n"); - + PowerMan.unregisterForSuspend(this); // Unregister with powermanager to be suspended // Must do this before fclose() or resume() will reopen. sceIoClose(_handle); - + PowerMan.endCriticalSection(); } @@ -87,7 +87,7 @@ PspIoStream::~PspIoStream() { */ void *PspIoStream::open() { DEBUG_ENTER_FUNC(); - + if (PowerMan.beginCriticalSection()) { // No need to open? Just return the _handle resume() already opened PSP_DEBUG_PRINT_FUNC("suspended\n"); @@ -97,13 +97,13 @@ void *PspIoStream::open() { if (!_handle) { _error = true; _handle = NULL; - } - + } + // Get the file size. This way is much faster than going to the end of the file and back SceIoStat stat; sceIoGetstat(_path.c_str(), &stat); _fileSize = *((uint32 *)(void *)&stat.st_size); // 4GB file (32 bits) is big enough for us - + PSP_DEBUG_PRINT("%s filesize[%d]\n", _path.c_str(), _fileSize); PowerMan.registerForSuspend(this); // Register with the powermanager to be suspended @@ -115,7 +115,7 @@ void *PspIoStream::open() { bool PspIoStream::err() const { DEBUG_ENTER_FUNC(); - + if (_error) // We dump since no printing to screen with suspend callback PSP_ERROR("mem_error[%d], source[%d], suspend error[%d], pos[%d]," "_errorPos[%d], _errorHandle[%p], suspendCount[%d]\n", @@ -142,9 +142,9 @@ int32 PspIoStream::size() const { } bool PspIoStream::physicalSeekFromCur(int32 offset) { - + int ret = sceIoLseek32(_handle, offset, PSP_SEEK_CUR); - + if (ret < 0) { _error = true; PSP_ERROR("failed to seek in file[%s] to [%x]. Error[%x]\n", _path.c_str(), offset, ret); @@ -158,7 +158,7 @@ bool PspIoStream::seek(int32 offs, int whence) { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT_FUNC("offset[0x%x], whence[%d], _pos[0x%x], _physPos[0x%x]\n", offs, whence, _pos, _physicalPos); _eos = false; - + int32 posToSearchFor = 0; switch (whence) { case SEEK_CUR: @@ -179,9 +179,9 @@ bool PspIoStream::seek(int32 offs, int whence) { _eos = true; return false; } - + _pos = posToSearchFor; - + return true; } @@ -198,33 +198,33 @@ uint32 PspIoStream::read(void *ptr, uint32 len) { if (len > lenRemainingInFile) { len = lenRemainingInFile; _eos = true; - } + } if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("suspended\n"); - + // check if we need to seek if (_pos != _physicalPos) PSP_DEBUG_PRINT("seeking from %x to %x\n", _physicalPos, _pos); if (!physicalSeekFromCur(_pos - _physicalPos)) { _error = true; return 0; - } - + } + int ret = sceIoRead(_handle, ptr, len); PowerMan.endCriticalSection(); - + _physicalPos += ret; // Update position _pos = _physicalPos; - + if (ret != (int)len) { // error PSP_ERROR("sceIoRead returned [0x%x] instead of len[0x%x]\n", ret, len); _error = true; - _errorSource = 4; + _errorSource = 4; } return ret; -} +} uint32 PspIoStream::write(const void *ptr, uint32 len) { DEBUG_ENTER_FUNC(); @@ -234,7 +234,7 @@ uint32 PspIoStream::write(const void *ptr, uint32 len) { return 0; _eos = false; // we can't have eos with write - + if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("suspended\n"); @@ -244,11 +244,11 @@ uint32 PspIoStream::write(const void *ptr, uint32 len) { _error = true; return 0; } - + int ret = sceIoWrite(_handle, ptr, len); - + PowerMan.endCriticalSection(); - + if (ret != (int)len) { _error = true; _errorSource = 5; @@ -257,10 +257,10 @@ uint32 PspIoStream::write(const void *ptr, uint32 len) { _physicalPos += ret; _pos = _physicalPos; - + if (_pos > _fileSize) - _fileSize = _pos; - + _fileSize = _pos; + return ret; } @@ -323,7 +323,7 @@ int PspIoStream::resume() { // Resume our previous position if needed if (_handle > 0 && _pos > 0) { ret = sceIoLseek32(_handle, _pos, PSP_SEEK_SET); - + _physicalPos = _pos; if (ret < 0) { // Check for problem diff --git a/backends/fs/psp/psp-stream.h b/backends/fs/psp/psp-stream.h index be3a1220de6..d4497aa79fe 100644 --- a/backends/fs/psp/psp-stream.h +++ b/backends/fs/psp/psp-stream.h @@ -33,22 +33,6 @@ #include "common/stream.h" #include "common/str.h" -class PspIoBufferedReadStream : public Common::BufferedSeekableReadStream { -public: - PspIoBufferedReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::YES) : BufferedSeekableReadStream(parentStream, bufSize, disposeParentStream) {} -protected: - virtual void allocBuf(uint32 bufSize) { _buf = (byte *)memalign(64, bufSize); } // want 64 byte alignment for cache - virtual void deallocBuf() { free(_buf); } -}; - -class PspIoBufferedWriteStream : public Common::BufferedWriteStream { -public: - PspIoBufferedWriteStream(WriteStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::YES) : BufferedWriteStream(parentStream, bufSize, disposeParentStream) {} -protected: - virtual void allocBuf(uint32 bufSize) { _buf = (byte *)memalign(64, bufSize); } - virtual void deallocBuf() { free(_buf); } -}; - /** * Class to handle special suspend/resume needs of PSP IO Streams */ @@ -61,7 +45,7 @@ protected: int _physicalPos; // physical position in file int _pos; // position. Sometimes virtual bool _eos; // EOS flag - + enum { SuspendError = 2, ResumeError = 3 @@ -74,9 +58,9 @@ protected: int _errorPos; SceUID _errorHandle; int _suspendCount; - + bool physicalSeekFromCur(int32 offset); - + public: /** @@ -101,7 +85,7 @@ public: virtual int32 size() const; virtual bool seek(int32 offs, int whence = SEEK_SET); virtual uint32 read(void *dataPtr, uint32 dataSize); - + // for suspending int suspend(); /* Suspendable interface (power manager) */ int resume(); /* " " */ diff --git a/backends/fs/stdiostream.cpp b/backends/fs/stdiostream.cpp index 8845d796c67..d0600f41a61 100644 --- a/backends/fs/stdiostream.cpp +++ b/backends/fs/stdiostream.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use FILE, fopen etc. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/fs/stdiostream.h" StdioStream::StdioStream(void *handle) : _handle(handle) { diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp index c74868b40de..f7b9c837f2b 100644 --- a/backends/fs/windows/windows-fs-factory.cpp +++ b/backends/fs/windows/windows-fs-factory.cpp @@ -23,6 +23,10 @@ */ #if defined(WIN32) + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/fs/windows/windows-fs-factory.h" #include "backends/fs/windows/windows-fs.cpp" diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp index 4f73d7384b5..fd32777a1bc 100644 --- a/backends/midi/alsa.cpp +++ b/backends/midi/alsa.cpp @@ -22,6 +22,9 @@ * $Id$ */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(USE_ALSA) diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp index 3486532549d..7bf702de58b 100644 --- a/backends/midi/camd.cpp +++ b/backends/midi/camd.cpp @@ -22,6 +22,9 @@ * $Id$ */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(__amigaos4__) diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp index aa0ad75f0a4..97db5cb2920 100644 --- a/backends/midi/coreaudio.cpp +++ b/backends/midi/coreaudio.cpp @@ -24,6 +24,9 @@ #ifdef MACOSX +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + // HACK to disable deprecated warnings under Mac OS X 10.5. // Apple depracted the AUGraphNewNode & AUGraphGetNodeInfo APIs // in favor of the new AUGraphAddNode & AUGraphNodeInfo APIs. diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp index 08f36a8b0fa..bca16df61ad 100644 --- a/backends/midi/coremidi.cpp +++ b/backends/midi/coremidi.cpp @@ -24,6 +24,9 @@ #ifdef MACOSX +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/config-manager.h" #include "common/util.h" #include "sound/musicplugin.h" diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp index 8c006b2cd94..5e4088fa178 100644 --- a/backends/midi/dmedia.cpp +++ b/backends/midi/dmedia.cpp @@ -29,6 +29,9 @@ #if defined(IRIX) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include "common/util.h" #include "common/config-manager.h" diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp index e3d2c35b39d..c0098742d02 100644 --- a/backends/midi/seq.cpp +++ b/backends/midi/seq.cpp @@ -28,6 +28,9 @@ * both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html) */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(USE_SEQ_MIDI) diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp index b00188dfea5..01e28aa5ca4 100644 --- a/backends/midi/stmidi.cpp +++ b/backends/midi/stmidi.cpp @@ -36,6 +36,9 @@ #if defined __MINT__ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include #include "sound/mpu401.h" #include "common/util.h" diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp index f507f1e00a4..d79a83809f1 100644 --- a/backends/midi/timidity.cpp +++ b/backends/midi/timidity.cpp @@ -34,7 +34,12 @@ * */ -#if defined (UNIX) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/scummsys.h" + +#if defined(USE_TIMIDITY) #include "common/util.h" #include "common/endian.h" diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index da44c40978d..81b29219b4d 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -24,6 +24,9 @@ #if defined(WIN32) && !defined(_WIN32_WCE) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #define WIN32_LEAN_AND_MEAN #include // winnt.h defines ARRAYSIZE, but we want our own one... @@ -106,7 +109,7 @@ void MidiDriver_WIN::sysEx(const byte *msg, uint16 length) { return; if (WaitForSingleObject (_streamEvent, 2000) == WAIT_TIMEOUT) { - warning ("Could not send SysEx - MMSYSTEM is still trying to send data."); + warning ("Could not send SysEx - MMSYSTEM is still trying to send data"); return; } diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build index 1c407bd4698..f3fb77cbcf1 100644 --- a/backends/platform/android/README.build +++ b/backends/platform/android/README.build @@ -82,7 +82,8 @@ Then build ScummVM: export ANDROID_TOP= - ./configure --backend=android --host=android --enable-zlib #and any other flags + ./configure --backend=android --host=android --enable-zlib --disable-timidity + # ... and any other configure flags you want make scummvm.apk This will build a "monolithic" ScummVM package, with the engines diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index f6af0fcff5e..38f387b201c 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -109,7 +109,7 @@ static void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) { env->DeleteLocalRef(cls); } -// floating point. use sparingly. +// floating point. use sparingly. template static inline T scalef(T in, float numerator, float denominator) { return static_cast(in) * numerator / denominator; @@ -177,7 +177,6 @@ private: GLESPaletteTexture* _game_texture; int _shake_offset; Common::Rect _focus_rect; - bool _full_screen_dirty; // Overlay layer GLES4444Texture* _overlay_texture; @@ -320,7 +319,6 @@ OSystem_Android::OSystem_Android(jobject am) _fsFactory(new POSIXFilesystemFactory()), _asset_archive(new AndroidAssetArchive(am)), _shake_offset(0), - _full_screen_dirty(false), _event_queue_lock(createMutex()) { } @@ -400,7 +398,7 @@ static void ScummVM_audioMixCallback(JNIEnv* env, jobject self, jsize len = env->GetArrayLength(jbuf); jbyte* buf = env->GetByteArrayElements(jbuf, NULL); if (buf == NULL) { - warning("Unable to get Java audio byte array. Skipping."); + warning("Unable to get Java audio byte array. Skipping"); return; } Audio::MixerImpl* mixer = @@ -862,6 +860,9 @@ void OSystem_Android::hideOverlay() { void OSystem_Android::clearOverlay() { ENTER("clearOverlay()"); _overlay_texture->fillBuffer(0); + + // Shouldn't need this, but works around a 'blank screen' bug on Nexus1 + updateScreen(); } void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) { @@ -887,6 +888,9 @@ void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch, // This 'pitch' is pixels not bytes _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0])); + + // Shouldn't need this, but works around a 'blank screen' bug on Nexus1? + updateScreen(); } int16 OSystem_Android::getOverlayHeight() { @@ -1135,7 +1139,7 @@ OSystem::MutexRef OSystem_Android::createMutex() { pthread_mutex_t *mutex = new pthread_mutex_t; if (pthread_mutex_init(mutex, &attr) != 0) { - warning("pthread_mutex_init() failed!"); + warning("pthread_mutex_init() failed"); delete mutex; return NULL; } @@ -1144,18 +1148,18 @@ OSystem::MutexRef OSystem_Android::createMutex() { void OSystem_Android::lockMutex(MutexRef mutex) { if (pthread_mutex_lock((pthread_mutex_t*)mutex) != 0) - warning("pthread_mutex_lock() failed!"); + warning("pthread_mutex_lock() failed"); } void OSystem_Android::unlockMutex(MutexRef mutex) { if (pthread_mutex_unlock((pthread_mutex_t*)mutex) != 0) - warning("pthread_mutex_unlock() failed!"); + warning("pthread_mutex_unlock() failed"); } void OSystem_Android::deleteMutex(MutexRef mutex) { pthread_mutex_t* m = (pthread_mutex_t*)mutex; if (pthread_mutex_destroy(m) != 0) - warning("pthread_mutex_destroy() failed!"); + warning("pthread_mutex_destroy() failed"); else delete m; } @@ -1330,7 +1334,7 @@ static void ScummVM_enableZoning(JNIEnv* env, jobject self, jboolean 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); + cpp_obj->setSurfaceSize(width, height); } const static JNINativeMethod gMethods[] = { diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java index d39aa363eff..6986f3988d5 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java @@ -23,6 +23,8 @@ import javax.microedition.khronos.egl.EGLSurface; import java.io.File; import java.util.concurrent.Semaphore; +import java.util.Map; +import java.util.LinkedHashMap; // At least in Android 2.1, eglCreateWindowSurface() requires an @@ -109,6 +111,51 @@ public class ScummVM implements SurfaceHolder.Callback { } } + // For debugging + private static final Map attribs; + static { + attribs = new LinkedHashMap(); + attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID); + attribs.put("BUFFER_SIZE", EGL10.EGL_BUFFER_SIZE); + attribs.put("RED_SIZE", EGL10.EGL_RED_SIZE); + attribs.put("GREEN_SIZE", EGL10.EGL_GREEN_SIZE); + attribs.put("BLUE_SIZE", EGL10.EGL_BLUE_SIZE); + attribs.put("ALPHA_SIZE", EGL10.EGL_ALPHA_SIZE); + //attribs.put("BIND_TO_RGB", EGL10.EGL_BIND_TO_TEXTURE_RGB); + //attribs.put("BIND_TO_RGBA", EGL10.EGL_BIND_TO_TEXTURE_RGBA); + attribs.put("CONFIG_CAVEAT", EGL10.EGL_CONFIG_CAVEAT); + attribs.put("DEPTH_SIZE", EGL10.EGL_DEPTH_SIZE); + attribs.put("LEVEL", EGL10.EGL_LEVEL); + attribs.put("MAX_PBUFFER_WIDTH", EGL10.EGL_MAX_PBUFFER_WIDTH); + attribs.put("MAX_PBUFFER_HEIGHT", EGL10.EGL_MAX_PBUFFER_HEIGHT); + attribs.put("MAX_PBUFFER_PIXELS", EGL10.EGL_MAX_PBUFFER_PIXELS); + //attribs.put("MAX_SWAP_INTERVAL", EGL10.EGL_MAX_SWAP_INTERVAL); + //attribs.put("MIN_SWAP_INTERVAL", EGL10.EGL_MIN_SWAP_INTERVAL); + attribs.put("NATIVE_RENDERABLE", EGL10.EGL_NATIVE_RENDERABLE); + attribs.put("NATIVE_VISUAL_ID", EGL10.EGL_NATIVE_VISUAL_ID); + attribs.put("NATIVE_VISUAL_TYPE", EGL10.EGL_NATIVE_VISUAL_TYPE); + attribs.put("SAMPLE_BUFFERS", EGL10.EGL_SAMPLE_BUFFERS); + attribs.put("SAMPLES", EGL10.EGL_SAMPLES); + attribs.put("STENCIL_SIZE", EGL10.EGL_STENCIL_SIZE); + attribs.put("SURFACE_TYPE", EGL10.EGL_SURFACE_TYPE); + attribs.put("TRANSPARENT_TYPE", EGL10.EGL_TRANSPARENT_TYPE); + attribs.put("TRANSPARENT_RED_VALUE", EGL10.EGL_TRANSPARENT_RED_VALUE); + attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE); + attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE); + } + private void dumpEglConfig(EGLConfig config) { + int[] value = new int[1]; + for (Map.Entry entry : attribs.entrySet()) { + egl.eglGetConfigAttrib(eglDisplay, config, + entry.getValue(), value); + if (value[0] == EGL10.EGL_NONE) + Log.d(LOG_TAG, entry.getKey() + ": NONE"); + else + Log.d(LOG_TAG, String.format("%s: %d", + entry.getKey(), value[0])); + } + } + // Called by ScummVM thread (from initBackend) private void createScummVMGLContext() { egl = (EGL10)EGLContext.getEGL(); @@ -125,10 +172,75 @@ public class ScummVM implements SurfaceHolder.Callback { EGLConfig[] configs = new EGLConfig[numConfigs]; egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs, num_config); - eglConfig = configs[0]; + + if (false) { + Log.d(LOG_TAG, + String.format("Found %d EGL configurations.", numConfigs)); + for (EGLConfig config : configs) + dumpEglConfig(config); + } + + // Android's eglChooseConfig is busted in several versions and + // devices so we have to filter/rank the configs again ourselves. + eglConfig = chooseEglConfig(configs); + if (false) { + Log.d(LOG_TAG, + String.format("Chose EGL config from %d possibilities.", numConfigs)); + dumpEglConfig(eglConfig); + } eglContext = egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, null); + if (eglContext == EGL10.EGL_NO_CONTEXT) + throw new RuntimeException("Failed to create context"); + } + + private EGLConfig chooseEglConfig(EGLConfig[] configs) { + int best = 0; + int bestScore = -1; + int[] value = new int[1]; + for (int i = 0; i < configs.length; i++) { + EGLConfig config = configs[i]; + int score = 10000; + egl.eglGetConfigAttrib(eglDisplay, config, + EGL10.EGL_SURFACE_TYPE, value); + if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0) + continue; // must have + + egl.eglGetConfigAttrib(eglDisplay, config, + EGL10.EGL_CONFIG_CAVEAT, value); + if (value[0] != EGL10.EGL_NONE) + score -= 1000; + + // Must be at least 555, but then smaller is better + final int[] colorBits = {EGL10.EGL_RED_SIZE, + EGL10.EGL_GREEN_SIZE, + EGL10.EGL_BLUE_SIZE, + EGL10.EGL_ALPHA_SIZE}; + for (int component : colorBits) { + egl.eglGetConfigAttrib(eglDisplay, config, + component, value); + if (value[0] >= 5) + score += 10; // boost if >5 bits accuracy + score -= value[0]; // penalize for wasted bits + } + + egl.eglGetConfigAttrib(eglDisplay, config, + EGL10.EGL_DEPTH_SIZE, value); + score -= value[0]; // penalize for wasted bits + + if (score > bestScore) { + best = i; + bestScore = score; + } + } + + if (bestScore < 0) { + Log.e(LOG_TAG, "Unable to find an acceptable EGL config, expect badness."); + return configs[0]; + } + + return configs[best]; } // Called by ScummVM thread @@ -137,12 +249,13 @@ public class ScummVM implements SurfaceHolder.Callback { try { surfaceLock.acquire(); } catch (InterruptedException e) { - Log.e(this.toString(), - "Interrupted while waiting for surface lock", e); + Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e); return; } eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeSurface, null); + if (eglSurface == EGL10.EGL_NO_SURFACE) + Log.e(LOG_TAG, "CreateWindowSurface failed!"); egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); GL10 gl = (GL10)eglContext.getGL(); @@ -302,8 +415,8 @@ public class ScummVM implements SurfaceHolder.Callback { if (buf_size < 0) { int guess = AUDIO_FRAME_SIZE * sample_rate / 100; // 10ms of audio Log.w(LOG_TAG, String.format( - "Unable to get min audio buffer size (error %d). Guessing %dB.", - buf_size, guess)); + "Unable to get min audio buffer size (error %d). Guessing %dB.", + buf_size, guess)); buf_size = guess; } Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio", diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp index d4c002fbd04..81a8f7fbc76 100644 --- a/backends/platform/android/video.cpp +++ b/backends/platform/android/video.cpp @@ -38,6 +38,9 @@ #include "backends/platform/android/video.h" +// Unfortunately, Android devices are too varied to make broad assumptions :/ +#define TEXSUBIMAGE_IS_EXPENSIVE 0 + #undef LOG_TAG #define LOG_TAG "ScummVM-video" @@ -158,13 +161,11 @@ void GLESTexture::allocBuffer(GLuint w, GLuint h) { // later (perhaps with multiple TexSubImage2D operations). CHECK_GL_ERROR(); glBindTexture(GL_TEXTURE_2D, _texture_name); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR(); glTexImage2D(GL_TEXTURE_2D, 0, glFormat(), @@ -177,6 +178,7 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, const void* buf, int pitch) { ENTER("updateBuffer(%u, %u, %u, %u, %p, %d)", x, y, w, h, buf, pitch); glBindTexture(GL_TEXTURE_2D, _texture_name); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); setDirtyRect(Common::Rect(x, y, x+w, y+h)); @@ -185,7 +187,25 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, glFormat(), glType(), buf); } else { // GLES removed the ability to specify pitch, so we - // have to do this row by row. + // have to do this ourselves. + if (h == 0) + return; + +#if TEXSUBIMAGE_IS_EXPENSIVE + byte tmpbuf[w * h * bytesPerPixel()]; + const byte* src = static_cast(buf); + byte* dst = tmpbuf; + GLuint count = h; + do { + memcpy(dst, src, w * bytesPerPixel()); + dst += w * bytesPerPixel(); + src += pitch; + } while (--count); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, + glFormat(), glType(), tmpbuf); +#else + // This version avoids the intermediate copy at the expense of + // repeat glTexSubImage2D calls. On some devices this is worse. const byte* src = static_cast(buf); do { glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, @@ -193,16 +213,15 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, ++y; src += pitch; } while (--h); +#endif } } void GLESTexture::fillBuffer(byte x) { - byte tmpbuf[_surface.h * _surface.w * bytesPerPixel()]; - memset(tmpbuf, 0, _surface.h * _surface.w * bytesPerPixel()); - glBindTexture(GL_TEXTURE_2D, _texture_name); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h, - glFormat(), glType(), tmpbuf); - setDirty(); + int rowbytes = _surface.w * bytesPerPixel(); + byte tmpbuf[_surface.h * rowbytes]; + memset(tmpbuf, x, _surface.h * rowbytes); + updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes); } void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { @@ -215,6 +234,7 @@ void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { //glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLint crop[4] = {0, _surface.h, _surface.w, -_surface.h}; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glColor4ub(0xff, 0xff, 0xff, 0xff); // Android GLES bug? glDrawTexiOES(x, y, 0, w, h); } else #endif diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 0d9b931d2c1..8fd12d66bf6 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -272,7 +272,7 @@ static int findGames(Game *games, int max, bool use_ini) games[curr_game].dir, games[curr_game].language, games[curr_game].platform, games, curr_game)) { - + strcpy(games[curr_game].text, ge->description().c_str()); #if 0 printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n", diff --git a/backends/platform/dingux/README.DINGUX b/backends/platform/dingux/README.DINGUX new file mode 100644 index 00000000000..d867e02f036 --- /dev/null +++ b/backends/platform/dingux/README.DINGUX @@ -0,0 +1,68 @@ +ScummVM-DINGUX README +============================================================================== + +Requirements +============ +- Dingoo A320/A330 +- Dingux installed on SD card +- Fixed Tremor libs in dingux rootfs (see below) + +Controls +============ +- Dpad: move mouse cursor +- Y: left mouse button click +- A: '0' key +- B: right mouse button click +- X: '.' key (skips dialogue line in some engines) +- Left Trigger: open global menu +- Right Trigger: ESC button, scene skip in some engines +- Select: opens virtual keyboard +- Start: F5 key, game menu in some engines + +Installation from binaries +============================== +Mount your dingux SD card in your pc, then copy the directory "scummvm" found in +the release package to a directory inside /pathtosdcard/local/dirofyourchoice +(on windows it would be SDLETTER:\local\dirofyourchoice). +At this point is sufficient to point your launcher (eg. gmenu2x) to scummvm.gpe +file included into the scummvm directory you copied to the SD card, and then launch it. + +Building from binaries +============================== +* ToDO * + +Kernel and rootfs WARNINGS +============================== +All the dingux root images (rootfs) i found floating on the net have +broken tremor libraries, which make scummvm crash in a bad way. +One solution is to replace the libraries in your rootfs by injecting these fixed ones: +http://hkzlab.ipv7.net/files/misc/dingux/dingux_fixed_tremor_libs.zip +After having added these libs, scummvm should work on your standard dingux kernel, +but this doesn't mean it will work perfectly: +non-opendingux kernels doesn't have lcd double buffering leading to a lot of annoying +tearing on screen. + +The best way to address all the problems in one shot, is to use an opendingux kernel for +your dingoo, which has some interesting advantages: +- The kernel gets updated and kept in sync with main linux tree +- Double buffering and centering of screen image +- Support for swap on compressed ram +I have prepared a rootfs image with fixed libs and swap-on-zram to use together with opendingux kernels: +http://hkzlab.ipv7.net/files/misc/dingux/opendingux/opendingux_kernel_rootfs.zip +The kernel and rootfs images in the zip file is what i use for developing scummvm on dingux. + +BTW, i have built images for the A330 and A320 with ILI9325 controllers too, +but these version aren't tested (i have an A320 with ILI9331, but if someone wants to +donate an A330 to a poor scummvm developer so i can try the port there too... :P) + +If you need a launcher with opendingux cpu frequency scaler support, you can find gmenu2x here: +http://www.treewalker.org/dingux/cpufreq.html + +I've also prepared a rootfs image for use on normal dingux kernels (non-opendingux ones). +It's based on elta's rootfs image with just the fixed libs replaced. +http://hkzlab.ipv7.net/files/misc/dingux/normal_dingux/rootfs_elta_fixtremor.zip +I still raccomand the use of opendingux kernel + rootfs, but if you don't, this roofs +image plus another kernel (eg. SiENcE's one) should be do the job. + +Enjoy + diff --git a/backends/platform/dingux/dingux-events.cpp b/backends/platform/dingux/dingux-events.cpp index b6070f68ca1..f9b519623d5 100644 --- a/backends/platform/dingux/dingux-events.cpp +++ b/backends/platform/dingux/dingux-events.cpp @@ -149,7 +149,7 @@ bool OSystem_SDL_Dingux::remapKey(SDL_Event &ev, Common::Event &event) { } return true; - } else if (ev.key.keysym.sym == BUT_A) { // virtual keyboard + } else if (ev.key.keysym.sym == BUT_A) { // key '0' ev.key.keysym.sym = SDLK_0; event.kbd.keycode = Common::KEYCODE_0; diff --git a/backends/platform/dingux/dingux.mk b/backends/platform/dingux/dingux.mk new file mode 100644 index 00000000000..882078fe462 --- /dev/null +++ b/backends/platform/dingux/dingux.mk @@ -0,0 +1,30 @@ +DINGUX_EXE_STRIPPED := scummvm_stripped$(EXEEXT) + +bundle_name = dingux-dist/scummvm + +all: $(DINGUX_EXE_STRIPPED) + +$(DINGUX_EXE_STRIPPED): $(EXECUTABLE) + $(STRIP) $< -o $@ + +dingux-distclean: + rm -rf $(bundle_name) + rm $(DINGUX_EXE_STRIPPED) + +dingux-dist: all + $(MKDIR) $(bundle_name) + $(MKDIR) $(bundle_name)/saves + $(STRIP) $(EXECUTABLE) -o $(bundle_name)/scummvm.elf + $(CP) $(DIST_FILES_THEMES) $(bundle_name)/ +ifdef DIST_FILES_ENGINEDATA + $(CP) $(DIST_FILES_ENGINEDATA) $(bundle_name)/ +endif + $(CP) $(DIST_FILES_DOCS) $(bundle_name)/ +ifdef DYNAMIC_MODULES + $(MKDIR) $(bundle_name)/plugins + $(CP) $(PLUGINS) $(bundle_name)/plugins + $(STRIP) $(bundle_name)/plugins/* +endif + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/dingux/scummvm.gpe $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/dingux/README.DINGUX $(bundle_name)/ diff --git a/backends/platform/dingux/scummvm.gpe b/backends/platform/dingux/scummvm.gpe new file mode 100644 index 00000000000..84ab0c6b95a --- /dev/null +++ b/backends/platform/dingux/scummvm.gpe @@ -0,0 +1,5 @@ +#!/bin/sh + +HOME=`pwd` +$HOME/scummvm.elf + diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index df7063c08a8..db8e41af482 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -69,6 +69,8 @@ else # TODO: Inherit the earth uses so much RAM that I have removed libmad in order to # claw some back. + + else ifdef DS_BUILD_I diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp index 71f4f93c270..581509f939a 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.cpp +++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp @@ -177,7 +177,7 @@ void drawText(int tx, int ty, const char *string, bool highlight) { baseAddress[ty * 32 + tx + p] = baseValue | tile; } } - + } @@ -292,7 +292,7 @@ void drawAutoComplete() { // When there's no completions on the bottom of the screen, it acts like a mouse pad // so this text indicates that drawText(11, 18, "MOUSE AREA", true); - + } else { @@ -303,10 +303,10 @@ void drawAutoComplete() { for (int r = 0; r < autoCompleteCount; r++) { int y = 12 + (r % 6) * 2; int x = 0 + ((r / 6) * 16); - + drawText(x, y, autoCompleteWord[r], selectedCompletion == r); } - + } } diff --git a/backends/platform/gp2x/build/README-GP2X b/backends/platform/gp2x/build/README-GP2X index f95a974230e..3c6591d369b 100644 --- a/backends/platform/gp2x/build/README-GP2X +++ b/backends/platform/gp2x/build/README-GP2X @@ -1,72 +1,40 @@ -ScummVM - GP2X SPECIFIC README - HEAD SVN +ScummVM - GP2X SPECIFIC README ------------------------------------------------------------------------ Contents: * About the backend/port <#About_the_backendport> - * Game compatability <#Game_compatibility> - * Included engines <#Included_engines> * Supported audio options <#Supported_audio_options> - * Supported cut-scene options <#Supported_cut-scene_options> - * Recent changes <#Recent_changes> - * How to save <#How_to_save> - * Controller mappings <#Controller_mappings> - * Know issues <#Know_issues> - * TODO's <#Major_TODOs> - * Additional resources/links <#Additional_resourceslinks> * Credits <#Credits> ------------------------------------------------------------------------ Please refer to the: -GP2X/GP2XWiz ScummVM Forum: -WiKi: +GP2X/GP2XWiz ScummVM Forum: +WiKi: -for the most current information on the port and any updates to this +for the most current information on the port and any updates to this documentation. +The wiki includes detailed instructions on how to use the port and +control information. + ------------------------------------------------------------------------ About the backend/port -This is the readme for the offficial GP2X ScummVM backend (also known as +This is the readme for the official GP2X ScummVM backend (also known as the GP2X port). This is an SVN test release of ScummVM for the GP2X, it would be appreciated if this SVN test distribution was not mirrored and that -people be directed to http://www.distant-earth.com/scummvm instead for +people be directed to http://scummvm.distant-earth.com/ instead for updated SVN builds. Full supported official releases of the GP2X ScummVM backend are made in line with main official releases and are avalalble from the ScummVM downloads page . -This build is in an active state of development and as such no -?expected? behavior can be guaranteed ;). - -SVN builds are quickly tested with firmware 2.0.0 for reference. - -Please refer to the GP2X ScummVM forum - and WiKi - for the latest information on -the port. - ------------------------------------------------------------------------- -Game compatibility - -For information on the compatability of a specific game please refer to -the GP2X compatability section of the ScummVM WiKi -. - -Please note the version and date of the ScummVM build you are running -when reviewing the above list. - ------------------------------------------------------------------------- -Included engines - -Just because an engine is included does not mean any/all of its games -are supported. Please check game compatability for more infomation. - ------------------------------------------------------------------------ Supported audio options @@ -78,106 +46,6 @@ FLAC audio is currently unsupported. For best results use uncompressed audio in games. ------------------------------------------------------------------------- -Supported cut-scene options - -No cut scene compression options are currently supported. - -DXA video support will be added as soon as it is stable. - ------------------------------------------------------------------------- -Recent changes - -Refined audio hacks to reduce audio delay a little more. -Enabled hardware scalar code. -Now built using SDL 1.2.9 for the parts of the port that use SDL (some -parts now hit the hardware directly). -Enabled new launcher - (Ensure defaulttheme.zip is in the same folder as -the executable). -Aspect Ratio Correction can now be disabled ?per game?. When adding a -game you can find this option on the GFX tab. -Note: This will cause the game to run with a black border at the bottom -as it will be rendered to a 320*200 frame. - ------------------------------------------------------------------------- -How to save - -NOTE: Everything is saved to the SD card, saves are stored in the saves -folder under your main ScummVM executable unless you set another save -location. - -The configiration file for ScummVM (.scummvmrc) is stored in the same -place as the ScummVM executable. - -The save process below is for Scumm engine games but the principle is -the same for all. - -In Game. - -1. Right Trigger -2. Select SAVE with B -3. Select a position with B -4. Right trigger puts ? in the name box for some text. -5. Press B to save - -Basically the emulated keys you can use are equivelent to the values -buttons are mapped to, - -I have a virtual keyboard like the GP32 one (left/right on the stick to -pick chars) to add in at some point ;-) - ------------------------------------------------------------------------- -Controller mappings - -Mouse emulation: - -Stick: Move Pointer -Stick Click: ?light? Left Click -B: Left click -X: Right click - -Keyboard emulation: - -Start: Return -Select: Escape -Y: Space Bar (Pause) -Right Trigger: Game Menu (Save, Load, Quit etc.) -Volume Buttons: Increase and Decrease volume (5% per press) - -Fancy button combos: - -NOTE: To use button combos press and hold the Left Trigger then... - -Y: Toggle "zoom" mode - Try it in larger games like Broken Sword. -Volume Buttons: Increase and Decrease subtitle speed (In SCUMM games) -Right Trigger: 0 (For skipping the copy protection in Monkey Island 2) -Select: Exit ScummVM completely (and gracefully) - ------------------------------------------------------------------------- -Know issues - -Possible random crash (well SegFault). I have had this happen twice and -have not tracked down the cause. -It happens very infrequently, both times it was in the DOTT CD intro. -Saving often is never a bad idea anyhow. - ------------------------------------------------------------------------- -TODO's - -Fix save support when using the Sky engine (Beneath a Steel Sky) - You -CAN'T save at the moment but auto save works. - ------------------------------------------------------------------------- -Additional resources/links - - * ScummVM WiKi GP2X page - * ScummVM forums GP2X forum - - * My own ScummVM page (for - SVN/test builds) - * Main ScummVM site (for official supported - release builds) - ------------------------------------------------------------------------ Credits diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gp2x/build/config.sh index 2bc49564f7c..e0a1bf12097 100755 --- a/backends/platform/gp2x/build/config.sh +++ b/backends/platform/gp2x/build/config.sh @@ -18,6 +18,7 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. ./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd -#--enable-plugins --default-dynamic +# --disable-release --enable-debug +# --enable-plugins --default-dynamic echo Generating config for GP2X complete. Check for errors. diff --git a/backends/platform/gp2x/build/scummvm.gpe b/backends/platform/gp2x/build/scummvm.gpe index 1e69c149b9b..c6b051831ca 100755 --- a/backends/platform/gp2x/build/scummvm.gpe +++ b/backends/platform/gp2x/build/scummvm.gpe @@ -4,7 +4,7 @@ mount -o sync,remount /dev/mmcsd/disc0/part1 /mnt/sd/ # Run ScummVM, important this bit. -./scummvm.gp2x +./scummvm.gph # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gp2x/events.cpp b/backends/platform/gp2x/events.cpp index a40967743c2..08553968d23 100644 --- a/backends/platform/gp2x/events.cpp +++ b/backends/platform/gp2x/events.cpp @@ -30,7 +30,6 @@ #include "backends/platform/gp2x/gp2x-common.h" #include "backends/platform/gp2x/gp2x-hw.h" -#include "backends/keymapper/keymapper.h" #include "common/util.h" #include "common/events.h" #include "graphics/scaler/aspect.h" // for aspect2Real @@ -42,27 +41,46 @@ #define JOY_XAXIS 0 #define JOY_YAXIS 1 -/* GP2X Wiz: Main Joystick Mappings */ +/* Quick default button states for modifiers. */ +int BUTTON_STATE_L = false; + enum { - GP2X_BUTTON_UP = 0, - GP2X_BUTTON_UPLEFT = 1, - GP2X_BUTTON_LEFT = 2, - GP2X_BUTTON_DOWNLEFT = 3, - GP2X_BUTTON_DOWN = 4, - GP2X_BUTTON_DOWNRIGHT = 5, - GP2X_BUTTON_RIGHT = 6, - GP2X_BUTTON_UPRIGHT = 7, - GP2X_BUTTON_START = 8, - GP2X_BUTTON_SELECT = 9, - GP2X_BUTTON_L = 10, - GP2X_BUTTON_R = 11, - GP2X_BUTTON_A = 12, - GP2X_BUTTON_B = 13, - GP2X_BUTTON_X = 14, - GP2X_BUTTON_Y = 15, - GP2X_BUTTON_VOLUP = 16, - GP2X_BUTTON_VOLDOWN = 17, - GP2X_BUTTON_CLICK = 18 + /* DPAD/Stick */ + BUTTON_UP = 0, + BUTTON_UPLEFT = 1, + BUTTON_LEFT = 2, + BUTTON_DOWNLEFT = 3, + BUTTON_DOWN = 4, + BUTTON_DOWNRIGHT = 5, + BUTTON_RIGHT = 6, + BUTTON_UPRIGHT = 7, + /* Joystick Buttons */ + BUTTON_MENU = 8, // Start on F100 GP2X + BUTTON_SELECT = 9, + BUTTON_L = 10, + BUTTON_R = 11, + BUTTON_A = 12, + BUTTON_B = 13, + BUTTON_X = 14, + BUTTON_Y = 15, + BUTTON_VOLUP = 16, + BUTTON_VOLDOWN = 17, + BUTTON_CLICK = 18 +}; + +enum { + /* Unused Joystick Buttons on the GP2X */ + BUTTON_HOME = 51, + BUTTON_HOLD = 52, + BUTTON_HELP = 53, + BUTTON_HELP2 = 54 +}; + +enum { + /* Touchscreen TapMode */ + TAPMODE_LEFT = 0, + TAPMODE_RIGHT = 1, + TAPMODE_HOVER = 2 }; static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { @@ -168,16 +186,22 @@ void OSystem_GP2X::handleKbdMouse() { } } -static byte SDLModToOSystemKeyFlags(SDLMod mod) { - byte b = 0; - if (mod & KMOD_SHIFT) - b |= Common::KBD_SHIFT; - if (mod & KMOD_ALT) - b |= Common::KBD_ALT; - if (mod & KMOD_CTRL) - b |= Common::KBD_CTRL; +static void SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { - return b; + event.kbd.flags = 0; + + if (mod & KMOD_SHIFT) + event.kbd.flags |= Common::KBD_SHIFT; + if (mod & KMOD_ALT) + event.kbd.flags |= Common::KBD_ALT; + if (mod & KMOD_CTRL) + event.kbd.flags |= Common::KBD_CTRL; + + // Sticky flags + if (mod & KMOD_NUM) + event.kbd.flags |= Common::KBD_NUM; + if (mod & KMOD_CAPS) + event.kbd.flags |= Common::KBD_CAPS; } void OSystem_GP2X::moveStick() { @@ -205,7 +229,6 @@ void OSystem_GP2X::moveStick() { _km.x_down_count = 0; } - if ((stickBtn[0])||(stickBtn[1])||(stickBtn[7])){ if (_km.y_down_count!=2){ _km.y_vel = -1; @@ -224,14 +247,9 @@ void OSystem_GP2X::moveStick() { } } -/* Quick default button states for modifiers. */ -int GP2X_BUTTON_STATE_L = false; - bool OSystem_GP2X::pollEvent(Common::Event &event) { SDL_Event ev; ev.type = SDL_NOEVENT; - int axis; - byte b = 0; handleKbdMouse(); @@ -242,398 +260,483 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { return true; } - // GP2X Input mappings. - - /* - Single Button - - Movement: - - GP2X_BUTTON_UP Cursor Up - GP2X_BUTTON_DOWN Cursor Down - GP2X_BUTTON_LEFT Cursor Left - GP2X_BUTTON_RIGHT Cursor Right - - GP2X_BUTTON_UPLEFT Cursor Up Left - GP2X_BUTTON_UPRIGHT Cursor Up Right - GP2X_BUTTON_DOWNLEFT Cursor Down Left - GP2X_BUTTON_DOWNRIGHT Cursor Down Right - - Button Emulation: - - GP2X_BUTTON_CLICK Left Mouse Click - GP2X_BUTTON_A . (Period) - GP2X_BUTTON_B Left Mouse Click - GP2X_BUTTON_Y Space Bar - GP2X_BUTTON_X Right Mouse Click - GP2X_BUTTON_L Combo Modifier (Left Trigger) - GP2X_BUTTON_R Return (Right Trigger) - GP2X_BUTTON_START F5 (Game Menu) - GP2X_BUTTON_SELECT Escape - GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up - GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down - - Combos: - - GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) or Virtual Keyboard if enabled - GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) - GP2X_BUTTON_L & GP2X_BUTTON_Y Toggles setZoomOnMouse() for larger then 320*240 games to scale to the point + raduis. - GP2X_BUTTON_L & GP2X_BUTTON_START Common::EVENT_MAINMENU (ScummVM Global Main Menu) - GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) - */ - while (SDL_PollEvent(&ev)) { - - switch (ev.type) { - case SDL_KEYDOWN:{ - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - + preprocessEvents(&ev); + if (dispatchSDLEvent(ev, event)) return true; - } - case SDL_KEYUP: - { - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - // Ctrl-Alt- will change the GFX mode - if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { - // Swallow these key up events - break; - } - - return true; - } - case SDL_MOUSEMOTION: - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, ev.motion.x, ev.motion.y); - - setMousePos(event.mouse.x, event.mouse.y); - return true; - - case SDL_MOUSEBUTTONDOWN: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONDOWN; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONDOWN; -#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) - else if (ev.button.button == SDL_BUTTON_WHEELUP) - event.type = Common::EVENT_WHEELUP; - else if (ev.button.button == SDL_BUTTON_WHEELDOWN) - event.type = Common::EVENT_WHEELDOWN; -#endif -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONDOWN; -#endif - else - break; - - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - case SDL_MOUSEBUTTONUP: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONUP; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONUP; -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONUP; -#endif - else - break; - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - // GP2X Button mapings. Main code - - case SDL_JOYBUTTONDOWN: - _stickBtn[ev.jbutton.button] = 1; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (_stickBtn[GP2X_BUTTON_L] && (ev.jbutton.button == GP2X_BUTTON_SELECT)) { - event.type = Common::EVENT_QUIT; - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYDOWN; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = true; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_SELECT: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_QUIT; - } else { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_A: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_PREDICTIVE_DIALOG; - } else { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_Y: - if (GP2X_BUTTON_STATE_L == true) { - setZoomOnMouse(); - } else { - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_START: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - GP2X_HW::mixerMoveVolume(2); - if (GP2X_HW::volumeLevel == 100) { - displayMessageOnOSD("Maximum Volume"); - } else { - displayMessageOnOSD("Increasing Volume"); - } - break; - - case GP2X_BUTTON_VOLDOWN: - GP2X_HW::mixerMoveVolume(1); - if (GP2X_HW::volumeLevel == 0) { - displayMessageOnOSD("Minimal Volume"); - } else { - displayMessageOnOSD("Decreasing Volume"); - } - break; - } - } - return true; - - case SDL_JOYBUTTONUP: - _stickBtn[ev.jbutton.button] = 0; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_CLICK) { - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYUP; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_SELECT: - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_A: - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_Y: - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_START: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = false; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - break; - case GP2X_BUTTON_VOLDOWN: - break; - } - } - return true; - - case SDL_JOYAXISMOTION: - axis = ev.jaxis.value; - if ( axis > JOY_DEADZONE) { - axis -= JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else if ( axis < -JOY_DEADZONE ) { - axis += JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else - axis = 0; - - if ( ev.jaxis.axis == JOY_XAXIS) { - if (axis != 0) { - _km.x_vel = (axis > 0) ? 1:-1; - _km.x_down_count = 1; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - } else if (ev.jaxis.axis == JOY_YAXIS) { -#ifndef JOY_INVERT_Y - axis = -axis; -#endif -#ifdef JOY_ANALOG - _km.y_vel = -axis / 2000; - _km.y_down_count = 0; -#else - if (axis != 0) { - _km.y_vel = (-axis > 0) ? 1: -1; - _km.y_down_count = 1; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -#endif - } - - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case SDL_VIDEOEXPOSE: - _forceFull = true; - break; - - case SDL_QUIT: - event.type = Common::EVENT_QUIT; - return true; - } } return false; } -bool OSystem_GP2X::remapKey(SDL_Event &ev,Common::Event &event) { +bool OSystem_GP2X::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) { + switch (ev.type) { + case SDL_KEYDOWN: + return handleKeyDown(ev, event); + case SDL_KEYUP: + return handleKeyUp(ev, event); + case SDL_MOUSEMOTION: + return handleMouseMotion(ev, event); + case SDL_MOUSEBUTTONDOWN: + return handleMouseButtonDown(ev, event); + case SDL_MOUSEBUTTONUP: + return handleMouseButtonUp(ev, event); + case SDL_JOYBUTTONDOWN: + return handleJoyButtonDown(ev, event); + case SDL_JOYBUTTONUP: + return handleJoyButtonUp(ev, event); + case SDL_JOYAXISMOTION: + return handleJoyAxisMotion(ev, event); + + case SDL_VIDEOEXPOSE: + _forceFull = true; + break; + + case SDL_QUIT: + event.type = Common::EVENT_QUIT; + return true; + + } + return false; } -void OSystem_GP2X::setupKeymapper() { -#ifdef ENABLE_KEYMAPPER - using namespace Common; - Keymapper *mapper = getEventManager()->getKeymapper(); +bool OSystem_GP2X::handleKeyDown(SDL_Event &ev, Common::Event &event) { - HardwareKeySet *keySet = new HardwareKeySet(); - keySet->addHardwareKey(new HardwareKey( "a", KeyState(KEYCODE_a), "a", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "s", KeyState(KEYCODE_s), "s", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "d", KeyState(KEYCODE_d), "d", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "f", KeyState(KEYCODE_f), "f", kActionKeyType )); - keySet->addHardwareKey(new HardwareKey( "n", KeyState(KEYCODE_n), "n (vk)", kTriggerLeftKeyType, kVirtualKeyboardActionType )); - keySet->addHardwareKey(new HardwareKey( "m", KeyState(KEYCODE_m), "m (remap)", kTriggerRightKeyType, kKeyRemapActionType )); - keySet->addHardwareKey(new HardwareKey( "[", KeyState(KEYCODE_LEFTBRACKET), "[ (select)", kSelectKeyType )); - keySet->addHardwareKey(new HardwareKey( "]", KeyState(KEYCODE_RIGHTBRACKET), "] (start)", kStartKeyType )); - mapper->registerHardwareKeySet(keySet); + SDLModToOSystemKeyFlags(SDL_GetModState(), event); - Keymap *globalMap = new Keymap("global"); - Keymap *guiMap = new Keymap("gui"); - Action *act; - Event evt ; + // Handle scroll lock as a key modifier + if (ev.key.keysym.sym == SDLK_SCROLLOCK) + _scrollLock = !_scrollLock; - act = new Action(globalMap, "MENU", "Menu", kGenericActionType, kSelectKeyType); - act->addKeyEvent(KeyState(KEYCODE_F5, ASCII_F5, 0)); + if (_scrollLock) + event.kbd.flags |= Common::KBD_SCRL; - act = new Action(globalMap, "SKCT", "Skip", kGenericActionType, kActionKeyType); - act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0)); - - act = new Action(globalMap, "PAUS", "Pause", kGenericActionType, kStartKeyType); - act->addKeyEvent(KeyState(KEYCODE_SPACE, ' ', 0)); - - act = new Action(globalMap, "SKLI", "Skip line", kGenericActionType, kActionKeyType); - act->addKeyEvent(KeyState(KEYCODE_PERIOD, '.', 0)); - - act = new Action(globalMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType); - act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0)); - - act = new Action(globalMap, "REMP", "Remap keys", kKeyRemapActionType); - act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - - mapper->addGlobalKeymap(globalMap); - - act = new Action(guiMap, "CLOS", "Close", kGenericActionType, kStartKeyType); - act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0)); - - act = new Action(guiMap, "CLIK", "Mouse click"); - act->addLeftClickEvent(); - - act = new Action(guiMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType); - act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0)); - - act = new Action(guiMap, "REMP", "Remap keys", kKeyRemapActionType); - act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - - mapper->addGlobalKeymap(guiMap); - - mapper->pushKeymap("global"); + // Alt-Return and Alt-Enter toggle full screen mode + if (event.kbd.hasFlags(Common::KBD_ALT) && (ev.key.keysym.sym == SDLK_RETURN || ev.key.keysym.sym == SDLK_KP_ENTER)) { + beginGFXTransaction(); + setFullscreenMode(!_videoMode.fullscreen); + endGFXTransaction(); +#ifdef USE_OSD + if (_videoMode.fullscreen) + displayMessageOnOSD("Fullscreen mode"); + else + displayMessageOnOSD("Windowed mode"); #endif + + return false; + } + + // Alt-S: Create a screenshot + if (event.kbd.hasFlags(Common::KBD_ALT) && ev.key.keysym.sym == 's') { + char filename[20]; + + for (int n = 0;; n++) { + SDL_RWops *file; + + sprintf(filename, "scummvm%05d.bmp", n); + file = SDL_RWFromFile(filename, "r"); + if (!file) + break; + SDL_RWclose(file); + } + if (saveScreenshot(filename)) + printf("Saved '%s'\n", filename); + else + printf("Could not save screenshot!\n"); + return false; + } + + // Ctrl-m toggles mouse capture + if (event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'm') { + toggleMouseGrab(); + return false; + } + + if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') { + event.type = Common::EVENT_QUIT; + return true; + } + + if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'u') { + event.type = Common::EVENT_MUTE; + return true; + } + + // Ctrl-Alt- will change the GFX mode + if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { + if (handleScalerHotkeys(ev.key)) + return false; + } + + if (remapKey(ev, event)) + return true; + + event.type = Common::EVENT_KEYDOWN; + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; + event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); + + return true; } +bool OSystem_GP2X::handleKeyUp(SDL_Event &ev, Common::Event &event) { + if (remapKey(ev, event)) + return true; + + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; + event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); + + // Ctrl-Alt- will change the GFX mode + SDLModToOSystemKeyFlags(SDL_GetModState(), event); + + // Set the scroll lock sticky flag + if (_scrollLock) + event.kbd.flags |= Common::KBD_SCRL; + + if (isScalerHotkey(event)) + // Swallow these key up events + return false; + + return true; +} + +bool OSystem_GP2X::handleMouseMotion(SDL_Event &ev, Common::Event &event) { + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, ev.motion.x, ev.motion.y); + + setMousePos(event.mouse.x, event.mouse.y); + return true; +} + +/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */ + +bool OSystem_GP2X::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { + if (ev.button.button == SDL_BUTTON_LEFT){ + if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ + event.type = Common::EVENT_RBUTTONDOWN; + else if (GPH::tapmodeLevel == TAPMODE_LEFT) /* TAPMODE_LEFT = Left Click Tap Mode */ + event.type = Common::EVENT_LBUTTONDOWN; + else if (GPH::tapmodeLevel == TAPMODE_RIGHT) /* TAPMODE_RIGHT = Right Click Tap Mode */ + event.type = Common::EVENT_RBUTTONDOWN; + else if (GPH::tapmodeLevel == TAPMODE_HOVER) /* TAPMODE_HOVER = Hover (No Click) Tap Mode */ + event.type = Common::EVENT_MOUSEMOVE; + else + event.type = Common::EVENT_LBUTTONDOWN; /* For normal mice etc. */ + } + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONDOWN; +#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) + else if (ev.button.button == SDL_BUTTON_WHEELUP) + event.type = Common::EVENT_WHEELUP; + else if (ev.button.button == SDL_BUTTON_WHEELDOWN) + event.type = Common::EVENT_WHEELDOWN; +#endif +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONDOWN; +#endif + else + return false; + + fillMouseEvent(event, ev.button.x, ev.button.y); + + return true; +} + +bool OSystem_GP2X::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { + if (ev.button.button == SDL_BUTTON_LEFT){ + if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ + event.type = Common::EVENT_RBUTTONUP; + else if (GPH::tapmodeLevel == TAPMODE_LEFT) /* TAPMODE_LEFT = Left Click Tap Mode */ + event.type = Common::EVENT_LBUTTONUP; + else if (GPH::tapmodeLevel == TAPMODE_RIGHT) /* TAPMODE_RIGHT = Right Click Tap Mode */ + event.type = Common::EVENT_RBUTTONUP; + else if (GPH::tapmodeLevel == TAPMODE_HOVER) /* TAPMODE_HOVER = Hover (No Click) Tap Mode */ + event.type = Common::EVENT_MOUSEMOVE; + else + event.type = Common::EVENT_LBUTTONUP; /* For normal mice etc. */ + + } + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONUP; +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONUP; +#endif + else + return false; + + fillMouseEvent(event, ev.button.x, ev.button.y); + + return true; +} + +/* Custom handleJoyButtonDown/handleJoyButtonUp to deal with the joystick buttons on GPH devices */ + +bool OSystem_GP2X::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { + + _stickBtn[ev.jbutton.button] = 1; + event.kbd.flags = 0; + + switch (ev.jbutton.button) { + case BUTTON_UP: + case BUTTON_UPLEFT: + case BUTTON_LEFT: + case BUTTON_DOWNLEFT: + case BUTTON_DOWN: + case BUTTON_DOWNRIGHT: + case BUTTON_RIGHT: + case BUTTON_UPRIGHT: + moveStick(); + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_B: + case BUTTON_CLICK: + if (BUTTON_STATE_L == true) { + setZoomOnMouse(); + fillMouseEvent(event, _km.x, _km.y); + } else { + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + } + break; + case BUTTON_X: + event.type = Common::EVENT_RBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_L: + BUTTON_STATE_L = true; + break; + case BUTTON_R: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } + break; + case BUTTON_SELECT: + case BUTTON_HOME: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_QUIT; + } else { + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); + } + break; + case BUTTON_A: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_PREDICTIVE_DIALOG; + } else { + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + } + break; + case BUTTON_Y: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + GPH::ToggleTapMode(); + if (GPH::tapmodeLevel == TAPMODE_LEFT) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); + } else if (GPH::tapmodeLevel == TAPMODE_RIGHT) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); + } else if (GPH::tapmodeLevel == TAPMODE_HOVER) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); + } + } else { + event.kbd.keycode = Common::KEYCODE_SPACE; + event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); + } + break; + case BUTTON_MENU: + case BUTTON_HELP: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } + break; + case BUTTON_VOLUP: + GP2X_HW::mixerMoveVolume(2); + if (GP2X_HW::volumeLevel == 100) { + displayMessageOnOSD("Maximum Volume"); + } else { + displayMessageOnOSD("Increasing Volume"); + } + break; + + case BUTTON_VOLDOWN: + GP2X_HW::mixerMoveVolume(1); + if (GP2X_HW::volumeLevel == 0) { + displayMessageOnOSD("Minimal Volume"); + } else { + displayMessageOnOSD("Decreasing Volume"); + } + break; + case BUTTON_HOLD: + event.type = Common::EVENT_QUIT; + break; + case BUTTON_HELP2: + GPH::ToggleTapMode(); + if (GPH::tapmodeLevel == TAPMODE_LEFT) { + displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click"); + } else if (GPH::tapmodeLevel == TAPMODE_RIGHT) { + displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click"); + } else if (GPH::tapmodeLevel == TAPMODE_HOVER) { + displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)"); + } + break; + } + return true; +} + +bool OSystem_GP2X::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { + _stickBtn[ev.jbutton.button] = 0; + event.kbd.flags = 0; + + switch (ev.jbutton.button) { + case BUTTON_UP: + case BUTTON_UPLEFT: + case BUTTON_LEFT: + case BUTTON_DOWNLEFT: + case BUTTON_DOWN: + case BUTTON_DOWNRIGHT: + case BUTTON_RIGHT: + case BUTTON_UPRIGHT: + moveStick(); + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_B: + case BUTTON_CLICK: + if (BUTTON_STATE_L == true) { + break; + } else { + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + } + break; + case BUTTON_X: + event.type = Common::EVENT_RBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_L: + BUTTON_STATE_L = false; + break; + case BUTTON_SELECT: + case BUTTON_HOME: + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); + break; + case BUTTON_A: + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + break; + case BUTTON_Y: + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = Common::KEYCODE_SPACE; + event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); + break; + case BUTTON_MENU: + case BUTTON_HELP: + event.type = Common::EVENT_KEYUP; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } + break; + case BUTTON_R: + event.type = Common::EVENT_KEYUP; + if (BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } + break; + case BUTTON_VOLUP: + break; + case BUTTON_VOLDOWN: + break; + case BUTTON_HOLD: + break; + case BUTTON_HELP2: + break; + } +return true; +} + +bool OSystem_GP2X::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { + int axis = ev.jaxis.value; + if ( axis > JOY_DEADZONE) { + axis -= JOY_DEADZONE; + event.type = Common::EVENT_MOUSEMOVE; + } else if ( axis < -JOY_DEADZONE ) { + axis += JOY_DEADZONE; + event.type = Common::EVENT_MOUSEMOVE; + } else + axis = 0; + + if ( ev.jaxis.axis == JOY_XAXIS) { +#ifdef JOY_ANALOG + _km.x_vel = axis/2000; + _km.x_down_count = 0; +#else + if (axis != 0) { + _km.x_vel = (axis > 0) ? 1:-1; + _km.x_down_count = 1; + } else { + _km.x_vel = 0; + _km.x_down_count = 0; + } +#endif + + } else if (ev.jaxis.axis == JOY_YAXIS) { +#ifndef JOY_INVERT_Y + axis = -axis; +#endif +#ifdef JOY_ANALOG + _km.y_vel = -axis / 2000; + _km.y_down_count = 0; +#else + if (axis != 0) { + _km.y_vel = (-axis > 0) ? 1: -1; + _km.y_down_count = 1; + } else { + _km.y_vel = 0; + _km.y_down_count = 0; + } +#endif + } + + fillMouseEvent(event, _km.x, _km.y); + + return true; +} + + +bool OSystem_GP2X::remapKey(SDL_Event &ev, Common::Event &event) { + return false; +} diff --git a/backends/platform/gp2x/gp2x-bundle.mk b/backends/platform/gp2x/gp2x-bundle.mk index c6fb72c1c34..67d22d18898 100755 --- a/backends/platform/gp2x/gp2x-bundle.mk +++ b/backends/platform/gp2x/gp2x-bundle.mk @@ -6,7 +6,7 @@ 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)/ @@ -28,13 +28,13 @@ ifdef DYNAMIC_MODULES endif tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 . - rm -R ./$(bundle_name) + 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)/ @@ -46,15 +46,15 @@ gp2x-bundle-debug: $(EXECUTABLE) $(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) + rm -R ./$(bundle_name) .PHONY: gp2x-bundle gp2x-bundle-debug diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h index b54e2d4d4f6..1c8708a8b12 100644 --- a/backends/platform/gp2x/gp2x-common.h +++ b/backends/platform/gp2x/gp2x-common.h @@ -113,6 +113,24 @@ public: // Sets up the keymapper with the backends hardware key set void setupKeymapper(); +protected: + virtual bool dispatchSDLEvent(SDL_Event &ev, Common::Event &event); + + // Handlers for specific SDL events, called by pollEvent. + // This way, if a backend inherits fromt the SDL backend, it can + // change the behavior of only a single event, without having to override all + // of pollEvent. + virtual bool handleKeyDown(SDL_Event &ev, Common::Event &event); + virtual bool handleKeyUp(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseMotion(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + virtual bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); + virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event); + +public: + // Set function that generates samples void setupMixer(); static void mixCallback(void *s, byte *samples, int len); @@ -153,6 +171,7 @@ public: bool hasFeature(Feature f); void setFeatureState(Feature f, bool enable); bool getFeatureState(Feature f); + void preprocessEvents(SDL_Event *event) {} void displayMessageOnOSD(const char *msg); @@ -297,6 +316,9 @@ protected: kMouseColorKey = 1 }; + // Scroll lock state - since SDL doesn't track it + bool _scrollLock; + // joystick SDL_Joystick *_joystick; bool _stickBtn[32]; @@ -374,7 +396,8 @@ protected: virtual bool remapKey(SDL_Event &ev, Common::Event &event); - void handleScalerHotkeys(const SDL_KeyboardEvent &key); + bool handleScalerHotkeys(const SDL_KeyboardEvent &key); + bool isScalerHotkey(const Common::Event &event); void moveStick(); int _gp2xInputType; diff --git a/backends/platform/gp2x/gp2x-hw.cpp b/backends/platform/gp2x/gp2x-hw.cpp index 2dc5b4f579d..6f544258ec7 100644 --- a/backends/platform/gp2x/gp2x-hw.cpp +++ b/backends/platform/gp2x/gp2x-hw.cpp @@ -30,6 +30,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "gp2x-common.h" #include "gp2x-hw.h" @@ -197,3 +200,28 @@ void gp2x_video_wait_vsync(void) } /* namespace GP2X_HW */ +namespace GPH { + +enum { + /* Touchscreen TapMode */ + TAPMODE_LEFT = 0, + TAPMODE_RIGHT = 1, + TAPMODE_HOVER = 2 +}; + +int tapmodeLevel = TAPMODE_LEFT; + +void ToggleTapMode() { + if (tapmodeLevel == TAPMODE_LEFT) { + tapmodeLevel = TAPMODE_RIGHT; + } else if (tapmodeLevel == TAPMODE_RIGHT) { + tapmodeLevel = TAPMODE_HOVER; + } else if (tapmodeLevel == TAPMODE_HOVER) { + tapmodeLevel = TAPMODE_LEFT; + } else { + tapmodeLevel = TAPMODE_LEFT; + } +} + + +} /* namespace GPH */ diff --git a/backends/platform/gp2x/gp2x-hw.h b/backends/platform/gp2x/gp2x-hw.h index 7e72812cc4a..872c44f118a 100644 --- a/backends/platform/gp2x/gp2x-hw.h +++ b/backends/platform/gp2x/gp2x-hw.h @@ -54,4 +54,12 @@ extern void gp2x_video_wait_vsync(void); } /* namespace GP2X_HW */ +namespace GPH { + +extern int tapmodeLevel; + +extern void ToggleTapMode(); + +} /* namespace GPH */ + #endif //GP2X_HW_H diff --git a/backends/platform/gp2x/gp2x-mem.cpp b/backends/platform/gp2x/gp2x-mem.cpp index 97a34ffb6a3..4a1802f311d 100644 --- a/backends/platform/gp2x/gp2x-mem.cpp +++ b/backends/platform/gp2x/gp2x-mem.cpp @@ -28,6 +28,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include #include #include diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 88d4f9d6323..0811380be99 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -28,6 +28,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/gp2x/gp2x-common.h" #include "backends/platform/gp2x/gp2x-hw.h" #include "backends/platform/gp2x/gp2x-mem.h" diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp index 4a3c668c524..d776db218e9 100644 --- a/backends/platform/gp2x/graphics.cpp +++ b/backends/platform/gp2x/graphics.cpp @@ -1601,7 +1601,7 @@ void OSystem_GP2X::displayMessageOnOSD(const char *msg) { #pragma mark --- Misc --- #pragma mark - -void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { +bool OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { // Ctrl-Alt-a toggles aspect ratio correction if (key.keysym.sym == 'a') { beginGFXTransaction(); @@ -1620,8 +1620,8 @@ void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { ); displayMessageOnOSD(buffer); - - return; + internUpdateScreen(); + return true; } int newMode = -1; @@ -1641,7 +1641,7 @@ void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { if (isNormalNumber || isKeypadNumber) { _scalerType = key.keysym.sym - (isNormalNumber ? SDLK_1 : SDLK_KP1); if (_scalerType >= ARRAYSIZE(s_gfxModeSwitchTable)) - return; + return false; while (s_gfxModeSwitchTable[_scalerType][factor] < 0) { assert(factor > 0); @@ -1675,5 +1675,27 @@ void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { displayMessageOnOSD(buffer); } } + internUpdateScreen(); + + return true; + } else { + return false; } } + +bool OSystem_GP2X::isScalerHotkey(const Common::Event &event) { + if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { + const bool isNormalNumber = (Common::KEYCODE_1 <= event.kbd.keycode && event.kbd.keycode <= Common::KEYCODE_9); + const bool isKeypadNumber = (Common::KEYCODE_KP1 <= event.kbd.keycode && event.kbd.keycode <= Common::KEYCODE_KP9); + const bool isScaleKey = (event.kbd.keycode == Common::KEYCODE_EQUALS || event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS || + event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS); + + if (isNormalNumber || isKeypadNumber) { + int keyValue = event.kbd.keycode - (isNormalNumber ? Common::KEYCODE_1 : Common::KEYCODE_KP1); + if (keyValue >= ARRAYSIZE(s_gfxModeSwitchTable)) + return false; + } + return (isScaleKey || event.kbd.keycode == 'a'); + } + return false; +} diff --git a/backends/platform/gp2xwiz/caanoo/config-alleng.sh b/backends/platform/gp2xwiz/caanoo/config-alleng.sh deleted file mode 100755 index 7a097c268b9..00000000000 --- a/backends/platform/gp2xwiz/caanoo/config-alleng.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -echo Quick script to make running configure all the time less painful -echo and let all the build work be done from the backend/build folder. - -# Assume Caanoo toolchain/build env. -. /opt/arm-caanoo/environment-setup - -# Export the tool names for cross-compiling -export DEFINES=-DNDEBUG - -# Edit the configure line to suit. -cd ../../../.. -./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac --disable-nasm --disable-vorbis --disable-hq-scalers --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic - -echo Generating config for GP2X Caanoo complete. Check for errors. diff --git a/backends/platform/gp2xwiz/caanoo/config.sh b/backends/platform/gp2xwiz/caanoo/config.sh deleted file mode 100755 index 73ce5da6240..00000000000 --- a/backends/platform/gp2xwiz/caanoo/config.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -echo Quick script to make running configure all the time less painful -echo and let all the build work be done from the backend/build folder. - -# Assume Caanoo toolchain/build env. -. /opt/arm-caanoo/environment-setup - -# Export the tool names for cross-compiling -export DEFINES=-DNDEBUG - -# Edit the configure line to suit. -cd ../../../.. -./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac --disable-nasm --disable-vorbis --disable-hq-scalers --with-sdl-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr/bin --with-mpeg2-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-tremor --with-tremor-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-zlib --with-zlib-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-vkeybd --enable-plugins --default-dynamic - -echo Generating config for GP2X Caanoo complete. Check for errors. diff --git a/backends/platform/gp2xwiz/gp2xwiz-events.cpp b/backends/platform/gp2xwiz/gp2xwiz-events.cpp deleted file mode 100644 index 19ef24ef580..00000000000 --- a/backends/platform/gp2xwiz/gp2xwiz-events.cpp +++ /dev/null @@ -1,501 +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$ - * - */ - -/* - * GP2X Wiz: Device Specific Event Handling. - * - */ - -#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" -#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" -#include "graphics/scaler/aspect.h" - -#include "common/util.h" -#include "common/events.h" - -// FIXME move joystick defines out and replace with confile file options -// we should really allow users to map any key to a joystick button using the keymapper. -#define JOY_DEADZONE 2200 - -#define JOY_XAXIS 0 -#define JOY_YAXIS 1 - -/* GP2X Wiz: Main Joystick Mappings */ -enum { - GP2X_BUTTON_UP = 0, - GP2X_BUTTON_UPLEFT = 1, - GP2X_BUTTON_LEFT = 2, - GP2X_BUTTON_DOWNLEFT = 3, - GP2X_BUTTON_DOWN = 4, - GP2X_BUTTON_DOWNRIGHT = 5, - GP2X_BUTTON_RIGHT = 6, - GP2X_BUTTON_UPRIGHT = 7, - GP2X_BUTTON_MENU = 8, - GP2X_BUTTON_SELECT = 9, - GP2X_BUTTON_L = 10, - GP2X_BUTTON_R = 11, - GP2X_BUTTON_A = 12, - GP2X_BUTTON_B = 13, - GP2X_BUTTON_X = 14, - GP2X_BUTTON_Y = 15, - GP2X_BUTTON_VOLUP = 16, - GP2X_BUTTON_VOLDOWN = 17 -}; - -static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { - if (key >= SDLK_F1 && key <= SDLK_F9) { - return key - SDLK_F1 + Common::ASCII_F1; - } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { - return key - SDLK_KP0 + '0'; - } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { - return key; - } else if (unicode) { - return unicode; - } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { - return key & ~0x20; - } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { - return 0; - } - return key; -} - -void OSystem_GP2XWIZ::fillMouseEvent(Common::Event &event, int x, int y) { - if (_videoMode.mode == GFX_HALF && !_overlayVisible){ - event.mouse.x = x*2; - event.mouse.y = y*2; - } else { - event.mouse.x = x; - event.mouse.y = y; - } - - // Update the "keyboard mouse" coords - _km.x = x; - _km.y = y; - - // Adjust for the screen scaling - if (!_overlayVisible) { - event.mouse.x /= _videoMode.scaleFactor; - event.mouse.y /= _videoMode.scaleFactor; - if (_videoMode.aspectRatioCorrection) - event.mouse.y = aspect2Real(event.mouse.y); - } -} - -static byte SDLModToOSystemKeyFlags(SDLMod mod) { - byte b = 0; - if (mod & KMOD_SHIFT) - b |= Common::KBD_SHIFT; - if (mod & KMOD_ALT) - b |= Common::KBD_ALT; - if (mod & KMOD_CTRL) - b |= Common::KBD_CTRL; - - return b; -} - -void OSystem_GP2XWIZ::moveStick() { - bool stickBtn[32]; - - memcpy(stickBtn, _stickBtn, sizeof(stickBtn)); - - if ((stickBtn[0])||(stickBtn[2])||(stickBtn[4])||(stickBtn[6])) - stickBtn[1] = stickBtn[3] = stickBtn[5] = stickBtn[7] = 0; - - if ((stickBtn[1])||(stickBtn[2])||(stickBtn[3])) { - if (_km.x_down_count!=2) { - _km.x_vel = -1; - _km.x_down_count = 1; - } else - _km.x_vel = -4; - } else if ((stickBtn[5])||(stickBtn[6])||(stickBtn[7])) { - if (_km.x_down_count!=2) { - _km.x_vel = 1; - _km.x_down_count = 1; - } else - _km.x_vel = 4; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - - if ((stickBtn[0])||(stickBtn[1])||(stickBtn[7])) { - if (_km.y_down_count!=2) { - _km.y_vel = -1; - _km.y_down_count = 1; - } else - _km.y_vel = -4; - } else if ((stickBtn[3])||(stickBtn[4])||(stickBtn[5])) { - if (_km.y_down_count!=2) { - _km.y_vel = 1; - _km.y_down_count = 1; - } else - _km.y_vel = 4; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -} - -/* Quick default button states for modifiers. */ -int GP2X_BUTTON_STATE_L = false; - -/* Override the SDL pollEvent with the Wiz's own event code. */ -bool OSystem_GP2XWIZ::pollEvent(Common::Event &event) { - SDL_Event ev; - ev.type = SDL_NOEVENT; - int axis; - byte b = 0; - - handleKbdMouse(); - - // If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED - if (_modeChanged) { - _modeChanged = false; - event.type = Common::EVENT_SCREEN_CHANGED; - return true; - } - - // GP2X Wiz Input mappings. - - /* - Single Button - - Movement: - - GP2X_BUTTON_UP Cursor Up - GP2X_BUTTON_DOWN Cursor Down - GP2X_BUTTON_LEFT Cursor Left - GP2X_BUTTON_RIGHT Cursor Right - - GP2X_BUTTON_UPLEFT Cursor Up Left - GP2X_BUTTON_UPRIGHT Cursor Up Right - GP2X_BUTTON_DOWNLEFT Cursor Down Left - GP2X_BUTTON_DOWNRIGHT Cursor Down Right - - Button Emulation: - - GP2X_BUTTON_A . (Period) - GP2X_BUTTON_B Left Mouse Click - GP2X_BUTTON_Y Space Bar - GP2X_BUTTON_X Right Mouse Click - GP2X_BUTTON_L Combo Modifier (Left Trigger) - GP2X_BUTTON_R Return (Right Trigger) - GP2X_BUTTON_MENU F5 (Game Menu) - GP2X_BUTTON_SELECT Escape - GP2X_BUTTON_VOLUP /dev/mixer Global Volume Up - GP2X_BUTTON_VOLDOWN /dev/mixer Global Volume Down - - Combos: - - GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) or Virtual Keyboard if enabled - GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) - GP2X_BUTTON_L & GP2X_BUTTON_MENU Common::EVENT_MAINMENU (ScummVM Global Main Menu) - GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) - */ - - while (SDL_PollEvent(&ev)) { - - switch (ev.type) { - case SDL_KEYDOWN:{ - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - - return true; - } - case SDL_KEYUP: - { - const bool event_complete = remapKey(ev,event); - - if (event_complete) - return true; - - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; - event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); - b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); - - // Ctrl-Alt- will change the GFX mode - if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { - // Swallow these key up events - break; - } - - return true; - } - case SDL_MOUSEMOTION: - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, ev.motion.x, ev.motion.y); - - setMousePos(event.mouse.x, event.mouse.y); - return true; - - case SDL_MOUSEBUTTONDOWN: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONDOWN; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONDOWN; -#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) - else if (ev.button.button == SDL_BUTTON_WHEELUP) - event.type = Common::EVENT_WHEELUP; - else if (ev.button.button == SDL_BUTTON_WHEELDOWN) - event.type = Common::EVENT_WHEELDOWN; -#endif -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONDOWN; -#endif - else - break; - - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - case SDL_MOUSEBUTTONUP: - if (ev.button.button == SDL_BUTTON_LEFT) - event.type = Common::EVENT_LBUTTONUP; - else if (ev.button.button == SDL_BUTTON_RIGHT) - event.type = Common::EVENT_RBUTTONUP; -#if defined(SDL_BUTTON_MIDDLE) - else if (ev.button.button == SDL_BUTTON_MIDDLE) - event.type = Common::EVENT_MBUTTONUP; -#endif - else - break; - fillMouseEvent(event, ev.button.x, ev.button.y); - - return true; - - case SDL_JOYBUTTONDOWN: - _stickBtn[ev.jbutton.button] = 1; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONDOWN; - fillMouseEvent(event, _km.x, _km.y); - } else if (_stickBtn[GP2X_BUTTON_L] && (ev.jbutton.button == GP2X_BUTTON_SELECT)) { - event.type = Common::EVENT_QUIT; - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYDOWN; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = true; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_SELECT: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_QUIT; - } else { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_A: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_PREDICTIVE_DIALOG; - } else { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_Y: - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_MENU: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - WIZ_HW::mixerMoveVolume(2); - if (WIZ_HW::volumeLevel == 100) { - displayMessageOnOSD("Maximum Volume"); - } else { - displayMessageOnOSD("Increasing Volume"); - } - break; - - case GP2X_BUTTON_VOLDOWN: - WIZ_HW::mixerMoveVolume(1); - if (WIZ_HW::volumeLevel == 0) { - displayMessageOnOSD("Minimal Volume"); - } else { - displayMessageOnOSD("Decreasing Volume"); - } - break; - } - } - return true; - - case SDL_JOYBUTTONUP: - _stickBtn[ev.jbutton.button] = 0; - if (ev.jbutton.button == GP2X_BUTTON_B) { - event.type = Common::EVENT_LBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button == GP2X_BUTTON_X) { - event.type = Common::EVENT_RBUTTONUP; - fillMouseEvent(event, _km.x, _km.y); - } else if (ev.jbutton.button < 8) { - moveStick(); - event.type = Common::EVENT_MOUSEMOVE; - fillMouseEvent(event, _km.x, _km.y); - } else { - event.type = Common::EVENT_KEYUP; - event.kbd.flags = 0; - switch (ev.jbutton.button) { - case GP2X_BUTTON_SELECT: - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_A: - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_Y: - event.kbd.keycode = Common::KEYCODE_SPACE; - event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); - break; - case GP2X_BUTTON_MENU: - if (GP2X_BUTTON_STATE_L == true) { - event.type = Common::EVENT_MAINMENU; - } else { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_L: - GP2X_BUTTON_STATE_L = false; - break; - case GP2X_BUTTON_R: - if (GP2X_BUTTON_STATE_L == true) { -#ifdef ENABLE_VKEYBD - event.kbd.keycode = Common::KEYCODE_F7; - event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); -#else - event.kbd.keycode = Common::KEYCODE_0; - event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); -#endif - } else { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); - } - break; - case GP2X_BUTTON_VOLUP: - break; - case GP2X_BUTTON_VOLDOWN: - break; - } - } - return true; - - case SDL_JOYAXISMOTION: - axis = ev.jaxis.value; - if ( axis > JOY_DEADZONE) { - axis -= JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else if ( axis < -JOY_DEADZONE ) { - axis += JOY_DEADZONE; - event.type = Common::EVENT_MOUSEMOVE; - } else - axis = 0; - - if ( ev.jaxis.axis == JOY_XAXIS) { - if (axis != 0) { - _km.x_vel = (axis > 0) ? 1:-1; - _km.x_down_count = 1; - } else { - _km.x_vel = 0; - _km.x_down_count = 0; - } - - } else if (ev.jaxis.axis == JOY_YAXIS) { -#ifndef JOY_INVERT_Y - axis = -axis; -#endif -#ifdef JOY_ANALOG - _km.y_vel = -axis / 2000; - _km.y_down_count = 0; -#else - if (axis != 0) { - _km.y_vel = (-axis > 0) ? 1: -1; - _km.y_down_count = 1; - } else { - _km.y_vel = 0; - _km.y_down_count = 0; - } -#endif - } - - fillMouseEvent(event, _km.x, _km.y); - - return true; - - case SDL_VIDEOEXPOSE: - _forceFull = true; - break; - - case SDL_QUIT: - event.type = Common::EVENT_QUIT; - return true; - } - } - return false; -} - -bool OSystem_GP2XWIZ::remapKey(SDL_Event &ev,Common::Event &event) { - return false; -} diff --git a/backends/platform/gp2xwiz/build/README-GP2XWIZ b/backends/platform/gph/build/README-GPH similarity index 97% rename from backends/platform/gp2xwiz/build/README-GP2XWIZ rename to backends/platform/gph/build/README-GPH index ec8142a6f3a..269fa901c9d 100644 --- a/backends/platform/gp2xwiz/build/README-GP2XWIZ +++ b/backends/platform/gph/build/README-GPH @@ -19,10 +19,10 @@ Contents: Please refer to the: -GP2X/GP2XWiz ScummVM Forum: -WiKi: +GP2X/GP2XWiz ScummVM Forum: +WiKi: -for the most current information on the port and any updates to this +for the most current information on the port and any updates to this documentation. ------------------------------------------------------------------------ @@ -112,7 +112,7 @@ Fancy button combos: NOTE: To use button combos press and hold the Left Trigger then... -Right Trigger: Display Virtual Keyboard +Right Trigger: Display Virtual Keyboard Menu: Bring up the Global main menu for ScummVM Select: Exit ScummVM completely (and gracefully) diff --git a/backends/platform/gp2xwiz/build/build.sh b/backends/platform/gph/build/build.sh similarity index 100% rename from backends/platform/gp2xwiz/build/build.sh rename to backends/platform/gph/build/build.sh diff --git a/backends/platform/gp2xwiz/build/bundle-debug.sh b/backends/platform/gph/build/bundle-debug.sh similarity index 100% rename from backends/platform/gp2xwiz/build/bundle-debug.sh rename to backends/platform/gph/build/bundle-debug.sh diff --git a/backends/platform/gp2xwiz/build/bundle.sh b/backends/platform/gph/build/bundle.sh similarity index 100% rename from backends/platform/gp2xwiz/build/bundle.sh rename to backends/platform/gph/build/bundle.sh diff --git a/backends/platform/gp2xwiz/build/clean.sh b/backends/platform/gph/build/clean.sh similarity index 100% rename from backends/platform/gp2xwiz/build/clean.sh rename to backends/platform/gph/build/clean.sh diff --git a/backends/platform/gp2xwiz/build/config-alleng.sh b/backends/platform/gph/build/config-alleng.sh similarity index 53% rename from backends/platform/gp2xwiz/build/config-alleng.sh rename to backends/platform/gph/build/config-alleng.sh index cfed463edfb..9ec8a09cd24 100755 --- a/backends/platform/gp2xwiz/build/config-alleng.sh +++ b/backends/platform/gph/build/config-alleng.sh @@ -13,10 +13,15 @@ export CXX=arm-open2x-linux-g++ export CXXFLAGS="-mcpu=arm926ej-s -mtune=arm926ej-s" export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib -export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic +./configure --backend=gph --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers \ + --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-png --with-png-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-vkeybd --enable-all-engines --enable-plugins --default-dynamic echo Generating config for GP2X Wiz complete. Check for errors. diff --git a/backends/platform/gp2xwiz/build/config.sh b/backends/platform/gph/build/config.sh similarity index 54% rename from backends/platform/gp2xwiz/build/config.sh rename to backends/platform/gph/build/config.sh index 54c4795298a..ac7c34ad121 100755 --- a/backends/platform/gp2xwiz/build/config.sh +++ b/backends/platform/gph/build/config.sh @@ -13,10 +13,15 @@ export CXX=arm-open2x-linux-g++ export CXXFLAGS="-mcpu=arm926ej-s -mtune=arm926ej-s" export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib -export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd --enable-plugins --default-dynamic +./configure --backend=gph --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers \ + --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-png --with-png-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-vkeybd --enable-plugins --default-dynamic echo Generating config for GP2X Wiz complete. Check for errors. diff --git a/backends/platform/gp2xwiz/build/scummvm-gdb.gpe b/backends/platform/gph/build/scummvm-gdb.gpe similarity index 84% rename from backends/platform/gp2xwiz/build/scummvm-gdb.gpe rename to backends/platform/gph/build/scummvm-gdb.gpe index 64b6c8b974f..63ce193ca87 100755 --- a/backends/platform/gp2xwiz/build/scummvm-gdb.gpe +++ b/backends/platform/gph/build/scummvm-gdb.gpe @@ -6,7 +6,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM via GDB (so make sure you have a terminal open or serial). # Oh, and GDB installed of course ;) -gdb --args ./scummvm.wiz --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +gdb --args ./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gp2xwiz/build/scummvm.gpe b/backends/platform/gph/build/scummvm.gpe similarity index 84% rename from backends/platform/gp2xwiz/build/scummvm.gpe rename to backends/platform/gph/build/scummvm.gpe index 42cc00a22ac..59ff562aebe 100755 --- a/backends/platform/gp2xwiz/build/scummvm.gpe +++ b/backends/platform/gph/build/scummvm.gpe @@ -5,7 +5,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM, important this bit. -./scummvm.wiz --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gp2xwiz/build/scummvm.ini b/backends/platform/gph/build/scummvm.ini similarity index 72% rename from backends/platform/gp2xwiz/build/scummvm.ini rename to backends/platform/gph/build/scummvm.ini index 5a8e6eefa14..c9cce923794 100644 --- a/backends/platform/gp2xwiz/build/scummvm.ini +++ b/backends/platform/gph/build/scummvm.ini @@ -2,3 +2,4 @@ name="ScummVM" path="/scummvm/scummvm.gpe" icon="/scummvm/scummvm.png" +title="/scummvm/scummvmb.png" diff --git a/backends/platform/gp2xwiz/build/scummvm.png b/backends/platform/gph/build/scummvm.png similarity index 100% rename from backends/platform/gp2xwiz/build/scummvm.png rename to backends/platform/gph/build/scummvm.png diff --git a/backends/platform/gph/build/scummvmb.png b/backends/platform/gph/build/scummvmb.png new file mode 100644 index 00000000000..24a27bc0e15 Binary files /dev/null and b/backends/platform/gph/build/scummvmb.png differ diff --git a/backends/platform/gp2xwiz/caanoo/caanoo-bundle.mk b/backends/platform/gph/caanoo-bundle.mk similarity index 70% rename from backends/platform/gp2xwiz/caanoo/caanoo-bundle.mk rename to backends/platform/gph/caanoo-bundle.mk index f8ac26382dc..b7b3c9e1886 100755 --- a/backends/platform/gp2xwiz/caanoo/caanoo-bundle.mk +++ b/backends/platform/gph/caanoo-bundle.mk @@ -11,13 +11,14 @@ caanoo-bundle: $(EXECUTABLE) $(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/caanoo/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/README-CAANOO - $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.ini $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm.gpe $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/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/ @@ -31,9 +32,9 @@ ifdef DYNAMIC_MODULES $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins" $(STRIP) $(bundle_name)/scummvm/plugins/* endif - + tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 . - rm -R ./$(bundle_name) + rm -R ./$(bundle_name) caanoo-bundle-debug: $(EXECUTABLE) $(MKDIR) "$(bundle_name)" @@ -41,13 +42,14 @@ caanoo-bundle-debug: $(EXECUTABLE) $(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/caanoo/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/README-CAANOO - $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.ini $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe + $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/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/ @@ -62,6 +64,6 @@ ifdef DYNAMIC_MODULES endif tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 . - rm -R ./$(bundle_name) + rm -R ./$(bundle_name) .PHONY: caanoo-bundle caanoo-bundle-debug diff --git a/backends/platform/gp2xwiz/caanoo/build.sh b/backends/platform/gph/caanoo/build.sh similarity index 100% rename from backends/platform/gp2xwiz/caanoo/build.sh rename to backends/platform/gph/caanoo/build.sh diff --git a/backends/platform/gp2xwiz/caanoo/bundle-debug.sh b/backends/platform/gph/caanoo/bundle-debug.sh similarity index 100% rename from backends/platform/gp2xwiz/caanoo/bundle-debug.sh rename to backends/platform/gph/caanoo/bundle-debug.sh diff --git a/backends/platform/gp2xwiz/caanoo/bundle.sh b/backends/platform/gph/caanoo/bundle.sh similarity index 100% rename from backends/platform/gp2xwiz/caanoo/bundle.sh rename to backends/platform/gph/caanoo/bundle.sh diff --git a/backends/platform/gp2xwiz/caanoo/clean.sh b/backends/platform/gph/caanoo/clean.sh similarity index 100% rename from backends/platform/gp2xwiz/caanoo/clean.sh rename to backends/platform/gph/caanoo/clean.sh diff --git a/backends/platform/gph/caanoo/config-alleng.sh b/backends/platform/gph/caanoo/config-alleng.sh new file mode 100755 index 00000000000..97fed942fa9 --- /dev/null +++ b/backends/platform/gph/caanoo/config-alleng.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +echo Quick script to make running configure all the time less painful +echo and let all the build work be done from the backend/build folder. + +# Assume Caanoo toolchain/build env and source it. +. /opt/arm-caanoo/environment-setup + +# Edit the configure line to suit. +cd ../../../.. +./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac \ + --disable-nasm --disable-vorbis --disable-hq-scalers \ + --with-sdl-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-tremor --with-tremor-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic + +echo Generating config for Caanoo complete. Check for errors. diff --git a/backends/platform/gph/caanoo/config.sh b/backends/platform/gph/caanoo/config.sh new file mode 100755 index 00000000000..11d597481a5 --- /dev/null +++ b/backends/platform/gph/caanoo/config.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +echo Quick script to make running configure all the time less painful +echo and let all the build work be done from the backend/build folder. + +# Assume Caanoo toolchain/build env. +. /opt/arm-caanoo/environment-setup + +# Edit the configure line to suit. +cd ../../../.. +./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac \ + --disable-nasm --disable-vorbis --disable-hq-scalers \ + --with-sdl-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-tremor --with-tremor-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-vkeybd --enable-plugins --default-dynamic + +echo Generating config for GP2X Caanoo complete. Check for errors. diff --git a/backends/platform/gp2xwiz/caanoo/scummvm-gdb.gpe b/backends/platform/gph/caanoo/scummvm-gdb.gpe similarity index 83% rename from backends/platform/gp2xwiz/caanoo/scummvm-gdb.gpe rename to backends/platform/gph/caanoo/scummvm-gdb.gpe index a8f2aae0fe5..63ce193ca87 100755 --- a/backends/platform/gp2xwiz/caanoo/scummvm-gdb.gpe +++ b/backends/platform/gph/caanoo/scummvm-gdb.gpe @@ -6,7 +6,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM via GDB (so make sure you have a terminal open or serial). # Oh, and GDB installed of course ;) -gdb --args ./scummvm.caanoo --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +gdb --args ./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gp2xwiz/caanoo/scummvm.gpe b/backends/platform/gph/caanoo/scummvm.gpe similarity index 83% rename from backends/platform/gp2xwiz/caanoo/scummvm.gpe rename to backends/platform/gph/caanoo/scummvm.gpe index 8341ffc3d70..37d0f65d189 100755 --- a/backends/platform/gp2xwiz/caanoo/scummvm.gpe +++ b/backends/platform/gph/caanoo/scummvm.gpe @@ -5,7 +5,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM, important this bit. -./scummvm.caanoo --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gp2xwiz/gp2xwiz-bundle.mk b/backends/platform/gph/gp2xwiz-bundle.mk similarity index 73% rename from backends/platform/gp2xwiz/gp2xwiz-bundle.mk rename to backends/platform/gph/gp2xwiz-bundle.mk index fa5a2478658..df4cae7f4fe 100755 --- a/backends/platform/gp2xwiz/gp2xwiz-bundle.mk +++ b/backends/platform/gph/gp2xwiz-bundle.mk @@ -11,13 +11,14 @@ gp2xwiz-bundle: $(EXECUTABLE) $(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)/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvm.gpe $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/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/ @@ -31,12 +32,12 @@ ifdef DYNAMIC_MODULES $(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) + rm -R ./$(bundle_name) gp2xwiz-bundle-debug: $(EXECUTABLE) $(MKDIR) "$(bundle_name)" @@ -44,13 +45,14 @@ gp2xwiz-bundle-debug: $(EXECUTABLE) $(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)/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe + $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/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/ @@ -63,11 +65,11 @@ 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) + rm -R ./$(bundle_name) .PHONY: gp2xwiz-bundle gp2xwiz-bundle-debug diff --git a/backends/platform/gph/gph-events.cpp b/backends/platform/gph/gph-events.cpp new file mode 100644 index 00000000000..2a6237c7945 --- /dev/null +++ b/backends/platform/gph/gph-events.cpp @@ -0,0 +1,481 @@ +/* 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$ + * + */ + +/* + * GPH: Device Specific Event Handling. + * + */ + +#include "backends/platform/gph/gph-sdl.h" +#include "backends/platform/gph/gph-hw.h" +#include "graphics/scaler/aspect.h" + +#include "common/util.h" +#include "common/events.h" + +#define JOY_DEADZONE 2200 + +#define JOY_XAXIS 0 +#define JOY_YAXIS 1 + +/* Quick default button states for modifiers. */ +int BUTTON_STATE_L = false; + +#if defined(CAANOO) + + /* Caanoo: Main Joystick Button Mappings */ + /* The Caanoo has an analogue stick so no digital DPAD */ + enum { + /* Joystick Buttons */ + BUTTON_A = 0, + BUTTON_X = 1, + BUTTON_B = 2, + BUTTON_Y = 3, + BUTTON_L = 4, + BUTTON_R = 5, + BUTTON_HOME = 6, // Home + BUTTON_HOLD = 7, // Hold (on Power) + BUTTON_HELP = 8, // Help I + BUTTON_HELP2 = 9, // Help II + BUTTON_CLICK = 10 // Stick Click + }; + + enum { + /* Unused Joystick Buttons on the Caanoo */ + BUTTON_VOLUP = 51, + BUTTON_VOLDOWN = 52, + BUTTON_UP = 53, + BUTTON_UPLEFT = 54, + BUTTON_LEFT = 55, + BUTTON_DOWNLEFT = 56, + BUTTON_DOWN = 57, + BUTTON_DOWNRIGHT = 58, + BUTTON_RIGHT = 59, + BUTTON_UPRIGHT = 60, + BUTTON_MENU = 61, + BUTTON_SELECT = 62 + }; + +#else + + /* Wiz: Main Joystick Mappings */ + enum { + /* DPAD */ + BUTTON_UP = 0, + BUTTON_UPLEFT = 1, + BUTTON_LEFT = 2, + BUTTON_DOWNLEFT = 3, + BUTTON_DOWN = 4, + BUTTON_DOWNRIGHT = 5, + BUTTON_RIGHT = 6, + BUTTON_UPRIGHT = 7, + /* Joystick Buttons */ + BUTTON_MENU = 8, + BUTTON_SELECT = 9, + BUTTON_L = 10, + BUTTON_R = 11, + BUTTON_A = 12, + BUTTON_B = 13, + BUTTON_X = 14, + BUTTON_Y = 15, + BUTTON_VOLUP = 16, + BUTTON_VOLDOWN = 17 + }; + + enum { + /* Unused Joystick Buttons on the Wiz */ + BUTTON_HOME = 51, + BUTTON_HOLD = 52, + BUTTON_CLICK = 53, + BUTTON_HELP = 54, + BUTTON_HELP2 = 55 + }; + +#endif + +enum { + /* Touchscreen TapMode */ + TAPMODE_LEFT = 0, + TAPMODE_RIGHT = 1, + TAPMODE_HOVER = 2 +}; + +static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) { + if (key >= SDLK_F1 && key <= SDLK_F9) { + return key - SDLK_F1 + Common::ASCII_F1; + } else if (key >= SDLK_KP0 && key <= SDLK_KP9) { + return key - SDLK_KP0 + '0'; + } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { + return key; + } else if (unicode) { + return unicode; + } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { + return key & ~0x20; + } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { + return 0; + } + return key; +} + + +void OSystem_GPH::fillMouseEvent(Common::Event &event, int x, int y) { + if (_videoMode.mode == GFX_HALF && !_overlayVisible){ + event.mouse.x = x*2; + event.mouse.y = y*2; + } else { + event.mouse.x = x; + event.mouse.y = y; + } + + // Update the "keyboard mouse" coords + _km.x = x; + _km.y = y; + + // Adjust for the screen scaling + if (!_overlayVisible) { + event.mouse.x /= _videoMode.scaleFactor; + event.mouse.y /= _videoMode.scaleFactor; + if (_videoMode.aspectRatioCorrection) + event.mouse.y = aspect2Real(event.mouse.y); + } +} + + +void OSystem_GPH::moveStick() { + bool stickBtn[32]; + + memcpy(stickBtn, _stickBtn, sizeof(stickBtn)); + + if ((stickBtn[0])||(stickBtn[2])||(stickBtn[4])||(stickBtn[6])) + stickBtn[1] = stickBtn[3] = stickBtn[5] = stickBtn[7] = 0; + + if ((stickBtn[1])||(stickBtn[2])||(stickBtn[3])) { + if (_km.x_down_count!=2) { + _km.x_vel = -1; + _km.x_down_count = 1; + } else + _km.x_vel = -4; + } else if ((stickBtn[5])||(stickBtn[6])||(stickBtn[7])) { + if (_km.x_down_count!=2) { + _km.x_vel = 1; + _km.x_down_count = 1; + } else + _km.x_vel = 4; + } else { + _km.x_vel = 0; + _km.x_down_count = 0; + } + + if ((stickBtn[0])||(stickBtn[1])||(stickBtn[7])) { + if (_km.y_down_count!=2) { + _km.y_vel = -1; + _km.y_down_count = 1; + } else + _km.y_vel = -4; + } else if ((stickBtn[3])||(stickBtn[4])||(stickBtn[5])) { + if (_km.y_down_count!=2) { + _km.y_vel = 1; + _km.y_down_count = 1; + } else + _km.y_vel = 4; + } else { + _km.y_vel = 0; + _km.y_down_count = 0; + } +} + +/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */ + +bool OSystem_GPH::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { + if (ev.button.button == SDL_BUTTON_LEFT){ + if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ + event.type = Common::EVENT_RBUTTONDOWN; + else if (GPH::tapmodeLevel == TAPMODE_LEFT) /* TAPMODE_LEFT = Left Click Tap Mode */ + event.type = Common::EVENT_LBUTTONDOWN; + else if (GPH::tapmodeLevel == TAPMODE_RIGHT) /* TAPMODE_RIGHT = Right Click Tap Mode */ + event.type = Common::EVENT_RBUTTONDOWN; + else if (GPH::tapmodeLevel == TAPMODE_HOVER) /* TAPMODE_HOVER = Hover (No Click) Tap Mode */ + event.type = Common::EVENT_MOUSEMOVE; + else + event.type = Common::EVENT_LBUTTONDOWN; /* For normal mice etc. */ + } + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONDOWN; +#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) + else if (ev.button.button == SDL_BUTTON_WHEELUP) + event.type = Common::EVENT_WHEELUP; + else if (ev.button.button == SDL_BUTTON_WHEELDOWN) + event.type = Common::EVENT_WHEELDOWN; +#endif +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONDOWN; +#endif + else + return false; + + fillMouseEvent(event, ev.button.x, ev.button.y); + + return true; +} + +bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { + if (ev.button.button == SDL_BUTTON_LEFT){ + if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ + event.type = Common::EVENT_RBUTTONUP; + else if (GPH::tapmodeLevel == TAPMODE_LEFT) /* TAPMODE_LEFT = Left Click Tap Mode */ + event.type = Common::EVENT_LBUTTONUP; + else if (GPH::tapmodeLevel == TAPMODE_RIGHT) /* TAPMODE_RIGHT = Right Click Tap Mode */ + event.type = Common::EVENT_RBUTTONUP; + else if (GPH::tapmodeLevel == TAPMODE_HOVER) /* TAPMODE_HOVER = Hover (No Click) Tap Mode */ + event.type = Common::EVENT_MOUSEMOVE; + else + event.type = Common::EVENT_LBUTTONUP; /* For normal mice etc. */ + } + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONUP; +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONUP; +#endif + else + return false; + + fillMouseEvent(event, ev.button.x, ev.button.y); + + return true; +} + +/* Custom handleJoyButtonDown/handleJoyButtonUp to deal with the joystick buttons on GPH devices */ + +bool OSystem_GPH::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { + + _stickBtn[ev.jbutton.button] = 1; + event.kbd.flags = 0; + + switch (ev.jbutton.button) { + case BUTTON_UP: + case BUTTON_UPLEFT: + case BUTTON_LEFT: + case BUTTON_DOWNLEFT: + case BUTTON_DOWN: + case BUTTON_DOWNRIGHT: + case BUTTON_RIGHT: + case BUTTON_UPRIGHT: + moveStick(); + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_B: + case BUTTON_CLICK: + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_X: + event.type = Common::EVENT_RBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_L: + BUTTON_STATE_L = true; + break; + case BUTTON_R: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } + break; + case BUTTON_SELECT: + case BUTTON_HOME: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_QUIT; + } else { + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); + } + break; + case BUTTON_A: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_PREDICTIVE_DIALOG; + } else { + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + } + break; + case BUTTON_Y: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + GPH::ToggleTapMode(); + if (GPH::tapmodeLevel == TAPMODE_LEFT) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); + } else if (GPH::tapmodeLevel == TAPMODE_RIGHT) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); + } else if (GPH::tapmodeLevel == TAPMODE_HOVER) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); + } + } else { + event.kbd.keycode = Common::KEYCODE_SPACE; + event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); + } + break; + case BUTTON_MENU: + case BUTTON_HELP: + event.type = Common::EVENT_KEYDOWN; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } + break; + case BUTTON_VOLUP: + WIZ_HW::mixerMoveVolume(2); + if (WIZ_HW::volumeLevel == 100) { + displayMessageOnOSD("Maximum Volume"); + } else { + displayMessageOnOSD("Increasing Volume"); + } + break; + case BUTTON_VOLDOWN: + WIZ_HW::mixerMoveVolume(1); + if (WIZ_HW::volumeLevel == 0) { + displayMessageOnOSD("Minimal Volume"); + } else { + displayMessageOnOSD("Decreasing Volume"); + } + break; + case BUTTON_HOLD: + event.type = Common::EVENT_QUIT; + break; + case BUTTON_HELP2: + GPH::ToggleTapMode(); + if (GPH::tapmodeLevel == TAPMODE_LEFT) { + displayMessageOnOSD("Touchscreen 'Tap Mode': Left Click"); + } else if (GPH::tapmodeLevel == TAPMODE_RIGHT) { + displayMessageOnOSD("Touchscreen 'Tap Mode': Right Click"); + } else if (GPH::tapmodeLevel == TAPMODE_HOVER) { + displayMessageOnOSD("Touchscreen 'Tap Mode': Hover (No Click)"); + } + break; + } + return true; +} + +bool OSystem_GPH::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { + + _stickBtn[ev.jbutton.button] = 0; + event.kbd.flags = 0; + + switch (ev.jbutton.button) { + case BUTTON_UP: + case BUTTON_UPLEFT: + case BUTTON_LEFT: + case BUTTON_DOWNLEFT: + case BUTTON_DOWN: + case BUTTON_DOWNRIGHT: + case BUTTON_RIGHT: + case BUTTON_UPRIGHT: + moveStick(); + event.type = Common::EVENT_MOUSEMOVE; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_B: + case BUTTON_CLICK: + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_X: + event.type = Common::EVENT_RBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + break; + case BUTTON_L: + BUTTON_STATE_L = false; + break; + case BUTTON_SELECT: + case BUTTON_HOME: + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = Common::KEYCODE_ESCAPE; + event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0); + break; + case BUTTON_A: + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = Common::KEYCODE_PERIOD; + event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + break; + case BUTTON_Y: + event.type = Common::EVENT_KEYUP; + event.kbd.keycode = Common::KEYCODE_SPACE; + event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0); + break; + case BUTTON_MENU: + case BUTTON_HELP: + event.type = Common::EVENT_KEYUP; + if (BUTTON_STATE_L == true) { + event.type = Common::EVENT_MAINMENU; + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0); + } + break; + case BUTTON_R: + event.type = Common::EVENT_KEYUP; + if (BUTTON_STATE_L == true) { +#ifdef ENABLE_VKEYBD + event.kbd.keycode = Common::KEYCODE_F7; + event.kbd.ascii = mapKey(SDLK_F7, ev.key.keysym.mod, 0); +#else + event.kbd.keycode = Common::KEYCODE_0; + event.kbd.ascii = mapKey(SDLK_0, ev.key.keysym.mod, 0); +#endif + } else { + event.kbd.keycode = Common::KEYCODE_RETURN; + event.kbd.ascii = mapKey(SDLK_RETURN, ev.key.keysym.mod, 0); + } + break; + case BUTTON_VOLUP: + break; + case BUTTON_VOLDOWN: + break; + case BUTTON_HOLD: + break; + case BUTTON_HELP2: + break; + } + return true; +} + +bool OSystem_GPH::remapKey(SDL_Event &ev,Common::Event &event) { + return false; +} diff --git a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp b/backends/platform/gph/gph-graphics.cpp similarity index 94% rename from backends/platform/gp2xwiz/gp2xwiz-graphics.cpp rename to backends/platform/gph/gph-graphics.cpp index 9b8a41a7cf0..8fada7e40a3 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp +++ b/backends/platform/gph/gph-graphics.cpp @@ -23,7 +23,7 @@ * */ -#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" +#include "backends/platform/gph/gph-sdl.h" #include "common/mutex.h" #include "graphics/font.h" @@ -38,15 +38,15 @@ static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { {0, 0, 0} }; -const OSystem::GraphicsMode *OSystem_GP2XWIZ::getSupportedGraphicsModes() const { +const OSystem::GraphicsMode *OSystem_GPH::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } -int OSystem_GP2XWIZ::getDefaultGraphicsMode() const { +int OSystem_GPH::getDefaultGraphicsMode() const { return GFX_NORMAL; } -bool OSystem_GP2XWIZ::setGraphicsMode(int mode) { +bool OSystem_GPH::setGraphicsMode(int mode) { Common::StackLock lock(_graphicsMutex); assert(_transactionMode == kTransactionActive); @@ -80,7 +80,7 @@ bool OSystem_GP2XWIZ::setGraphicsMode(int mode) { return true; } -void OSystem_GP2XWIZ::setGraphicsModeIntern() { +void OSystem_GPH::setGraphicsModeIntern() { Common::StackLock lock(_graphicsMutex); ScalerProc *newScalerProc = 0; @@ -109,7 +109,7 @@ void OSystem_GP2XWIZ::setGraphicsModeIntern() { blitCursor(); } -void OSystem_GP2XWIZ::initSize(uint w, uint h) { +void OSystem_GPH::initSize(uint w, uint h) { assert(_transactionMode == kTransactionActive); // Avoid redundant res changes @@ -127,7 +127,7 @@ void OSystem_GP2XWIZ::initSize(uint w, uint h) { _transactionDetails.sizeChanged = true; } -bool OSystem_GP2XWIZ::loadGFXMode() { +bool OSystem_GPH::loadGFXMode() { if (_videoMode.screenWidth > 320 || _videoMode.screenHeight > 240) { _videoMode.aspectRatioCorrection = false; setGraphicsMode(GFX_HALF); @@ -155,7 +155,7 @@ bool OSystem_GP2XWIZ::loadGFXMode() { return OSystem_SDL::loadGFXMode(); } -void OSystem_GP2XWIZ::drawMouse() { +void OSystem_GPH::drawMouse() { if (!_mouseVisible || !_mouseSurface) { _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; return; @@ -226,7 +226,7 @@ void OSystem_GP2XWIZ::drawMouse() { addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); } -void OSystem_GP2XWIZ::undrawMouse() { +void OSystem_GPH::undrawMouse() { const int x = _mouseBackup.x; const int y = _mouseBackup.y; @@ -244,7 +244,7 @@ void OSystem_GP2XWIZ::undrawMouse() { } } -void OSystem_GP2XWIZ::internUpdateScreen() { +void OSystem_GPH::internUpdateScreen() { SDL_Surface *srcSurf, *origSurf; int height, width; ScalerProc *scalerProc; @@ -256,7 +256,8 @@ void OSystem_GP2XWIZ::internUpdateScreen() { #endif // If the shake position changed, fill the dirty area with blackness - if (_currentShakePos != _newShakePos) { + if (_currentShakePos != _newShakePos || + (_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) { SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor}; if (_videoMode.aspectRatioCorrection && !_overlayVisible) @@ -314,6 +315,7 @@ void OSystem_GP2XWIZ::internUpdateScreen() { width = _videoMode.overlayWidth; height = _videoMode.overlayHeight; scalerProc = Normal1x; + scale1 = 1; } @@ -441,7 +443,7 @@ void OSystem_GP2XWIZ::internUpdateScreen() { _mouseNeedsRedraw = false; } -void OSystem_GP2XWIZ::showOverlay() { +void OSystem_GPH::showOverlay() { if (_videoMode.mode == GFX_HALF){ _mouseCurState.x = _mouseCurState.x / 2; _mouseCurState.y = _mouseCurState.y / 2; @@ -449,7 +451,7 @@ void OSystem_GP2XWIZ::showOverlay() { OSystem_SDL::showOverlay(); } -void OSystem_GP2XWIZ::hideOverlay() { +void OSystem_GPH::hideOverlay() { if (_videoMode.mode == GFX_HALF){ _mouseCurState.x = _mouseCurState.x * 2; _mouseCurState.y = _mouseCurState.y * 2; @@ -457,7 +459,7 @@ void OSystem_GP2XWIZ::hideOverlay() { OSystem_SDL::hideOverlay(); } -void OSystem_GP2XWIZ::warpMouse(int x, int y) { +void OSystem_GPH::warpMouse(int x, int y) { if (_mouseCurState.x != x || _mouseCurState.y != y) { if (_videoMode.mode == GFX_HALF && !_overlayVisible){ x = x / 2; diff --git a/backends/platform/gp2xwiz/gp2xwiz-hw.cpp b/backends/platform/gph/gph-hw.cpp similarity index 78% rename from backends/platform/gp2xwiz/gp2xwiz-hw.cpp rename to backends/platform/gph/gph-hw.cpp index bc1aa00ce4d..fa52526f017 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-hw.cpp +++ b/backends/platform/gph/gph-hw.cpp @@ -28,7 +28,10 @@ * */ -#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/platform/gph/gph-hw.h" #include #include @@ -82,3 +85,28 @@ void mixerMoveVolume(int direction) { } } /* namespace WIZ_HW */ + +namespace GPH { + +enum { + /* Touchscreen TapMode */ + TAPMODE_LEFT = 0, + TAPMODE_RIGHT = 1, + TAPMODE_HOVER = 2 +}; + +int tapmodeLevel = TAPMODE_LEFT; + +void ToggleTapMode() { + if (tapmodeLevel == TAPMODE_LEFT) { + tapmodeLevel = TAPMODE_RIGHT; + } else if (tapmodeLevel == TAPMODE_RIGHT) { + tapmodeLevel = TAPMODE_HOVER; + } else if (tapmodeLevel == TAPMODE_HOVER) { + tapmodeLevel = TAPMODE_LEFT; + } else { + tapmodeLevel = TAPMODE_LEFT; + } +} + +} /* namespace GPH */ diff --git a/backends/platform/gp2xwiz/gp2xwiz-hw.h b/backends/platform/gph/gph-hw.h similarity index 88% rename from backends/platform/gp2xwiz/gp2xwiz-hw.h rename to backends/platform/gph/gph-hw.h index 507841e902b..7276276608a 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-hw.h +++ b/backends/platform/gph/gph-hw.h @@ -28,8 +28,8 @@ * */ -#ifndef GP2XWIZ_HW_H -#define GP2XWIZ_HW_H +#ifndef GPH_HW_H +#define GPH_HW_H namespace WIZ_HW { @@ -41,4 +41,12 @@ extern void mixerMoveVolume(int); } /* namespace WIZ_HW */ -#endif //GP2XWIZ_HW_H +namespace GPH { + +extern int tapmodeLevel; + +extern void ToggleTapMode(); + +} /* namespace GPH */ + +#endif //GPH_HW_H diff --git a/backends/platform/gp2xwiz/gp2xwiz-main.cpp b/backends/platform/gph/gph-main.cpp similarity index 91% rename from backends/platform/gp2xwiz/gp2xwiz-main.cpp rename to backends/platform/gph/gph-main.cpp index 839afa6a958..c433ba9f3f1 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-main.cpp +++ b/backends/platform/gph/gph-main.cpp @@ -23,11 +23,15 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include -#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h" -#include "backends/platform/gp2xwiz/gp2xwiz-hw.h" +// #include "backends/platform/gph/gph-options.h" +#include "backends/platform/gph/gph-sdl.h" +#include "backends/platform/gph/gph-hw.h" #include "backends/plugins/posix/posix-provider.h" #include "base/main.h" @@ -57,7 +61,7 @@ #define DUMP_STDOUT int main(int argc, char *argv[]) { - g_system = new OSystem_GP2XWIZ(); + g_system = new OSystem_GPH(); assert(g_system); #ifdef DYNAMIC_MODULES PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); @@ -70,7 +74,7 @@ int main(int argc, char *argv[]) { return res; } -void OSystem_GP2XWIZ::initBackend() { +void OSystem_GPH::initBackend() { /* Setup default save path to be workingdir/saves */ @@ -158,13 +162,16 @@ void OSystem_GP2XWIZ::initBackend() { /* Make sure SDL knows that we have a joystick we want to use. */ ConfMan.setInt("joystick_num", 0); + /* Now setup any device specific user options (Left handed mode, that sort of thing). */ + // GPH::setOptions(); + printf("%s\n", "Passing to OSystem::SDL initBackend."); /* Pass to SDL backend to do the heavy lifting */ OSystem_SDL::initBackend(); } -void OSystem_GP2XWIZ::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { +void OSystem_GPH::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { /* Setup default extra data paths for engine data files and plugins */ char workDirName[PATH_MAX+1]; @@ -199,7 +206,7 @@ void OSystem_GP2XWIZ::addSysArchivesToSearchSet(Common::SearchSet &s, int priori } } -void OSystem_GP2XWIZ::quit() { +void OSystem_GPH::quit() { WIZ_HW::deviceDeinit(); diff --git a/backends/platform/gp2xwiz/gp2xwiz-sdl.h b/backends/platform/gph/gph-sdl.h similarity index 84% rename from backends/platform/gp2xwiz/gp2xwiz-sdl.h rename to backends/platform/gph/gph-sdl.h index e312d0f26de..136363f9a04 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-sdl.h +++ b/backends/platform/gph/gph-sdl.h @@ -23,8 +23,8 @@ * */ -#ifndef GP2XWIZ_SDL_H -#define GP2XWIZ_SDL_H +#ifndef GPH_SDL_H +#define GPH_SDL_H #include "backends/platform/sdl/sdl.h" @@ -40,9 +40,9 @@ enum { #define PATH_MAX 255 #endif -class OSystem_GP2XWIZ : public OSystem_SDL { +class OSystem_GPH : public OSystem_SDL { public: - OSystem_GP2XWIZ() {} + OSystem_GPH() {} /* Graphics */ void initSize(uint w, uint h); @@ -59,7 +59,6 @@ public: void hideOverlay(); /* Event Stuff */ - bool pollEvent(Common::Event &event); void moveStick(); void fillMouseEvent(Common::Event&, int, int); void warpMouse(int, int); @@ -72,6 +71,11 @@ public: protected: bool _stickBtn[32]; + + bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); + bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); + bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); }; -#endif +#endif //GPH_SDL_H diff --git a/backends/platform/gp2xwiz/module.mk b/backends/platform/gph/module.mk similarity index 75% rename from backends/platform/gp2xwiz/module.mk rename to backends/platform/gph/module.mk index edf2f2a7172..f5567f581e6 100644 --- a/backends/platform/gp2xwiz/module.mk +++ b/backends/platform/gph/module.mk @@ -1,10 +1,10 @@ -MODULE := backends/platform/gp2xwiz +MODULE := backends/platform/gph MODULE_OBJS := \ - gp2xwiz-events.o \ - gp2xwiz-graphics.o \ - gp2xwiz-hw.o \ - gp2xwiz-main.o + gph-events.o \ + gph-graphics.o \ + gph-hw.o \ + gph-main.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/iphone/iphone_common.h b/backends/platform/iphone/iphone_common.h index 1f5ed019824..7c7770f4435 100644 --- a/backends/platform/iphone/iphone_common.h +++ b/backends/platform/iphone/iphone_common.h @@ -67,12 +67,19 @@ void iphone_main(int argc, char *argv[]); #endif // On the ObjC side -void iPhone_updateScreen(); +void iPhone_updateScreen(int mouseX, int mouseY); void iPhone_updateScreenRect(unsigned short* screen, int x1, int y1, int x2, int y2); +void iPhone_updateOverlayRect(unsigned short* screen, int x1, int y1, int x2, int y2); void iPhone_initSurface(int width, int height); bool iPhone_fetchEvent(int *outEvent, float *outX, float *outY); const char* iPhone_getDocumentsDir(); bool iPhone_isHighResDevice(); +int iPhone_getScreenHeight(); +int iPhone_getScreenWidth(); +void iPhone_enableOverlay(int state); +void iPhone_setMouseCursor(short* buffer, int width, int height); + +uint getSizeNextPOT(uint size); #ifdef __cplusplus } diff --git a/backends/platform/iphone/iphone_main.m b/backends/platform/iphone/iphone_main.m index d8992de5bb2..1fb2cc37889 100644 --- a/backends/platform/iphone/iphone_main.m +++ b/backends/platform/iphone/iphone_main.m @@ -103,13 +103,24 @@ int main(int argc, char** argv) { [NSThread detachNewThreadSelector:@selector(mainLoop:) toTarget:self withObject:nil]; } +- (void)applicationDidResume +{ +} + +- (void)applicationWillSuspend +{ +} + +- (void)applicationWillTerminate +{ +} + - (void)applicationSuspend:(struct __GSEvent *)event { //[self setApplicationBadge:NSLocalizedString(@"ON", nil)]; [_view applicationSuspend]; } - (void)applicationResume:(struct __GSEvent *)event { - [self removeApplicationBadge]; [_view applicationResume]; // Workaround, need to "hide" and unhide the statusbar to properly remove it, diff --git a/backends/platform/iphone/iphone_video.h b/backends/platform/iphone/iphone_video.h index 1060a2a223e..aed15ecfd5d 100644 --- a/backends/platform/iphone/iphone_video.h +++ b/backends/platform/iphone/iphone_video.h @@ -54,6 +54,8 @@ GLint _visibleWidth; GLint _visibleHeight; GLuint _screenTexture; + GLuint _overlayTexture; + GLuint _mouseCursorTexture; } - (id)initWithFrame:(struct CGRect)frame; @@ -65,6 +67,11 @@ - (void)initSurface; - (void)updateSurface; +- (void)updateMainSurface; +- (void)updateOverlaySurface; +- (void)updateMouseSurface; + +-(void)updateMouseCursor; - (id)getEvent; diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m index cd8b38acb30..821d3de6340 100644 --- a/backends/platform/iphone/iphone_video.m +++ b/backends/platform/iphone/iphone_video.m @@ -32,23 +32,88 @@ static int _height = 0; static int _fullWidth; static int _fullHeight; static CGRect _screenRect; + static char* _textureBuffer = 0; static int _textureWidth = 0; static int _textureHeight = 0; + +static char* _overlayTexBuffer = 0; +static int _overlayTexWidth = 0; +static int _overlayTexHeight = 0; +static int _overlayWidth = 0; +static int _overlayHeight = 0; +static float _overlayPortraitRatio = 1.0f; + NSLock* _lock = nil; static int _needsScreenUpdate = 0; +static int _overlayIsEnabled = 0; static UITouch* _firstTouch = NULL; static UITouch* _secondTouch = NULL; +static short* _mouseCursor = NULL; +static int _mouseCursorHeight = 0; +static int _mouseCursorWidth = 0; +static int _mouseX = 0; +static int _mouseY = 0; + // static long lastTick = 0; // static int frames = 0; +#define printOpenGLError() printOglError(__FILE__, __LINE__) + +int printOglError(const char *file, int line) +{ + int retCode = 0; + + // returns 1 if an OpenGL error occurred, 0 otherwise. + GLenum glErr = glGetError(); + while( glErr != GL_NO_ERROR) + { + fprintf(stderr, "glError: %u (%s: %d)\n", glErr, file, line ); + retCode = 1; + glErr = glGetError(); + } + return retCode; +} + +void iPhone_setMouseCursor(short* buffer, int width, int height) { + _mouseCursor = buffer; + + _mouseCursorWidth = width; + _mouseCursorHeight = height; + + [sharedInstance performSelectorOnMainThread:@selector(updateMouseCursor) withObject:nil waitUntilDone: YES]; +} + +void iPhone_enableOverlay(int state) { + _overlayIsEnabled = state; +} + +int iPhone_getScreenHeight() { + return _overlayHeight; +} + +int iPhone_getScreenWidth() { + return _overlayWidth; +} + bool iPhone_isHighResDevice() { return _fullHeight > 480; } -void iPhone_updateScreen() { +void iPhone_updateScreen(int mouseX, int mouseY) { + //printf("Mouse: (%i, %i)\n", mouseX, mouseY); + + //_mouseX = _overlayHeight - (float)mouseX / _width * _overlayHeight; + //_mouseY = (float)mouseY / _height * _overlayWidth; + + //_mouseX = _overlayHeight - mouseX; + //_mouseY = mouseY; + + _mouseX = (_overlayWidth - mouseX) / (float)_overlayWidth * _overlayHeight; + _mouseY = mouseY / (float)_overlayHeight * _overlayWidth; + if (!_needsScreenUpdate) { _needsScreenUpdate = 1; [sharedInstance performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO]; @@ -56,16 +121,17 @@ void iPhone_updateScreen() { } void iPhone_updateScreenRect(unsigned short* screen, int x1, int y1, int x2, int y2) { - //[_lock lock]; - int y; - for (y = y1; y < y2; ++y) { + for (y = y1; y < y2; ++y) memcpy(&_textureBuffer[(y * _textureWidth + x1 )* 2], &screen[y * _width + x1], (x2 - x1) * 2); - } - - //[_lock unlock]; } +void iPhone_updateOverlayRect(unsigned short* screen, int x1, int y1, int x2, int y2) { + int y; + //printf("Overlaywidth: %u, fullwidth %u\n", _overlayWidth, _fullWidth); + for (y = y1; y < y2; ++y) + memcpy(&_overlayTexBuffer[(y * _overlayTexWidth + x1 )* 2], &screen[y * _overlayWidth + x1], (x2 - x1) * 2); +} void iPhone_initSurface(int width, int height) { _width = width; @@ -92,6 +158,19 @@ bool iPhone_fetchEvent(int *outEvent, float *outX, float *outY) { return true; } +uint getSizeNextPOT(uint size) { + if ((size & (size - 1)) || !size) { + int log = 0; + + while (size >>= 1) + ++log; + + size = (2 << log); + } + + return size; +} + const char* iPhone_getDocumentsDir() { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; @@ -110,18 +189,6 @@ bool getLocalMouseCoords(CGPoint *point) { return true; } -uint getSizeNextPOT(uint size) { - if ((size & (size - 1)) || !size) { - int log = 0; - - while (size >>= 1) - ++log; - - size = (2 << log); - } - - return size; -} @implementation iPhoneView @@ -131,7 +198,15 @@ uint getSizeNextPOT(uint size) { } - (id)initWithFrame:(struct CGRect)frame { - [super initWithFrame: frame]; + self = [super initWithFrame: frame]; + + if([[UIScreen mainScreen] respondsToSelector: NSSelectorFromString(@"scale")]) + { + if([self respondsToSelector: NSSelectorFromString(@"contentScaleFactor")]) + { + //self.contentScaleFactor = [[UIScreen mainScreen] scale]; + } + } _fullWidth = frame.size.width; _fullHeight = frame.size.height; @@ -143,6 +218,8 @@ uint getSizeNextPOT(uint size) { _keyboardView = nil; _context = nil; _screenTexture = 0; + _overlayTexture = 0; + _mouseCursorTexture = 0; return self; } @@ -156,6 +233,8 @@ uint getSizeNextPOT(uint size) { if (_screenTexture) free(_textureBuffer); + + free(_overlayTexBuffer); } - (void *)getSurface { @@ -181,6 +260,38 @@ uint getSizeNextPOT(uint size) { } _needsScreenUpdate = 0; + if (_overlayIsEnabled) { + glClear(GL_COLOR_BUFFER_BIT); printOpenGLError(); + } + + [self updateMainSurface]; + + if (_overlayIsEnabled) { + [self updateOverlaySurface]; + [self updateMouseSurface]; + } + + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); + [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; + +} + +-(void)updateMouseCursor { + if (_mouseCursorTexture == 0) { + glGenTextures(1, &_mouseCursorTexture); printOpenGLError(); + glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); printOpenGLError(); + } + + glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSizeNextPOT(_mouseCursorWidth), getSizeNextPOT(_mouseCursorHeight), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _mouseCursor); printOpenGLError(); + + free(_mouseCursor); + _mouseCursor = NULL; +} + +- (void)updateMainSurface { GLfloat vertices[] = { 0.0f + _heightOffset, 0.0f + _widthOffset, _visibleWidth - _heightOffset, 0.0f + _widthOffset, @@ -198,20 +309,76 @@ uint getSizeNextPOT(uint size) { 0.0f, texHeight }; - glVertexPointer(2, GL_FLOAT, 0, vertices); - glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + glVertexPointer(2, GL_FLOAT, 0, vertices); printOpenGLError(); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); printOpenGLError(); + + glBindTexture(GL_TEXTURE_2D, _screenTexture); printOpenGLError(); - //[_lock lock]; // Unfortunately we have to update the whole texture every frame, since glTexSubImage2D is actually slower in all cases // due to the iPhone internals having to convert the whole texture back from its internal format when used. // In the future we could use several tiled textures instead. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureWidth, _textureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _textureBuffer); - //[_lock unlock]; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _textureWidth, _textureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _textureBuffer); printOpenGLError(); + glDisable(GL_BLEND); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); +} - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); - [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; +- (void)updateOverlaySurface { + GLfloat vertices[] = { + 0.0f, 0.0f, + _overlayHeight, 0.0f, + 0.0f, _overlayWidth * _overlayPortraitRatio, + _overlayHeight, _overlayWidth * _overlayPortraitRatio + }; + float texWidth = _overlayWidth / (float)_overlayTexWidth; + float texHeight = _overlayHeight / (float)_overlayTexHeight; + + const GLfloat texCoords[] = { + texWidth, 0.0f, + 0.0f, 0.0f, + texWidth, texHeight, + 0.0f, texHeight + }; + + glVertexPointer(2, GL_FLOAT, 0, vertices); printOpenGLError(); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); printOpenGLError(); + + glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _overlayTexWidth, _overlayTexHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _overlayTexBuffer); printOpenGLError(); + glEnable(GL_BLEND); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); +} + +- (void)updateMouseSurface { + + int width = _mouseCursorWidth / (float)_backingWidth * _backingHeight; + int height = _mouseCursorHeight / (float)_backingHeight * _backingWidth; + + GLfloat vertices[] = { + _mouseX, _mouseY, + _mouseX + height, _mouseY, + _mouseX, _mouseY + width, + _mouseX + height, _mouseY + width + }; + + //printf("Cursor: width %u height %u\n", _mouseCursorWidth, _mouseCursorHeight); + + float texWidth = _mouseCursorWidth / (float)getSizeNextPOT(_mouseCursorWidth); + float texHeight = _mouseCursorHeight / (float)getSizeNextPOT(_mouseCursorHeight); + + const GLfloat texCoords[] = { + texWidth, 0.0f, + 0.0f, 0.0f, + texWidth, texHeight, + 0.0f, texHeight + }; + + glVertexPointer(2, GL_FLOAT, 0, vertices); printOpenGLError(); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); printOpenGLError(); + + glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); + glEnable(GL_BLEND); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError(); } - (void)initSurface { @@ -232,28 +399,39 @@ uint getSizeNextPOT(uint size) { _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if (!_context || [EAGLContext setCurrentContext:_context]) { - glGenFramebuffersOES(1, &_viewFramebuffer); - glGenRenderbuffersOES(1, &_viewRenderbuffer); + glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError(); + glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError(); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); + glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError(); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id)self.layer]; - glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); + glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth); - glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth); printOpenGLError(); + glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight); printOpenGLError(); if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); return; } - glViewport(0, 0, _backingWidth, _backingHeight); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + _overlayHeight = _backingWidth; + _overlayWidth = _backingHeight; + _overlayTexWidth = getSizeNextPOT(_overlayHeight); + _overlayTexHeight = getSizeNextPOT(_overlayWidth); - glEnable(GL_TEXTURE_2D); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); + int textureSize = _overlayTexWidth * _overlayTexHeight * 2; + _overlayTexBuffer = (char *)malloc(textureSize); + memset(_overlayTexBuffer, 0, textureSize); + + glViewport(0, 0, _backingWidth, _backingHeight); printOpenGLError(); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError(); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnable(GL_TEXTURE_2D); printOpenGLError(); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError(); + glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError(); } } @@ -261,22 +439,32 @@ uint getSizeNextPOT(uint size) { glLoadIdentity(); if (orientation == UIDeviceOrientationLandscapeRight) { - glRotatef(-90, 0, 0, 1); + glRotatef(-90, 0, 0, 1); printOpenGLError(); } else if (orientation == UIDeviceOrientationLandscapeLeft) { - glRotatef(90, 0, 0, 1); + glRotatef(90, 0, 0, 1); printOpenGLError(); } else { - glRotatef(180, 0, 0, 1); + glRotatef(180, 0, 0, 1); printOpenGLError(); } - glOrthof(0, _backingWidth, 0, _backingHeight, 0, 1); + glOrthof(0, _backingWidth, 0, _backingHeight, 0, 1); printOpenGLError(); if (_screenTexture > 0) { - glDeleteTextures(1, &_screenTexture); + glDeleteTextures(1, &_screenTexture); printOpenGLError(); } - glGenTextures(1, &_screenTexture); - glBindTexture(GL_TEXTURE_2D, _screenTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glGenTextures(1, &_screenTexture); printOpenGLError(); + glBindTexture(GL_TEXTURE_2D, _screenTexture); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); printOpenGLError(); + + if (_overlayTexture > 0) { + glDeleteTextures(1, &_overlayTexture); printOpenGLError(); + } + + glGenTextures(1, &_overlayTexture); printOpenGLError(); + glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); printOpenGLError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); printOpenGLError(); if (_textureBuffer) { free(_textureBuffer); @@ -286,12 +474,12 @@ uint getSizeNextPOT(uint size) { _textureBuffer = (char*)malloc(textureSize); memset(_textureBuffer, 0, textureSize); - glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); + glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); // The color buffer is triple-buffered, so we clear it multiple times right away to avid doing any glClears later. int clearCount = 5; while (clearCount-- > 0) { - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); printOpenGLError(); [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; } @@ -320,6 +508,7 @@ uint getSizeNextPOT(uint size) { //printf("Rect: %i, %i, %i, %i\n", _widthOffset, _heightOffset, rectWidth, rectHeight); _screenRect = CGRectMake(_widthOffset, _heightOffset, rectWidth, rectHeight); + _overlayPortraitRatio = 1.0f; } else { float ratio = (float)_height / (float)_width; int height = _fullWidth * ratio; @@ -340,6 +529,7 @@ uint getSizeNextPOT(uint size) { [self addSubview:[_keyboardView inputView]]; [self addSubview: _keyboardView]; [[_keyboardView inputView] becomeFirstResponder]; + _overlayPortraitRatio = (_overlayHeight * ratio) / _overlayWidth; } } @@ -421,7 +611,7 @@ uint getSizeNextPOT(uint size) { - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - NSSet *allTouches = [event allTouches]; + //NSSet *allTouches = [event allTouches]; for (UITouch* touch in touches) { if (touch == _firstTouch) { diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp index c1c7ffdc0c6..c30e34dd058 100644 --- a/backends/platform/iphone/osys_events.cpp +++ b/backends/platform/iphone/osys_events.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "gui/message.h" #include "common/translation.h" @@ -60,16 +63,31 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) { int y = 0; switch (_screenOrientation) { case kScreenOrientationPortrait: - x = (int)(xUnit * _screenWidth); - y = (int)(yUnit * _screenHeight); + if (_overlayVisible) { + x = (int)(xUnit * _overlayWidth); + y = (int)(yUnit * _overlayHeight); + } else { + x = (int)(xUnit * _screenWidth); + y = (int)(yUnit * _screenHeight); + } break; case kScreenOrientationLandscape: - x = (int)(yUnit * _screenWidth); - y = (int)((1.0 - xUnit) * _screenHeight); + if (_overlayVisible) { + x = (int)(yUnit * _overlayWidth); + y = (int)((1.0 - xUnit) * _overlayHeight); + } else { + x = (int)(yUnit * _screenWidth); + y = (int)((1.0 - xUnit) * _screenHeight); + } break; case kScreenOrientationFlippedLandscape: - x = (int)((1.0 - yUnit) * _screenWidth); - y = (int)(xUnit * _screenHeight); + if (_overlayVisible) { + x = (int)((1.0 - yUnit) * _overlayWidth); + y = (int)(xUnit * _overlayHeight); + } else { + x = (int)((1.0 - yUnit) * _screenWidth); + y = (int)(xUnit * _screenHeight); + } break; } @@ -262,15 +280,18 @@ bool OSystem_IPHONE::handleEvent_mouseDragged(Common::Event &event, int x, int y mouseNewPosX = (int)(_mouseX - deltaX / 0.5f); mouseNewPosY = (int)(_mouseY - deltaY / 0.5f); + int widthCap = _overlayVisible ? _overlayWidth : _screenWidth; + int heightCap = _overlayVisible ? _overlayHeight : _screenHeight; + if (mouseNewPosX < 0) mouseNewPosX = 0; - else if (mouseNewPosX > _screenWidth) - mouseNewPosX = _screenWidth; + else if (mouseNewPosX > widthCap) + mouseNewPosX = widthCap; if (mouseNewPosY < 0) mouseNewPosY = 0; - else if (mouseNewPosY > _screenHeight) - mouseNewPosY = _screenHeight; + else if (mouseNewPosY > heightCap) + mouseNewPosY = heightCap; } else { mouseNewPosX = x; diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp index 6c26b6ca8dc..9dc4e202c46 100644 --- a/backends/platform/iphone/osys_main.cpp +++ b/backends/platform/iphone/osys_main.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include #include @@ -54,13 +57,13 @@ void *OSystem_IPHONE::s_soundParam = NULL; OSystem_IPHONE::OSystem_IPHONE() : _savefile(NULL), _mixer(NULL), _timer(NULL), _offscreen(NULL), - _overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL), + _overlayVisible(false), _fullscreen(NULL), _mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0), _secondaryTapped(false), _lastSecondaryTap(0), _screenOrientation(kScreenOrientationFlippedLandscape), _needEventRestPeriod(false), _mouseClickAndDragEnabled(false), _gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false), _fullScreenOverlayIsDirty(false), - _mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1), _screenChangeCount(0) - + _mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1), _screenChangeCount(0), + _overlayHeight(0), _overlayWidth(0), _overlayBuffer(0) { _queuedInputEvent.type = (Common::EventType)0; _lastDrawnMouseRect = Common::Rect(0, 0, 0, 0); diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h index 3c80c839980..c925078b467 100644 --- a/backends/platform/iphone/osys_main.h +++ b/backends/platform/iphone/osys_main.h @@ -66,6 +66,9 @@ protected: Graphics::Surface _framebuffer; byte *_offscreen; OverlayColor *_overlayBuffer; + uint16 _overlayHeight; + uint16 _overlayWidth; + uint16 *_fullscreen; uint16 _palette[256]; @@ -144,7 +147,7 @@ public: virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); virtual int16 getOverlayHeight(); virtual int16 getOverlayWidth(); - virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<565>(); } + virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::createPixelFormat<5551>(); } virtual bool showMouse(bool visible); diff --git a/backends/platform/iphone/osys_sound.cpp b/backends/platform/iphone/osys_sound.cpp index 55892580f65..cd364f57ac0 100644 --- a/backends/platform/iphone/osys_sound.cpp +++ b/backends/platform/iphone/osys_sound.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "osys_main.h" void OSystem_IPHONE::AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB) { diff --git a/backends/platform/iphone/osys_video.cpp b/backends/platform/iphone/osys_video.cpp index 76c2031758b..88368a0eecd 100644 --- a/backends/platform/iphone/osys_video.cpp +++ b/backends/platform/iphone/osys_video.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "osys_main.h" const OSystem::GraphicsMode* OSystem_IPHONE::getSupportedGraphicsModes() const { @@ -57,10 +60,10 @@ void OSystem_IPHONE::initSize(uint width, uint height, const Graphics::PixelForm _offscreen = (byte *)malloc(width * height); bzero(_offscreen, width * height); - free(_overlayBuffer); + //free(_overlayBuffer); int fullSize = _screenWidth * _screenHeight * sizeof(OverlayColor); - _overlayBuffer = (OverlayColor *)malloc(fullSize); + //_overlayBuffer = (OverlayColor *)malloc(fullSize); clearOverlay(); free(_fullscreen); @@ -70,6 +73,14 @@ void OSystem_IPHONE::initSize(uint width, uint height, const Graphics::PixelForm iPhone_initSurface(width, height); + if (_overlayBuffer == NULL) { + _overlayHeight = iPhone_getScreenHeight(); + _overlayWidth = iPhone_getScreenWidth(); + + printf("Overlay: (%u x %u)\n", _overlayWidth, _overlayHeight); + _overlayBuffer = new OverlayColor[_overlayHeight * _overlayWidth]; + } + _fullScreenIsDirty = false; dirtyFullScreen(); _mouseVisible = false; @@ -187,7 +198,7 @@ void OSystem_IPHONE::updateScreen() { _fullScreenIsDirty = false; _fullScreenOverlayIsDirty = false; - iPhone_updateScreen(); + iPhone_updateScreen(_mouseX - _mouseHotspotX, _mouseY - _mouseHotspotY); } void OSystem_IPHONE::internUpdateScreen() { @@ -222,8 +233,9 @@ void OSystem_IPHONE::internUpdateScreen() { if (_overlayVisible) drawDirtyOverlayRect(dirtyRect); + else + drawMouseCursorOnRectUpdate(dirtyRect, mouseRect); - drawMouseCursorOnRectUpdate(dirtyRect, mouseRect); updateHardwareSurfaceForRect(dirtyRect); } @@ -234,8 +246,8 @@ void OSystem_IPHONE::internUpdateScreen() { //printf("Drawing: (%i, %i) -> (%i, %i)\n", dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); drawDirtyOverlayRect(dirtyRect); - drawMouseCursorOnRectUpdate(dirtyRect, mouseRect); - updateHardwareSurfaceForRect(dirtyRect); + //drawMouseCursorOnRectUpdate(dirtyRect, mouseRect); + //updateHardwareSurfaceForRect(dirtyRect); } } } @@ -256,16 +268,17 @@ void OSystem_IPHONE::drawDirtyRect(const Common::Rect& dirtyRect) { } void OSystem_IPHONE::drawDirtyOverlayRect(const Common::Rect& dirtyRect) { - int h = dirtyRect.bottom - dirtyRect.top; - - uint16 *src = (uint16 *)&_overlayBuffer[dirtyRect.top * _screenWidth + dirtyRect.left]; - uint16 *dst = &_fullscreen[dirtyRect.top * _screenWidth + dirtyRect.left]; - int x = (dirtyRect.right - dirtyRect.left) * 2; - for (int y = h; y > 0; y--) { - memcpy(dst, src, x); - src += _screenWidth; - dst += _screenWidth; - } + // int h = dirtyRect.bottom - dirtyRect.top; + // + // uint16 *src = (uint16 *)&_overlayBuffer[dirtyRect.top * _screenWidth + dirtyRect.left]; + // uint16 *dst = &_fullscreen[dirtyRect.top * _screenWidth + dirtyRect.left]; + // int x = (dirtyRect.right - dirtyRect.left) * 2; + // for (int y = h; y > 0; y--) { + // memcpy(dst, src, x); + // src += _screenWidth; + // dst += _screenWidth; + // } + iPhone_updateOverlayRect(_overlayBuffer, dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); } void OSystem_IPHONE::drawMouseCursorOnRectUpdate(const Common::Rect& updatedRect, const Common::Rect& mouseRect) { @@ -283,16 +296,19 @@ void OSystem_IPHONE::drawMouseCursorOnRectUpdate(const Common::Rect& updatedRect srcY -= top; top = 0; } - //int right = left + _mouseWidth; + int bottom = top + _mouseHeight; if (bottom > _screenWidth) bottom = _screenWidth; - int displayWidth = _mouseWidth; + + int displayWidth = _mouseWidth; if (_mouseWidth + left > _screenWidth) displayWidth = _screenWidth - left; - int displayHeight = _mouseHeight; + + int displayHeight = _mouseHeight; if (_mouseHeight + top > _screenHeight) displayHeight = _screenHeight - top; + byte *src = &_mouseBuf[srcY * _mouseWidth + srcX]; uint16 *dst = &_fullscreen[top * _screenWidth + left]; for (int y = displayHeight; y > srcY; y--) { @@ -337,6 +353,7 @@ void OSystem_IPHONE::showOverlay() { //printf("showOverlay()\n"); _overlayVisible = true; dirtyFullOverlayScreen(); + iPhone_enableOverlay(true); } void OSystem_IPHONE::hideOverlay() { @@ -344,11 +361,12 @@ void OSystem_IPHONE::hideOverlay() { _overlayVisible = false; _dirtyOverlayRects.clear(); dirtyFullScreen(); + iPhone_enableOverlay(false); } void OSystem_IPHONE::clearOverlay() { //printf("clearOverlay()\n"); - bzero(_overlayBuffer, _screenWidth * _screenHeight * sizeof(OverlayColor)); + bzero(_overlayBuffer, _overlayWidth * _overlayHeight * sizeof(OverlayColor)); dirtyFullOverlayScreen(); } @@ -358,8 +376,8 @@ void OSystem_IPHONE::grabOverlay(OverlayColor *buf, int pitch) { OverlayColor *src = _overlayBuffer; do { - memcpy(buf, src, _screenWidth * sizeof(OverlayColor)); - src += _screenWidth; + memcpy(buf, src, _overlayWidth * sizeof(OverlayColor)); + src += _overlayWidth; buf += pitch; } while (--h); } @@ -380,11 +398,11 @@ void OSystem_IPHONE::copyRectToOverlay(const OverlayColor *buf, int pitch, int x y = 0; } - if (w > _screenWidth - x) - w = _screenWidth - x; + if (w > _overlayWidth - x) + w = _overlayWidth - x; - if (h > _screenHeight - y) - h = _screenHeight - y; + if (h > _overlayHeight - y) + h = _overlayHeight - y; if (w <= 0 || h <= 0) return; @@ -393,24 +411,24 @@ void OSystem_IPHONE::copyRectToOverlay(const OverlayColor *buf, int pitch, int x _dirtyOverlayRects.push_back(Common::Rect(x, y, x + w, y + h)); } - OverlayColor *dst = _overlayBuffer + (y * _screenWidth + x); - if (_screenWidth == pitch && pitch == w) + OverlayColor *dst = _overlayBuffer + (y * _overlayWidth + x); + if (_overlayWidth == pitch && pitch == w) memcpy(dst, buf, h * w * sizeof(OverlayColor)); else { do { memcpy(dst, buf, w * sizeof(OverlayColor)); buf += pitch; - dst += _screenWidth; + dst += _overlayWidth; } while (--h); } } int16 OSystem_IPHONE::getOverlayHeight() { - return _screenHeight; + return _overlayHeight; } int16 OSystem_IPHONE::getOverlayWidth() { - return _screenWidth; + return _overlayWidth; } bool OSystem_IPHONE::showMouse(bool visible) { @@ -440,13 +458,31 @@ void OSystem_IPHONE::dirtyFullScreen() { void OSystem_IPHONE::dirtyFullOverlayScreen() { if (!_fullScreenOverlayIsDirty) { _dirtyOverlayRects.clear(); - _dirtyOverlayRects.push_back(Common::Rect(0, 0, _screenWidth, _screenHeight)); + _dirtyOverlayRects.push_back(Common::Rect(0, 0, _overlayWidth, _overlayHeight)); _fullScreenOverlayIsDirty = true; } } void OSystem_IPHONE::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { - //printf("setMouseCursor(%i, %i)\n", hotspotX, hotspotY); + //printf("setMouseCursor(%i, %i, scale %u)\n", hotspotX, hotspotY, cursorTargetScale); + + int texWidth = getSizeNextPOT(w); + int texHeight = getSizeNextPOT(h); + int bufferSize = texWidth * texHeight * sizeof(int16); + int16* mouseBuf = (int16*)malloc(bufferSize); + memset(mouseBuf, 0, bufferSize); + + for (int x = 0; x < w; ++x) { + for (int y = 0; y < h; ++y) { + byte color = buf[y * w + x]; + if (color != keycolor) + mouseBuf[y * texWidth + x] = _palette[color] | 0x1; + else + mouseBuf[y * texWidth + x] = 0x0; + } + } + + iPhone_setMouseCursor(mouseBuf, w, h); if (_mouseBuf != NULL && (_mouseWidth != w || _mouseHeight != h)) { free(_mouseBuf); diff --git a/backends/platform/linuxmoto/linuxmoto-events.cpp b/backends/platform/linuxmoto/linuxmoto-events.cpp index 379e34b7ac8..eb1bbc93942 100644 --- a/backends/platform/linuxmoto/linuxmoto-events.cpp +++ b/backends/platform/linuxmoto/linuxmoto-events.cpp @@ -128,7 +128,7 @@ bool OSystem_LINUXMOTO::remapKey(SDL_Event &ev, Common::Event &event) { // VirtualKeyboard - Right Soft key else if (ev.key.keysym.sym == SDLK_F11) { ev.key.keysym.sym = SDLK_F7; - } + } #endif // Joystick to Mouse diff --git a/backends/platform/linuxmoto/linuxmoto-main.cpp b/backends/platform/linuxmoto/linuxmoto-main.cpp index 97f12e8ce14..09b03c31d6b 100644 --- a/backends/platform/linuxmoto/linuxmoto-main.cpp +++ b/backends/platform/linuxmoto/linuxmoto-main.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/n64/Makefile b/backends/platform/n64/Makefile index b8b2e61f779..cffe2773129 100644 --- a/backends/platform/n64/Makefile +++ b/backends/platform/n64/Makefile @@ -15,7 +15,7 @@ AR = $(GCCN64PREFIX)ar cru RANLIB = $(GCCN64PREFIX)ranlib DEFINES += -D__N64__ -DLIMIT_FPS -DNONSTANDARD_PORT -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_FANCY_THEMES -DDISABLE_DOSBOX_OPL -DENABLE_VKEYBD -DUSE_ZLIB -LIBS += -lpakfs -lframfs -ln64 -ln64utils -lromfs +LIBS += -lpakfs -lframfs -ln64 -ln64utils -lromfs #DEFINES += -D_ENABLE_DEBUG_ @@ -31,7 +31,7 @@ DEFINES += -DUSE_VORBIS -DUSE_TREMOR LIBS += -lvorbisidec endif -LIBS += -lm -lstdc++ -lc -lgcc -lz -lnosys +LIBS += -lm -lstdc++ -lc -lgcc -lz -lnosys CXXFLAGS = -g -mno-extern-sdata -O2 --param max-inline-insns-auto=20 -fomit-frame-pointer -march=vr4300 -mtune=vr4300 -mhard-float -fno-rtti -fno-exceptions -Wno-multichar -Wshadow -I$(LIBN64PATH) -I$(TOOLPATH)/include -I./ -I$(srcdir) -I$(srcdir)/engines LDFLAGS = -g -march=vr4300 -mtune=vr4300 -nodefaultlibs -nostartfiles -mno-crt0 -L$(LIBN64PATH) -L$(TOOLPATH)/lib $(LIBS) -T n64ld_cpp.x -Xlinker -Map -Xlinker scummvm.map @@ -49,7 +49,7 @@ USE_RGB_COLOR=0 ENABLED=STATIC_PLUGIN -ENABLE_SCUMM = $(ENABLED) +#ENABLE_SCUMM = $(ENABLED) #ENABLE_SCI = $(ENABLED) #ENABLE_GOB = $(ENABLED) #ENABLE_PARALLACTION = $(ENABLED) @@ -74,7 +74,7 @@ all: $(TARGET).v64 $(TARGET).v64: $(TARGET).bin ROMFS.img bootcode cat bootcode $(TARGET).bin ROMFS.img > $(TARGET).v64 - ./pad_rom.sh + ./pad_rom.sh $(TARGET).v64 ROMFS.img: genromfs -f ./ROMFS.img -d ./ROMFS -V romtest diff --git a/backends/platform/n64/README.N64 b/backends/platform/n64/README.N64 index c6ae6f021e5..b47b239658d 100644 --- a/backends/platform/n64/README.N64 +++ b/backends/platform/n64/README.N64 @@ -97,15 +97,15 @@ A - '.' / Skip dialogues in some games C buttons - Numeric keypad keys * Using a N64 Mouse: -Used like a normal PC mouse. +Used like a normal PC mouse. Notes ===== -- If virtual keyboard doesn't show up, you need to make sure you included +- If virtual keyboard doesn't show up, you need to make sure you included 'vkeybd_default.zip' in the root of your romfs image. -- In some games (mostly gob) cursor movement might be choppy, it's a known +- In some games (mostly gob) cursor movement might be choppy, it's a known problem and related on how N64 port manages screen updates. diff --git a/backends/platform/n64/module.mk b/backends/platform/n64/module.mk index 429b63802ea..c8ceb327013 100644 --- a/backends/platform/n64/module.mk +++ b/backends/platform/n64/module.mk @@ -6,7 +6,7 @@ MODULE_OBJS := \ osys_n64_events.o \ osys_n64_utilities.o \ pakfs_save_manager.o \ - framfs_save_manager.o + framfs_save_manager.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/n64/n64.mk b/backends/platform/n64/n64.mk new file mode 100644 index 00000000000..2e383e670d8 --- /dev/null +++ b/backends/platform/n64/n64.mk @@ -0,0 +1,29 @@ +N64_EXE_STRIPPED := scummvm_stripped$(EXEEXT) + +bundle_name = n64-dist/scummvm +BASESIZE = 2097152 + +all: $(N64_EXE_STRIPPED) + +$(N64_EXE_STRIPPED): $(EXECUTABLE) + $(STRIP) $< -o $@ + +n64-distclean: + rm -rf $(bundle_name) + rm $(N64_EXE_STRIPPED) + +n64-dist: all + $(MKDIR) $(bundle_name) + $(MKDIR) $(bundle_name)/romfs +ifdef DIST_FILES_ENGINEDATA + $(CP) $(DIST_FILES_ENGINEDATA) $(bundle_name)/romfs +endif + $(CP) $(DIST_FILES_DOCS) $(bundle_name)/ + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/romfs + genromfs -f $(bundle_name)/romfs.img -d $(bundle_name)/romfs -V scummvmn64 + mips64-objcopy $(EXECUTABLE) $(bundle_name)/scummvm.elf -O binary + cat $(N64SDK)/hkz-libn64/bootcode $(bundle_name)/scummvm.elf $(bundle_name)/romfs.img > scummvm.v64 + $(srcdir)/backends/platform/n64/pad_rom.sh scummvm.v64 + rm scummvm.bak + mv scummvm.v64 $(bundle_name)/scummvm.v64 + diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp index 06ff38e5862..8862693138d 100644 --- a/backends/platform/n64/osys_n64_base.cpp +++ b/backends/platform/n64/osys_n64_base.cpp @@ -859,7 +859,7 @@ void OSystem_N64::getTimeAndDate(TimeDate &t) const { // No RTC inside the N64, read mips timer to simulate // passing of time, not a perfect solution, but can't think // of anything better. - + uint32 now = getMilliTick(); t.tm_sec = (now / 1000) % 60; @@ -867,7 +867,7 @@ void OSystem_N64::getTimeAndDate(TimeDate &t) const { t.tm_hour = (((now / 1000) / 60) / 60) % 24; t.tm_mday = 1; t.tm_mon = 0; - t.tm_year = 1900; + t.tm_year = 110; return; } diff --git a/backends/platform/n64/pad_rom.sh b/backends/platform/n64/pad_rom.sh index 0660f6c2044..085203306f1 100644 --- a/backends/platform/n64/pad_rom.sh +++ b/backends/platform/n64/pad_rom.sh @@ -1,13 +1,13 @@ #!/bin/bash -TARGET="scummvm" +TARGET=$1 BASESIZE=2097152 -CARTSIZE=`ls -l $TARGET.v64 | cut -d" " -f5` +CARTSIZE=`ls -l $1 | cut -d" " -f5` REMAINDER=`echo $CARTSIZE % $BASESIZE | bc` REMAINDER=`echo $BASESIZE - $REMAINDER | bc` CARTSIZE=`echo $CARTSIZE + $REMAINDER | bc` -ucon64 -q --n64 --v64 --chk --padn=$CARTSIZE $TARGET.v64 +ucon64 -q --n64 --v64 --chk --padn=$CARTSIZE $1 diff --git a/backends/platform/openpandora/build/PXML.xml b/backends/platform/openpandora/build/PXML.xml new file mode 100755 index 00000000000..f4d2e2a595e --- /dev/null +++ b/backends/platform/openpandora/build/PXML.xml @@ -0,0 +1,34 @@ + + + + + + ScummVM + + + + + + + + + + + Point & click game interpreter. + + + + + + + + + + + + + + + + + diff --git a/backends/platform/openpandora/build/README-OPENPANDORA b/backends/platform/openpandora/build/README-OPENPANDORA new file mode 100755 index 00000000000..c8aabcbb7a0 --- /dev/null +++ b/backends/platform/openpandora/build/README-OPENPANDORA @@ -0,0 +1,19 @@ +ScummVM - OPENPANDORA SPECIFIC README +------------------------------------------------------------------------ +Please refer to the: + +ScummVM Forum: +WiKi: + +for the most current information on the port and any updates to this +documentation. + +The wiki includes detailed instructions on how to use the port and +control information. + +------------------------------------------------------------------------ +Credits + +Core ScummVM code (c) The ScummVM Team +OpenPandora backend (c) John Willis +Detailed (c) information can be found within the source code diff --git a/backends/platform/openpandora/build/README-PND.txt b/backends/platform/openpandora/build/README-PND.txt new file mode 100755 index 00000000000..942c3a43e22 --- /dev/null +++ b/backends/platform/openpandora/build/README-PND.txt @@ -0,0 +1,38 @@ +ScummVM - OPENPANDORA README - HOW TO INSTALL +------------------------------------------------------------------------ + +Please refer to the: + +ScummVM Forum: +WiKi: + +for the most current information on the port and any updates to this +documentation. + +------------------------------------------------------------------------ +Installing: + +This archive contains ScummVM in a PND format ready to be copied to the +OpenPandora and used. + +To install just copy the .pnd file from this archive to your device. + +You will need to place the .pnd file in a suitable location on your SD +card. + +/pandora/desktop <- place here if you wish the icon to show on the + desktop. Documentation will show in the menu. + +/pandora/menu <- place here if you wish the icon to show on the + Xfce menu. Documentation will show in the menu. + +/pandora/apps <- place here if you wish the icon to show on the + desktop and in the menu. Documentation will show + in the menu. + +------------------------------------------------------------------------ +Credits + +Core ScummVM code (c) The ScummVM Team +OpenPandora backend (c) John Willis +Detailed (c) information can be found within the source code diff --git a/backends/platform/openpandora/build/build.sh b/backends/platform/openpandora/build/build.sh new file mode 100755 index 00000000000..10b98fe0927 --- /dev/null +++ b/backends/platform/openpandora/build/build.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +echo Quick script to make building all the time less painful. + +. /usr/local/angstrom/arm/environment-setup + +CROSS_COMPILE=arm-angstrom-linux-gnueabi- +export CROSS_COMPILE + +# Export the tool names for cross-compiling +export CXX=arm-angstrom-linux-gnueabi-g++ +export CC=arm-angstrom-linux-gnueabi-gcc +export DEFINES=-DNDEBUG + +cd ../../../.. + +echo Building ScummVM/OpenPandora. +make + +echo Build for OpenPandora complete - Please check build logs. diff --git a/backends/platform/openpandora/build/bundle.sh b/backends/platform/openpandora/build/bundle.sh new file mode 100755 index 00000000000..12d34380bc5 --- /dev/null +++ b/backends/platform/openpandora/build/bundle.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +. /usr/local/angstrom/arm/environment-setup + +CROSS_COMPILE=arm-angstrom-linux-gnueabi- +export CROSS_COMPILE + +echo Quick script to make building a distribution of the OpenPanodra backend more consistent. + +cd ../../../.. + +make op-bundle +make op-pnd diff --git a/backends/platform/openpandora/build/clean.sh b/backends/platform/openpandora/build/clean.sh new file mode 100755 index 00000000000..3574db22984 --- /dev/null +++ b/backends/platform/openpandora/build/clean.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +echo Quick script to make building all the time less painful. + +. /usr/local/angstrom/arm/environment-setup + +cd ../../../.. + +echo Cleaning ScummVM for the OpenPandora. +make clean diff --git a/backends/platform/openpandora/build/config-alleng.sh b/backends/platform/openpandora/build/config-alleng.sh new file mode 100755 index 00000000000..f3fa1a0f943 --- /dev/null +++ b/backends/platform/openpandora/build/config-alleng.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +echo Quick script to make running configure all the time less painful +echo and let all the build work be done from the backend/build folder. + +. /usr/local/angstrom/arm/environment-setup + +CROSS_COMPILE=arm-angstrom-linux-gnueabi- +export CROSS_COMPILE + +# Export the tool names for cross-compiling +export CXX=arm-angstrom-linux-gnueabi-g++ +export CPPFLAGS=-I/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/include +export LDFLAGS=-L/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib + +export DEFINES=-DNDEBUG + +# Edit the configure line to suit. +cd ../../../.. +./configure --backend=openpandora --host=openpandora --disable-nasm \ + --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --disable-vorbis --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-all-engines --enable-plugins --default-dynamic + +echo Generating config for OpenPandora complete. Check for errors. diff --git a/backends/platform/openpandora/build/config.sh b/backends/platform/openpandora/build/config.sh new file mode 100755 index 00000000000..9bc52a9bc4b --- /dev/null +++ b/backends/platform/openpandora/build/config.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +echo Quick script to make running configure all the time less painful +echo and let all the build work be done from the backend/build folder. + +. /usr/local/angstrom/arm/environment-setup + +CROSS_COMPILE=arm-angstrom-linux-gnueabi- +export CROSS_COMPILE + +# Export the tool names for cross-compiling +export CXX=arm-angstrom-linux-gnueabi-g++ +export CPPFLAGS=-I/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/include +export LDFLAGS=-L/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib + +export DEFINES=-DNDEBUG + +# Edit the configure line to suit. +cd ../../../.. +./configure --backend=openpandora --host=openpandora --disable-nasm \ + --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --disable-vorbis --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-plugins --default-dynamic + +echo Generating config for OpenPandora complete. Check for errors. diff --git a/backends/platform/openpandora/build/icon/preview-pic.png b/backends/platform/openpandora/build/icon/preview-pic.png new file mode 100755 index 00000000000..2f4a536d307 Binary files /dev/null and b/backends/platform/openpandora/build/icon/preview-pic.png differ diff --git a/backends/platform/openpandora/build/icon/scummvm.png b/backends/platform/openpandora/build/icon/scummvm.png new file mode 100755 index 00000000000..128e59efc40 Binary files /dev/null and b/backends/platform/openpandora/build/icon/scummvm.png differ diff --git a/backends/platform/openpandora/build/index.html b/backends/platform/openpandora/build/index.html new file mode 100755 index 00000000000..34d381d0f89 --- /dev/null +++ b/backends/platform/openpandora/build/index.html @@ -0,0 +1,26 @@ + + +

+

Welcome to the ScummVM!

+

+ +

+

ScummVM: OpenPandora Specific Documentation

+

+ +ScummVM OpenPandora README
+ScummVM OpenPandora Website
+ScummVM OpenPandora WiKi
+ +

+

ScummVM: General Documentation

+

+ +ScummVM website
+ScummVM README
+ScummVM NEWS
+ScummVM Authors
+ScummVM Copyright
+GPL Licence
+ + diff --git a/backends/platform/openpandora/build/pnd_make.sh b/backends/platform/openpandora/build/pnd_make.sh new file mode 100755 index 00000000000..b19de87bb4a --- /dev/null +++ b/backends/platform/openpandora/build/pnd_make.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +######adjust path of genpxml.sh if you want to use that "feture"##### + +TEMP=`getopt -o p:d:x:i:c -- "$@"` + +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +eval set -- "$TEMP" +while true ; do + case "$1" in + -p) echo "PNDNAME set to $2" ;PNDNAME=$2;shift 2;; + -d) echo "FOLDER set to $2" ;FOLDER=$2;shift 2 ;; + -x) echo "PXML set to $2" ;PXML=$2;shift 2 ;; + -i) echo "ICON set to $2" ;ICON=$2;shift 2 ;; + -c) echo "-c set, will create compressed squasfs image instead of iso $2" ;SQUASH=1;shift 1 ;; + --) shift ; break ;; + *) echo "Error while parsing arguments! $2" ; exit 1 ;; + esac +done + +rnd=$RANDOM; # random number for genpxml and index$rnd.xml + +#generate pxml if guess or empty +if [ ! $PXML ] || [ $PXML = "guess" ] && [ $PNDNAME ] && [ $FOLDER ]; then + PXMLtxt=$(/home/user/libpnd/pandora-libraries/testdata/scripts/genpxml.sh $FOLDER $ICON) + PXML=$FOLDER/PXML.xml + echo "$PXMLtxt" > $FOLDER/PXML.xml +fi + +#check arguments +if [ ! $PNDNAME ] || [ ! $FOLDER ] || [ ! $PXML ]; then + echo " Usage: pnd_make.sh -p your.pnd -d folder/containing/your/app/ -x + your.pxml (or \"guess\" to try to generate it from the folder) -i icon.png" + exit 1 +fi +if [ ! -d $FOLDER ]; then echo "$FOLDER doesnt exist"; exit 1; fi #check if folder actually exists +if [ ! -f $PXML ]; then echo "$PXML doesnt exist"; exit 1; fi #check if pxml actually exists + +#make iso from folder +if [ ! $SQUASH ]; then + mkisofs -o $PNDNAME.iso -R $FOLDER +else + if [ $(mksquashfs -version | awk '{if ($3 >= 4) print 1}') = 1 ]; then + echo "your squashfs version is older then version 4, please upgrade to 4.0 or later" + exit 1 + fi + mksquashfs -no-recovery -nopad $FOLDER $PNDNAME.iso +fi +#append pxml to iso +cat $PNDNAME.iso $PXML > $PNDNAME +rm $PNDNAME.iso #cleanup + +#append icon if specified +if [ $ICON ]; then # check if we want to add an icon + if [ ! -f $ICON ]; then #does the icon actually exist? + echo "$ICON doesnt exist" + else # yes + mv $PNDNAME $PNDNAME.tmp + cat $PNDNAME.tmp $ICON > $PNDNAME # append icon + rm $PNDNAME.tmp #cleanup + fi +fi + +if [ $PXML = "guess" ];then rm $FOLDER/PXML.xml; fi #cleanup diff --git a/backends/platform/openpandora/build/runscummvm.sh b/backends/platform/openpandora/build/runscummvm.sh new file mode 100755 index 00000000000..48d24a2b817 --- /dev/null +++ b/backends/platform/openpandora/build/runscummvm.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Make sure any extra libs not in the firmware are pulled in. +LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:../lib +export LD_LIBRARY_PATH + +# Ensure we have a folder to store save games on the SD card. +mkdir saves + +# make a runtime dir, just incase it creates anything in CWD +mkdir runtime +cd runtime + +../bin/scummvm --fullscreen --gfx-mode=2x --config=../scummvm.config diff --git a/backends/platform/openpandora/module.mk b/backends/platform/openpandora/module.mk new file mode 100755 index 00000000000..1e5f6bcd693 --- /dev/null +++ b/backends/platform/openpandora/module.mk @@ -0,0 +1,16 @@ +MODULE := backends/platform/openpandora + +MODULE_OBJS := \ + op-graphics.o \ + op-events.o \ + op-options.o \ + op-main.o + +MODULE_DIRS += \ + backends/platform/openpandora/ + +# We don't use the rules.mk here on purpose +OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS) + +# Hack to ensure the SDL backend is built so we can use OSystem_SDL. +-include $(srcdir)/backends/platform/sdl/module.mk diff --git a/backends/platform/openpandora/op-bundle.mk b/backends/platform/openpandora/op-bundle.mk new file mode 100755 index 00000000000..163f4711ce7 --- /dev/null +++ b/backends/platform/openpandora/op-bundle.mk @@ -0,0 +1,85 @@ +# Special target to create bundles and PND's for the OpenPandora. + +#bundle_name = release/scummvm-op-`date '+%Y-%m-%d'` +bundle_name = release/scummvm-op +f=$(shell which $(STRIP)) +libloc = $(shell dirname $(f)) + +op-bundle: $(EXECUTABLE) + $(MKDIR) "$(bundle_name)" + $(MKDIR) "$(bundle_name)/scummvm" + $(MKDIR) "$(bundle_name)/scummvm/bin" + $(MKDIR) "$(bundle_name)/scummvm/data" + $(MKDIR) "$(bundle_name)/scummvm/docs" + $(MKDIR) "$(bundle_name)/scummvm/icon" + $(MKDIR) "$(bundle_name)/scummvm/lib" + + $(CP) $(srcdir)/backends/platform/openpandora/build/runscummvm.sh $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/openpandora/build/PXML.xml $(bundle_name)/scummvm/data/ + + $(CP) $(srcdir)/backends/platform/openpandora/build/icon/scummvm.png $(bundle_name)/scummvm/icon/ + $(CP) $(srcdir)/backends/platform/openpandora/build/icon/preview-pic.png $(bundle_name)/scummvm/icon/ + + + $(CP) $(srcdir)/backends/platform/openpandora/build/README-OPENPANDORA $(bundle_name)/scummvm/docs/ + $(CP) $(srcdir)/backends/platform/openpandora/build/index.html $(bundle_name)/scummvm/docs/ + + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/docs/ + + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/data/ + $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/scummvm/data/ + + $(STRIP) $(EXECUTABLE) -o $(bundle_name)/scummvm/bin/$(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)/../arm-angstrom-linux-gnueabi/usr/lib/libFLAC.so.8.2.0 $(bundle_name)/scummvm/lib/libFLAC.so.8 + tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 . + rm -R ./$(bundle_name) + +op-pnd: $(EXECUTABLE) + $(MKDIR) "$(bundle_name)" + $(MKDIR) "$(bundle_name)/scummvm" + $(MKDIR) "$(bundle_name)/scummvm/bin" + $(MKDIR) "$(bundle_name)/scummvm/data" + $(MKDIR) "$(bundle_name)/scummvm/docs" + $(MKDIR) "$(bundle_name)/scummvm/icon" + $(MKDIR) "$(bundle_name)/scummvm/lib" + + $(CP) $(srcdir)/backends/platform/openpandora/build/runscummvm.sh $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/openpandora/build/PXML.xml $(bundle_name)/scummvm/data/ + + $(CP) $(srcdir)/backends/platform/openpandora/build/icon/scummvm.png $(bundle_name)/scummvm/icon/ + $(CP) $(srcdir)/backends/platform/openpandora/build/icon/preview-pic.png $(bundle_name)/scummvm/icon/ + + + $(CP) $(srcdir)/backends/platform/openpandora/build/README-OPENPANDORA $(bundle_name)/scummvm/docs/ + $(CP) $(srcdir)/backends/platform/openpandora/build/index.html $(bundle_name)/scummvm/docs/ + + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/docs/ + + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/data/ + $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/scummvm/data/ + + $(STRIP) $(EXECUTABLE) -o $(bundle_name)/scummvm/bin/$(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)/../arm-angstrom-linux-gnueabi/usr/lib/libFLAC.so.8.2.0 $(bundle_name)/scummvm/lib/libFLAC.so.8 + + $(srcdir)/backends/platform/openpandora/build/pnd_make.sh -p $(bundle_name).pnd -d $(bundle_name)/scummvm -x $(bundle_name)/scummvm/data/PXML.xml -i $(bundle_name)/scummvm/icon/scummvm.png + + $(CP) $(srcdir)/backends/platform/openpandora/build/README-PND.txt $(bundle_name) + tar -cvjf $(bundle_name)-pnd.tar.bz2 $(bundle_name).pnd $(bundle_name)/README-PND.txt + rm -R ./$(bundle_name) +# rm $(bundle_name).pnd + +.PHONY: op-bundle op-pnd diff --git a/backends/platform/openpandora/op-events.cpp b/backends/platform/openpandora/op-events.cpp new file mode 100755 index 00000000000..24283aa8ba9 --- /dev/null +++ b/backends/platform/openpandora/op-events.cpp @@ -0,0 +1,176 @@ +/* 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$ + * + */ + +/* + * OpenPandora: Device Specific Event Handling. + * + */ + +#include "backends/platform/openpandora/op-sdl.h" +#include "backends/platform/openpandora/op-options.h" + +/* Quick default button states for modifiers. */ +int BUTTON_STATE_L = false; + +enum { + /* Touchscreen TapMode */ + TAPMODE_LEFT = 0, + TAPMODE_RIGHT = 1, + TAPMODE_HOVER = 2 +}; + +/* On the OpenPandora by default the ABXY and L/R Trigger buttons are returned by SDL as + (A): SDLK_HOME (B): SDLK_END (X): SDLK_PAGEDOWN (Y): SDLK_PAGEUP (L): SDLK_RSHIFT (R): SDLK_RCTRL +*/ + +bool OSystem_OP::handleKeyDown(SDL_Event &ev, Common::Event &event) { + switch (ev.key.keysym.sym) { + case SDLK_HOME: + event.type = Common::EVENT_LBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_END: + event.type = Common::EVENT_RBUTTONDOWN; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_PAGEDOWN: + event.type = Common::EVENT_MAINMENU; + return true; + break; + case SDLK_PAGEUP: + OP::ToggleTapMode(); + if (OP::tapmodeLevel == TAPMODE_LEFT) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Left Click"); + } else if (OP::tapmodeLevel == TAPMODE_RIGHT) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Right Click"); + } else if (OP::tapmodeLevel == TAPMODE_HOVER) { + displayMessageOnOSD("Touchscreen 'Tap Mode' - Hover (No Click)"); + } + break; + case SDLK_RSHIFT: + BUTTON_STATE_L = true; + break; + case SDLK_RCTRL: + break; + default: + return OSystem_SDL::handleKeyDown(ev, event); + break; + } + return false; +} + +bool OSystem_OP::handleKeyUp(SDL_Event &ev, Common::Event &event) { + switch (ev.key.keysym.sym) { + case SDLK_HOME: + event.type = Common::EVENT_LBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_END: + event.type = Common::EVENT_RBUTTONUP; + fillMouseEvent(event, _km.x, _km.y); + return true; + break; + case SDLK_PAGEDOWN: + event.type = Common::EVENT_MAINMENU; + return true; + break; + case SDLK_PAGEUP: + break; + case SDLK_RSHIFT: + BUTTON_STATE_L = false; + break; + case SDLK_RCTRL: + break; + default: + return OSystem_SDL::handleKeyUp(ev, event); + break; + } + return false; +} + +/* Custom handleMouseButtonDown/handleMouseButtonUp to deal with 'Tap Mode' for the touchscreen */ + +bool OSystem_OP::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { + if (ev.button.button == SDL_BUTTON_LEFT){ + if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ + event.type = Common::EVENT_RBUTTONDOWN; + else if (OP::tapmodeLevel == TAPMODE_LEFT) /* TAPMODE_LEFT = Left Click Tap Mode */ + event.type = Common::EVENT_LBUTTONDOWN; + else if (OP::tapmodeLevel == TAPMODE_RIGHT) /* TAPMODE_RIGHT = Right Click Tap Mode */ + event.type = Common::EVENT_RBUTTONDOWN; + else if (OP::tapmodeLevel == TAPMODE_HOVER) /* TAPMODE_HOVER = Hover (No Click) Tap Mode */ + event.type = Common::EVENT_MOUSEMOVE; + else + event.type = Common::EVENT_LBUTTONDOWN; /* For normal mice etc. */ + } + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONDOWN; +#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN) + else if (ev.button.button == SDL_BUTTON_WHEELUP) + event.type = Common::EVENT_WHEELUP; + else if (ev.button.button == SDL_BUTTON_WHEELDOWN) + event.type = Common::EVENT_WHEELDOWN; +#endif +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONDOWN; +#endif + else + return false; + + fillMouseEvent(event, ev.button.x, ev.button.y); + + return true; +} + +bool OSystem_OP::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { + if (ev.button.button == SDL_BUTTON_LEFT){ + if (BUTTON_STATE_L == true) /* BUTTON_STATE_L = Left Trigger Held, force Right Click */ + event.type = Common::EVENT_RBUTTONUP; + else if (OP::tapmodeLevel == TAPMODE_LEFT) /* TAPMODE_LEFT = Left Click Tap Mode */ + event.type = Common::EVENT_LBUTTONUP; + else if (OP::tapmodeLevel == TAPMODE_RIGHT) /* TAPMODE_RIGHT = Right Click Tap Mode */ + event.type = Common::EVENT_RBUTTONUP; + else if (OP::tapmodeLevel == TAPMODE_HOVER) /* TAPMODE_HOVER = Hover (No Click) Tap Mode */ + event.type = Common::EVENT_MOUSEMOVE; + else + event.type = Common::EVENT_LBUTTONUP; /* For normal mice etc. */ + } + else if (ev.button.button == SDL_BUTTON_RIGHT) + event.type = Common::EVENT_RBUTTONUP; +#if defined(SDL_BUTTON_MIDDLE) + else if (ev.button.button == SDL_BUTTON_MIDDLE) + event.type = Common::EVENT_MBUTTONUP; +#endif + else + return false; + + fillMouseEvent(event, ev.button.x, ev.button.y); + + return true; +} diff --git a/backends/platform/openpandora/op-graphics.cpp b/backends/platform/openpandora/op-graphics.cpp new file mode 100755 index 00000000000..ef95f52e994 --- /dev/null +++ b/backends/platform/openpandora/op-graphics.cpp @@ -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$ + * $Id$ + * + */ + +#include "backends/platform/openpandora/op-sdl.h" +#include "common/mutex.h" +#include "common/translation.h" +#include "common/util.h" + +#include "graphics/scaler/aspect.h" +#include "graphics/surface.h" + +bool OSystem_OP::loadGFXMode() { + /* FIXME: For now we just cheat and set the overlay to 640*480 not 800*480 and let SDL + deal with the boarders (it saves cleaning up the overlay when the game screen is + smaller than the overlay ;) + */ + _videoMode.overlayWidth = 640; + _videoMode.overlayHeight = 480; + _videoMode.fullscreen = true; + + if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) + _videoMode.aspectRatioCorrection = false; + + OSystem_SDL::loadGFXMode(); + + return true; + +} diff --git a/backends/platform/openpandora/op-main.cpp b/backends/platform/openpandora/op-main.cpp new file mode 100755 index 00000000000..4febd404c34 --- /dev/null +++ b/backends/platform/openpandora/op-main.cpp @@ -0,0 +1,265 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/scummsys.h" +#include + +#include "backends/platform/openpandora/op-sdl.h" +#include "backends/plugins/posix/posix-provider.h" +#include "base/main.h" + +#include "common/archive.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/events.h" +#include "common/util.h" + +#include "common/file.h" +#include "base/main.h" + +#include "backends/saves/default/default-saves.h" + +#include "backends/timer/default/default-timer.h" +#include "sound/mixer_intern.h" + +#include +#include +#include +#include +#include +#include +#include // for getTimeAndDate() + +/* Dump console info to files. */ +#define DUMP_STDOUT + +static SDL_Cursor *hiddenCursor; + +int main(int argc, char *argv[]) { + g_system = new OSystem_OP(); + assert(g_system); + +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); +#endif + + // Invoke the actual ScummVM main entry point: + int res = scummvm_main(argc, argv); + g_system->quit(); + + return res; +} + +static Uint32 timer_handler(Uint32 interval, void *param) { + ((DefaultTimerManager *)param)->handler(); + return interval; +} + +void OSystem_OP::initBackend() { + + assert(!_inited); + + uint8_t hiddenCursorData = 0; + + int joystick_num = ConfMan.getInt("joystick_num"); + uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; + + if (ConfMan.hasKey("disable_sdl_parachute")) + sdlFlags |= SDL_INIT_NOPARACHUTE; + + if (joystick_num > -1) + sdlFlags |= SDL_INIT_JOYSTICK; + + if (SDL_Init(sdlFlags) == -1) { + error("Could not initialize SDL: %s", SDL_GetError()); + } + + hiddenCursor = SDL_CreateCursor(&hiddenCursorData, &hiddenCursorData, 8, 1, 0, 0); + + /* Setup default save path to be workingdir/saves */ + + char savePath[PATH_MAX+1]; + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Could not obtain current working directory."); + } else { + printf("Current working directory: %s\n", workDirName); + } + + strcpy(savePath, workDirName); + strcat(savePath, "/../saves"); + printf("Current save directory: %s\n", savePath); + struct stat sb; + if (stat(savePath, &sb) == -1) + if (errno == ENOENT) // Create the dir if it does not exist + if (mkdir(savePath, 0755) != 0) + warning("mkdir for '%s' failed!", savePath); + + _savefile = new DefaultSaveFileManager(savePath); + + #ifdef DUMP_STDOUT + // The OpenPandora has a serial console on the EXT connection but most users do not use this so we + // output all our STDOUT and STDERR to files for debug purposes. + char STDOUT_FILE[PATH_MAX+1]; + char STDERR_FILE[PATH_MAX+1]; + + strcpy(STDOUT_FILE, workDirName); + strcpy(STDERR_FILE, workDirName); + strcat(STDOUT_FILE, "/scummvm.stdout.txt"); + strcat(STDERR_FILE, "/scummvm.stderr.txt"); + + // Flush the output in case anything is queued + fclose(stdout); + fclose(stderr); + + // Redirect standard input and standard output + FILE *newfp = freopen(STDOUT_FILE, "w", stdout); + if (newfp == NULL) { + #if !defined(stdout) + stdout = fopen(STDOUT_FILE, "w"); + #else + newfp = fopen(STDOUT_FILE, "w"); + if (newfp) { + *stdout = *newfp; + } + #endif + } + + newfp = freopen(STDERR_FILE, "w", stderr); + if (newfp == NULL) { + #if !defined(stderr) + stderr = fopen(STDERR_FILE, "w"); + #else + newfp = fopen(STDERR_FILE, "w"); + if (newfp) { + *stderr = *newfp; + } + #endif + } + + setbuf(stderr, NULL); + printf("%s\n", "Debug: STDOUT and STDERR redirected to text files."); + #endif /* DUMP_STDOUT */ + + /* Trigger autosave every 4 minutes. */ + ConfMan.registerDefault("autosave_period", 4 * 60); + + ConfMan.registerDefault("fullscreen", true); + + /* Make sure that aspect ratio correction is enabled on the 1st run to stop + users asking me what the 'wasted space' at the bottom is ;-). */ + ConfMan.registerDefault("aspect_ratio", true); + + /* Make sure SDL knows that we have a joystick we want to use. */ + ConfMan.setInt("joystick_num", 0); + + _graphicsMutex = createMutex(); + + /* On the OpenPandora we need to work around an SDL assumption that + returns relative mouse coordinates when you get to the screen + edges using the touchscreen. The workaround is to set a blank + SDL cursor and not disable it (Hackish I know). + + The root issues likes in the Windows Manager GRAB code in SDL. + That is why the issue is not seen on framebuffer devices like the + GP2X (there is no X window manager ;)). + */ + SDL_ShowCursor(SDL_ENABLE); + SDL_SetCursor(hiddenCursor); + + // Enable unicode support if possible + SDL_EnableUNICODE(1); + + memset(&_oldVideoMode, 0, sizeof(_oldVideoMode)); + memset(&_videoMode, 0, sizeof(_videoMode)); + memset(&_transactionDetails, 0, sizeof(_transactionDetails)); + + _videoMode.mode = GFX_DOUBLESIZE; + _videoMode.scaleFactor = 2; + _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); + _scalerProc = Normal2x; + _scalerType = 0; + + _videoMode.fullscreen = true; + + // enable joystick + if (joystick_num > -1 && SDL_NumJoysticks() > 0) { + printf("Using joystick: %s\n", SDL_JoystickName(0)); + _joystick = SDL_JoystickOpen(joystick_num); + } + + setupMixer(); + + // Note: We could implement a custom SDLTimerManager by using + // SDL_AddTimer. That might yield better timer resolution, but it would + // also change the semantics of a timer: Right now, ScummVM timers + // *never* run in parallel, due to the way they are implemented. If we + // switched to SDL_AddTimer, each timer might run in a separate thread. + // However, not all our code is prepared for that, so we can't just + // switch. Still, it's a potential future change to keep in mind. + _timer = new DefaultTimerManager(); + _timerID = SDL_AddTimer(10, &timer_handler, _timer); + + // Invoke parent implementation of this method + OSystem::initBackend(); + + _inited = true; +} + +void OSystem_OP::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + + /* Setup default extra data paths for engine data files and plugins */ + + char workDirName[PATH_MAX+1]; + + if (getcwd(workDirName, PATH_MAX) == NULL) { + error("Error: Could not obtain current working directory."); + } + + char enginedataPath[PATH_MAX+1]; + + strcpy(enginedataPath, workDirName); + strcat(enginedataPath, "/../data"); + printf("Default engine data directory: %s\n", enginedataPath); + + Common::FSNode engineNode(enginedataPath); + if (engineNode.exists() && engineNode.isDirectory()) { + s.add("__OP_ENGDATA__", new Common::FSDirectory(enginedataPath), priority); + } +} + +void OSystem_OP::quit() { + + SDL_FreeCursor(hiddenCursor); + + #ifdef DUMP_STDOUT + printf("%s\n", "Debug: STDOUT and STDERR text files closed."); + fclose(stdout); + fclose(stderr); + #endif /* DUMP_STDOUT */ + + OSystem_SDL::quit(); +} diff --git a/backends/platform/openpandora/op-options.cpp b/backends/platform/openpandora/op-options.cpp new file mode 100755 index 00000000000..f8711b868a3 --- /dev/null +++ b/backends/platform/openpandora/op-options.cpp @@ -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$ + * + */ + +/* + * OpenPandora: Options, custom code and hardware stuff. + * + */ + +#include "backends/platform/openpandora/op-options.h" + +namespace OP { + +enum { + /* Touchscreen TapMode */ + TAPMODE_LEFT = 0, + TAPMODE_RIGHT = 1, + TAPMODE_HOVER = 2 +}; + +int tapmodeLevel = TAPMODE_LEFT; + +void ToggleTapMode() { + if (tapmodeLevel == TAPMODE_LEFT) { + tapmodeLevel = TAPMODE_RIGHT; + } else if (tapmodeLevel == TAPMODE_RIGHT) { + tapmodeLevel = TAPMODE_HOVER; + } else if (tapmodeLevel == TAPMODE_HOVER) { + tapmodeLevel = TAPMODE_LEFT; + } else { + tapmodeLevel = TAPMODE_LEFT; + } +} + +} /* namespace OP */ diff --git a/engines/gob/helper.h b/backends/platform/openpandora/op-options.h old mode 100644 new mode 100755 similarity index 78% rename from engines/gob/helper.h rename to backends/platform/openpandora/op-options.h index d1f24792a5d..8c2bb1cc897 --- a/engines/gob/helper.h +++ b/backends/platform/openpandora/op-options.h @@ -23,18 +23,20 @@ * */ -#ifndef GOB_HELPER_H -#define GOB_HELPER_H +/* + * OpenPandora: Options, custom code and hardware stuff. + * + */ -namespace Gob { +#ifndef OP_OPTIONS_H +#define OP_OPTIONS_H -/** A strncpy that forces the final \0. */ -inline char *strncpy0(char *dest, const char *src, size_t n) { - strncpy(dest, src, n); - dest[n] = 0; - return dest; -} +namespace OP { -} // End of namespace Gob +extern int tapmodeLevel; -#endif // GOB_HELPER_H +extern void ToggleTapMode(); + +} /* namespace OP */ + +#endif //OP_OPTIONS_H diff --git a/backends/platform/openpandora/op-sdl.h b/backends/platform/openpandora/op-sdl.h new file mode 100755 index 00000000000..8561b424988 --- /dev/null +++ b/backends/platform/openpandora/op-sdl.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef OP_SDL_H +#define OP_SDL_H + +#include "backends/platform/sdl/sdl.h" + +#define __OPENPANDORA__ +#define MIXER_DOUBLE_BUFFERING 1 + +#ifndef PATH_MAX + #define PATH_MAX 255 +#endif + +class OSystem_OP : public OSystem_SDL { +public: + OSystem_OP() {} + + /* Events */ + bool handleKeyDown(SDL_Event &ev, Common::Event &event); + bool handleKeyUp(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonDown(SDL_Event &ev, Common::Event &event); + bool handleMouseButtonUp(SDL_Event &ev, Common::Event &event); + + /* Graphics */ + bool loadGFXMode(); + + /* Platform Setup Stuff */ + void addSysArchivesToSearchSet(Common::SearchSet &s, int priority); + void initBackend(); + void quit(); + +protected: + +}; +#endif diff --git a/backends/platform/ps2/Makefile.gdb b/backends/platform/ps2/Makefile.gdb index 53646a95465..48dcebc1d4c 100644 --- a/backends/platform/ps2/Makefile.gdb +++ b/backends/platform/ps2/Makefile.gdb @@ -51,7 +51,7 @@ INCDIR = ../../../ DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -D_EE -D__PLAYSTATION2__ -D__PS2_DEBUG__ -g -Wall -Wno-multichar -INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) +INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) INCLUDES += -I $(PS2GDB)/ee -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines TARGET = elf/scummvm.elf @@ -72,16 +72,16 @@ OBJS := backends/platform/ps2/DmaPipe.o \ backends/platform/ps2/ps2mutex.o \ backends/platform/ps2/ps2time.o \ backends/platform/ps2/ps2debug.o - + MODULE_DIRS += . BACKEND := ps2 include $(srcdir)/Makefile.common -LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile LDFLAGS += -L $(PS2GDB)/lib -L $(PS2SDK)/ee/lib -L . -LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS)) +LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS)) LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lps2gdbStub -lps2ip -ldebug -lkernel -lstdc++ all: $(TARGET) diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2 index 8c813412537..472ba5ec3a3 100644 --- a/backends/platform/ps2/Makefile.ps2 +++ b/backends/platform/ps2/Makefile.ps2 @@ -1,45 +1,22 @@ # $Header: Exp $ include $(PS2SDK)/Defs.make -PS2_EXTRA = /home/tony/GSOC/ps2/sdk-extra +PS2_EXTRA = /works/devel/ps2/sdk-extra PS2_EXTRA_INCS = /zlib/include /libmad/ee/include /SjPcm/ee/src /tremor PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /tremor/tremor -# Set to 1 to enable, 0 to disable dynamic modules -DYNAMIC_MODULES = 1 -# Set to 1 to enable, 0 to disable more detailed printing of gcc commands -VERBOSE_BUILD=0 - -# Test for dynamic plugins -ifeq ($(DYNAMIC_MODULES),1) -ENABLED = DYNAMIC_PLUGIN -DEFINES = -DDYNAMIC_MODULES -PRE_OBJS_FLAGS = -Wl,--whole-archive -POST_OBJS_FLAGS = -Wl,--no-whole-archive -else -ENABLED = STATIC_PLUGIN -endif - -#control build -DISABLE_SCALERS = true -DISABLE_HQ_SCALERS = true +ENABLED=STATIC_PLUGIN ENABLE_SCUMM = $(ENABLED) ENABLE_SCUMM_7_8 = $(ENABLED) ENABLE_HE = $(ENABLED) ENABLE_AGI = $(ENABLED) ENABLE_AGOS = $(ENABLED) -ENABLE_AGOS2 = $(ENABLED) ENABLE_CINE = $(ENABLED) ENABLE_CRUISE = $(ENABLED) -ENABLE_DRACI = $(ENABLED) ENABLE_DRASCULA = $(ENABLED) ENABLE_GOB = $(ENABLED) -ENABLE_GROOVIE = $(ENABLED) -# ENABLE_GROOVIE2 = $(ENABLED) -ENABLE_IHNM = $(ENABLED) ENABLE_KYRA = $(ENABLED) -# ENABLE_LOL = $(ENABLED) ENABLE_LURE = $(ENABLED) # ENABLE_M4 = $(ENABLED) ENABLE_MADE = $(ENABLED) @@ -47,18 +24,16 @@ ENABLE_PARALLACTION = $(ENABLED) ENABLE_QUEEN = $(ENABLED) ENABLE_SAGA = $(ENABLED) ENABLE_SAGA2 = $(ENABLED) -ENABLE_SCI = $(ENABLED) -# ENABLE_SCI32 = $(ENABLED) +ENABLE_IHNM = $(ENABLED) ENABLE_SKY = $(ENABLED) ENABLE_SWORD1 = $(ENABLED) ENABLE_SWORD2 = $(ENABLED) -ENABLE_TEENAGENT = $(ENABLED) -ENABLE_TINSEL = $(ENABLED) +# ENABLE_TINSEL = $(ENABLED) ENABLE_TOUCHE = $(ENABLED) -ENABLE_TUCKER = $(ENABLED) HAVE_GCC3 = true -CC = ee-gcc + +CC = ee-gcc CXX = ee-g++ AS = ee-gcc LD = ee-gcc @@ -67,60 +42,51 @@ RANLIB = ee-ranlib STRIP = ee-strip MKDIR = mkdir -p RM = rm -f -RM_REC = rm -rf -MODULE_DIRS = ./ srcdir = ../../.. VPATH = $(srcdir) INCDIR = ../../../ -DEPDIR = .deps +# DEPDIR = .deps + +DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar + + +INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) +INCLUDES += -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines TARGET = elf/scummvm.elf -DEFINES += -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -DDISABLE_SAVEGAME_SORTING -D_EE -D__PLAYSTATION2__ -G2 -O2 -Wall -Wno-multichar -fno-rtti -fno-exceptions -DNO_ADAPTOR -DEFINES += -DUSE_ELF_LOADER -DMIPS_TARGET -DONE_PLUGIN_AT_A_TIME - -INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) -INCLUDES += -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines - -CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP - -# Variables for dynamic plugin building -PLUGIN_PREFIX = -PLUGIN_SUFFIX = .plg -PLUGIN_EXTRA_DEPS = $(srcdir)/backends/plugins/elf/plugin.syms elf/scummvm.elf -PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -PLUGIN_LDFLAGS += -nostartfiles -Wl,-q,--just-symbols,elf/scummvm.elf,-T$(srcdir)/backends/plugins/ps2/plugin.ld,--retain-symbols-file,$(srcdir)/backends/plugins/elf/plugin.syms -lstdc++ -lc +OBJS := backends/platform/ps2/DmaPipe.o \ + backends/platform/ps2/Gs2dScreen.o \ + backends/platform/ps2/irxboot.o \ + backends/platform/ps2/ps2input.o \ + backends/platform/ps2/ps2pad.o \ + backends/platform/ps2/savefilemgr.o \ + backends/platform/ps2/fileio.o \ + backends/platform/ps2/asyncfio.o \ + backends/platform/ps2/icon.o \ + backends/platform/ps2/cd.o \ + backends/platform/ps2/eecodyvdfs.o \ + backends/platform/ps2/rpckbd.o \ + backends/platform/ps2/systemps2.o \ + backends/platform/ps2/ps2mutex.o \ + backends/platform/ps2/ps2time.o \ + backends/platform/ps2/ps2debug.o +MODULE_DIRS += . BACKEND := ps2 -LDFLAGS = -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(srcdir)/backends/plugins/ps2/main_prog.ld +include $(srcdir)/Makefile.common + +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile LDFLAGS += -L $(PS2SDK)/ee/lib -L . LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS)) -LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++ - -OBJS := $(srcdir)/backends/platform/ps2/DmaPipe.o \ - $(srcdir)/backends/platform/ps2/Gs2dScreen.o \ - $(srcdir)/backends/platform/ps2/irxboot.o \ - $(srcdir)/backends/platform/ps2/ps2input.o \ - $(srcdir)/backends/platform/ps2/ps2pad.o \ - $(srcdir)/backends/platform/ps2/savefilemgr.o \ - $(srcdir)/backends/platform/ps2/fileio.o \ - $(srcdir)/backends/platform/ps2/asyncfio.o \ - $(srcdir)/backends/platform/ps2/icon.o \ - $(srcdir)/backends/platform/ps2/cd.o \ - $(srcdir)/backends/platform/ps2/eecodyvdfs.o \ - $(srcdir)/backends/platform/ps2/rpckbd.o \ - $(srcdir)/backends/platform/ps2/systemps2.o \ - $(srcdir)/backends/platform/ps2/ps2mutex.o \ - $(srcdir)/backends/platform/ps2/ps2time.o \ - $(srcdir)/backends/platform/ps2/ps2debug.o - -include $(srcdir)/Makefile.common +LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++ +LDFLAGS += -s all: $(TARGET) $(TARGET): $(OBJS) - $(LD) $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LDFLAGS) -o $@ + $(LD) $^ $(LDFLAGS) -o $@ diff --git a/backends/platform/ps2/fileio.cpp b/backends/platform/ps2/fileio.cpp index 8c10156aaf1..826a2578e4d 100644 --- a/backends/platform/ps2/fileio.cpp +++ b/backends/platform/ps2/fileio.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/ps2/fileio.h" #include diff --git a/backends/platform/ps2/iop/CoDyVDfs/iop/imports.lst b/backends/platform/ps2/iop/CoDyVDfs/iop/imports.lst index d3ed3b0442c..eb85e044623 100644 --- a/backends/platform/ps2/iop/CoDyVDfs/iop/imports.lst +++ b/backends/platform/ps2/iop/CoDyVDfs/iop/imports.lst @@ -24,10 +24,10 @@ I_DelDrv iomanX_IMPORTS_end sifcmd_IMPORTS_start -I_sceSifInitRpc -I_sceSifSetRpcQueue -I_sceSifRegisterRpc -I_sceSifRpcLoop +I_sceSifInitRpc +I_sceSifSetRpcQueue +I_sceSifRegisterRpc +I_sceSifRpcLoop sifcmd_IMPORTS_end stdio_IMPORTS_start @@ -59,7 +59,7 @@ thbase_IMPORTS_start I_CreateThread I_StartThread I_GetThreadId -I_DelayThread +I_DelayThread thbase_IMPORTS_end diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 357404c5c49..d525a35b7d8 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include #include #include diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile index e5642008977..9f6b5c8921a 100644 --- a/backends/platform/psp/Makefile +++ b/backends/platform/psp/Makefile @@ -126,7 +126,7 @@ endif # PSP LIBS PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \ -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \ - -lpspkernel + -lpspkernel -lpspnet_inet # Add in PSPSDK includes and libraries. @@ -148,7 +148,10 @@ OBJS := powerman.o \ thread.o \ rtc.o \ mp3.o \ - tests.o + png_loader.o \ + image_viewer.o \ + tests.o \ + dummy.o BACKEND := psp @@ -200,4 +203,4 @@ SCEkxploit: $(TARGET).elf $(PSP_EBOOT_SFO) $(PACK_PBP) "%__SCE__$(TARGET)/$(PSP_EBOOT)" $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ $(PSP_EBOOT_ICON1) $(PSP_EBOOT_PIC0) $(PSP_EBOOT_PIC1) \ $(PSP_EBOOT_SND0) NULL $(PSP_EBOOT_PSAR) - + diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP index f4d5bae6d65..b83f1cab6d6 100644 --- a/backends/platform/psp/README.PSP +++ b/backends/platform/psp/README.PSP @@ -1,81 +1,130 @@ -ScummVM-PSP 1.2.0svn README +ScummVM-PSP 1.3.0svn README ============================================================================== Installation ============ - - Copy the relevant game datafiles to your memory stick (location - doesn't matter). - - Install ScummVM like any other homebrew - - Run ScummVM and use the launcher to add games and run them - + - Copy the relevant game datafiles to your memory stick (location doesn't matter). + - Install ScummVM like any other homebrew. + - Run ScummVM and use the launcher to add games and run them. + - Press Start to return to the launcher and play another game. Controls ======== - -Left trigger - ESC Right trigger - Modifier key (see below for uses) +Left trigger - ESC (Usually skips cutscenes. Depends on game) Analog - Mouse movement -Right trigger + Analog - Fine control mouse -Directions - Arrow keys -Directions + Right Trigger - Diagonal arrow keys -Triangle - Enter -Cross - Mouse button 1 -Circle - Mouse button 2 -Square - '.' (skip dialogue in some games) -Start - F5 (Main Menu) -Right trigger + Start - Return-To-Launcher menu +Right trigger + Analog - Fine mouse movement +D-Pad - Arrow keys (useful mostly in SCI and AGI games) +D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) +Triangle - Enter (useful for some dialogs) +Cross - Left Mouse Button (usually the main button) +Circle - Right Mouse Button (secondary button in some games) +Square - '.' (skip dialogue in some games e.g. Scumm) +Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) +Right trigger + Start - F5 (Main Menu in some games) +Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). +Right trigger + Select - Show Image Viewer (see below) +Start - Global Menu. Allows you to 'Return To Launcher' to play another game -Virtual Keyboard -================ +Virtual Keyboard Mode +===================== +Start - Enter key. Also exits virtual keyboard mode +Select - Exit the virtual keyboard mode +Right trigger - Input letters: lowercase/uppercase (press to toggle) +Left trigger - Input numbers/symbols (press to toggle) +D-Pad - Select square of characters (up, down, left or right) +Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen + by the button in the corresponding position. The 2 top characters are chosen by the + triggers. +Analog - Moves in a direction (left/right/up/down) (Useful to keep moving + while typing in AGI games among other things) -Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen. -Start - Enter -Right trigger - Switch to/between letter modes -Left trigger - Switch to/between numbers and symbols -D-Pad - Select square of characters -Buttons/Triggers - Choose a specific character +Image Viewer +============ +For your convenience, I've included a simple image viewer in the PSP port. +You can view anything you want while playing a game. +There are a few simple rules to follow: + +- Images must be of PNG format. If you have images in another format, many + graphics utilities will convert them for you. +- Images must be named psp_image1.png, psp_image2.png etc. This is to make + sure there's no possible conflict between image files and game files. +- Images must be placed in the game directories. When using the image viewer, + only the images of the particular game being played will be available for viewing. +- Don't place any images in the ScummVM directory, or you won't be able to see + the images in the game directories. +- There's no guarantee that you'll be able to view your image. This is because + big images take a lot of memory (more than the size of the image on disk). If there + isn't enough memory left to show the image, ScummVM will tell you so. Try to make the + image smaller by either shrinking it or reducing the colors to 256 color palette mode. + +Image Viewer Controls: +===================== +Left/Right - previous/next image (e.g. go from psp_image1.png to psp_image2.png) +Up/down - zoom in/out +Analog - move around the image +Triggers, Start: - exit image viewer + + +1st Person Game Mode (Can be ignored by most users) +==================== +This is a special mode built for 1st person games like Lands of Lore. If you don't have these games you can +safely ignore this mode. To enter or leave this mode, use the combo: + +Right Trigger + Left Trigger + Square + +Some buttons have been switched around to make these games more playable: +Square - Is the modifier key instead of Right Trigger. +Left/Right Trigger - Strafe left/right +D-Pad Left/Right - Turn left/right +Square + D-Pad - F1/F2/F3/F4 +Square + Select - Image Viewer +Square + Start - Esc (shows game menu) + + + + Notes ===== +- Notice that you can switch between games! This is much faster than quitting + and having to start ScummVM all over again. Go to the global menu and choose 'Return To Launcher'. + (Some games may not have the Return To Launcher option available yet.) -- Plugin files are NOT interchangeable between versions! You must copy ALL the - plugin files that come with every version of scummvm. They sit in the /plugin +- The PSP version of ScummVM uses the Media Engine to accelerate decoding of MP3 files. This means + that if you have the choice of compressing using Ogg files or MP3 files, choose MP3 -- the game + will generally run faster. + +- Plugin files are NOT interchangeable between ScummVM versions! You must copy ALL the + plugin files that come with every version of ScummVM. They sit in the /plugin subdirectory. If you get a crash upon startup, try deleting all the existing plugin files in the plugin directory and copying the new ones over again. -- While it's possible to compress certain game resources to reduce their size, - this can (and usually will) cause games (especially animation) to be choppy - sometimes, as it ofcourse needs extra CPU power to decode these files. - As such, it is recommended to play games in their original, uncompressed, - form whenever possible. - - This README may be outdated, for more up-to-date instructions and notes see the PSP Port Wiki: http://wiki.scummvm.org/index.php/PlayStation_Portable Frequently Asked Questions ========================== -Q: Pressing select doesn't make the virtual keyboard show up on screen! -A: You need to make sure that the kbd.zip file is in the same directory as the scummvm executable. - Q: Scummvm crashes upon starting up! A: See the first note above. +Q: Pressing select doesn't make the virtual keyboard show up on screen! +A: You need to make sure that the kbd.zip file is in the same directory as the ScummVM executable. + Q: What do I need to run the games? -A: A 1.00 or 1.50 firmware PSP (or an EBOOT loader on firmware 2.00 or - higher), and the necessary datafiles for the game you want to play and - obviously this ScummVM port. +A: A PSP that can run homebrew and the necessary datafiles for the game you want to play. Q: Can I run game X with this? A: You can find the list of supported games on the compatibility page - on http://www.scummvm.org. - Note that ScummVM is NOT a 'DOS (game) emulator', but written - specifically for certain games/engines. + at http://www.scummvm.org + Note that ScummVM is NOT an emulator. The supported games engines have been painstakingly rewritten. + It's not easy to add support for a game you want that currently isn't supported. Q: My Monkey Island 1 doesn't have any music, what gives? A: If your version of Monkey Island came on a CD then it has the music - as CD Audio tracks. You need to rip those to MP3/Ogg and copy them - to the same directory as the game datafiles for music to work. + as CD Audio tracks. You need to rip those to MP3/Ogg (MP3 is preferred), naming them track1.mp3 track2.mp3 + etc. and copy them to the same directory as the game datafiles for music to work. Q: Game X crashes, or feature Y doesn't work. Can you fix this? A: Possibly. @@ -83,21 +132,23 @@ A: Possibly. played them all start-to-finish on the PSP, so it's possible there are bugs or issues that we're not aware of. When you encounter such a bug, please use the "Bug Tracker" you find linked - on the ScummVM website, and mention all relevant info (i.e. that you're + on the ScummVM website, and mention all relevant info i.e. that you're using the PSP version, which ScummVM version it is, if the problem exists - in a recent PC SVN version, a detailed description of the problem, - and if at all possible a nearby savegame), this will make it much easier + in a recent PC version, a detailed description of the problem, + and if at all possible a nearby savegame. This will make it much easier for us to reproduce (and hopefully fix) the problem. Building the source code ======================== To build ScummVM for PSP you need: +- ScummVM source code (svn co https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk) + - PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) - PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) - Note: This usually gets installed by the PSP toolchain, - so you don't have to do it manually. + Note: This usually gets installed by the PSP toolchain, + so you don't have to do it manually. - zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) @@ -107,21 +158,15 @@ To build ScummVM for PSP you need: - libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) - - (*) = optional -When you've installed these libraries (read their README.PSP for instructions), -type "make" in the backends/platform/psp directory to build a 1.00 firmware -EBOOT.PBP, or "make kxploit" to build the 1.50/kxploit EBOOT.PBPs - -You can control most of the build process (engines and libraries used) from -the Makefile. - +Once you've installed these libraries (read their README.PSP for instructions), +create a subdirectory in your ScummVM folder called 'builds/psp'. Then, in this folder, type +'../../configure --host=psp --enable-plugins --default-dynamic'. If everything is installed +correctly, ScummVM will inform you as it finds the right components. Finally type 'make' to build. Port Authors ============ - Joost Peters (joostp@scummvm.org) Paolo Costabel (paoloc@pacbell.net) Thomas Mayer (tommybear@internode.on.net) diff --git a/backends/platform/psp/README.PSP.in b/backends/platform/psp/README.PSP.in index 2d53fd3b47f..57058abd854 100644 --- a/backends/platform/psp/README.PSP.in +++ b/backends/platform/psp/README.PSP.in @@ -3,79 +3,95 @@ ScummVM-PSP @VERSION@ README Installation ============ - - Copy the relevant game datafiles to your memory stick (location - doesn't matter). - - Install ScummVM like any other homebrew - - Run ScummVM and use the launcher to add games and run them - + - Copy the relevant game datafiles to your memory stick (location doesn't matter). + - Install ScummVM like any other homebrew. + - Run ScummVM and use the launcher to add games and run them. Controls ======== - -Left trigger - ESC Right trigger - Modifier key (see below for uses) +Left trigger - ESC (Usually skips cutscenes. Depends on game) Analog - Mouse movement -Right trigger + Analog - Fine control mouse -Directions - Arrow keys -Directions + Right Trigger - Diagonal arrow keys -Triangle - Enter -Cross - Mouse button 1 -Circle - Mouse button 2 -Square - '.' (skip dialogue in some games) -Start - F5 (Main Menu) -Right trigger + Start - Return-To-Launcher menu +Right trigger + Analog - Fine mouse movement +D-Pad - Arrow keys (useful mostly in SCI and AGI games) +D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) +Triangle - Enter (useful for some dialogs) +Cross - Left Mouse Button (usually the main button) +Circle - Right Mouse Button (secondary button in some games) +Square - '.' (skip dialogue in some games e.g. Scumm) +Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) +Start - Global Menu. Allows you to 'Return To Launcher' to play another game +Right trigger + Start - F5 (Main Menu in some games) +Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). -Virtual Keyboard -================ +Virtual Keyboard Mode +===================== +Start - Enter key. Also exits virtual keyboard mode +Select - Exit the virtual keyboard mode +Right trigger - Input letters: lowercase/uppercase (press to toggle) +Left trigger - Input numbers/symbols (press to toggle) +D-Pad - Select square of characters (up, down, left or right) +Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen + by the button in the corresponding position. The 2 top characters are chosen by the + triggers. +Analog - Moves in a direction (left/right/up/down) (Useful to keep moving + while typing in AGI games among other things) + +1st Person Game Mode (Can be ignored by most users) +==================== +This is a special mode built for 1st person games like Lands of Lore. If you don't have these games you can +safely ignore this mode. To enter or leave this mode, use the combo: + +Right Trigger + Left Trigger + Square + +Some buttons have been switched around to make these games more playable: +Square - Is the modifier key instead of Right Trigger. +Left/Right Trigger - Strafe left/right +D-Pad Left/Right - Turn left/right +Square + D-Pad - F1/F2/F3/F4 +Square + Start - Esc (shows game menu) -Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen. -Start - Enter -Right trigger - Switch to/between letter modes -Left trigger - Switch to/between numbers and symbols -D-Pad - Select square of characters -Buttons/Triggers - Choose a specific character Notes ===== +- Notice that you can switch between games! This is much faster than quitting + and having to start ScummVM all over again. Go to the global menu and choose 'Return To Launcher'. + (Some games may not have the Return To Launcher option available yet.) -- Plugin files are NOT interchangeable between versions! You must copy ALL the - plugin files that come with every version of scummvm. They sit in the /plugin +- The PSP version of ScummVM uses the Media Engine to accelerate decoding of MP3 files. This means + that if you have the choice of compressing using Ogg files or MP3 files, choose MP3 -- the game + will generally run faster. + +- Plugin files are NOT interchangeable between ScummVM versions! You must copy ALL the + plugin files that come with every version of ScummVM. They sit in the /plugin subdirectory. If you get a crash upon startup, try deleting all the existing plugin files in the plugin directory and copying the new ones over again. -- While it's possible to compress certain game resources to reduce their size, - this can (and usually will) cause games (especially animation) to be choppy - sometimes, as it ofcourse needs extra CPU power to decode these files. - As such, it is recommended to play games in their original, uncompressed, - form whenever possible. - - This README may be outdated, for more up-to-date instructions and notes see the PSP Port Wiki: http://wiki.scummvm.org/index.php/PlayStation_Portable Frequently Asked Questions ========================== -Q: Pressing select doesn't make the virtual keyboard show up on screen! -A: You need to make sure that the kbd.zip file is in the same directory as the scummvm executable. - Q: Scummvm crashes upon starting up! A: See the first note above. +Q: Pressing select doesn't make the virtual keyboard show up on screen! +A: You need to make sure that the kbd.zip file is in the same directory as the ScummVM executable. + Q: What do I need to run the games? -A: A 1.00 or 1.50 firmware PSP (or an EBOOT loader on firmware 2.00 or - higher), and the necessary datafiles for the game you want to play and - obviously this ScummVM port. +A: A PSP that can run homebrew and the necessary datafiles for the game you want to play. Q: Can I run game X with this? A: You can find the list of supported games on the compatibility page - on http://www.scummvm.org. - Note that ScummVM is NOT a 'DOS (game) emulator', but written - specifically for certain games/engines. + at http://www.scummvm.org + Note that ScummVM is NOT an emulator. The supported games engines have been painstakingly rewritten. + It's not easy to add support for a game you want that currently isn't supported. Q: My Monkey Island 1 doesn't have any music, what gives? A: If your version of Monkey Island came on a CD then it has the music - as CD Audio tracks. You need to rip those to MP3/Ogg and copy them - to the same directory as the game datafiles for music to work. + as CD Audio tracks. You need to rip those to MP3/Ogg (MP3 is preferred), naming them track1.mp3 track2.mp3 + etc. and copy them to the same directory as the game datafiles for music to work. Q: Game X crashes, or feature Y doesn't work. Can you fix this? A: Possibly. @@ -83,21 +99,23 @@ A: Possibly. played them all start-to-finish on the PSP, so it's possible there are bugs or issues that we're not aware of. When you encounter such a bug, please use the "Bug Tracker" you find linked - on the ScummVM website, and mention all relevant info (i.e. that you're + on the ScummVM website, and mention all relevant info i.e. that you're using the PSP version, which ScummVM version it is, if the problem exists - in a recent PC SVN version, a detailed description of the problem, - and if at all possible a nearby savegame), this will make it much easier + in a recent PC version, a detailed description of the problem, + and if at all possible a nearby savegame. This will make it much easier for us to reproduce (and hopefully fix) the problem. Building the source code ======================== To build ScummVM for PSP you need: +- ScummVM source code (svn co https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk) + - PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) - PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) - Note: This usually gets installed by the PSP toolchain, - so you don't have to do it manually. + Note: This usually gets installed by the PSP toolchain, + so you don't have to do it manually. - zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) @@ -107,21 +125,15 @@ To build ScummVM for PSP you need: - libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) - - (*) = optional -When you've installed these libraries (read their README.PSP for instructions), -type "make" in the backends/platform/psp directory to build a 1.00 firmware -EBOOT.PBP, or "make kxploit" to build the 1.50/kxploit EBOOT.PBPs - -You can control most of the build process (engines and libraries used) from -the Makefile. - +Once you've installed these libraries (read their README.PSP for instructions), +create a subdirectory in your ScummVM folder called 'builds/psp'. Then, in this folder, type +'../../configure --host=psp --enable-plugins --default-dynamic'. If everything is installed +correctly, ScummVM will inform you as it finds the right components. Finally type 'make' to build. Port Authors ============ - Joost Peters (joostp@scummvm.org) Paolo Costabel (paoloc@pacbell.net) Thomas Mayer (tommybear@internode.on.net) diff --git a/backends/platform/psp/audio.cpp b/backends/platform/psp/audio.cpp index 14691befeec..b5a72dccd02 100644 --- a/backends/platform/psp/audio.cpp +++ b/backends/platform/psp/audio.cpp @@ -23,10 +23,10 @@ * */ -#include +#include #include - -#include "common/scummsys.h" + +#include "common/scummsys.h" #include "backends/platform/psp/audio.h" //#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ @@ -39,37 +39,37 @@ bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, call if (_init) { PSP_ERROR("audio device already initialized\n"); return true; - } + } - PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n", + PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n", freq, numOfChannels, numOfSamples, callback, (uint32)userData); - + numOfSamples = PSP_AUDIO_SAMPLE_ALIGN(numOfSamples); uint32 bufLen = numOfSamples * numOfChannels * NUM_BUFFERS * sizeof(uint16); - + PSP_DEBUG_PRINT("total buffer size[%d]\n", bufLen); - + _buffers[0] = (byte *)memalign(64, bufLen); if (!_buffers[0]) { PSP_ERROR("failed to allocate memory for audio buffers\n"); return false; } memset(_buffers[0], 0, bufLen); // clean the buffer - + // Fill in the rest of the buffer pointers byte *pBuffer = _buffers[0]; for (int i = 1; i < NUM_BUFFERS; i++) { pBuffer += numOfSamples * numOfChannels * sizeof(uint16); _buffers[i] = pBuffer; } - + // Reserve a HW channel for our audio _pspChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, numOfSamples, numOfChannels == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO); if (_pspChannel < 0) { PSP_ERROR("failed to reserve audio channel\n"); return false; } - + PSP_DEBUG_PRINT("reserved channel[%d] for audio\n", _pspChannel); // Save our data @@ -80,17 +80,17 @@ bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, call _userData = userData; _bufferToFill = 0; _bufferToPlay = 0; - + _init = true; _paused = true; // start in paused mode - + threadCreateAndStart("audioThread", PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD); // start the consumer thread - + return true; } // The real thread function -void PspAudio::threadFunction() { +void PspAudio::threadFunction() { assert(_callback); PSP_DEBUG_PRINT_FUNC("audio thread started\n"); @@ -108,12 +108,12 @@ void PspAudio::threadFunction() { PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill); _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data nextBuffer(_bufferToFill); - + PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay); playBuffer(); nextBuffer(_bufferToPlay); } // while _init - + // destroy everything free(_buffers[0]); sceAudioChRelease(_pspChannel); @@ -136,7 +136,7 @@ inline bool PspAudio::playBuffer() { ret = sceAudioOutputBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]); else ret = sceAudioOutputPannedBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]); - + if (ret < 0) { PSP_ERROR("failed to output audio. Error[%d]\n", ret); return false; @@ -146,5 +146,5 @@ inline bool PspAudio::playBuffer() { void PspAudio::close() { PSP_DEBUG_PRINT("close has been called ***************\n"); - _init = false; + _init = false; } diff --git a/backends/platform/psp/audio.h b/backends/platform/psp/audio.h index 07f70cec7da..f5179028dc5 100644 --- a/backends/platform/psp/audio.h +++ b/backends/platform/psp/audio.h @@ -35,9 +35,9 @@ public: FREQUENCY = 44100 /* only frequency we allow */ }; typedef void (* callbackFunc)(void *userData, byte *samples, int len); // audio callback to call - PspAudio() : _pspChannel(0), - _numOfChannels(0), _numOfSamples(0), _callback(0), - _bufferToPlay(0), _bufferToFill(0), + PspAudio() : _pspChannel(0), + _numOfChannels(0), _numOfSamples(0), _callback(0), + _bufferToPlay(0), _bufferToFill(0), _init(false), _paused(true) { for (int i=0; i textureDimension && textureDimension < 512) + textureDimension <<= 1; - PSP_DEBUG_PRINT("power of 2 = %u\n", textureDimension); + PSP_DEBUG_PRINT("size[%u]. power of 2[%u]\n", size, textureDimension); return textureDimension; } @@ -539,51 +539,41 @@ void GuRenderer::render() { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT("Buffer[%p] Palette[%p]\n", _buffer->getPixels(), _palette->getRawValues()); - setMaxTextureOffsetByIndex(0, 0); - guProgramDrawBehavior(); if (_buffer->hasPalette()) guLoadPalette(); guProgramTextureFormat(); - guLoadTexture(); - Vertex *vertices = guGetVertices(); - fillVertices(vertices); + // Loop over patches of 512x512 pixel textures and draw them + for (uint32 j = 0; j < _buffer->getSourceHeight(); j += 512) { + _textureLoadOffset.y = j; + + for (uint32 i = 0; i < _buffer->getSourceWidth(); i += 512) { + _textureLoadOffset.x = i; + + guLoadTexture(); + Vertex *vertices = guGetVertices(); + fillVertices(vertices); - guDrawVertices(vertices); - - if (_buffer->getSourceWidth() > 512) { - setMaxTextureOffsetByIndex(1, 0); - - guLoadTexture(); - - vertices = guGetVertices(); - fillVertices(vertices); - - guDrawVertices(vertices); + guDrawVertices(vertices); + } } } -inline void GuRenderer::setMaxTextureOffsetByIndex(uint32 x, uint32 y) { - DEBUG_ENTER_FUNC(); - const uint32 maxTextureSizeShift = 9; /* corresponds to 512 = max texture size*/ - - _maxTextureOffset.x = x << maxTextureSizeShift; /* x times 512 */ - _maxTextureOffset.y = y << maxTextureSizeShift; /* y times 512 */ -} - inline void GuRenderer::guProgramDrawBehavior() { DEBUG_ENTER_FUNC(); - PSP_DEBUG_PRINT("blending[%s] colorTest[%s] reverseAlpha[%s] keyColor[%u]\n", _blending ? "on" : "off", _colorTest ? "on" : "off", _alphaReverse ? "on" : "off", _keyColor); + PSP_DEBUG_PRINT("blending[%s] colorTest[%s] reverseAlpha[%s] keyColor[%u]\n", + _blending ? "on" : "off", _colorTest ? "on" : "off", + _alphaReverse ? "on" : "off", _keyColor); if (_blending) { sceGuEnable(GU_BLEND); - if (_alphaReverse) // Reverse the alpha value (0 is 1) + if (_alphaReverse) // Reverse the alpha value (ie. 0 is 1) easier to do in some cases sceGuBlendFunc(GU_ADD, GU_ONE_MINUS_SRC_ALPHA, GU_SRC_ALPHA, 0, 0); - else // Normal alpha values + else // Normal alpha values sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); } else @@ -591,7 +581,9 @@ inline void GuRenderer::guProgramDrawBehavior() { if (_colorTest) { sceGuEnable(GU_COLOR_TEST); - sceGuColorFunc(GU_NOTEQUAL, _keyColor, 0x00ffffff); + sceGuColorFunc(GU_NOTEQUAL, // show only colors not equal to this color + _keyColor, + 0x00ffffff); // match everything but alpha } else sceGuDisable(GU_COLOR_TEST); } @@ -612,7 +604,8 @@ inline void GuRenderer::guLoadPalette() { PSP_DEBUG_PRINT("bpp[%d], pixelformat[%d], mask[%x]\n", _buffer->getBitsPerPixel(), _palette->getPixelFormat(), mask); sceGuClutMode(convertToGuPixelFormat(_palette->getPixelFormat()), 0, mask, 0); - sceGuClutLoad(_palette->getNumOfEntries() >> 3, _palette->getRawValues()); + sceGuClutLoad(_palette->getNumOfEntries() >> 3, // it's in batches of 8 for some reason + _palette->getRawValues()); } inline void GuRenderer::guProgramTextureFormat() { @@ -658,7 +651,17 @@ inline uint32 GuRenderer::convertToGuPixelFormat(PSPPixelFormat::Type format) { inline void GuRenderer::guLoadTexture() { DEBUG_ENTER_FUNC(); - sceGuTexImage(0, _buffer->getTextureWidth(), _buffer->getTextureHeight(), _buffer->getWidth(), _buffer->getPixels() + _buffer->_pixelFormat.pixelsToBytes(_maxTextureOffset.x)); + byte *startPoint = _buffer->getPixels(); + if (_textureLoadOffset.x) + startPoint += _buffer->_pixelFormat.pixelsToBytes(_textureLoadOffset.x); + if (_textureLoadOffset.y) + startPoint += _buffer->getWidthInBytes() * _textureLoadOffset.y; + + sceGuTexImage(0, + _buffer->getTextureWidth(), // texture width (must be power of 2) + _buffer->getTextureHeight(), // texture height (must be power of 2) + _buffer->getWidth(), // width of a line of the image (to get to the next line) + startPoint); // where to start reading } inline Vertex *GuRenderer::guGetVertices() { @@ -676,40 +679,40 @@ void GuRenderer::fillVertices(Vertex *vertices) { uint32 outputWidth = _displayManager->getOutputWidth(); uint32 outputHeight = _displayManager->getOutputHeight(); - float textureStartX, textureStartY, textureEndX, textureEndY; - // Texture adjustments for eliminating half-pixel artifacts from scaling // Not necessary if we don't scale - float textureAdjustment = 0.0f; + float textureFix = 0.0f; if (_useGlobalScaler && - (_displayManager->getScaleX() != 1.0f || _displayManager->getScaleX() != 1.0f)) - textureAdjustment = 0.5f; - - textureStartX = textureAdjustment + _offsetInBuffer.x; //debug - textureStartY = textureAdjustment + _offsetInBuffer.y; - // We subtract maxTextureOffset because our shifted texture starts at 512 and will go to 640 - textureEndX = _offsetInBuffer.x + _drawSize.width - textureAdjustment - _maxTextureOffset.x; - textureEndY = _offsetInBuffer.y + _drawSize.height - textureAdjustment; + (_displayManager->getScaleX() != 1.0f || _displayManager->getScaleY() != 1.0f)) + textureFix = 0.5f; + // These coordinates describe an area within the texture. ie. we already loaded a square of texture, + // now the coordinates within it are 0 to the edge of the area of the texture we want to draw + float textureStartX = textureFix + _offsetInBuffer.x; + float textureStartY = textureFix + _offsetInBuffer.y; + // even when we draw one of several textures, we use the whole drawsize of the image. The GU + // will draw what it can with the texture it has and scale it properly for us. + float textureEndX = -textureFix + _offsetInBuffer.x + _drawSize.width - _textureLoadOffset.x; + float textureEndY = -textureFix + _offsetInBuffer.y + _drawSize.height - _textureLoadOffset.y; // For scaling to the final image size, calculate the gaps on both sides uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0; uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0; // Save scaled offset on screen - float scaledOffsetOnScreenX = scaleSourceToOutputX(_offsetOnScreen.x); - float scaledOffsetOnScreenY = scaleSourceToOutputY(_offsetOnScreen.y); + float scaledOffsetOnScreenX = scaleSourceToOutput(true, _offsetOnScreen.x); + float scaledOffsetOnScreenY = scaleSourceToOutput(false, _offsetOnScreen.y); + + float imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutput(true, stretch(true, _textureLoadOffset.x))); + float imageStartY = gapY + scaledOffsetOnScreenY + (scaleSourceToOutput(false, stretch(false, _textureLoadOffset.y))); + + float imageEndX, imageEndY; - float imageStartX, imageStartY, imageEndX, imageEndY; - - imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutputX(_maxTextureOffset.x)); - imageStartY = gapY + scaledOffsetOnScreenY; - if (_fullScreen) { // shortcut - imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX; + imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX; imageEndY = PSP_SCREEN_HEIGHT - gapY + scaledOffsetOnScreenY; // needed for screen shake } else { /* !fullScreen */ - imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width); - imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height); + imageEndX = gapX + scaledOffsetOnScreenX + scaleSourceToOutput(true, stretch(true, _drawSize.width)); + imageEndY = gapY + scaledOffsetOnScreenY + scaleSourceToOutput(false, stretch(false, _drawSize.height)); } vertices[0].u = textureStartX; @@ -728,8 +731,8 @@ void GuRenderer::fillVertices(Vertex *vertices) { PSP_DEBUG_PRINT("ImageStart: X[%f] Y[%f] ImageEnd: X[%.1f] Y[%.1f]\n", imageStartX, imageStartY, imageEndX, imageEndY); } -/* Scale the input X offset to appear in proper position on the screen */ -inline float GuRenderer::scaleSourceToOutputX(float offset) { +/* Scale the input X/Y offset to appear in proper position on the screen */ +inline float GuRenderer::scaleSourceToOutput(bool x, float offset) { float result; if (!_useGlobalScaler) @@ -737,28 +740,22 @@ inline float GuRenderer::scaleSourceToOutputX(float offset) { else if (!offset) result = 0.0f; else - result = offset * _displayManager->getScaleX(); + result = x ? offset * _displayManager->getScaleX() : offset * _displayManager->getScaleY(); return result; } -/* Scale the input Y offset to appear in proper position on the screen */ -inline float GuRenderer::scaleSourceToOutputY(float offset) { - float result; - - if (!_useGlobalScaler) - result = offset; - else if (!offset) - result = 0.0f; - else - result = offset * _displayManager->getScaleY(); - - return result; +/* Scale the input X/Y offset to appear in proper position on the screen */ +inline float GuRenderer::stretch(bool x, float size) { + if (!_stretch) + return size; + return (x ? size * _stretchX : size * _stretchY); } inline void GuRenderer::guDrawVertices(Vertex *vertices) { DEBUG_ENTER_FUNC(); + // This function shouldn't need changing. The '32' here refers to floating point vertices. sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2, 0, vertices); } diff --git a/backends/platform/psp/display_client.h b/backends/platform/psp/display_client.h index d05b0b046c2..005fc76c7c4 100644 --- a/backends/platform/psp/display_client.h +++ b/backends/platform/psp/display_client.h @@ -30,6 +30,7 @@ #include "graphics/surface.h" #include "common/system.h" #include "backends/platform/psp/memory.h" +#include "backends/platform/psp/psppixelformat.h" #define MAX_TEXTURE_SIZE 512 @@ -173,8 +174,13 @@ protected: class GuRenderer { public: // Constructors - GuRenderer() : _useGlobalScaler(false), _buffer(0), _palette(0), _blending(false), _alphaReverse(false), _colorTest(false), _keyColor(0), _fullScreen(false) {} - GuRenderer(Buffer *buffer, Palette *palette) : _useGlobalScaler(false), _buffer(buffer), _palette(palette), _blending(false), _alphaReverse(false), _colorTest(false), _keyColor(0), _fullScreen(false) {} + GuRenderer() : _useGlobalScaler(false), _buffer(0), _palette(0), + _blending(false), _alphaReverse(false), _colorTest(false), + _keyColor(0), _fullScreen(false), _stretch(false), _stretchX(1.0f), _stretchY(1.0f) {} + GuRenderer(Buffer *buffer, Palette *palette) : + _useGlobalScaler(false), _buffer(buffer), _palette(palette), + _blending(false), _alphaReverse(false), _colorTest(false), + _keyColor(0), _fullScreen(false), _stretch(false), _stretchX(1.0f), _stretchY(1.0f) {} static void setDisplayManager(DisplayManager *dm) { _displayManager = dm; } // Called by the Display Manager // Setters @@ -189,8 +195,7 @@ public: } void setBuffer(Buffer *buffer) { _buffer = buffer; } void setPalette(Palette *palette) { _palette = palette; } - void setMaxTextureOffsetByIndex(uint32 x, uint32 y); // For drawing multiple textures - void setOffsetOnScreen(uint32 x, uint32 y) { _offsetOnScreen.x = x; _offsetOnScreen.y = y; } + void setOffsetOnScreen(int x, int y) { _offsetOnScreen.x = x; _offsetOnScreen.y = y; } void setOffsetInBuffer(uint32 x, uint32 y) { _offsetInBuffer.x = x; _offsetInBuffer.y = y; } void setColorTest(bool value) { _colorTest = value; } void setKeyColor(uint32 value) { _keyColor = _buffer->_pixelFormat.convertTo32BitColor(value); } @@ -198,6 +203,8 @@ public: void setAlphaReverse(bool value) { _alphaReverse = value; } void setFullScreen(bool value) { _fullScreen = value; } // Shortcut for rendering void setUseGlobalScaler(bool value) { _useGlobalScaler = value; } // Scale to screen + void setStretch(bool active) { _stretch = active; } + void setStretchXY(float x, float y) { _stretchX = x; _stretchY = y; } static void cacheInvalidate(void *pointer, uint32 size); @@ -215,11 +222,11 @@ protected: void guDrawVertices(Vertex *vertices); uint32 convertToGuPixelFormat(PSPPixelFormat::Type format); - float scaleSourceToOutputX(float offset); - float scaleSourceToOutputY(float offset); + float scaleSourceToOutput(bool x, float offset); + float stretch(bool x, float size); friend class MasterGuRenderer; - Point _maxTextureOffset; ///> For rendering textures > 512 pixels + Point _textureLoadOffset; ///> For rendering textures > 512 pixels Point _offsetOnScreen; ///> Where on screen to draw Point _offsetInBuffer; ///> Where in the texture to draw bool _useGlobalScaler; ///> Scale to the output size on screen @@ -232,6 +239,8 @@ protected: bool _colorTest; uint32 _keyColor; ///> Color to test against for color test. in 32 bits. bool _fullScreen; ///> Speeds up for fullscreen rendering + bool _stretch; ///> Whether zooming is activated + float _stretchX, _stretchY; }; #endif /* PSP_SCREEN_H */ diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp index e65d6f4fd01..7454211da63 100644 --- a/backends/platform/psp/display_manager.cpp +++ b/backends/platform/psp/display_manager.cpp @@ -34,6 +34,7 @@ #include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/cursor.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/image_viewer.h" #define USE_DISPLAY_CALLBACK // to use callback for finishing the render #include "backends/platform/psp/display_manager.h" @@ -59,28 +60,93 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = { {0, 0, 0} }; + +// Class VramAllocator ----------------------------------- + +DECLARE_SINGLETON(VramAllocator) + +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" + + +void *VramAllocator::allocate(int32 size, bool smallAllocation /* = false */) { + DEBUG_ENTER_FUNC(); + assert(size > 0); + + byte *lastAddress = smallAllocation ? (byte *)VRAM_SMALL_ADDRESS : (byte *)VRAM_START_ADDRESS; + Common::List::iterator i; + + // Find a block that fits, starting from the beginning + for (i = _allocList.begin(); i != _allocList.end(); ++i) { + byte *currAddress = (*i).address; + + if (currAddress - lastAddress >= size) // We found a match + break; + + if ((*i).getEnd() > lastAddress) + lastAddress = (byte *)(*i).getEnd(); + } + + if (lastAddress + size > (byte *)VRAM_END_ADDRESS) { + PSP_DEBUG_PRINT("No space for allocation of %d bytes. %d bytes already allocated.\n", + size, _bytesAllocated); + return NULL; + } + + _allocList.insert(i, Allocation(lastAddress, size)); + _bytesAllocated += size; + + PSP_DEBUG_PRINT("Allocated in VRAM, size %u at %p.\n", size, lastAddress); + PSP_DEBUG_PRINT("Total allocated %u, remaining %u.\n", _bytesAllocated, (2 * 1024 * 1024) - _bytesAllocated); + + return lastAddress; +} + +// Deallocate a block from VRAM +void VramAllocator::deallocate(void *address) { + DEBUG_ENTER_FUNC(); + address = (byte *)CACHED(address); // Make sure all addresses are the same + + Common::List::iterator i; + + // Find the Allocator to deallocate + for (i = _allocList.begin(); i != _allocList.end(); ++i) { + if ((*i).address == address) { + _bytesAllocated -= (*i).size; + _allocList.erase(i); + PSP_DEBUG_PRINT("Deallocated address[%p], size[%u]\n", (*i).address, (*i).size); + return; + } + } + + PSP_DEBUG_PRINT("Address[%p] not allocated.\n", address); +} + + // Class MasterGuRenderer ---------------------------------------------- void MasterGuRenderer::setupCallbackThread() { DEBUG_ENTER_FUNC(); - + // start the thread that updates the display - threadCreateAndStart("DisplayCbThread", PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD); + threadCreateAndStart("DisplayCbThread", PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD); } // this function gets called by PspThread when starting the new thread void MasterGuRenderer::threadFunction() { DEBUG_ENTER_FUNC(); - + // Create the callback. It should always get the pointer to MasterGuRenderer _callbackId = sceKernelCreateCallback("Display Callback", guCallback, this); if (_callbackId < 0) { - PSP_ERROR("failed to create display callback\n"); + PSP_ERROR("failed to create display callback\n"); } - + PSP_DEBUG_PRINT("created callback. Going to sleep\n"); - sceKernelSleepThreadCB(); // sleep until we get a callback + sceKernelSleepThreadCB(); // sleep until we get a callback } // This callback is called when the render is finished. It swaps the buffers @@ -88,12 +154,12 @@ int MasterGuRenderer::guCallback(int, int, void *__this) { MasterGuRenderer *_this = (MasterGuRenderer *)__this; - sceGuSync(0, 0); // make sure we wait for GU to finish + sceGuSync(0, 0); // make sure we wait for GU to finish sceDisplayWaitVblankStartCB(); // wait for v-blank without eating main thread cycles sceGuSwapBuffers(); // swap the back and front buffers _this->_renderFinished = true; // Only this thread can set the variable to true - + return 0; } @@ -149,7 +215,7 @@ inline void MasterGuRenderer::guPreRender() { DEBUG_ENTER_FUNC(); _renderFinished = false; // set to synchronize with callback thread - + #ifdef ENABLE_RENDER_MEASURE _lastRenderTime = g_system->getMillis(); #endif /* ENABLE_RENDER_MEASURE */ @@ -178,7 +244,7 @@ inline void MasterGuRenderer::guPostRender() { else sceKernelNotifyCallback(_callbackId, 0); // notify the callback. Nothing extra to pass #else - sceGuSync(0, 0); + sceGuSync(0, 0); #ifdef ENABLE_RENDER_MEASURE uint32 now = g_system->getMillis(); @@ -188,7 +254,7 @@ inline void MasterGuRenderer::guPostRender() { sceDisplayWaitVblankStart(); sceGuSwapBuffers(); _renderFinished = true; -#endif /* !USE_DISPLAY_CALLBACK */ +#endif /* !USE_DISPLAY_CALLBACK */ } void MasterGuRenderer::guShutDown() { @@ -216,7 +282,7 @@ void DisplayManager::init() { #ifdef USE_DISPLAY_CALLBACK _masterGuRenderer.setupCallbackThread(); #endif - + } void DisplayManager::setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format) { @@ -286,10 +352,10 @@ void DisplayManager::calculateScaleParams() { break; case KEEP_ASPECT_RATIO: { // maximize the height while keeping aspect ratio float aspectRatio = (float)_displayParams.screenSource.width / (float)_displayParams.screenSource.height; - + _displayParams.screenOutput.height = PSP_SCREEN_HEIGHT; // always full height _displayParams.screenOutput.width = (uint32)(PSP_SCREEN_HEIGHT * aspectRatio); - + if (_displayParams.screenOutput.width > PSP_SCREEN_WIDTH) // we can't have wider than the screen _displayParams.screenOutput.width = PSP_SCREEN_WIDTH; } @@ -301,7 +367,7 @@ void DisplayManager::calculateScaleParams() { default: PSP_ERROR("Unsupported graphics mode[%d].\n", _graphicsMode); } - + // calculate scale factors for X and Y _displayParams.scaleX = ((float)_displayParams.screenOutput.width) / _displayParams.screenSource.width; _displayParams.scaleY = ((float)_displayParams.screenOutput.height) / _displayParams.screenSource.height; @@ -316,51 +382,54 @@ bool DisplayManager::renderAll() { if (!_masterGuRenderer.isRenderFinished()) { PSP_DEBUG_PRINT("Callback render not finished.\n"); return false; // didn't render - } + } #endif /* USE_DISPLAY_CALLBACK */ - + // This is cheaper than checking time, so we do it first + // Any one of these being dirty causes everything to draw if (!_screen->isDirty() && - (!_overlay->isDirty()) && - (!_cursor->isDirty()) && - (!_keyboard->isDirty())) { + !_overlay->isDirty() && + !_cursor->isDirty() && + !_keyboard->isDirty() && + !_imageViewer->isDirty()) { PSP_DEBUG_PRINT("Nothing dirty\n"); return true; // nothing to render } - if (!isTimeToUpdate()) + if (!isTimeToUpdate()) return false; // didn't render - PSP_DEBUG_PRINT("screen[%s], overlay[%s], cursor[%s], keyboard[%s]\n", + PSP_DEBUG_PRINT("dirty: screen[%s], overlay[%s], cursor[%s], keyboard[%s], imageViewer[%s]\n", _screen->isDirty() ? "true" : "false", _overlay->isDirty() ? "true" : "false", _cursor->isDirty() ? "true" : "false", - _keyboard->isDirty() ? "true" : "false" + _keyboard->isDirty() ? "true" : "false", + _imageViewer->isDirty() ? "true" : "false", ); _masterGuRenderer.guPreRender(); // Set up rendering _screen->render(); - _screen->setClean(); // clean out dirty bit + + if (_imageViewer->isVisible()) + _imageViewer->render(); + _imageViewer->setClean(); if (_overlay->isVisible()) - _overlay->render(); - + _overlay->render(); _overlay->setClean(); if (_cursor->isVisible()) _cursor->render(); - _cursor->setClean(); if (_keyboard->isVisible()) _keyboard->render(); - _keyboard->setClean(); - - _masterGuRenderer.guPostRender(); + _masterGuRenderer.guPostRender(); + return true; // rendered successfully } diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h index 626415696a8..5c7d4c799ad 100644 --- a/backends/platform/psp/display_manager.h +++ b/backends/platform/psp/display_manager.h @@ -27,6 +27,48 @@ #define PSP_DISPLAY_MAN_H #include "backends/platform/psp/thread.h" +#include "common/list.h" + +#define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */ +#define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */ + +/** + * Class that allocates memory in the VRAM + */ +class VramAllocator : public Common::Singleton { +public: + VramAllocator() : _bytesAllocated(0) {} + void *allocate(int32 size, bool smallAllocation = false); // smallAllocation e.g. palettes + void deallocate(void *pointer); + + static inline bool isAddressInVram(void *address) { + if ((uint32)(CACHED(address)) >= VRAM_START_ADDRESS && (uint32)(CACHED(address)) < VRAM_END_ADDRESS) + return true; + return false; + } + + +private: + /** + * Used to allocate in VRAM + */ + struct Allocation { + byte *address; + uint32 size; + void *getEnd() { return address + size; } + Allocation(void *Address, uint32 Size) : address((byte *)Address), size(Size) {} + Allocation() : address(0), size(0) {} + }; + + enum { + VRAM_START_ADDRESS = 0x04000000, + VRAM_END_ADDRESS = 0x04200000, + VRAM_SMALL_ADDRESS = VRAM_END_ADDRESS - (4 * 1024) // 4K in the end for small allocations + }; + Common::List _allocList; // List of allocations + uint32 _bytesAllocated; +}; + /** * Class used only by DisplayManager to start/stop GU rendering @@ -39,7 +81,7 @@ public: void guPostRender(); void guShutDown(); bool isRenderFinished() { return _renderFinished; } - void setupCallbackThread(); + void setupCallbackThread(); private: virtual void threadFunction(); // for the display callback thread static uint32 _displayList[]; @@ -47,13 +89,14 @@ private: void guProgramDisplayBufferSizes(); static int guCallback(int, int, void *__this); // for the display callback bool _renderFinished; // for sync with render callback - int _callbackId; // to keep track of render callback + int _callbackId; // to keep track of render callback }; class Screen; class Overlay; class Cursor; class PSPKeyboard; +class ImageViewer; /** * Class that manages all display clients @@ -65,7 +108,8 @@ public: KEEP_ASPECT_RATIO, STRETCHED_FULL_SCREEN }; - DisplayManager() : _screen(0), _cursor(0), _overlay(0), _keyboard(0), _lastUpdateTime(0), _graphicsMode(0) {} + DisplayManager() : _screen(0), _cursor(0), _overlay(0), _keyboard(0), + _imageViewer(0), _lastUpdateTime(0), _graphicsMode(0) {} ~DisplayManager(); void init(); @@ -76,11 +120,13 @@ public: uint32 getDefaultGraphicsMode() const { return STRETCHED_FULL_SCREEN; } const OSystem::GraphicsMode* getSupportedGraphicsModes() const { return _supportedModes; } - // Setters + // Setters for pointers void setScreen(Screen *screen) { _screen = screen; } void setCursor(Cursor *cursor) { _cursor = cursor; } void setOverlay(Overlay *overlay) { _overlay = overlay; } void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } + void setImageViewer(ImageViewer *imageViewer) { _imageViewer = imageViewer; } + void setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format); // Getters @@ -106,6 +152,7 @@ private: Cursor *_cursor; Overlay *_overlay; PSPKeyboard *_keyboard; + ImageViewer *_imageViewer; MasterGuRenderer _masterGuRenderer; uint32 _lastUpdateTime; // For limiting FPS diff --git a/backends/platform/psp/dummy.cpp b/backends/platform/psp/dummy.cpp new file mode 100644 index 00000000000..4236734d4bd --- /dev/null +++ b/backends/platform/psp/dummy.cpp @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + + //#include "common/scummsys.h" + #include + #include + #include + #include + #include + +//void userWriteFn(png_structp png_ptr, png_bytep data, png_size_t length) { +//} + +//void userFlushFn(png_structp png_ptr) { +//} + + // Dummy functions are pulled in so that we don't need to build the plugins with certain libs + + int dummyFunc() { + + // For Broken Sword 2.5 + volatile int i; + i = clock(); + rename("dummyA", "dummyB"); + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_set_write_fn(png_ptr, NULL, NULL, NULL); + png_infop info_ptr; + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + png_destroy_write_struct(&png_ptr, &info_ptr); + + // For lua's usage of libc: very heavy usage so it pulls in sockets? + setsockopt(0, 0, 0, NULL, 0); + getsockopt(0, 0, 0, NULL, NULL); + + return i; +} \ No newline at end of file diff --git a/backends/platform/psp/image_viewer.cpp b/backends/platform/psp/image_viewer.cpp new file mode 100644 index 00000000000..26b7f31c97f --- /dev/null +++ b/backends/platform/psp/image_viewer.cpp @@ -0,0 +1,327 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/stream.h" +#include "common/archive.h" +#include "common/events.h" +#include "common/ptr.h" +#include "gui/message.h" +#include "engines/engine.h" +#include "backends/platform/psp/input.h" +#include "backends/platform/psp/display_manager.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/image_viewer.h" +#include "backends/platform/psp/png_loader.h" +#include "backends/platform/psp/thread.h" + +static const char *imageName = "psp_image"; +#define PSP_SCREEN_HEIGHT 272 +#define PSP_SCREEN_WIDTH 480 + +bool ImageViewer::load(int imageNum) { + if (_init) + unload(); + + // build string + char number[8]; + sprintf(number, "%d", imageNum); + Common::String imageNameStr(imageName); + Common::String specificImageName = imageNameStr + Common::String(number) + Common::String(".png"); + + // search for image file + if (!SearchMan.hasFile(specificImageName)) { + PSP_ERROR("file %s not found\n", specificImageName.c_str()); + return false; + } + + Common::ScopedPtr file(SearchMan.createReadStreamForMember(specificImageName)); + + _buffer = new Buffer(); + _palette = new Palette(); + _renderer = new GuRenderer(); + + assert(_buffer); + assert(_palette); + assert(_renderer); + + // Load a PNG into our buffer and palette. Size it by the actual size of the image + PngLoader image(file, *_buffer, *_palette, Buffer::kSizeBySourceSize); + + PngLoader::Status status = image.allocate(); // allocate the buffers for the file + + char error[100]; + if (status == PngLoader::BAD_FILE) { + sprintf(error, "Cannot display %s. Not a proper PNG file", specificImageName.c_str()); + GUI::TimedMessageDialog dialog(error, 4000); + dialog.runModal(); + return false; + } else if (status == PngLoader::OUT_OF_MEMORY) { + sprintf(error, "Out of memory loading %s. Try making the image smaller", specificImageName.c_str()); + GUI::TimedMessageDialog dialog(error, 4000); + dialog.runModal(); + return false; + } + // try to load the image file + if (!image.load()) { + sprintf(error, "Cannot display %s. Not a proper PNG file", specificImageName.c_str()); + GUI::TimedMessageDialog dialog(error, 4000); + dialog.runModal(); + return false; + } + + setConstantRendererOptions(); + setFullScreenImageParams(); // prepare renderer for full screen view + + _imageNum = imageNum; // now we can say we displayed this image + _init = true; + + return true; +} + +void ImageViewer::setConstantRendererOptions() { + _renderer->setBuffer(_buffer); + _renderer->setPalette(_palette); + + _renderer->setAlphaBlending(false); + _renderer->setColorTest(false); + _renderer->setUseGlobalScaler(false); + _renderer->setStretch(true); + _renderer->setOffsetInBuffer(0, 0); + _renderer->setDrawWholeBuffer(); +} + +void ImageViewer::unload() { + _init = false; + delete _buffer; + delete _palette; + delete _renderer; + _buffer = 0; + _palette = 0; + _renderer = 0; +} + +void ImageViewer::resetOnEngineDone() { + _imageNum = 0; +} + +void ImageViewer::setVisible(bool visible) { + DEBUG_ENTER_FUNC(); + + if (_visible == visible) + return; + + // from here on, we're making the loader visible + if (visible && g_engine) { // we can only run the image viewer when there's an engine + g_engine->pauseEngine(true); + + load(_imageNum ? _imageNum : 1); // load the 1st image or the current + } + + if (visible && _init) { // we managed to load + _visible = true; + setViewerButtons(true); + + { // so dialog goes out of scope, destroying all allocations + GUI::TimedMessageDialog dialog("Image Viewer", 1000); + dialog.runModal(); + } + + runLoop(); // only listen to viewer events + } else { // we were asked to make invisible or failed to load + _visible = false; + unload(); + setViewerButtons(false); + + if (g_engine && g_engine->isPaused()) + g_engine->pauseEngine(false); + } + setDirty(); +} + +// This is the only way we can truly pause the games +// Sad but true. +void ImageViewer::runLoop() { + while (_visible) { + Common::Event event; + PspThread::delayMillis(30); + _inputHandler->getAllInputs(event); + _displayManager->renderAll(); + } +} + +void ImageViewer::setViewerButtons(bool active) { + _inputHandler->setImageViewerMode(active); +} + +void ImageViewer::loadNextImage() { + if (!load(_imageNum+1)) { // try to load the next image + if (!load(_imageNum)) // we failed, so reload the current image + setVisible(false); // just hide + } + setDirty(); +} + +void ImageViewer::loadLastImage() { + if (_imageNum - 1 > 0) { + if (!load(_imageNum-1)) + if (!load(_imageNum)) + setVisible(false); // we can't even show the old image so hide + } + setDirty(); +} + +void ImageViewer::setFullScreenImageParams() { + // we try to fit the image fullscreen at least in one dimension + uint32 width = _buffer->getSourceWidth(); + uint32 height = _buffer->getSourceHeight(); + + _centerX = PSP_SCREEN_WIDTH / 2.0f; + _centerY = PSP_SCREEN_HEIGHT / 2.0f; + + // see if we fit width wise + if (PSP_SCREEN_HEIGHT >= (int)((height * PSP_SCREEN_WIDTH) / (float)width)) { + setZoom(PSP_SCREEN_WIDTH / (float)width); + } else { + setZoom(PSP_SCREEN_HEIGHT / (float)height); + } +} + +void ImageViewer::render() { + if (_init) { + assert(_buffer); + assert(_renderer); + + // move the image slightly. Note that we count on the renderer's timing + switch (_movement) { + case EVENT_MOVE_LEFT: + moveImageX(-_visibleWidth / 100.0f); + break; + case EVENT_MOVE_UP: + moveImageY(-_visibleHeight / 100.0f); + break; + case EVENT_MOVE_RIGHT: + moveImageX(_visibleWidth / 100.0f); + break; + case EVENT_MOVE_DOWN: + moveImageY(_visibleHeight / 100.0f); + break; + default: + break; + } + _renderer->render(); + } +} + +void ImageViewer::modifyZoom(bool up) { + float factor = _zoomFactor; + if (up) + factor += 0.1f; + else // down + factor -= 0.1f; + + setZoom(factor); +} + +void ImageViewer::setZoom(float value) { + if (value <= 0.0f) // don't want 0 or negative zoom + return; + + _zoomFactor = value; + _renderer->setStretchXY(value, value); + setOffsetParams(); +} + +void ImageViewer::moveImageX(float val) { + float newVal = _centerX + val; + + if (newVal - (_visibleWidth / 2) > PSP_SCREEN_WIDTH - 4 || newVal + (_visibleWidth / 2) < 4) + return; + _centerX = newVal; + setOffsetParams(); +} + +void ImageViewer::moveImageY(float val) { + float newVal = _centerY + val; + + if (newVal - (_visibleHeight / 2) > PSP_SCREEN_HEIGHT - 4 || newVal + (_visibleHeight / 2) < 4) + return; + _centerY = newVal; + setOffsetParams(); +} + +// Set the renderer with the proper offset on the screen +// +void ImageViewer::setOffsetParams() { + _visibleWidth = _zoomFactor * _buffer->getSourceWidth(); + _visibleHeight = _zoomFactor * _buffer->getSourceHeight(); + + int offsetX = _centerX - (int)(_visibleWidth * 0.5f); + int offsetY = _centerY - (int)(_visibleHeight * 0.5f); + + _renderer->setOffsetOnScreen(offsetX, offsetY); + setDirty(); +} + +// Handler events coming in from the inputHandler +// +void ImageViewer::handleEvent(uint32 event) { + DEBUG_ENTER_FUNC(); + + switch (event) { + case EVENT_HIDE: + setVisible(false); + break; + case EVENT_SHOW: + setVisible(true); + break; + case EVENT_ZOOM_IN: + modifyZoom(true); + break; + case EVENT_ZOOM_OUT: + modifyZoom(false); + break; + case EVENT_MOVE_LEFT: + case EVENT_MOVE_UP: + case EVENT_MOVE_RIGHT: + case EVENT_MOVE_DOWN: + case EVENT_MOVE_STOP: + _movement = (Event)event; + break; + case EVENT_NEXT_IMAGE: + loadNextImage(); + break; + case EVENT_LAST_IMAGE: + loadLastImage(); + break; + default: + PSP_ERROR("Unknown event %d\n", event); + break; + } +} \ No newline at end of file diff --git a/backends/platform/psp/image_viewer.h b/backends/platform/psp/image_viewer.h new file mode 100644 index 00000000000..ef8b196dbe5 --- /dev/null +++ b/backends/platform/psp/image_viewer.h @@ -0,0 +1,105 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#ifndef PSP_IMAGE_VIEWER_H +#define PSP_IMAGE_VIEWER_H + +class InputHandler; + +class ImageViewer : public DisplayClient { +public: + enum Event { + EVENT_NONE = -1, + EVENT_HIDE = 0, + EVENT_SHOW = 1, + EVENT_ZOOM_IN, + EVENT_ZOOM_OUT, + EVENT_MOVE_LEFT, + EVENT_MOVE_UP, + EVENT_MOVE_RIGHT, + EVENT_MOVE_DOWN, + EVENT_MOVE_STOP, + EVENT_NEXT_IMAGE, + EVENT_LAST_IMAGE, + }; + +private: + Buffer *_buffer; + Palette *_palette; + GuRenderer *_renderer; + bool _visible; + bool _dirty; + bool _init; + uint32 _imageNum; // current image number + float _zoomFactor; // how much we're zooming in/out on the image + float _visibleHeight, _visibleWidth; + float _centerX, _centerY; + Event _movement; + + InputHandler *_inputHandler; + DisplayManager *_displayManager; + + void setFullScreenImageParams(); + void loadNextImage(); + void loadLastImage(); + void setViewerButtons(bool active); + void setConstantRendererOptions(); + void moveImageX(float val); + void moveImageY(float val); + bool load(int imageNum); + void unload(); + void runLoop(); // to get total pausing we have to do our own loop + + void setZoom(float value); + void setOffsetParams(); + void modifyZoom(bool up); // up or down + void setVisible(bool visible); + +public: + + ImageViewer() : _buffer(0), _palette(0), _visible(false), + _dirty(false), _init(false), _imageNum(0), + _zoomFactor(0.0f), _visibleHeight(0.0f), _visibleWidth(0.0f), + _centerX(0.0f), _centerY(0.0f), _movement(EVENT_MOVE_STOP), + _inputHandler(0), _displayManager(0) {} + ~ImageViewer() { unload(); } // deallocate images + bool load(); + void render(); + bool isVisible() { return _visible; } + bool isDirty() { return _dirty; } + void setDirty() { _dirty = true; } + void setClean() { if (!_visible) // otherwise we want to keep rendering + _dirty = false; + } + void resetOnEngineDone(); + + void handleEvent(uint32 event); + + // pointer setters + void setInputHandler(InputHandler *inputHandler) { _inputHandler = inputHandler; } + void setDisplayManager(DisplayManager *displayManager) { _displayManager = displayManager; } +}; + +#endif /* PSP_IMAGE_VIEWER_H */ \ No newline at end of file diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp index 2a91ce455a3..665f41504fb 100644 --- a/backends/platform/psp/input.cpp +++ b/backends/platform/psp/input.cpp @@ -23,238 +23,274 @@ * */ -// Todo: handle events that should fire because of shift going off -// Solution: handle shift on a button-by-button basis, only allowing it when the button is up. Also a inputmap-wide button. At buttonup, shiftstate is inspected per button. +#include +#include "gui/message.h" +#include "backends/platform/psp/input.h" //#define __PSP_DEBUG_FUNCS__ /* Uncomment for debugging the stack */ //#define __PSP_DEBUG_PRINT__ /* Uncomment for debug prints */ - #include "backends/platform/psp/trace.h" -#include "backends/platform/psp/psppixelformat.h" -#include "backends/platform/psp/input.h" - // Defines for working with PSP buttons -#define CHANGED(x) (_buttonsChanged & (x)) -#define PRESSED(x) ((_buttonsChanged & (x)) && (pad.Buttons & (x))) -#define UNPRESSED(x) ((_buttonsChanged & (x)) && !(pad.Buttons & (x))) -#define DOWN(x) (pad.Buttons & (x)) +#define DOWN(x) ((pad.Buttons & (x)) == (x)) #define UP(x) (!(pad.Buttons & (x))) #define PSP_DPAD (PSP_CTRL_DOWN|PSP_CTRL_UP|PSP_CTRL_LEFT|PSP_CTRL_RIGHT) #define PSP_4BUTTONS (PSP_CTRL_CROSS | PSP_CTRL_CIRCLE | PSP_CTRL_TRIANGLE | PSP_CTRL_SQUARE) #define PSP_TRIGGERS (PSP_CTRL_LTRIGGER | PSP_CTRL_RTRIGGER) +#define PSP_ALL_BUTTONS (PSP_DPAD | PSP_4BUTTONS | PSP_TRIGGERS | PSP_CTRL_START | PSP_CTRL_SELECT) #define PAD_CHECK_TIME 53 -void InputHandler::init() { - sceCtrlSetSamplingCycle(0); // set sampling to vsync. n = n usecs - sceCtrlSetSamplingMode(1); // analog +Button::Button() { + clear(); } -bool InputHandler::getAllInputs(Common::Event &event) { - DEBUG_ENTER_FUNC(); - - uint32 time = g_system->getMillis(); // may not be necessary with read - if (time - _lastPadCheckTime < PAD_CHECK_TIME) { - return false; - } - - _lastPadCheckTime = time; - SceCtrlData pad; - - sceCtrlPeekBufferPositive(&pad, 1); // Peek ignores sleep. Read sleeps thread - - bool haveEvent; - - memset(&event, 0, sizeof(event)); - - if (_keyboard->isVisible()) - haveEvent = _keyboard->processInput(event, pad); - else - haveEvent = getEvent(event, pad); - - if (haveEvent) { - PSP_DEBUG_PRINT("Have event[%s]\n", haveEvent ? "true" : "false"); - PSP_DEBUG_PRINT("event.type[%d]\n", event.type); - } - - return haveEvent; +inline void Button::clear() { + _key = Common::KEYCODE_INVALID; + _ascii = 0; + _flag = 0; + _pspEventDown.clear(); + _pspEventUp.clear(); } -bool InputHandler::getEvent(Common::Event &event, SceCtrlData &pad) { - DEBUG_ENTER_FUNC(); - - _buttonsChanged = pad.Buttons ^ _prevButtons; - bool haveEvent = false; - - // Collect events from different sources - haveEvent = getDpadEvent(event, pad); - - if (!haveEvent) - haveEvent = getButtonEvent(event, pad); - - if (!haveEvent) - haveEvent = getNubEvent(event, pad); - - _prevButtons = pad.Buttons; - - return haveEvent; +inline bool Button::getEvent(Common::Event &event, PspEvent &pspEvent, bool down) { + if (down) { + if (!_pspEventDown.isEmpty()) + pspEvent = _pspEventDown; + } else { // up + if (!_pspEventUp.isEmpty()) + pspEvent = _pspEventUp; + } + if (_key != Common::KEYCODE_INVALID) { + event.type = down ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; + event.kbd.keycode = _key; + event.kbd.ascii = _ascii; + event.kbd.flags |= _flag; + return true; + } else if (_flag) { // handle flag only events + event.type = down ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; + event.kbd.flags |= down ? _flag : 0; + return true; + } + return false; } -bool InputHandler::getDpadEvent(Common::Event &event, SceCtrlData &pad) { - DEBUG_ENTER_FUNC(); - - int newDpadX = 0, newDpadY = 0; - bool haveEvent = false; - - if (DOWN(PSP_CTRL_UP)) { - newDpadY++; - if (DOWN(PSP_CTRL_RTRIGGER)) // Shifting causes diagonals - newDpadX++; - } - if (DOWN(PSP_CTRL_RIGHT)) { - newDpadX++; - if (DOWN(PSP_CTRL_RTRIGGER)) - newDpadY--; - } - if (DOWN(PSP_CTRL_DOWN)) { - newDpadY--; - if (DOWN(PSP_CTRL_RTRIGGER)) - newDpadX--; - } - if (DOWN(PSP_CTRL_LEFT)) { - newDpadX--; - if (DOWN(PSP_CTRL_RTRIGGER)) - newDpadY++; - } - - if (newDpadX != _dpadX || newDpadY != _dpadY) { - if (_dpadX == 0 && _dpadY == 0) { // We were in the middle so we pressed dpad - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = translateDpad(newDpadX, newDpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; // Get ascii - _dpadX = newDpadX; - _dpadY = newDpadY; - } else if (newDpadX == 0 && newDpadY == 0) {// We're now centered so we unpressed dpad - event.type = Common::EVENT_KEYUP; - event.kbd.keycode = translateDpad(_dpadX, _dpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = newDpadX; - _dpadY = newDpadY; - } else { // we moved from one pressed dpad direction to another one - event.type = Common::EVENT_KEYUP; // first release the last dpad direction - event.kbd.keycode = translateDpad(_dpadX, _dpadY); - event.kbd.ascii = event.kbd.keycode - Common::KEYCODE_KP0 + '0'; - _dpadX = 0; // so that we'll pick up a new dpad movement the next round - _dpadY = 0; - } - - PSP_DEBUG_PRINT("Keypad event. DpadX[%d], DpadY[%d]\n", _dpadX, _dpadY); - haveEvent = true; - } - - return haveEvent; +void Button::setPspEvent(PspEventType typeDown, uint32 dataDown, PspEventType typeUp, uint32 dataUp) { + _pspEventDown.type = typeDown; + _pspEventDown.data = dataDown; + _pspEventUp.type = typeUp; + _pspEventUp.data = dataUp; } -inline Common::KeyCode InputHandler::translateDpad(int x, int y) { - DEBUG_ENTER_FUNC(); - Common::KeyCode key; +// Translates bitfields to our constants +// We put combined bitfields first to make sure we pick up diagonals +const uint32 ButtonPad::_buttonMap[] = { + PSP_CTRL_UP | PSP_CTRL_LEFT, + PSP_CTRL_UP | PSP_CTRL_RIGHT, + PSP_CTRL_DOWN | PSP_CTRL_RIGHT, + PSP_CTRL_DOWN | PSP_CTRL_LEFT, + PSP_CTRL_RIGHT, PSP_CTRL_DOWN, PSP_CTRL_LEFT, PSP_CTRL_UP, + PSP_CTRL_CROSS, PSP_CTRL_CIRCLE, PSP_CTRL_TRIANGLE, PSP_CTRL_SQUARE, + PSP_CTRL_LTRIGGER, PSP_CTRL_RTRIGGER, PSP_CTRL_START, PSP_CTRL_SELECT +}; - if (x == -1) { - if (y == -1) - key = Common::KEYCODE_KP1; - else if (y == 0) - key = Common::KEYCODE_KP4; - else /* y == 1 */ - key = Common::KEYCODE_KP7; - } else if (x == 0) { - if (y == -1) - key = Common::KEYCODE_KP2; - else /* y == 1 */ - key = Common::KEYCODE_KP8; - } else {/* x == 1 */ - if (y == -1) - key = Common::KEYCODE_KP3; - else if (y == 0) - key = Common::KEYCODE_KP6; - else /* y == 1 */ - key = Common::KEYCODE_KP9; - } - - return key; +ButtonPad::ButtonPad() : _prevButtonState(0), _shifted(UNSHIFTED), _padMode(PAD_MODE_NORMAL), + _comboMode(false), _combosEnabled(true) { + for (int i = UNSHIFTED; i < SHIFTED_MODE_LAST; i++) + _buttonsChanged[i] = 0; + clearButtons(); } +void ButtonPad::clearButtons() { + for (int i = BTN_UP_LEFT; i < BTN_LAST; i++) { + _button[i][UNSHIFTED].clear(); + _button[i][SHIFTED].clear(); + } +} -bool InputHandler::getButtonEvent(Common::Event &event, SceCtrlData &pad) { +void ButtonPad::initButtons() { + switch (_padMode) { + case PAD_MODE_NORMAL: + initButtonsNormalMode(); + break; + case PAD_MODE_LOL: + initButtonsLolMode(); + break; + default: + break; + } +} + +void ButtonPad::initButtonsNormalMode() { DEBUG_ENTER_FUNC(); - bool haveEvent = false; + PSP_DEBUG_PRINT("initializing buttons for normal mode\n"); + clearButtons(); - if (PRESSED(PSP_CTRL_SELECT)) - _keyboard->setVisible(true); + // Dpad + _button[BTN_UP_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP7, '7'); + _button[BTN_LEFT][SHIFTED].setKey(Common::KEYCODE_KP7, '7'); // same as up_left + _button[BTN_UP][UNSHIFTED].setKey(Common::KEYCODE_KP8, '8'); + _button[BTN_UP_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP9, '9'); + _button[BTN_UP][SHIFTED].setKey(Common::KEYCODE_KP9, '9'); // same as up_right + _button[BTN_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP4, '4'); + _button[BTN_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP6, '6'); + _button[BTN_DOWN_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP1, '1'); + _button[BTN_DOWN][SHIFTED].setKey(Common::KEYCODE_KP1, '1'); // same as down_left + _button[BTN_DOWN][UNSHIFTED].setKey(Common::KEYCODE_KP2, '2'); + _button[BTN_DOWN_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP3, '3'); + _button[BTN_RIGHT][SHIFTED].setKey(Common::KEYCODE_KP3, '3'); // same as down_right - else if (CHANGED(PSP_4BUTTONS | PSP_TRIGGERS | PSP_CTRL_START)) { - if (CHANGED(PSP_CTRL_CROSS)) { - event.type = DOWN(PSP_CTRL_CROSS) ? Common::EVENT_LBUTTONDOWN : Common::EVENT_LBUTTONUP; - event.mouse.x = _cursor->getX(); // Could this have to do with SCI enter problem? - event.mouse.y = _cursor->getY(); - PSP_DEBUG_PRINT("%s\n", event.type == Common::EVENT_LBUTTONDOWN ? "LButtonDown" : "LButtonUp"); - } else if (CHANGED(PSP_CTRL_CIRCLE)) { - event.type = DOWN(PSP_CTRL_CIRCLE) ? Common::EVENT_RBUTTONDOWN : Common::EVENT_RBUTTONUP; - event.mouse.x = _cursor->getX(); - event.mouse.y = _cursor->getY(); - PSP_DEBUG_PRINT("%s\n", event.type == Common::EVENT_LBUTTONDOWN ? "RButtonDown" : "RButtonUp"); - } else { - //any of the other buttons. - event.type = _buttonsChanged & pad.Buttons ? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP; - event.kbd.ascii = 0; - event.kbd.flags = 0; + // Other buttons + _button[BTN_CROSS][UNSHIFTED].setPspEvent(PSP_EVENT_LBUTTON, true, PSP_EVENT_LBUTTON, false); + _button[BTN_CIRCLE][UNSHIFTED].setPspEvent(PSP_EVENT_RBUTTON, true, PSP_EVENT_RBUTTON, false); + _button[BTN_TRIANGLE][UNSHIFTED].setKey(Common::KEYCODE_RETURN, '\r'); + _button[BTN_SQUARE][UNSHIFTED].setKey(Common::KEYCODE_PERIOD, '.'); + _button[BTN_SQUARE][SHIFTED].setKey(Common::KEYCODE_SPACE, ' '); + _button[BTN_LTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_ESCAPE, 27); + _button[BTN_RTRIGGER][SHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + _button[BTN_RTRIGGER][UNSHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + _button[BTN_RTRIGGER][SHIFTED].setKey(Common::KEYCODE_INVALID, 0, Common::KBD_SHIFT); + _button[BTN_RTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_INVALID, 0, Common::KBD_SHIFT); + _button[BTN_START][SHIFTED].setKey(Common::KEYCODE_F5, Common::ASCII_F5); + _button[BTN_START][UNSHIFTED].setKey(Common::KEYCODE_F5, Common::ASCII_F5, Common::KBD_CTRL); + _button[BTN_SELECT][UNSHIFTED].setPspEvent(PSP_EVENT_SHOW_VIRTUAL_KB, true, PSP_EVENT_NONE, 0); + _button[BTN_SELECT][SHIFTED].setPspEvent(PSP_EVENT_IMAGE_VIEWER, true, PSP_EVENT_NONE, 0); +} - if (CHANGED(PSP_CTRL_LTRIGGER)) { - event.kbd.keycode = Common::KEYCODE_ESCAPE; - event.kbd.ascii = 27; - } else if (CHANGED(PSP_CTRL_START)) { - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = Common::ASCII_F5; - if (DOWN(PSP_CTRL_RTRIGGER)) { - event.kbd.flags |= Common::KBD_CTRL; // Main menu to allow RTL +void ButtonPad::initButtonsLolMode() { + DEBUG_ENTER_FUNC(); + initButtonsNormalMode(); // set normal button configuration + PSP_DEBUG_PRINT("initializing buttons for LOL mode\n"); + + // Square is our new shift button + _button[BTN_SQUARE][UNSHIFTED].clear(); + _button[BTN_SQUARE][UNSHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + _button[BTN_SQUARE][SHIFTED].clear(); + _button[BTN_SQUARE][SHIFTED].setPspEvent(PSP_EVENT_SHIFT, true, PSP_EVENT_SHIFT, false); + + // Dpad + _button[BTN_LEFT][UNSHIFTED].clear(); + _button[BTN_LEFT][UNSHIFTED].setKey(Common::KEYCODE_KP7, '7'); + _button[BTN_LEFT][SHIFTED].clear(); + _button[BTN_LEFT][SHIFTED].setKey(Common::KEYCODE_F1, Common::ASCII_F1); + _button[BTN_UP][SHIFTED].clear(); + _button[BTN_UP][SHIFTED].setKey(Common::KEYCODE_F2, Common::ASCII_F2); + _button[BTN_RIGHT][UNSHIFTED].clear(); + _button[BTN_RIGHT][UNSHIFTED].setKey(Common::KEYCODE_KP9, '9'); + _button[BTN_RIGHT][SHIFTED].clear(); + _button[BTN_RIGHT][SHIFTED].setKey(Common::KEYCODE_F3, Common::ASCII_F3); + _button[BTN_DOWN][SHIFTED].clear(); + _button[BTN_DOWN][SHIFTED].setKey(Common::KEYCODE_F4, Common::ASCII_F4); + + // Buttons + _button[BTN_LTRIGGER][UNSHIFTED].clear(); + _button[BTN_LTRIGGER][SHIFTED].clear(); + _button[BTN_LTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_KP4, '4'); // Triggers turn + _button[BTN_RTRIGGER][UNSHIFTED].clear(); + _button[BTN_RTRIGGER][SHIFTED].clear(); + _button[BTN_RTRIGGER][UNSHIFTED].setKey(Common::KEYCODE_KP6, '6'); + _button[BTN_START][SHIFTED].clear(); + _button[BTN_START][SHIFTED].setKey(Common::KEYCODE_ESCAPE, 27); +} + +bool ButtonPad::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + //PSP_DEBUG_PRINT("buttons[%x]\n", pad.Buttons); + + uint32 curButtonState = PSP_ALL_BUTTONS & pad.Buttons; // we only care about these + + if (_combosEnabled) + modifyButtonsForCombos(pad); // change buttons for combos + + return getEventFromButtonState(event, pspEvent, curButtonState); +} + +bool ButtonPad::getEventFromButtonState(Common::Event &event, PspEvent &pspEvent, uint32 buttonState) { + DEBUG_ENTER_FUNC(); + _buttonsChanged[_shifted] |= buttonState ^ _prevButtonState; // add any buttons that changed + _prevButtonState = buttonState; + + for (int shiftState = UNSHIFTED; shiftState < SHIFTED_MODE_LAST; shiftState++) { + if (_buttonsChanged[shiftState]) { // any button to address? + PSP_DEBUG_PRINT("found changed buttons\n"); + ButtonType buttonType = BTN_LAST; + bool buttonDown = false; // normally we release a button (as in when we're in a different shiftmode) + + for (int i = BTN_UP_LEFT; i < BTN_LAST; i++) { + uint32 buttonCode = _buttonMap[i]; + if ((_buttonsChanged[shiftState] & buttonCode) == buttonCode) { // check for this changed button + buttonType = (ButtonType)i; // we know which button changed + _buttonsChanged[shiftState] &= ~buttonCode; // save the fact that we treated this button + if (shiftState == _shifted) + buttonDown = buttonState & buttonCode ? true : false; // pressed or released? + + PSP_DEBUG_PRINT("button[%i] pressed\n", i); + break; } - } else if (CHANGED(PSP_CTRL_SQUARE)) { - event.kbd.keycode = Common::KEYCODE_PERIOD; - event.kbd.ascii = '.'; - } else if (CHANGED(PSP_CTRL_TRIANGLE)) { - event.kbd.keycode = Common::KEYCODE_RETURN; - event.kbd.ascii = '\r'; - } else if (DOWN(PSP_CTRL_RTRIGGER)) { // An event - event.kbd.flags |= Common::KBD_SHIFT; } - PSP_DEBUG_PRINT("Ascii[%d]. Key %s.\n", event.kbd.ascii, event.type == Common::EVENT_KEYDOWN ? "down" : "up"); - } - haveEvent = true; + assert (buttonType < BTN_LAST); + bool haveEvent = _button[buttonType][shiftState].getEvent(event, pspEvent, buttonDown); + if (haveEvent) + PSP_DEBUG_PRINT("have event. key[%d] flag[%x] %s\n", event.kbd.ascii, event.kbd.flags, buttonDown ? "down" : "up"); + return haveEvent; + } } - return haveEvent; + return false; } -bool InputHandler::getNubEvent(Common::Event &event, SceCtrlData &pad) { +void ButtonPad::modifyButtonsForCombos(SceCtrlData &pad) { + if (DOWN(PSP_CTRL_RTRIGGER | PSP_CTRL_LTRIGGER)) { + if (!_comboMode) { // we're entering combo mode + PSP_DEBUG_PRINT("entering combo mode\n"); + _button[BTN_SQUARE][UNSHIFTED].clear(); + _button[BTN_SQUARE][SHIFTED].clear(); + _button[BTN_DOWN][SHIFTED].clear(); + _button[BTN_DOWN][UNSHIFTED].clear(); + _button[BTN_UP][SHIFTED].clear(); + _button[BTN_UP][UNSHIFTED].clear(); + _button[BTN_SQUARE][UNSHIFTED].setPspEvent(PSP_EVENT_MODE_SWITCH, true, PSP_EVENT_NONE, true); + _button[BTN_SQUARE][SHIFTED].setPspEvent(PSP_EVENT_MODE_SWITCH, true, PSP_EVENT_NONE, true); + _button[BTN_DOWN][UNSHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, false, PSP_EVENT_NONE, true); + _button[BTN_DOWN][SHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, false, PSP_EVENT_NONE, true); + _button[BTN_UP][UNSHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, true, PSP_EVENT_NONE, true); + _button[BTN_UP][SHIFTED].setPspEvent(PSP_EVENT_CHANGE_SPEED, true, PSP_EVENT_NONE, true); + _comboMode = true; + } + } else { // no combo buttons are pressed now + if (_comboMode) { // we have been running in combo mode + initButtons(); // reset the button configuration + _comboMode = false; + } + } +} + +bool Nub::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { DEBUG_ENTER_FUNC(); - bool haveEvent = false; + if (_dpadMode) { // Convert the nub to a D-Pad + uint32 buttonState; + translateToDpadState(pad.Lx, pad.Ly, buttonState); + return _buttonPad.getEventFromButtonState(event, pspEvent, buttonState); + } + int32 analogStepX = pad.Lx; // Goes up to 255. int32 analogStepY = pad.Ly; - int32 oldX = _cursor->getX(); - int32 oldY = _cursor->getY(); - analogStepX = modifyNubAxisMotion(analogStepX); analogStepY = modifyNubAxisMotion(analogStepY); + int32 oldX = _cursor->getX(); + int32 oldY = _cursor->getY(); + if (analogStepX != 0 || analogStepY != 0) { PSP_DEBUG_PRINT("raw x[%d], y[%d]\n", analogStepX, analogStepY); // If no movement then this has no effect - if (DOWN(PSP_CTRL_RTRIGGER)) { + if (_shifted) { // Fine control mode for analog if (analogStepX != 0) { if (analogStepX > 0) @@ -281,15 +317,29 @@ bool InputHandler::getNubEvent(Common::Event &event, SceCtrlData &pad) { event.type = Common::EVENT_MOUSEMOVE; event.mouse.x = newX; event.mouse.y = newY; - haveEvent = true; - PSP_DEBUG_PRINT("Nub event. X[%d], Y[%d]\n", newX, newY); + return true; } } - return haveEvent; + return false; } -inline int32 InputHandler::modifyNubAxisMotion(int32 input) { +void Nub::translateToDpadState(int dpadX, int dpadY, uint32 &buttonState) { + #define MIN_NUB_POSITION 70 + buttonState = 0; + + if (dpadX > 127 + MIN_NUB_POSITION) + buttonState |= PSP_CTRL_RIGHT; + else if (dpadX < 127 - MIN_NUB_POSITION) + buttonState |= PSP_CTRL_LEFT; + + if (dpadY > 127 + MIN_NUB_POSITION) + buttonState |= PSP_CTRL_DOWN; + else if (dpadY < 127 - MIN_NUB_POSITION) + buttonState |= PSP_CTRL_UP; +} + +inline int32 Nub::modifyNubAxisMotion(int32 input) { DEBUG_ENTER_FUNC(); const int MIN_NUB_MOTION = 30; @@ -304,3 +354,220 @@ inline int32 InputHandler::modifyNubAxisMotion(int32 input) { return input; } + +inline bool Nub::isButtonDown() { + if (_dpadMode) // only relevant in dpad mode + return _buttonPad.isButtonDown(); + return false; +} + +const char *InputHandler::_padModeText[] = { + "Normal Button Mode", + "1st Person RPG Button Mode" +}; + +void InputHandler::init() { + sceCtrlSetSamplingCycle(0); // set sampling to vsync. n = n usecs + sceCtrlSetSamplingMode(1); // analog + + _buttonPad.initButtons(); + _nub.init(); +} + +bool InputHandler::getAllInputs(Common::Event &event) { + DEBUG_ENTER_FUNC(); + + uint32 time = g_system->getMillis(); // may not be necessary with read + if (time - _lastPadCheckTime < PAD_CHECK_TIME) { + return false; + } + + _lastPadCheckTime = time; + SceCtrlData pad; + + sceCtrlPeekBufferPositive(&pad, 1); // Peek doesn't sleep. Read sleeps the thread + + bool haveEvent; + //memset(&event, 0, sizeof(event)); + + haveEvent = getEvent(event, pad); + + if (haveEvent) { + PSP_DEBUG_PRINT("Have event[%s]. Type[%d]\n", haveEvent ? "true" : "false", event.type); + } + + return haveEvent; +} + +bool InputHandler::getEvent(Common::Event &event, SceCtrlData &pad) { + DEBUG_ENTER_FUNC(); + + PspEvent pspEvent; + bool haveEvent = false; + + if (_keyboard->isVisible()) { + haveEvent = _keyboard->processInput(event, pspEvent, pad); + } else { // only process buttonpad if keyboard invisible + haveEvent = _buttonPad.getEvent(event, pspEvent, pad); + } + + if (!haveEvent && pspEvent.isEmpty()) + haveEvent = _nub.getEvent(event, pspEvent, pad); + + // handle any pending PSP events + if (!haveEvent && pspEvent.isEmpty()) { + if (!_pendingPspEvent.isEmpty()) { + pspEvent = _pendingPspEvent; + _pendingPspEvent.clear(); + } + } + + // handle any PSP events we might have + if (!pspEvent.isEmpty()) + haveEvent |= handlePspEvent(event, pspEvent); // overrides any event we might have + + return haveEvent; +} + +bool InputHandler::handlePspEvent(Common::Event &event, PspEvent &pspEvent) { + bool haveEvent = false; + + PSP_DEBUG_PRINT("have pspEvent[%d] data[%d]\n", pspEvent.type, pspEvent.data); + + switch (pspEvent.type) { + case PSP_EVENT_SHIFT: + handleShiftEvent((ShiftMode)pspEvent.data); + break; + case PSP_EVENT_SHOW_VIRTUAL_KB: + _keyboard->setVisible((bool)pspEvent.data); + if ((pspEvent.data && _keyboard->isVisible()) || !pspEvent.data) // don't change mode if keyboard didn't load + _nub.setDpadMode((bool)pspEvent.data); // set nub to keypad/regular mode + break; + case PSP_EVENT_LBUTTON: + haveEvent = true; + if (pspEvent.data) // down + handleMouseEvent(event, Common::EVENT_LBUTTONDOWN, "LButtonDown"); + else + handleMouseEvent(event, Common::EVENT_LBUTTONUP, "LButtonUp"); + break; + case PSP_EVENT_RBUTTON: + haveEvent = true; + if (pspEvent.data) // down + handleMouseEvent(event, Common::EVENT_RBUTTONDOWN, "RButtonDown"); + else + handleMouseEvent(event, Common::EVENT_RBUTTONUP, "RButtonUp"); + break; + case PSP_EVENT_MODE_SWITCH: + handleModeSwitchEvent(); + break; + /*case PSP_EVENT_CHANGE_SPEED: + handleSpeedChange(pspEvent.data); + break;*/ + case PSP_EVENT_IMAGE_VIEWER: + _imageViewer->handleEvent(pspEvent.data); + break; + case PSP_EVENT_IMAGE_VIEWER_SET_BUTTONS: + setImageViewerMode(pspEvent.data); + break; + default: + PSP_ERROR("Unhandled PSP Event[%d]\n", pspEvent.type); + break; + } + + return haveEvent; +} + +void InputHandler::handleMouseEvent(Common::Event &event, Common::EventType type, const char *string) { + event.type = type; + event.mouse.x = _cursor->getX(); + event.mouse.y = _cursor->getY(); + PSP_DEBUG_PRINT("%s event, x[%d], y[%d]\n", string, event.mouse.x, event.mouse.y); +} + +void InputHandler::handleShiftEvent(ShiftMode shifted) { + _buttonPad.setShifted(shifted); + _nub.setShifted(shifted); +} + +void InputHandler::handleModeSwitchEvent() { + // check if we can't switch modes right now + if (_buttonPad.isButtonDown() || _nub.isButtonDown()) { // can't switch yet + PSP_DEBUG_PRINT("postponing mode switch event\n"); + _pendingPspEvent.type = PSP_EVENT_MODE_SWITCH; // queue it to be done later + } else { // we can switch + PSP_DEBUG_PRINT("mode switch event\n"); + _padMode = (PspPadMode)(_padMode + 1); + if (_padMode >= PAD_MODE_LAST) + _padMode = PAD_MODE_NORMAL; + + GUI::TimedMessageDialog dialog(_padModeText[_padMode], 1500); + dialog.runModal(); + + _buttonPad.setPadMode(_padMode); + _buttonPad.initButtons(); + } +} + +/* +void InputHandler::handleSpeedChange(bool up) { + char *dialogMsg; + + if (up) { + dialogMsg = " + + GUI::TimedMessageDialog dialog(_padModeText[_padMode], 1500); + dialog.runModal(); +}*/ + +void InputHandler::setImageViewerMode(bool active) { + if (_buttonPad.isButtonDown() || _nub.isButtonDown()) { // can't switch yet + PSP_DEBUG_PRINT("postponing image viewer on event\n"); + _pendingPspEvent.type = PSP_EVENT_IMAGE_VIEWER_SET_BUTTONS; // queue it to be done later + _pendingPspEvent.data = active; + } else if (active) { + _nub.setDpadMode(true); + _buttonPad.enableCombos(false); // disable combos + setButtonsForImageViewer(); + } else { // deactivate + _nub.setDpadMode(false); + _nub.init(); + _buttonPad.enableCombos(true); // re-enable combos + _buttonPad.initButtons(); + } +} + +void InputHandler::setButtonsForImageViewer() { + DEBUG_ENTER_FUNC(); + + // Dpad + _buttonPad.clearButtons(); + _buttonPad.getButton(ButtonPad::BTN_UP, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_ZOOM_IN, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_DOWN, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_ZOOM_OUT, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_LEFT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_LAST_IMAGE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_RIGHT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_NEXT_IMAGE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_LTRIGGER, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_RTRIGGER, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_START, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_SELECT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + + //Nub + _nub.getPad().clearButtons(); + _nub.getPad().getButton(ButtonPad::BTN_UP, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_UP, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); + _nub.getPad().getButton(ButtonPad::BTN_DOWN, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_DOWN, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); + _nub.getPad().getButton(ButtonPad::BTN_LEFT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_LEFT, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); + _nub.getPad().getButton(ButtonPad::BTN_RIGHT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_RIGHT, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); +} + + diff --git a/backends/platform/psp/input.h b/backends/platform/psp/input.h index cd686d9e02e..9a1ab6faab7 100644 --- a/backends/platform/psp/input.h +++ b/backends/platform/psp/input.h @@ -28,36 +28,175 @@ #include "common/scummsys.h" #include "common/events.h" -#include "backends/platform/psp/display_client.h" -#include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/pspkeyboard.h" #include "backends/platform/psp/cursor.h" +#include "backends/platform/psp/image_viewer.h" #include +enum PspEventType { + PSP_EVENT_NONE = 0, + PSP_EVENT_SHIFT, + PSP_EVENT_SHOW_VIRTUAL_KB, + PSP_EVENT_LBUTTON, + PSP_EVENT_RBUTTON, + PSP_EVENT_MODE_SWITCH, + PSP_EVENT_CHANGE_SPEED, + PSP_EVENT_IMAGE_VIEWER, + PSP_EVENT_IMAGE_VIEWER_SET_BUTTONS, + PSP_EVENT_LAST +}; + +struct PspEvent { + PspEventType type; + uint32 data; + PspEvent() { clear(); } + void clear() { + type = PSP_EVENT_NONE; + data = 0; + } + bool isEmpty() { return type == PSP_EVENT_NONE; } +}; + +enum PspPadMode { + PAD_MODE_NORMAL, + PAD_MODE_LOL, + PAD_MODE_LAST +}; + +enum ShiftMode { + UNSHIFTED = 0, + SHIFTED = 1, + SHIFTED_MODE_LAST +}; + + +class Button { +private: + Common::KeyCode _key; + uint32 _ascii; + uint32 _flag; + PspEvent _pspEventDown; // event when we press + PspEvent _pspEventUp; // event when we release +public: + Button(); + void clear(); + bool getEvent(Common::Event &event, PspEvent &pspEvent, bool buttonDown); + void setKey(Common::KeyCode key, uint32 ascii = 0, uint32 flag = 0) { _key = key; _ascii = ascii; _flag = flag; } + void setPspEvent(PspEventType typeDown, uint32 dataDown, PspEventType typeUp, uint32 dataUp); +}; + +class ButtonPad { +public: + enum ButtonType { // must match the buttonMap + BTN_UP_LEFT, + BTN_UP_RIGHT, + BTN_DOWN_RIGHT, + BTN_DOWN_LEFT, + BTN_RIGHT, + BTN_DOWN, + BTN_LEFT, + BTN_UP, + BTN_CROSS, + BTN_CIRCLE, + BTN_TRIANGLE, + BTN_SQUARE, + BTN_LTRIGGER, + BTN_RTRIGGER, + BTN_START, + BTN_SELECT, + BTN_LAST + }; + +private: + Button _button[BTN_LAST][SHIFTED_MODE_LAST]; + uint32 _buttonsChanged[SHIFTED_MODE_LAST]; // normal and shifted + uint32 _prevButtonState; + ShiftMode _shifted; + PspPadMode _padMode; + bool _comboMode; // are we in the middle of combos + bool _combosEnabled; // can we do combos + static const uint32 _buttonMap[]; // maps the buttons to their values + + void initButtonsNormalMode(); + void initButtonsLolMode(); + void modifyButtonsForCombos(SceCtrlData &pad); + +public: + ButtonPad(); + void initButtons(); // set the buttons to the mode that's selected + void clearButtons(); // empty the buttons of all events + + bool getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); + bool getEventFromButtonState(Common::Event &event, PspEvent &pspEvent, uint32 buttonState); + + void setShifted(ShiftMode shifted) { _shifted = shifted; } + void setPadMode(PspPadMode mode) { _padMode = mode; } + bool isButtonDown() { return _prevButtonState; } + + void enableCombos(bool value) { _combosEnabled = value; } + Button &getButton(ButtonType type, ShiftMode mode) { return _button[type][mode]; } +}; + +class Nub { +private: + Cursor *_cursor; // to enable changing/getting cursor position + + ShiftMode _shifted; + bool _dpadMode; + + ButtonPad _buttonPad; // private buttonpad for dpad mode + + int32 modifyNubAxisMotion(int32 input); + void translateToDpadState(int dpadX, int dpadY, uint32 &buttonState); // convert nub data to dpad data +public: + Nub() : _shifted(UNSHIFTED), _dpadMode(false) { } + void init() { _buttonPad.initButtons(); } + + void setCursor(Cursor *cursor) { _cursor = cursor; } + + // setters + void setDpadMode(bool active) { _dpadMode = active; } + void setShifted(ShiftMode shifted) { _shifted = shifted; } + + // getters + bool isButtonDown(); + bool getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); + ButtonPad &getPad() { return _buttonPad; } +}; + class InputHandler { public: - InputHandler() : _cursor(0), _keyboard(0), _prevButtons(0), _lastPadCheckTime(0), _buttonsChanged(0), _dpadX(0), _dpadY(0) {} + InputHandler() : _keyboard(0), _cursor(0), _imageViewer(0), _padMode(PAD_MODE_NORMAL), + _lastPadCheckTime(0) {} + // pointer setters + void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } + void setCursor(Cursor *cursor) { _cursor = cursor; _nub.setCursor(cursor); } + void setImageViewer(ImageViewer *imageViewer) { _imageViewer = imageViewer; } void init(); bool getAllInputs(Common::Event &event); - void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } - void setCursor(Cursor *cursor) { _cursor = cursor; } + void setImageViewerMode(bool active); private: - Cursor *_cursor; + Nub _nub; + ButtonPad _buttonPad; + + // Pointers to relevant other classes PSPKeyboard *_keyboard; - uint32 _prevButtons; + Cursor *_cursor; + ImageViewer *_imageViewer; + + PspPadMode _padMode; // whice mode we're in + PspEvent _pendingPspEvent; // an event that can't be handled yet uint32 _lastPadCheckTime; - uint32 _buttonsChanged; - int32 _dpadX, _dpadY; - int32 _accelX, _accelY; + static const char *_padModeText[]; bool getEvent(Common::Event &event, SceCtrlData &pad); - bool getDpadEvent(Common::Event &event, SceCtrlData &pad); - bool getButtonEvent(Common::Event &event, SceCtrlData &pad); - bool getNubEvent(Common::Event &event, SceCtrlData &pad); - int32 modifyNubAxisMotion(int32 input); - Common::KeyCode translateDpad(int x, int y); + bool handlePspEvent(Common::Event &event, PspEvent &pspEvent); + void handleMouseEvent(Common::Event &event, Common::EventType type, const char *string); + void handleShiftEvent(ShiftMode shifted); + void handleModeSwitchEvent(); + void setButtonsForImageViewer(); }; #endif /* PSP_INPUT_H */ diff --git a/backends/platform/psp/memory.cpp b/backends/platform/psp/memory.cpp index 29d0482d9a1..924ab356e85 100644 --- a/backends/platform/psp/memory.cpp +++ b/backends/platform/psp/memory.cpp @@ -25,8 +25,8 @@ #include "common/scummsys.h" #include "common/singleton.h" -#include "common/list.h" #include "backends/platform/psp/psppixelformat.h" +#define PSP_INCLUDE_SWAP #include "backends/platform/psp/memory.h" // Class Copier -------------------------------------------------------------------------- @@ -37,23 +37,6 @@ //#define TEST_MEMORY_COPY -extern "C" { - -#ifdef TEST_MEMORY_COPY /* we won't be able to run in this case b/c of printouts */ -extern void *__real_memcpy(void *dst, void *src, size_t bytes); -#endif - -void *__wrap_memcpy(void *dst, void *src, size_t bytes) { -#ifdef TEST_MEMORY_COPY /* we won't be able to run in this case */ - return __real_memcpy(dst, src, bytes); -#else - PspMemory::fastCopy((byte *)dst, (byte *)src, bytes); - return dst; -#endif -} - -} - void PspMemory::copy(byte *dst, const byte *src, uint32 bytes) { DEBUG_ENTER_FUNC(); @@ -66,29 +49,29 @@ void PspMemory::copy(byte *dst, const byte *src, uint32 bytes) { // align the destination pointer first uint32 prefixDst = (((uint32)dst) & 0x3); - + if (prefixDst) { - prefixDst = 4 - prefixDst; // prefix only if we have address % 4 != 0 + prefixDst = 4 - prefixDst; // prefix only if we have address % 4 != 0 PSP_DEBUG_PRINT("prefixDst[%d]\n", prefixDst); bytes -= prefixDst; // remember we assume bytes >= 4 - + if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue copy8(dst, src, bytes + prefixDst); #ifdef TEST_MEMORY_COPY testCopy(debugDst, debugSrc, debugBytes); -#endif +#endif return; } - + while (prefixDst--) { *dst++ = *src++; - } + } } - + // check the source pointer alignment now uint32 alignSrc = (((uint32)src) & 0x3); - + if (alignSrc) { // we'll need to realign our reads copy32Misaligned((uint32 *)dst, src, bytes, alignSrc); } else { @@ -97,104 +80,14 @@ void PspMemory::copy(byte *dst, const byte *src, uint32 bytes) { #ifdef TEST_MEMORY_COPY testCopy(debugDst, debugSrc, debugBytes); -#endif -} - -void PspMemory::testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes) { - - bool mismatch = false; - PSP_INFO_PRINT("testing fastCopy..."); - - for (uint32 i = 0; i < debugBytes; i++) { - if (debugDst[i] != debugSrc[i]) { - if (!mismatch) { - PSP_INFO_PRINT("**** mismatch in copy! ****\n"); - PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes); - mismatch = true; - } - PSP_INFO_PRINT("[%d]%x!=%x ", i, debugSrc[i], debugDst[i]); - } - } - if (mismatch) { - PSP_INFO_PRINT("\n"); - } else { - PSP_INFO_PRINT("ok\n"); - } -} - -// -// used to swap red and blue -void PspMemory::swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { - DEBUG_ENTER_FUNC(); - -#ifdef TEST_MEMORY_COPY - uint32 debugBytes = bytes; - const uint16 *debugDst = dst16, *debugSrc = src16; #endif - - // align the destination pointer first - uint32 prefixDst = (((uint32)dst16) & 0x3); // for swap, we can only have 2 or 0 as our prefix - - if (prefixDst) { - bytes -= prefixDst; // remember we assume bytes > 4 - *dst16++ = format.swapRedBlue16(*src16++); - - if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue - swap16(dst16, src16, bytes, format); - -#ifdef TEST_MEMORY_COPY - testSwap(debugDst, debugSrc, debugBytes, format); -#endif - return; - } - } - - // check the source pointer alignment now - uint32 alignSrc = (((uint32)src16) & 0x3); - - if (alignSrc) { // we'll need to realign our reads - PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src16, dst16); - swap32Misaligned((uint32 *)dst16, src16, bytes, format); - } else { - swap32Aligned((uint32 *)dst16, (const uint32 *)src16, bytes, format); - } - -#ifdef TEST_MEMORY_COPY - testSwap(debugDst, debugSrc, debugBytes, format); -#endif - } -void PspMemory::testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format) { - - bool mismatch = false; - PSP_INFO_PRINT("testing fastSwap..."); - - uint32 shorts = debugBytes >> 1; - - for (uint32 i = 0; i < shorts; i++) { - if (debugDst[i] != format.swapRedBlue16(debugSrc[i])) { - if (!mismatch) { - PSP_INFO_PRINT("**** mismatch in swap! ****\n"); - PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes); - mismatch = true; - } - PSP_INFO_PRINT("[%d]%x!=%x ", i<<1, format.swapRedBlue16(debugSrc[i]), debugDst[i]); - } - } - if (mismatch) { - PSP_INFO_PRINT("\n"); - } else { - PSP_INFO_PRINT("ok\n"); - } -} - - void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) { PSP_DEBUG_PRINT("copy32Aligned(): dst32[%p], src32[%p], bytes[%d]\n", dst32, src32, bytes); int words8 = bytes >> 5; - + // try blocks of 8 words at a time if (words8) { while (words8--) { @@ -217,11 +110,11 @@ void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) dst32[7] = d; dst32 += 8; src32 += 8; - } + } } - + int words4 = (bytes & 0x1F) >> 4; - + // try blocks of 4 words at a time if (words4) { uint32 a, b, c, d; @@ -236,10 +129,10 @@ void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) dst32 += 4; src32 += 4; } - + int bytesLeft = (bytes & 0xF); // only look at bytes left after we did the above int wordsLeft = bytesLeft >> 2; - + // now just do single words while (wordsLeft) { *dst32++ = *src32++; @@ -252,55 +145,20 @@ void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) byte *dst = (byte *)dst32; byte *src = (byte *)src32; - + while (bytesLeft--) { *dst++ = *src++; } } -void PspMemory::swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format) { - DEBUG_ENTER_FUNC(); - int words4 = bytes >> 4; - - // try blocks of 4 words at a time - while (words4--) { - uint32 a, b, c, d; - a = format.swapRedBlue32(src32[0]); - b = format.swapRedBlue32(src32[1]); - c = format.swapRedBlue32(src32[2]); - d = format.swapRedBlue32(src32[3]); - dst32[0] = a; - dst32[1] = b; - dst32[2] = c; - dst32[3] = d; - dst32 += 4; - src32 += 4; - } - - uint32 bytesLeft = bytes & 0xF; - uint32 words = bytesLeft >> 2; - - // now just do words - while (words--) { - *dst32++ = format.swapRedBlue32(*src32++); - } - - bytesLeft = bytes & 0x3; - - if (bytesLeft) { // for swap, can only be 1 short left - *((uint16 *)dst32) = format.swapRedBlue16(*((uint16 *)src32)); - } -} - - // More challenging -- need to shift // Assume dst is aligned void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc) { PSP_DEBUG_PRINT("copy32Misaligned: dst32[%p], src[%p], bytes[%d], alignSrc[%d]\n", dst32, src, bytes, alignSrc); - + uint32 *src32 = (uint32 *)(((uint32)src) & 0xFFFFFFFC); // remove misalignment uint32 shiftValue, lastShiftValue; - + switch (alignSrc) { case 1: shiftValue = 8; @@ -320,9 +178,9 @@ void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, u // Try to do groups of 4 words uint32 words4 = bytes >> 4; - + srcWord = *src32; // preload 1st word so we read ahead - + for (; words4; words4--) { dstWord = srcWord >> shiftValue; srcWord = src32[1]; @@ -343,12 +201,12 @@ void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, u src32 += 4; dst32 += 4; } - + uint32 words = (bytes & 0xF) >> 2; // now get remaining words - + // we read one word ahead of what we write // setup the first read - + for (; words ;words--) { dstWord = srcWord >> shiftValue; srcWord = src32[1]; // we still go one ahead @@ -356,9 +214,9 @@ void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, u dstWord |= srcWord << lastShiftValue; *dst32++ = dstWord; } - + uint32 bytesLeft = bytes & 3; // and remaining bytes - + if (bytesLeft) { byte *dst8 = (byte *)dst32; byte *src8 = ((byte *)src32) + ((uint32)src & 0x3); // get exact location we should be at @@ -369,14 +227,137 @@ void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, u } } +void PspMemory::testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes) { + + bool mismatch = false; + PSP_INFO_PRINT("testing fastCopy..."); + + for (uint32 i = 0; i < debugBytes; i++) { + if (debugDst[i] != debugSrc[i]) { + if (!mismatch) { + PSP_INFO_PRINT("**** mismatch in copy! ****\n"); + PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes); + mismatch = true; + } + PSP_INFO_PRINT("[%d]%x!=%x ", i, debugSrc[i], debugDst[i]); + } + } + if (mismatch) { + PSP_INFO_PRINT("\n"); + } else { + PSP_INFO_PRINT("ok\n"); + } +} + +// +// used to swap red and blue +void PspMemorySwap::swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { + DEBUG_ENTER_FUNC(); + +#ifdef TEST_MEMORY_COPY + uint32 debugBytes = bytes; + const uint16 *debugDst = dst16, *debugSrc = src16; +#endif + + // align the destination pointer first + uint32 prefixDst = (((uint32)dst16) & 0x3); // for swap, we can only have 2 or 0 as our prefix + + if (prefixDst) { + bytes -= prefixDst; // remember we assume bytes > 4 + *dst16++ = format.swapRedBlue16(*src16++); + + if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue + swap16(dst16, src16, bytes, format); + +#ifdef TEST_MEMORY_COPY + testSwap(debugDst, debugSrc, debugBytes, format); +#endif + return; + } + } + + // check the source pointer alignment now + uint32 alignSrc = (((uint32)src16) & 0x3); + + if (alignSrc) { // we'll need to realign our reads + PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src16, dst16); + swap32Misaligned((uint32 *)dst16, src16, bytes, format); + } else { + swap32Aligned((uint32 *)dst16, (const uint32 *)src16, bytes, format); + } + +#ifdef TEST_MEMORY_COPY + testSwap(debugDst, debugSrc, debugBytes, format); +#endif + +} + +void PspMemorySwap::testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format) { + + bool mismatch = false; + PSP_INFO_PRINT("testing fastSwap..."); + + uint32 shorts = debugBytes >> 1; + + for (uint32 i = 0; i < shorts; i++) { + if (debugDst[i] != format.swapRedBlue16(debugSrc[i])) { + if (!mismatch) { + PSP_INFO_PRINT("**** mismatch in swap! ****\n"); + PSP_INFO_PRINT("dst[%p], src[%p], bytes[%u]\n", debugDst, debugSrc, debugBytes); + mismatch = true; + } + PSP_INFO_PRINT("[%d]%x!=%x ", i<<1, format.swapRedBlue16(debugSrc[i]), debugDst[i]); + } + } + if (mismatch) { + PSP_INFO_PRINT("\n"); + } else { + PSP_INFO_PRINT("ok\n"); + } +} + +void PspMemorySwap::swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format) { + DEBUG_ENTER_FUNC(); + int words4 = bytes >> 4; + + // try blocks of 4 words at a time + while (words4--) { + uint32 a, b, c, d; + a = format.swapRedBlue32(src32[0]); + b = format.swapRedBlue32(src32[1]); + c = format.swapRedBlue32(src32[2]); + d = format.swapRedBlue32(src32[3]); + dst32[0] = a; + dst32[1] = b; + dst32[2] = c; + dst32[3] = d; + dst32 += 4; + src32 += 4; + } + + uint32 bytesLeft = bytes & 0xF; + uint32 words = bytesLeft >> 2; + + // now just do words + while (words--) { + *dst32++ = format.swapRedBlue32(*src32++); + } + + bytesLeft = bytes & 0x3; + + if (bytesLeft) { // for swap, can only be 1 short left + *((uint16 *)dst32) = format.swapRedBlue16(*((uint16 *)src32)); + } +} + // More challenging -- need to shift // We assume dst is aligned -void PspMemory::swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { +void PspMemorySwap::swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { DEBUG_ENTER_FUNC(); const uint32 shiftValue = 16; uint32 *src32 = (uint32 *)(((uint32)src16) & 0xFFFFFFFC); // remove misalignment - + // Try to do groups of 4 words uint32 words4 = bytes >> 4; uint32 srcWord = src32[0]; // preload @@ -401,15 +382,15 @@ void PspMemory::swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 byte src32 += 4; dst32 += 4; } - + uint32 words = (bytes & 0xF) >> 2; - + // we read one word ahead of what we write // setup the first read if (words) { //srcWord = *src32++; // don't need this. already loaded src32++; // we already have the value loaded in - + while (words--) { uint32 dstWord = srcWord >> shiftValue; srcWord = *src32++; @@ -417,86 +398,10 @@ void PspMemory::swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 byte *dst32++ = format.swapRedBlue32(dstWord); } } - + uint32 bytesLeft = bytes & 3; - + if (bytesLeft) { // for swap, can only be 1 short left *((uint16 *)dst32) = format.swapRedBlue16((uint16)(srcWord >> shiftValue)); } } - -inline void PspMemory::copy16(uint16 *dst16, const uint16 *src16, uint32 bytes) { - PSP_DEBUG_PRINT("copy16(): dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes); - - uint32 shorts = bytes >> 1; - uint32 remainingBytes = bytes & 1; - - for (; shorts > 0 ; shorts--) { - *dst16++ = *src16++; - } - if (remainingBytes) - *(byte *)dst16 = *(byte *)src16; -} - -// Class VramAllocator ----------------------------------- - -DECLARE_SINGLETON(VramAllocator) - -//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ -//#define __PSP_DEBUG_PRINT__ - -#include "backends/platform/psp/trace.h" - - -void *VramAllocator::allocate(int32 size, bool smallAllocation /* = false */) { - DEBUG_ENTER_FUNC(); - assert(size > 0); - - byte *lastAddress = smallAllocation ? (byte *)VRAM_SMALL_ADDRESS : (byte *)VRAM_START_ADDRESS; - Common::List::iterator i; - - // Find a block that fits, starting from the beginning - for (i = _allocList.begin(); i != _allocList.end(); ++i) { - byte *currAddress = (*i).address; - - if (currAddress - lastAddress >= size) // We found a match - break; - - if ((*i).getEnd() > lastAddress) - lastAddress = (byte *)(*i).getEnd(); - } - - if (lastAddress + size > (byte *)VRAM_END_ADDRESS) { - PSP_DEBUG_PRINT("No space for allocation of %d bytes. %d bytes already allocated.\n", - size, _bytesAllocated); - return NULL; - } - - _allocList.insert(i, Allocation(lastAddress, size)); - _bytesAllocated += size; - - PSP_DEBUG_PRINT("Allocated in VRAM, size %u at %p.\n", size, lastAddress); - PSP_DEBUG_PRINT("Total allocated %u, remaining %u.\n", _bytesAllocated, (2 * 1024 * 1024) - _bytesAllocated); - - return lastAddress; -} - -// Deallocate a block from VRAM -void VramAllocator::deallocate(void *address) { - DEBUG_ENTER_FUNC(); - address = (byte *)CACHED(address); // Make sure all addresses are the same - - Common::List::iterator i; - - // Find the Allocator to deallocate - for (i = _allocList.begin(); i != _allocList.end(); ++i) { - if ((*i).address == address) { - _bytesAllocated -= (*i).size; - _allocList.erase(i); - PSP_DEBUG_PRINT("Deallocated address[%p], size[%u]\n", (*i).address, (*i).size); - return; - } - } - - PSP_DEBUG_PRINT("Address[%p] not allocated.\n", address); -} diff --git a/backends/platform/psp/memory.h b/backends/platform/psp/memory.h index 793bc948880..54e9225b2e5 100644 --- a/backends/platform/psp/memory.h +++ b/backends/platform/psp/memory.h @@ -27,18 +27,24 @@ #ifndef PSP_MEMORY_H #define PSP_MEMORY_H -#include "backends/platform/psp/psppixelformat.h" -#include "common/list.h" - -#define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */ -#define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */ - #define MIN_AMOUNT_FOR_COMPLEX_COPY 8 #define MIN_AMOUNT_FOR_MISALIGNED_COPY 8 //#define __PSP_DEBUG_PRINT__ -#include "backends/platform/psp/trace.h" +//#include "backends/platform/psp/trace.h" + +// These instructions don't generate automatically but are faster then copying byte by byte +inline void lwl_copy(byte *dst, const byte *src) { + register uint32 data; + asm volatile ("lwr %0,0(%1)\n\t" + "lwl %0,3(%1)\n\t" + : "=&r" (data) : "r" (src), "m" (*src)); + + asm volatile ("swr %1,0(%2)\n\t" + "swl %1,3(%2)\n\t" + : "=m" (*dst) : "r" (data), "r" (dst)); +} /** * Class that does memory copying and swapping if needed @@ -46,42 +52,69 @@ class PspMemory { private: static void testCopy(const byte *debugDst, const byte *debugSrc, uint32 debugBytes); - static void testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format); static void copy(byte *dst, const byte *src, uint32 bytes); - static void swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format); static void copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes); - static void swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format); static void copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc); - static void swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format); - static void copy16(uint16 *dst, const uint16 *src, uint32 bytes); - // For swapping, we know that we have multiples of 16 bits - static void swap16(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { - PSP_DEBUG_PRINT("swap16 called with dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes); - uint32 shorts = bytes >> 1; - - while (shorts--) { - *dst16++ = format.swapRedBlue16(*src16++); + static inline void copy8(byte *dst, const byte *src, int32 bytes) { + //PSP_DEBUG_PRINT("copy8 called with dst[%p], src[%p], bytes[%d]\n", dst, src, bytes); + uint32 words = bytes >> 2; + for (; words; words--) { + lwl_copy(dst, src); + dst += 4; + src += 4; } - } - - static void copy8(byte *dst, const byte *src, uint32 bytes) { - PSP_DEBUG_PRINT("copy8 called with dst[%p], src[%p], bytes[%d]\n", dst, src, bytes); - while (bytes--) { + + uint32 bytesLeft = bytes & 0x3; + for (; bytesLeft; bytesLeft--) { *dst++ = *src++; } } -public: +public: // This is the interface to the outside world - static void fastCopy(byte *dst, const byte *src, uint32 bytes) { + static void *fastCopy(void *dstv, const void *srcv, int32 bytes) { + byte *dst = (byte *)dstv; + byte *src = (byte *)srcv; + if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { copy8(dst, src, bytes); } else { // go to more powerful copy copy(dst, src, bytes); } - } + return dstv; + } +}; + +inline void *psp_memcpy(void *dst, const void *src, int32 bytes) { + return PspMemory::fastCopy(dst, src, bytes); +} + +#endif /* PSP_MEMORY_H */ + +#if defined(PSP_INCLUDE_SWAP) && !defined(PSP_MEMORY_SWAP_H) +#define PSP_MEMORY_SWAP_H + +//#include "backends/platform/psp/psppixelformat.h" + +class PspMemorySwap { +private: + static void testSwap(const uint16 *debugDst, const uint16 *debugSrc, uint32 debugBytes, PSPPixelFormat &format); + static void swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format); + static void swap32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes, PSPPixelFormat &format); + static void swap32Misaligned(uint32 *dst32, const uint16 *src16, uint32 bytes, PSPPixelFormat &format); + // For swapping, we know that we have multiples of 16 bits + static void swap16(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { + PSP_DEBUG_PRINT("swap16 called with dst16[%p], src16[%p], bytes[%d]\n", dst16, src16, bytes); + uint32 shorts = bytes >> 1; + + while (shorts--) { + *dst16++ = format.swapRedBlue16(*src16++); + } +} + +public: static void fastSwap(byte *dst, const byte *src, uint32 bytes, PSPPixelFormat &format) { if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY * 2) { swap16((uint16 *)dst, (uint16 *)src, bytes, format); @@ -91,41 +124,6 @@ public: } }; -/** - * Class that allocates memory in the VRAM - */ -class VramAllocator : public Common::Singleton { -public: - VramAllocator() : _bytesAllocated(0) {} - void *allocate(int32 size, bool smallAllocation = false); // smallAllocation e.g. palettes - void deallocate(void *pointer); - - static inline bool isAddressInVram(void *address) { - if ((uint32)(CACHED(address)) >= VRAM_START_ADDRESS && (uint32)(CACHED(address)) < VRAM_END_ADDRESS) - return true; - return false; - } +#endif /* PSP_INCLUDE_SWAP */ -private: - /** - * Used to allocate in VRAM - */ - struct Allocation { - byte *address; - uint32 size; - void *getEnd() { return address + size; } - Allocation(void *Address, uint32 Size) : address((byte *)Address), size(Size) {} - Allocation() : address(0), size(0) {} - }; - - enum { - VRAM_START_ADDRESS = 0x04000000, - VRAM_END_ADDRESS = 0x04200000, - VRAM_SMALL_ADDRESS = VRAM_END_ADDRESS - (4 * 1024) // 4K in the end for small allocations - }; - Common::List _allocList; // List of allocations - uint32 _bytesAllocated; -}; - -#endif /* PSP_MEMORY_H */ diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk index a854ec12525..e3eac153ddb 100644 --- a/backends/platform/psp/module.mk +++ b/backends/platform/psp/module.mk @@ -16,7 +16,10 @@ MODULE_OBJS := powerman.o \ thread.o \ rtc.o \ mp3.o \ - tests.o + png_loader.o \ + image_viewer.o \ + tests.o \ + dummy.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp index 98e8a0404bc..0e88418f13b 100644 --- a/backends/platform/psp/mp3.cpp +++ b/backends/platform/psp/mp3.cpp @@ -38,13 +38,13 @@ #include #include #include -#include +#include #include "backends/platform/psp/mp3.h" //#define DISABLE_PSP_MP3 // to make us use the regular MAD decoder instead //#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ -//#define __PSP_DEBUG_PRINT__ +//#define __PSP_DEBUG_PRINT__ #include "backends/platform/psp/trace.h" //#define PRINT_BUFFERS /* to debug MP3 buffers */ @@ -77,7 +77,7 @@ enum { bool Mp3PspStream::initDecoder() { DEBUG_ENTER_FUNC(); - + if (_decoderInit) { PSP_ERROR("Already initialized!"); return true; @@ -97,15 +97,15 @@ bool Mp3PspStream::initDecoder() { PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n"); _decoderFail = true; return false; - } - } else { + } + } else { if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) { PSP_ERROR("failed to load AVCODEC module. ME cannot start.\n"); _decoderFail = true; return false; } } - + PSP_DEBUG_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening _decoderInit = true; @@ -114,10 +114,10 @@ bool Mp3PspStream::initDecoder() { bool Mp3PspStream::stopDecoder() { DEBUG_ENTER_FUNC(); - + if (!_decoderInit) return true; - + // Based on PSP firmware version, we need to do different things to do Media Engine processing if (sceKernelDevkitVersion() == 0x01050001){ // TODO: how do we unload? /* if (!unloadAudioModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL) || @@ -130,10 +130,10 @@ bool Mp3PspStream::stopDecoder() { if (sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) < 0) { PSP_ERROR("failed to unload avcodec module\n"); return false; - } + } } - - _decoderInit = false; + + _decoderInit = false; return true; } @@ -176,26 +176,27 @@ Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse _length(0, 1000), _sampleRate(0), _totalTime(mad_timer_zero) { - + DEBUG_ENTER_FUNC(); assert(_decoderInit); // must be initialized by now - + // let's leave the buffer guard -- who knows, it may be good? memset(_buf, 0, sizeof(_buf)); memset(_codecInBuffer, 0, sizeof(_codecInBuffer)); - + initStream(); // init needed stuff for the stream findValidHeader(); // get a first header so we can read basic stuff - + _sampleRate = _header.samplerate; // copy it before it gets destroyed - + _stereo = (MAD_NCHANNELS(&_header) == 2); + while (_state != MP3_STATE_EOS) findValidHeader(); // get a first header so we can read basic stuff - + _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate()); - + deinitStream(); _state = MP3_STATE_INIT; @@ -221,7 +222,7 @@ int Mp3PspStream::initStream() { // Read the first few sample bytes into the buffer readMP3DataIntoBuffer(); - + return true; } @@ -229,7 +230,7 @@ bool Mp3PspStream::initStreamME() { // The following will eventually go into the thread memset(_codecParams, 0, sizeof(_codecParams)); - + // Init the MP3 hardware int ret = 0; ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002); @@ -244,22 +245,22 @@ bool Mp3PspStream::initStreamME() { return false; } PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret); - + PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate); _codecParams[10] = _sampleRate; - + ret = sceAudiocodecInit(_codecParams, 0x1002); if (ret < 0) { PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret); return false; } - + return true; } Mp3PspStream::~Mp3PspStream() { DEBUG_ENTER_FUNC(); - + deinitStream(); releaseStreamME(); // free the memory used for this stream @@ -276,17 +277,17 @@ void Mp3PspStream::deinitStream() { // Deinit MAD mad_header_finish(&_header); mad_stream_finish(&_stream); - + _state = MP3_STATE_EOS; } void Mp3PspStream::releaseStreamME() { sceAudiocodecReleaseEDRAM(_codecParams); -} +} void Mp3PspStream::decodeMP3Data() { DEBUG_ENTER_FUNC(); - + do { if (_state == MP3_STATE_INIT) { initStream(); @@ -295,17 +296,17 @@ void Mp3PspStream::decodeMP3Data() { if (_state == MP3_STATE_EOS) return; - + findValidHeader(); // seach for next valid header while (_state == MP3_STATE_READY) { // not a real 'while'. Just for easy flow _stream.error = MAD_ERROR_NONE; uint32 frame_size = _stream.next_frame - _stream.this_frame; - - updatePcmLength(); // Retrieve the number of PCM samples. + + updatePcmLength(); // Retrieve the number of PCM samples. // We seem to change this, so it needs to be dynamic - + PSP_DEBUG_PRINT("MP3 frame size[%d]. pcmLength[%d]\n", frame_size, _pcmLength); memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned @@ -315,7 +316,7 @@ void Mp3PspStream::decodeMP3Data() { _codecParams[8] = (unsigned long)_pcmSamples; _codecParams[7] = frame_size; _codecParams[9] = _pcmLength * 2; // x2 for stereo, though this one's not so important - + // debug #ifdef PRINT_BUFFERS PSP_DEBUG_PRINT("mp3 frame:\n"); @@ -415,10 +416,13 @@ bool Mp3PspStream::seek(const Timestamp &where) { mad_timer_t destination; mad_timer_set(&destination, time / 1000, time % 1000, 1000); + // Important to release and re-init the ME + releaseStreamME(); + initStreamME(); + // Check if we need to rewind if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) { initStream(); - initStreamME(); } // Skip ahead @@ -469,38 +473,38 @@ int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) { DEBUG_ENTER_FUNC(); int samples = 0; -#ifdef PRINT_BUFFERS +#ifdef PRINT_BUFFERS int16 *debugBuffer = buffer; -#endif - +#endif + // Keep going as long as we have input available while (samples < numSamples && _state != MP3_STATE_EOS) { const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header)); - + while (samples < len) { *buffer++ = _pcmSamples[_posInFrame << 1]; samples++; if (MAD_NCHANNELS(&_header) == 2) { *buffer++ = _pcmSamples[(_posInFrame << 1) + 1]; samples++; - } + } _posInFrame++; // always skip an extra sample since ME always outputs stereo } - + if (_posInFrame >= _pcmLength) { // We used up all PCM data in the current frame -- read & decode more decodeMP3Data(); } } - + #ifdef PRINT_BUFFERS PSP_INFO_PRINT("buffer:\n"); for (int i = 0; i> 1, PSP_SCREEN_HEIGHT >> 1); // Mouse in the middle of the screen @@ -76,12 +76,18 @@ void OSystem_PSP::initBackend() { _displayManager.setScreen(&_screen); _displayManager.setOverlay(&_overlay); _displayManager.setKeyboard(&_keyboard); + _displayManager.setImageViewer(&_imageViewer); _displayManager.init(); // Set pointers for input handler _inputHandler.setCursor(&_cursor); _inputHandler.setKeyboard(&_keyboard); + _inputHandler.setImageViewer(&_imageViewer); _inputHandler.init(); + + // Set pointers for image viewer + _imageViewer.setInputHandler(&_inputHandler); + _imageViewer.setDisplayManager(&_displayManager); _savefile = new PSPSaveFileManager; @@ -97,6 +103,12 @@ void OSystem_PSP::initBackend() { OSystem::initBackend(); } +// Let's us know an engine +void OSystem_PSP::engineDone() { + // for now, all we need is to reset the image number on the viewer + _imageViewer.resetOnEngineDone(); +} + bool OSystem_PSP::hasFeature(Feature f) { return (f == kFeatureOverlaySupportsAlpha || f == kFeatureCursorHasPalette); } @@ -148,7 +160,7 @@ Common::List OSystem_PSP::getSupportedFormats() const { void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; _displayManager.setSizeAndPixelFormat(width, height, format); _cursor.setVisible(false); @@ -167,7 +179,7 @@ int16 OSystem_PSP::getHeight() { void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; _screen.setPartialPalette(colors, start, num); _cursor.setScreenPalette(colors, start, num); _cursor.clearKeyColor(); @@ -175,7 +187,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; + _pendingUpdate = false; _cursor.setCursorPalette(colors, start, num); _cursor.enableCursorPalette(true); _cursor.clearKeyColor(); // Do we need this? @@ -183,25 +195,25 @@ void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) { void OSystem_PSP::disableCursorPalette(bool disable) { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _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; + _pendingUpdate = false; _screen.copyFromRect(buf, pitch, x, y, w, h); } Graphics::Surface *OSystem_PSP::lockScreen() { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; return _screen.lockAndGetForEditing(); } void OSystem_PSP::unlockScreen() { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; // The screen is always completely updated anyway, so we don't have to force a full update here. _screen.unlock(); } @@ -219,7 +231,7 @@ void OSystem_PSP::setShakePos(int shakeOffset) { void OSystem_PSP::showOverlay() { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; _overlay.setVisible(true); _cursor.setLimits(_overlay.getWidth(), _overlay.getHeight()); _cursor.useGlobalScaler(false); // mouse with overlay is 1:1 @@ -227,7 +239,7 @@ void OSystem_PSP::showOverlay() { void OSystem_PSP::hideOverlay() { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; _overlay.setVisible(false); _cursor.setLimits(_screen.getWidth(), _screen.getHeight()); _cursor.useGlobalScaler(true); // mouse needs to be scaled with screen @@ -235,7 +247,7 @@ void OSystem_PSP::hideOverlay() { void OSystem_PSP::clearOverlay() { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _pendingUpdate = false; _overlay.clearBuffer(); } @@ -246,7 +258,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; + _pendingUpdate = false; _overlay.copyFromRect(buf, pitch, x, y, w, h); } @@ -266,7 +278,7 @@ 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); @@ -276,14 +288,14 @@ bool OSystem_PSP::showMouse(bool v) { void OSystem_PSP::warpMouse(int x, int y) { DEBUG_ENTER_FUNC(); - _pendingUpdate = false; + _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; - + _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); @@ -310,16 +322,16 @@ bool OSystem_PSP::pollEvent(Common::Event &event) { // 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; + _pendingUpdateCounter = 0; } - } else + } else _pendingUpdateCounter = 0; // reset the counter, no pending - + return _inputHandler.getAllInputs(event); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 5721296c94e..52b8f4e8877 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -32,10 +32,12 @@ #include "sound/mixer_intern.h" #include "backends/base-backend.h" #include "backends/fs/psp/psp-fs-factory.h" + #include "backends/platform/psp/display_client.h" #include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/cursor.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/image_viewer.h" #include "backends/platform/psp/display_manager.h" #include "backends/platform/psp/input.h" #include "backends/platform/psp/audio.h" @@ -60,6 +62,7 @@ private: InputHandler _inputHandler; PspAudio _audio; PspTimer _pspTimer; + ImageViewer _imageViewer; public: OSystem_PSP() : _savefile(0), _mixer(0), _timer(0), _pendingUpdate(false), _pendingUpdateCounter(0) {} @@ -146,6 +149,7 @@ public: Common::SaveFileManager *getSavefileManager() { return _savefile; } FilesystemFactory *getFilesystemFactory() { return &PSPFilesystemFactory::instance(); } void getTimeAndDate(TimeDate &t) const; + virtual void engineDone(); void quit(); diff --git a/backends/platform/psp/png_loader.cpp b/backends/platform/psp/png_loader.cpp new file mode 100644 index 00000000000..08f370f36db --- /dev/null +++ b/backends/platform/psp/png_loader.cpp @@ -0,0 +1,210 @@ +/* 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$ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/scummsys.h" +#include "common/stream.h" +#include "backends/platform/psp/psppixelformat.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/png_loader.h" + +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ + +#include "backends/platform/psp/trace.h" + +PngLoader::Status PngLoader::allocate() { + DEBUG_ENTER_FUNC(); + + if (!findImageDimensions()) { + PSP_ERROR("failed to get image dimensions\n"); + return BAD_FILE; + } + + _buffer->setSize(_width, _height, _sizeBy); + + uint32 bitsPerPixel = _bitDepth * _channels; + + if (_paletteSize) { // 8 or 4-bit image + if (bitsPerPixel == 4) { + _buffer->setPixelFormat(PSPPixelFormat::Type_Palette_4bit); + _palette->setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_4bit); + _paletteSize = 16; // round up + } else if (bitsPerPixel == 8) { // 8-bit image + _buffer->setPixelFormat(PSPPixelFormat::Type_Palette_8bit); + _palette->setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_8bit); + _paletteSize = 256; // round up + } else { + PSP_ERROR("too many bits per pixel[%d] for a palette\n", bitsPerPixel); + return BAD_FILE; + } + + } else { // 32-bit image + _buffer->setPixelFormat(PSPPixelFormat::Type_8888); + } + + if (!_buffer->allocate()) { + PSP_ERROR("failed to allocate buffer\n"); + return OUT_OF_MEMORY; + } + if (_buffer->hasPalette() && !_palette->allocate()) { + PSP_ERROR("failed to allocate palette\n"); + return OUT_OF_MEMORY; + } + return OK; +} + +bool PngLoader::load() { + DEBUG_ENTER_FUNC(); + // Try to load the image + _file->seek(0); // Go back to start + + if (!loadImageIntoBuffer()) { + PSP_DEBUG_PRINT("failed to load image\n"); + return false; + } + + PSP_DEBUG_PRINT("succeded in loading image\n"); + + if (_paletteSize == 16) // 4-bit + _buffer->flipNibbles(); // required because of PNG 4-bit format + return true; +} + +void PngLoader::warningFn(png_structp png_ptr, png_const_charp warning_msg) { + // ignore PNG warnings +} + +// Read function for png library to be able to read from our SeekableReadStream +// +void PngLoader::libReadFunc(png_structp pngPtr, png_bytep data, png_size_t length) { + Common::SeekableReadStream *file; + + file = (Common::SeekableReadStream *)pngPtr->io_ptr; + + file->read(data, length); +} + +bool PngLoader::basicImageLoad() { + DEBUG_ENTER_FUNC(); + _pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!_pngPtr) + return false; + + png_set_error_fn(_pngPtr, (png_voidp) NULL, (png_error_ptr) NULL, warningFn); + + _infoPtr = png_create_info_struct(_pngPtr); + if (!_infoPtr) { + png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL); + return false; + } + // Set the png lib to use our read function + png_set_read_fn(_pngPtr, (void *)_file, libReadFunc); + + unsigned int sig_read = 0; + + png_set_sig_bytes(_pngPtr, sig_read); + png_read_info(_pngPtr, _infoPtr); + int interlaceType; + png_get_IHDR(_pngPtr, _infoPtr, (png_uint_32 *)&_width, (png_uint_32 *)&_height, &_bitDepth, + &_colorType, &interlaceType, int_p_NULL, int_p_NULL); + _channels = png_get_channels(_pngPtr, _infoPtr); + + if (_colorType & PNG_COLOR_MASK_PALETTE) + _paletteSize = _infoPtr->num_palette; + + return true; +} + +/* Get the width and height of a png image */ +bool PngLoader::findImageDimensions() { + DEBUG_ENTER_FUNC(); + + bool status = basicImageLoad(); + + PSP_DEBUG_PRINT("width[%d], height[%d], paletteSize[%d], bitDepth[%d], channels[%d], rowBytes[%d]\n", _width, _height, _paletteSize, _bitDepth, _channels, _infoPtr->rowbytes); + png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); + return status; +} + +// +// Load a texture from a png image +// +bool PngLoader::loadImageIntoBuffer() { + DEBUG_ENTER_FUNC(); + + if (!basicImageLoad()) { + png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); + return false; + } + png_set_strip_16(_pngPtr); // Strip off 16 bit channels in case they occur + + if (_paletteSize) { + // Copy the palette + png_colorp srcPal = _infoPtr->palette; + for (int i = 0; i < _infoPtr->num_palette; i++) { + unsigned char alphaVal = (i < _infoPtr->num_trans) ? _infoPtr->trans[i] : 0xFF; // Load alpha if it's there + _palette->setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal); + srcPal++; + } + } else { // Not a palettized image + if (_colorType == PNG_COLOR_TYPE_GRAY && _bitDepth < 8) + png_set_gray_1_2_4_to_8(_pngPtr); // Round up grayscale images + if (png_get_valid(_pngPtr, _infoPtr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(_pngPtr); // Convert trans channel to alpha for 32 bits + + png_set_add_alpha(_pngPtr, 0xff, PNG_FILLER_AFTER); // Filler for alpha if none exists + } + + uint32 rowBytes = png_get_rowbytes(_pngPtr, _infoPtr); + + // there seems to be a bug in libpng where it doesn't increase the rowbytes or the + // channel even after we add the alpha channel + if (_channels == 3 && (rowBytes / _width) == 3) { + _channels = 4; + rowBytes = _width * _channels; + } + + PSP_DEBUG_PRINT("rowBytes[%d], channels[%d]\n", rowBytes, _channels); + + unsigned char *line = (unsigned char*) malloc(rowBytes); + if (!line) { + png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL); + PSP_ERROR("Couldn't allocate line\n"); + return false; + } + + for (size_t y = 0; y < _height; y++) { + png_read_row(_pngPtr, line, png_bytep_NULL); + _buffer->copyFromRect(line, rowBytes, 0, y, _width, 1); // Copy into buffer + } + free(line); + png_read_end(_pngPtr, _infoPtr); + png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); + + return true; +} diff --git a/backends/platform/psp/png_loader.h b/backends/platform/psp/png_loader.h new file mode 100644 index 00000000000..4119bfef2b3 --- /dev/null +++ b/backends/platform/psp/png_loader.h @@ -0,0 +1,74 @@ +/* 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 PSP_PNG_IMAGE_H +#define PSP_PNG_IMAGE_H + +#include + +class PngLoader { +private: + bool basicImageLoad(); // common operation + bool findImageDimensions(); // find dimensions of a given PNG file + bool loadImageIntoBuffer(); + + static void warningFn(png_structp png_ptr, png_const_charp warning_msg); + static void libReadFunc(png_structp pngPtr, png_bytep data, png_size_t length); + + Common::SeekableReadStream *_file; + Buffer *_buffer; + Palette *_palette; + + uint32 _width; + uint32 _height; + uint32 _paletteSize; + Buffer::HowToSize _sizeBy; + + // PNG lib values + int _bitDepth; + png_structp _pngPtr; + png_infop _infoPtr; + int _colorType; + uint32 _channels; + +public: + enum Status { + OK, + OUT_OF_MEMORY, + BAD_FILE + }; + + PngLoader(Common::SeekableReadStream *file, Buffer &buffer, Palette &palette, + Buffer::HowToSize sizeBy = Buffer::kSizeByTextureSize) : + _file(file), _buffer(&buffer), _palette(&palette), + _width(0), _height(0), _paletteSize(0), + _bitDepth(0), _sizeBy(sizeBy), _pngPtr(0), + _infoPtr(0), _colorType(0), _channels(0) {} + + PngLoader::Status allocate(); + bool load(); +}; + +#endif /* PSP_PNG_IMAGE_H */ diff --git a/backends/platform/psp/powerman.cpp b/backends/platform/psp/powerman.cpp index eaadad16c57..869d9b3023e 100644 --- a/backends/platform/psp/powerman.cpp +++ b/backends/platform/psp/powerman.cpp @@ -84,7 +84,7 @@ bool PowerManager::unregisterForSuspend(Suspendable *item) { // Unregister from stream list _listMutex.lock(); - + _suspendList.remove(item); _listCounter--; @@ -114,11 +114,11 @@ PowerManager::~PowerManager() { ********************************************/ void PowerManager::pollPauseEngine() { DEBUG_ENTER_FUNC(); - - + + bool pause = _pauseFlag; // We copy so as not to have multiple values - if (pause != _pauseFlagOld) { + 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 @@ -147,7 +147,7 @@ bool PowerManager::beginCriticalSection() { DEBUG_ENTER_FUNC(); bool ret = false; - + _flagMutex.lock(); // Check the access flag @@ -156,7 +156,7 @@ bool PowerManager::beginCriticalSection() { PSP_DEBUG_PRINT("I got blocked. ThreadId[%x]\n", sceKernelGetThreadId()); debugPM(); - + _threadSleep.wait(_flagMutex); PSP_DEBUG_PRINT_FUNC("I got released. ThreadId[%x]\n", sceKernelGetThreadId()); @@ -184,11 +184,11 @@ void PowerManager::endCriticalSection() { 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(); } @@ -198,7 +198,7 @@ void PowerManager::endCriticalSection() { } } - _flagMutex.unlock(); + _flagMutex.unlock(); } /******************************************* @@ -209,7 +209,7 @@ void PowerManager::endCriticalSection() { void PowerManager::suspend() { DEBUG_ENTER_FUNC(); - if (_pauseFlag) + if (_pauseFlag) return; // Very important - make sure we only suspend once scePowerLock(0); // Also critical to make sure PSP doesn't suspend before we're done @@ -232,9 +232,9 @@ void PowerManager::suspend() { PspThread::delayMicros(50000); // We wait 50 msec at a time } - // It's possible that the polling thread missed our pause event, but there's + // 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. + // We can't know if there's polling going on or not. // It's usually not a critical thing anyway. _PMStatus = kGettingFlagMutexSuspend; @@ -249,12 +249,12 @@ void PowerManager::suspend() { // Check if anyone is in a critical section. If so, we'll wait for them if (_criticalCounter > 0) { _PMStatus = kWaitCritSectionSuspend; - + _pmSleep.wait(_flagMutex); - + _PMStatus = kDoneWaitingCritSectionSuspend; - } - + } + _flagMutex.unlock(); _PMStatus = kGettingListMutexSuspend; @@ -275,7 +275,7 @@ void PowerManager::suspend() { _PMStatus = kDoneSuspend; scePowerUnlock(0); // Allow the PSP to go to sleep now - + _PMStatus = kDonePowerUnlock; } @@ -286,22 +286,22 @@ void PowerManager::suspend() { ********************************************/ void PowerManager::resume() { DEBUG_ENTER_FUNC(); - + _PMStatus = kBeginResume; // Make sure we can't get another suspend scePowerLock(0); _PMStatus = kCheckingPauseFlag; - - if (!_pauseFlag) + + if (!_pauseFlag) return; // Make sure we can only resume once _PMStatus = kGettingListMutexResume; // First we notify our Suspendables. Loop over list, calling resume() _listMutex.lock(); - + _PMStatus = kIteratingListResume; // Iterate @@ -314,12 +314,12 @@ void PowerManager::resume() { _PMStatus = kDoneIteratingListResume; _listMutex.unlock(); - + _PMStatus = kGettingFlagMutexResume; // Now we set the suspend flag to false _flagMutex.lock(); - + _PMStatus = kGotFlagMutexResume; _suspendFlag = false; @@ -328,11 +328,11 @@ void PowerManager::resume() { // Signal the threads to wake up _threadSleep.releaseAll(); - + _PMStatus = kDoneSignallingSuspendedThreadsResume; _flagMutex.unlock(); - + _PMStatus = kDoneResume; _pauseFlag = false; // Signal engine to unpause -- no mutex needed diff --git a/backends/platform/psp/psp.spec b/backends/platform/psp/psp.spec index ac325b7fd6b..71774133735 100644 --- a/backends/platform/psp/psp.spec +++ b/backends/platform/psp/psp.spec @@ -1,3 +1,3 @@ %rename lib old_lib *lib: -%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspaudiocodec -lpspkernel +%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspaudiocodec -lpspkernel -lpspnet_inet diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index 41cf4513236..019f6c12d1f 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -103,7 +103,7 @@ int exit_callback(void) { #ifdef ENABLE_PROFILING gprof_cleanup(); -#endif +#endif sceKernelExitGame(); return 0; @@ -170,12 +170,12 @@ int main(void) { #endif /* unit/speed tests */ -#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) +#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) PSP_INFO_PRINT("running tests\n"); psp_tests(); sceKernelSleepThread(); // that's it. That's all we're doing #endif - + int res = scummvm_main(argc, argv); g_system->quit(); // TODO: Consider removing / replacing this! diff --git a/backends/platform/psp/pspkeyboard.cpp b/backends/platform/psp/pspkeyboard.cpp index eb081fc5f45..f2107266927 100644 --- a/backends/platform/psp/pspkeyboard.cpp +++ b/backends/platform/psp/pspkeyboard.cpp @@ -23,19 +23,23 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + //#define PSP_KB_SHELL /* Need a hack to properly load the keyboard from the PSP shell */ #ifdef PSP_KB_SHELL -#define PSP_KB_SHELL_PATH "ms0:/psp/game4xx/scummvm-solid/" /* path to kbd.zip */ +#define PSP_KB_SHELL_PATH "ms0:/psp/game5xx/scummvm-solid/" /* path to kbd.zip */ #endif #include #include -#include #include "backends/platform/psp/psppixelformat.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/png_loader.h" +#include "backends/platform/psp/input.h" #include "common/keyboard.h" #include "common/fs.h" #include "common/unzip.h" @@ -77,9 +81,9 @@ short PSPKeyboard::_modeChar[MODE_COUNT][5][6] = { }, { //numbers { K('1'), K('2'), K('3'), K('4'), K(0), K(0) }, - { C(F5), C(F8), C(F7), C(F6), C(F9), C(F10) }, + { C(F5), C(F6), C(F7), C(F8), C(F9), C(F10) }, { K('5'), K('6'), K('7'), K('8'), K(0), K(0) }, - { C(F1), C(F4), C(F3), C(F2), K(0), K(0) }, + { C(F1), C(F2), C(F3), C(F4), K(0), K(0) }, { K('\b'), K('0'), K(' '), K('9'), K(0), K(0) } }, { //symbols @@ -91,16 +95,6 @@ short PSPKeyboard::_modeChar[MODE_COUNT][5][6] = { } }; -// Read function for png library to be able to read from our SeekableReadStream -// -void pngReadStreamRead(png_structp png_ptr, png_bytep data, png_size_t length) { - Common::SeekableReadStream *file; - - file = (Common::SeekableReadStream *)png_ptr->io_ptr; - - file->read(data, length); -} - // Array with file names const char *PSPKeyboard::_guiStrings[] = { "keys4.png", "keys_s4.png", @@ -281,8 +275,6 @@ bool PSPKeyboard::load() { // Loop through all png images for (i = 0; i < guiStringsSize; i++) { - uint32 height = 0, width = 0, paletteSize = 0; - PSP_DEBUG_PRINT("Opening %s.\n", _guiStrings[i]); // Look for the file in the kbd directory @@ -309,49 +301,18 @@ bool PSPKeyboard::load() { goto ERROR; } - if (getPngImageSize(file, &width, &height, &paletteSize) == 0) { // Check image size and palette size - // Allocate memory for image - PSP_DEBUG_PRINT("width[%d], height[%d], paletteSize[%d]\n", width, height, paletteSize); - _buffers[i].setSize(width, height, Buffer::kSizeByTextureSize); + PngLoader image(file, _buffers[i], _palettes[i]); - if (paletteSize) { // 8 or 4-bit image - if (paletteSize <= 16) { // 4 bit - _buffers[i].setPixelFormat(PSPPixelFormat::Type_Palette_4bit); - _palettes[i].setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_4bit); - paletteSize = 16; - } else if (paletteSize <= 256) { // 8-bit image - paletteSize = 256; - _buffers[i].setPixelFormat(PSPPixelFormat::Type_Palette_8bit); - _palettes[i].setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_8bit); - } else { - PSP_ERROR("palette of %d too big!\n", paletteSize); - goto ERROR; - } - - } else { // 32-bit image - _buffers[i].setPixelFormat(PSPPixelFormat::Type_8888); - } - - _buffers[i].allocate(); - _palettes[i].allocate(); - - // Try to load the image - file->seek(0); // Go back to start - - if (loadPngImage(file, _buffers[i], _palettes[i]) != 0) - goto ERROR; - else { // Success - PSP_DEBUG_PRINT("Managed to load the image\n"); - - if (paletteSize == 16) // 4-bit - _buffers[i].flipNibbles(); - - delete file; - } - } else { - PSP_ERROR("couldn't obtain PNG image size\n"); + if (image.allocate() != PngLoader::OK) { + PSP_ERROR("Failed to allocate memory for keyboard image %s\n", _guiStrings[i]); goto ERROR; } + if (!image.load()) { + PSP_ERROR("Failed to load image from file %s\n", _guiStrings[i]); + goto ERROR; + } + + delete file; } /* for loop */ _init = true; @@ -376,124 +337,6 @@ ERROR: return false; } -static void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) { - // ignore PNG warnings -} - -/* Get the width and height of a png image */ -int PSPKeyboard::getPngImageSize(Common::SeekableReadStream *file, uint32 *png_width, uint32 *png_height, u32 *paletteSize) { - DEBUG_ENTER_FUNC(); - - png_structp png_ptr; - png_infop info_ptr; - unsigned int sig_read = 0; - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - return -1; - } - png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn); - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - return -1; - } - // Set the png lib to use our read function - png_set_read_fn(png_ptr, (void *)file, pngReadStreamRead); - - png_set_sig_bytes(png_ptr, sig_read); - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); - if (color_type & PNG_COLOR_MASK_PALETTE) - *paletteSize = info_ptr->num_palette; - else - *paletteSize = 0; - - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - - *png_width = width; - *png_height = height; - - return 0; -} - -// Load a texture from a png image -// -int PSPKeyboard::loadPngImage(Common::SeekableReadStream *file, Buffer &buffer, Palette &palette) { - DEBUG_ENTER_FUNC(); - - png_structp png_ptr; - png_infop info_ptr; - unsigned int sig_read = 0; - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; - size_t y; - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) { - PSP_ERROR("Couldn't create read struct to load keyboard\n"); - return -1; - } - // Use dummy error function - png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn); - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - PSP_ERROR("Couldn't create info struct to load keyboard\n"); - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - return -1; - } - - // Set the png lib to use our customized read function - png_set_read_fn(png_ptr, (void *)file, pngReadStreamRead); - - png_set_sig_bytes(png_ptr, sig_read); - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); - - // Strip off 16 bit channels. Not really needed but whatever - png_set_strip_16(png_ptr); - - if (color_type == PNG_COLOR_TYPE_PALETTE) { - // Copy the palette - png_colorp srcPal = info_ptr->palette; - for (int i = 0; i < info_ptr->num_palette; i++) { - unsigned char alphaVal = (i < info_ptr->num_trans) ? info_ptr->trans[i] : 0xFF; // Load alpha if it's there - palette.setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal); - srcPal++; - } - } else { // Not a palettized image - // Round up grayscale images - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); - // Convert trans channel to alpha for 32 bits - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); - // Filler for alpha? - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - } - - unsigned char *line = (unsigned char*) malloc(info_ptr->rowbytes); - if (!line) { - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - PSP_ERROR("Couldn't allocate line\n"); - return -1; - } - - for (y = 0; y < height; y++) { - png_read_row(png_ptr, line, png_bytep_NULL); - buffer.copyFromRect(line, info_ptr->rowbytes, 0, y, width, 1); // Copy into buffer - //memcpy(buffer.getPixels()[y * buffer.getWidthInBytes()], line, info_ptr->rowbytes); - } - - free(line); - - png_read_end(png_ptr, info_ptr); - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - - return 0; -} - // Defines for working with PSP buttons #define CHANGED(x) (_buttonsChanged & (x)) #define PRESSED(x) ((_buttonsChanged & (x)) && (pad.Buttons & (x))) @@ -508,10 +351,11 @@ int PSPKeyboard::loadPngImage(Common::SeekableReadStream *file, Buffer &buffer, * Uses the state machine. * returns whether we have an event */ -bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { +bool PSPKeyboard::processInput(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) { DEBUG_ENTER_FUNC(); bool haveEvent = false; // Whether we have an event for the event manager to process + bool havePspEvent = false; event.kbd.flags = 0; _buttonsChanged = _prevButtons ^ pad.Buttons; @@ -530,11 +374,11 @@ bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { haveEvent = true; _dirty = true; if (UP(PSP_CTRL_START)) - _state = kInvisible; // Make us invisible if unpressed + havePspEvent = true; } // Check for being in state of moving the keyboard onscreen or pressing select else if (_state == kMove) - handleMoveState(pad); + havePspEvent = handleMoveState(pad); else if (_state == kDefault) haveEvent = handleDefaultState(event, pad); else if (_state == kCornersSelected) @@ -544,12 +388,16 @@ bool PSPKeyboard::processInput(Common::Event &event, SceCtrlData &pad) { else if (_state == kLTriggerDown) handleLTriggerDownState(pad); // Deal with trigger states + if (havePspEvent) { + pspEvent.type = PSP_EVENT_SHOW_VIRTUAL_KB; // tell the input handler we're off + pspEvent.data = false; + } _prevButtons = pad.Buttons; return haveEvent; } -void PSPKeyboard::handleMoveState(SceCtrlData &pad) { +bool PSPKeyboard::handleMoveState(SceCtrlData &pad) { DEBUG_ENTER_FUNC(); if (UP(PSP_CTRL_SELECT)) { // Toggle between visible and invisible @@ -560,6 +408,9 @@ void PSPKeyboard::handleMoveState(SceCtrlData &pad) { _state = kDefault; _moved = false; // reset moved flag } + if (_state == kInvisible) { + return true; // we become invisible + } } else if (DOWN(PSP_DPAD)) { // How we move the KB onscreen _moved = true; _dirty = true; @@ -573,6 +424,7 @@ void PSPKeyboard::handleMoveState(SceCtrlData &pad) { else /* DOWN(PSP_CTRL_RIGHT) */ increaseKeyboardLocationX(5); } + return false; } bool PSPKeyboard::handleDefaultState(Common::Event &event, SceCtrlData &pad) { diff --git a/backends/platform/psp/pspkeyboard.h b/backends/platform/psp/pspkeyboard.h index a30e7d0f32c..ebf21cfd540 100644 --- a/backends/platform/psp/pspkeyboard.h +++ b/backends/platform/psp/pspkeyboard.h @@ -29,12 +29,15 @@ #include "common/events.h" #include "common/stream.h" #include "backends/platform/psp/display_client.h" +//#include "backends/platform/psp/input.h" #include //number of modes #define MODE_COUNT 4 #define guiStringsSize 8 /* size of guistrings array */ +class PspEvent; + class PSPKeyboard : public DisplayClient { private: @@ -58,10 +61,9 @@ public: void setClean() { _dirty = false; } bool isVisible() const { return _state != kInvisible; } // Check if visible void setVisible(bool val); - bool processInput(Common::Event &event, SceCtrlData &pad); // Process input + bool processInput(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); // Process input void moveTo(const int newX, const int newY); // Move keyboard void render(); // Draw the keyboard onscreen - private: enum CursorDirections { kUp = 0, @@ -75,14 +77,11 @@ private: Palette _palettes[guiStringsSize]; GuRenderer _renderer; - int loadPngImage(Common::SeekableReadStream *file, Buffer &buffer, Palette &palette); - int getPngImageSize(Common::SeekableReadStream *, uint32 *png_width, uint32 *png_height, uint32 *paletteSize); - uint32 convert_pow2(uint32 size); void increaseKeyboardLocationX(int amount); // Move keyboard onscreen void increaseKeyboardLocationY(int amount); void convertCursorToXY(CursorDirections cur, int &x, int &y); - void handleMoveState(SceCtrlData &pad); + bool handleMoveState(SceCtrlData &pad); bool handleDefaultState(Common::Event &event, SceCtrlData &pad); bool handleCornersSelectedState(Common::Event &event, SceCtrlData &pad); bool getInputChoice(Common::Event &event, SceCtrlData &pad); diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp index 57edea7e491..f26e5770a61 100644 --- a/backends/platform/psp/rtc.cpp +++ b/backends/platform/psp/rtc.cpp @@ -23,13 +23,13 @@ * */ -#include +#include #include #include - -#include "common/scummsys.h" -#include "backends/platform/psp/rtc.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 */ @@ -51,13 +51,13 @@ void PspRtc::init() { // init our starting ticks #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 +// 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 @@ -66,22 +66,22 @@ uint32 PspRtc::getMillis() { _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; - + + _lastMillis = millis; + return millis + _milliOffset; } uint32 PspRtc::getMicros() { uint32 ticks[2]; - + sceRtcGetCurrentTick((u64 *)ticks); ticks[0] -= _startMicros; - - return ticks[0]; + + return ticks[0]; } diff --git a/backends/platform/psp/rtc.h b/backends/platform/psp/rtc.h index 7c1a28474d3..841d636e2be 100644 --- a/backends/platform/psp/rtc.h +++ b/backends/platform/psp/rtc.h @@ -27,7 +27,7 @@ #define _PSP_RTC_H_ #include "common/singleton.h" - + class PspRtc : public Common::Singleton { private: uint32 _startMillis; @@ -47,4 +47,4 @@ public: uint32 getMicros(); }; -#endif \ No newline at end of file +#endif diff --git a/backends/platform/psp/tests.cpp b/backends/platform/psp/tests.cpp index f65c13ae83b..4064ee1d980 100644 --- a/backends/platform/psp/tests.cpp +++ b/backends/platform/psp/tests.cpp @@ -23,13 +23,13 @@ * */ -// PSP speed and unit tests. Activate in tests.h -// You may also want to build without any engines. - +// PSP speed and unit tests. Activate in tests.h +// You may also want to build without any engines. + #include "backends/platform/psp/tests.h" -#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) - +#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) + #include "common/scummsys.h" #include #include @@ -49,16 +49,16 @@ #define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */ #define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */ - + //#define __PSP_DEBUG_FUNCS__ //#define __PSP_DEBUG_PRINT__ - + // Results: (333Mhz/222Mhz) // Getting a tick: 1-2 us // Getting a time structure: 9/14us // ie. using a tick and just dividing by 1000 saves us time. - -#include "backends/platform/psp/trace.h" + +#include "backends/platform/psp/trace.h" class PspSpeedTests { public: @@ -67,11 +67,11 @@ public: void seekSpeed(); void msReadSpeed(); void threadFunctionsSpeed(); - void semaphoreSpeed(); + void semaphoreSpeed(); static int threadFunc(SceSize args, void *argp); void semaphoreManyThreadSpeed(); void fastCopySpeed(); - + private: enum { MEMCPY_BUFFER_SIZE = 8192 @@ -95,16 +95,16 @@ void PspSpeedTests::tickSpeed() { uint32 currentTicks1[2]; uint32 currentTicks2[2]; - + sceRtcGetCurrentTick((u64 *)currentTicks1); sceRtcGetCurrentTick((u64 *)currentTicks2); PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks1[0], currentTicks1[1], currentTicks1[0], currentTicks1[1]); PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks2[0], currentTicks2[1], currentTicks2[0], currentTicks2[1]); - + pspTime time; sceRtcSetTick(&time, (u64 *)currentTicks2); - PSP_INFO_PRINT("current tick in time, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time.year, time.month, time.day, time.hour, time.minutes, time.seconds, time.microseconds); - + PSP_INFO_PRINT("current tick in time, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time.year, time.month, time.day, time.hour, time.minutes, time.seconds, time.microseconds); + pspTime time1; pspTime time2; sceRtcGetCurrentClockLocalTime(&time1); @@ -119,7 +119,7 @@ void PspSpeedTests::getMicrosSpeed() { time2 = PspRtc::instance().getMicros(); time3 = PspRtc::instance().getMicros(); time4 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("getMicros() times: %d, %d, %d\n", time4-time3, time3-time2, time2-time1); } @@ -128,8 +128,8 @@ void PspSpeedTests::readAndTime(uint32 bytes, char *buffer, FILE *file) { // test minimal read fread(buffer, bytes, 1, file); uint32 time2 = PspRtc::instance().getMicros(); - - PSP_INFO_PRINT("Reading %d byte takes %dus\n", bytes, time2-time1); + + PSP_INFO_PRINT("Reading %d byte takes %dus\n", bytes, time2-time1); } /* @@ -158,7 +158,7 @@ void PspSpeedTests::msReadSpeed() { file = fopen("ms0:/psp/music/track1.mp3", "r"); char *buffer = (char *)malloc(2 * 1024 * 1024); - + readAndTime(1, buffer, file); readAndTime(10, buffer, file); readAndTime(50, buffer, file); @@ -170,32 +170,32 @@ void PspSpeedTests::msReadSpeed() { readAndTime(6000, buffer, file); readAndTime(7000, buffer, file); readAndTime(8000, buffer, file); - readAndTime(9000, buffer, file); + readAndTime(9000, buffer, file); readAndTime(10000, buffer, file); readAndTime(30000, buffer, file); readAndTime(50000, buffer, file); readAndTime(80000, buffer, file); readAndTime(100000, buffer, file); - + fclose(file); - free(buffer); + free(buffer); } - + void PspSpeedTests::seekAndTime(int bytes, int origin, FILE *file) { char buffer[1000]; - + uint32 time1 = PspRtc::instance().getMicros(); // test minimal read fseek(file, bytes, origin); uint32 time2 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("Seeking %d byte from %d took %dus\n", bytes, origin, time2-time1); time1 = PspRtc::instance().getMicros(); // test minimal read fread(buffer, 1000, 1, file); time2 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("Reading 1000 bytes took %dus\n", time2-time1); } @@ -246,9 +246,9 @@ int PspSpeedTests::getThreadIdSpeed() { uint32 time1 = PspRtc::instance().getMicros(); int threadId = sceKernelGetThreadId(); uint32 time2 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("Getting thread ID %d took %dus\n", threadId, time2-time1); - + return threadId; } @@ -257,7 +257,7 @@ void PspSpeedTests::getPrioritySpeed() { uint32 time1 = PspRtc::instance().getMicros(); int priority = sceKernelGetThreadCurrentPriority(); uint32 time2 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("Getting thread priority %d took %dus\n", priority, time2-time1); } @@ -266,7 +266,7 @@ void PspSpeedTests::changePrioritySpeed(int id, int priority) { uint32 time1 = PspRtc::instance().getMicros(); sceKernelChangeThreadPriority(id, priority); uint32 time2 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("Changing thread priority to %d for id %d took %dus\n", priority, id, time2-time1); } @@ -280,53 +280,53 @@ void PspSpeedTests::threadFunctionsSpeed() { changePrioritySpeed(id, 30); changePrioritySpeed(id, 35); changePrioritySpeed(id, 25); - + // test context switch time for (int i=0; i<10; i++) { uint time1 = PspRtc::instance().getMicros(); PspThread::delayMicros(0); uint time2 = PspRtc::instance().getMicros(); - PSP_INFO_PRINT("poll %d. context switch Time = %dus\n", i, time2-time1); // 10-15us - } + PSP_INFO_PRINT("poll %d. context switch Time = %dus\n", i, time2-time1); // 10-15us + } } - -void PspSpeedTests::semaphoreSpeed() { + +void PspSpeedTests::semaphoreSpeed() { PspSemaphore sem(1); - + uint32 time1 = PspRtc::instance().getMicros(); - + sem.take(); - + uint32 time2 = PspRtc::instance().getMicros(); - + PSP_INFO_PRINT("taking semaphore took %d us\n", time2-time1); // 10us - + uint32 time3 = PspRtc::instance().getMicros(); - + sem.give(); - + uint32 time4 = PspRtc::instance().getMicros(); PSP_INFO_PRINT("releasing semaphore took %d us\n", time4-time3); //10us-55us } int PspSpeedTests::threadFunc(SceSize args, void *argp) { PSP_INFO_PRINT("thread %x created.\n", sceKernelGetThreadId()); - + _sem.take(); - + PSP_INFO_PRINT("grabbed semaphore. Quitting thread\n"); - + return 0; } -void PspSpeedTests::semaphoreManyThreadSpeed() { - +void PspSpeedTests::semaphoreManyThreadSpeed() { + // create 4 threads for (int i=0; i<4; i++) { int thid = sceKernelCreateThread("my_thread", PspSpeedTests::threadFunc, 0x18, 0x10000, THREAD_ATTR_USER, NULL); sceKernelStartThread(thid, 0, 0); } - + PSP_INFO_PRINT("main thread. created threads\n"); uint32 threads = _sem.numOfWaitingThreads(); @@ -334,10 +334,10 @@ void PspSpeedTests::semaphoreManyThreadSpeed() { threads = _sem.numOfWaitingThreads(); PSP_INFO_PRINT("main thread: waiting threads[%d]\n", threads); } - + PSP_INFO_PRINT("main: semaphore value[%d]\n", _sem.getValue()); PSP_INFO_PRINT("main thread: waiting threads[%d]\n", _sem.numOfWaitingThreads()); - + _sem.give(4); } @@ -346,31 +346,31 @@ void PspSpeedTests::fastCopySpecificSize(byte *dst, byte *src, uint32 bytes) { uint32 fastcopyTime, memcpyTime; const int iterations = 2000; int intc; - + intc = pspSdkDisableInterrupts(); - + time1 = PspRtc::instance().getMicros(); for (int i=0; i 0) { if ((int)wrStream->write(index, curLength) != curLength) { PSP_ERROR("couldn't write %d bytes\n", curLength); @@ -595,22 +595,22 @@ bool PspUnitTests::testFileSystem() { PSP_ERROR("couldn't write %d bytes\n", curLength); return false; } - + delete wrStream; - + PSP_INFO_PRINT("reading...\n"); - + rdStream = file.createReadStream(); if (!rdStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } - + // seek to beginning if (!rdStream->seek(0, SEEK_SET)) { PSP_ERROR("couldn't seek to the beginning after writing the file\n"); return false; - } + } // read the contents char *readBuffer = new char[BufSize + 4]; @@ -619,96 +619,96 @@ bool PspUnitTests::testFileSystem() { while (rdStream->read(index, 100) == 100) { index += 100; } - + if (!rdStream->eos()) { PSP_ERROR("didn't find EOS at end of stream\n"); - return false; + return false; } - + // compare for (i=0; i<(int)BufSize; i++) if (buffer[i] != readBuffer[i]) { PSP_ERROR("reading/writing mistake at %x. Got %x instead of %x\n", i, readBuffer[i], buffer[i]); return false; } - + // Check for exceeding limit for (i=0; i<4; i++) { if (readBuffer[BufSize + i]) { PSP_ERROR("read exceeded limits. %d = %x\n", BufSize + i, readBuffer[BufSize + i]); } - } - + } + delete rdStream; - + PSP_INFO_PRINT("writing...\n"); - + wrStream = file.createWriteStream(); if (!wrStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } - + const char *phrase = "Jello is really fabulous"; uint32 phraseLen = strlen(phrase); - + int ret; if ((ret = wrStream->write(phrase, phraseLen)) != (int)phraseLen) { PSP_ERROR("couldn't write phrase. Got %d instead of %d\n", ret, phraseLen); return false; } - + PSP_INFO_PRINT("reading...\n"); - + delete wrStream; rdStream = file.createReadStream(); if (!rdStream) { PSP_ERROR("%s couldn't be created.\n", path); return false; } - + char *readPhrase = new char[phraseLen + 2]; memset(readPhrase, 0, phraseLen + 2); - + if ((ret = rdStream->read(readPhrase, phraseLen) != phraseLen)) { PSP_ERROR("read error on phrase. Got %d instead of %d\n", ret, phraseLen); return false; } - + for (i=0; i<(int)phraseLen; i++) { if (readPhrase[i] != phrase[i]) { PSP_ERROR("bad read/write in phrase. At %d, %x != %x\n", i, readPhrase[i], phrase[i]); return false; } - } - + } + // check for exceeding if (readPhrase[i] != 0) { PSP_ERROR("found excessive copy in phrase. %c at %d\n", readPhrase[i], i); return false; } - + PSP_INFO_PRINT("trying to read end...\n"); - + // seek to end if (!rdStream->seek(0, SEEK_END)) { PSP_ERROR("couldn't seek to end for append\n"); return false; }; - + // try to read if (rdStream->read(readPhrase, 2) || !rdStream->eos()) { PSP_ERROR("was able to read at end of file\n"); return false; } - + PSP_INFO_PRINT("ok\n"); return true; } void psp_tests() { PSP_INFO_PRINT("in tests\n"); - + #ifdef PSP_ENABLE_SPEED_TESTS // Speed tests PspSpeedTests speedTests; @@ -718,18 +718,18 @@ void psp_tests() { speedTests.seekSpeed(); speedTests.msReadSpeed(); speedTests.threadFunctionsSpeed(); - speedTests.semaphoreSpeed(); + speedTests.semaphoreSpeed(); speedTests.semaphoreManyThreadSpeed(); speedTests.fastCopySpeed(); -#endif - +#endif + #ifdef PSP_ENABLE_UNIT_TESTS // Unit tests PspUnitTests unitTests; - + //unitTests.testFastCopy(); unitTests.testFileSystem(); -#endif -} +#endif +} -#endif /* (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) */ \ No newline at end of file +#endif /* (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) */ diff --git a/backends/platform/psp/tests.h b/backends/platform/psp/tests.h index 1518acfb4c3..9af7ba8d7db 100644 --- a/backends/platform/psp/tests.h +++ b/backends/platform/psp/tests.h @@ -23,14 +23,14 @@ * */ -#ifndef _PSP_TESTS_H_ +#ifndef _PSP_TESTS_H_ #define _PSP_TESTS_H_ //#define PSP_ENABLE_UNIT_TESTS // run unit tests //#define PSP_ENABLE_SPEED_TESTS // run speed tests -#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) +#if defined (PSP_ENABLE_UNIT_TESTS) || defined (PSP_ENABLE_SPEED_TESTS) void psp_tests(); #endif -#endif /* _PSP_TESTS_H_ */ \ No newline at end of file +#endif /* _PSP_TESTS_H_ */ diff --git a/backends/platform/psp/thread.cpp b/backends/platform/psp/thread.cpp index e757c2f575c..3e1303a4e63 100644 --- a/backends/platform/psp/thread.cpp +++ b/backends/platform/psp/thread.cpp @@ -23,12 +23,12 @@ * */ -#include +#include #include "backends/platform/psp/thread.h" #include "backends/platform/psp/trace.h" - -// Class PspThreadable -------------------------------------------------- + +// Class PspThreadable -------------------------------------------------- // Inherit this to create C++ threads easily bool PspThreadable::threadCreateAndStart(const char *threadName, int priority, int stackSize, bool useVfpu /*= false*/) { @@ -38,41 +38,41 @@ bool PspThreadable::threadCreateAndStart(const char *threadName, int priority, i PSP_ERROR("thread already created!\n"); return false; } - + _threadId = sceKernelCreateThread(threadName, __threadCallback, priority, stackSize, THREAD_ATTR_USER, 0); // add VFPU support if (_threadId < 0) { PSP_ERROR("failed to create %s thread. Error code %d\n", threadName, _threadId); return false; } - + // We want to pass the pointer to this, but we'll have to take address of this so use a little trick PspThreadable *_this = this; - + if (sceKernelStartThread(_threadId, sizeof(uint32 *), &_this) < 0) { PSP_ERROR("failed to start %s thread id[%d]\n", threadName, _threadId); return false; } - - PSP_DEBUG_PRINT("Started %s thread with id[%x]\n", threadName, _threadId); - + + PSP_DEBUG_PRINT("Started %s thread with id[%x]\n", threadName, _threadId); + return true; } // Callback function to be called by PSP kernel int PspThreadable::__threadCallback(SceSize, void *__this) { DEBUG_ENTER_FUNC(); - + PspThreadable *_this = *(PspThreadable **)__this; // Dereference the copied value which was 'this' - + _this->threadFunction(); // call the virtual function - + return 0; } // PspThread class // Utilities to access general thread functions - + void PspThread::delayMillis(uint32 ms) { sceKernelDelayThread(ms * 1000); } @@ -90,8 +90,8 @@ void PspThread::delayMicros(uint32 us) { PspSemaphore::PspSemaphore(int initialValue, int maxValue/*=255*/) { DEBUG_ENTER_FUNC(); _handle = 0; - _handle = (uint32)sceKernelCreateSema("ScummVM Sema", 0 /* attr */, - initialValue, maxValue, + _handle = (uint32)sceKernelCreateSema("ScummVM Sema", 0 /* attr */, + initialValue, maxValue, 0 /*option*/); if (!_handle) PSP_ERROR("failed to create semaphore.\n"); @@ -108,10 +108,10 @@ int PspSemaphore::numOfWaitingThreads() { DEBUG_ENTER_FUNC(); SceKernelSemaInfo info; info.numWaitThreads = 0; - + if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0) PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle); - + return info.numWaitThreads; } @@ -119,10 +119,10 @@ int PspSemaphore::getValue() { DEBUG_ENTER_FUNC(); SceKernelSemaInfo info; info.currentCount = 0; - + if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0) PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle); - + return info.currentCount; } @@ -130,18 +130,18 @@ 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(); - + uint32 *pTimeOut = 0; - if (timeOut) + if (timeOut) pTimeOut = &timeOut; - + if (sceKernelWaitSema(_handle, 1, pTimeOut) < 0) // we always wait for 1 return false; return true; @@ -149,9 +149,9 @@ bool PspSemaphore::takeWithTimeOut(uint32 timeOut) { bool PspSemaphore::give(int num /*=1*/) { DEBUG_ENTER_FUNC(); - + if (sceKernelSignalSema((SceUID)_handle, num) < 0) - return false; + return false; return true; } @@ -161,7 +161,7 @@ bool PspMutex::lock() { DEBUG_ENTER_FUNC(); int threadId = sceKernelGetThreadId(); bool ret = true; - + if (_ownerId == threadId) { _recursiveCount++; } else { @@ -176,19 +176,19 @@ 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; } @@ -200,7 +200,7 @@ void PspCondition::releaseAll() { 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; iw, bestMode->h); @@ -539,7 +539,7 @@ bool OSystem_SDL::loadGFXMode() { assert(_inited); _forceFull = true; -#if !defined(__MAEMO__) && !defined(GP2XWIZ) && !defined(LINUXMOTO) && !defined(DINGUX) +#if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) && !defined(OPENPANDORA) _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; @@ -785,7 +785,7 @@ void OSystem_SDL::internUpdateScreen() { #endif // If the shake position changed, fill the dirty area with blackness - if (_currentShakePos != _newShakePos || + if (_currentShakePos != _newShakePos || (_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) { SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor}; diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp index 9d116d325ae..a9e1f5cf4be 100644 --- a/backends/platform/sdl/main.cpp +++ b/backends/platform/sdl/main.cpp @@ -23,6 +23,8 @@ * */ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + // Fix for bug #2895217 "MSVC compilation broken with r47595": // We need to keep this on top of the "common/scummsys.h" include, // otherwise we will get errors about the windows headers redefining @@ -38,7 +40,7 @@ // Several SDL based ports use a custom main, and hence do not want to compile // of this file. The following "#if" ensures that. -#if !defined(__MAEMO__) && !defined(_WIN32_WCE) && !defined(GP2XWIZ)&& !defined(LINUXMOTO) && !defined(__SYMBIAN32__) && !defined(DINGUX) +#if !defined(__MAEMO__) && !defined(__SYMBIAN32__) && !defined(_WIN32_WCE) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) && !defined(OPENPANDORA) #include "backends/platform/sdl/sdl.h" diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index 22fc561b0fb..8725a7df8a8 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #if defined(WIN32) #define WIN32_LEAN_AND_MEAN #include @@ -79,7 +82,7 @@ #endif #if defined(MACOSX) || defined(IPHONE) -#include "CoreFoundation/CoreFoundation.h" +#include #endif @@ -116,6 +119,26 @@ static AspectRatio getDesiredAspectRatio() { } #endif +#if defined(WIN32) + struct SdlConsoleHidingWin32 { + DWORD myPid; + DWORD myTid; + HWND consoleHandle; + }; + + // console hiding for win32 + static BOOL CALLBACK initBackendFindConsoleWin32Proc(HWND hWnd, LPARAM lParam) { + DWORD pid, tid; + SdlConsoleHidingWin32 *variables = (SdlConsoleHidingWin32 *)lParam; + tid = GetWindowThreadProcessId(hWnd, &pid); + if ((tid == variables->myTid) && (pid == variables->myPid)) { + variables->consoleHandle = hWnd; + return FALSE; + } + return TRUE; + } +#endif + void OSystem_SDL::initBackend() { assert(!_inited); @@ -135,6 +158,25 @@ void OSystem_SDL::initBackend() { if (joystick_num > -1) sdlFlags |= SDL_INIT_JOYSTICK; +#if 0 + // NEW CODE TO HIDE CONSOLE FOR WIN32 +#if defined(WIN32) + // console hiding for win32 + SdlConsoleHidingWin32 consoleHidingWin32; + consoleHidingWin32.consoleHandle = 0; + consoleHidingWin32.myPid = GetCurrentProcessId(); + consoleHidingWin32.myTid = GetCurrentThreadId(); + EnumWindows (initBackendFindConsoleWin32Proc, (LPARAM)&consoleHidingWin32); + + if (!ConfMan.getBool("show_console")) { + if (consoleHidingWin32.consoleHandle) { + // We won't find a window with our TID/PID in case we were started from command-line + ShowWindow(consoleHidingWin32.consoleHandle, SW_HIDE); + } + } +#endif +#endif + if (SDL_Init(sdlFlags) == -1) { error("Could not initialize SDL: %s", SDL_GetError()); } diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 5c901ba7116..e7f9a06d803 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -412,7 +412,7 @@ protected: // Scroll lock state - since SDL doesn't track it bool _scrollLock; - + // joystick SDL_Joystick *_joystick; diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl index 8b7151c1805..8786ecff32b 100644 --- a/backends/platform/symbian/AdaptAllMMPs.pl +++ b/backends/platform/symbian/AdaptAllMMPs.pl @@ -8,41 +8,42 @@ chdir("../../../"); @mmp_files = ( # Engine Project files - "mmp/scummvm_agi.mmp", - "mmp/scummvm_agos.mmp", - "mmp/scummvm_cine.mmp", - "mmp/scummvm_cruise.mmp", - "mmp/scummvm_drascula.mmp", - "mmp/scummvm_gob.mmp", - "mmp/scummvm_groovie.mmp", - "mmp/scummvm_kyra.mmp", - "mmp/scummvm_lure.mmp", + "mmp/scummvm_agi.mmp", + "mmp/scummvm_agos.mmp", + "mmp/scummvm_cine.mmp", + "mmp/scummvm_cruise.mmp", + "mmp/scummvm_drascula.mmp", + "mmp/scummvm_gob.mmp", + "mmp/scummvm_groovie.mmp", + "mmp/scummvm_kyra.mmp", + "mmp/scummvm_lure.mmp", "mmp/scummvm_m4.mmp", "mmp/scummvm_made.mmp", - "mmp/scummvm_parallaction.mmp", - "mmp/scummvm_queen.mmp", - "mmp/scummvm_saga.mmp", - "mmp/scummvm_scumm.mmp", - "mmp/scummvm_sky.mmp", - "mmp/scummvm_sword1.mmp", + "mmp/scummvm_parallaction.mmp", + "mmp/scummvm_queen.mmp", + "mmp/scummvm_saga.mmp", + "mmp/scummvm_scumm.mmp", + "mmp/scummvm_sky.mmp", + "mmp/scummvm_sword1.mmp", "mmp/scummvm_sword2.mmp", - "mmp/scummvm_touche.mmp", - "mmp/scummvm_tinsel.mmp", - "mmp/scummvm_tucker.mmp", - "mmp/scummvm_sci.mmp", - "mmp/scummvm_draci.mmp", - "mmp/scummvm_teenagent.mmp", - "mmp/scummvm_mohawk.mmp", - "mmp/scummvm_hugo.mmp", + "mmp/scummvm_touche.mmp", + "mmp/scummvm_tinsel.mmp", + "mmp/scummvm_tucker.mmp", + "mmp/scummvm_sci.mmp", + "mmp/scummvm_draci.mmp", + "mmp/scummvm_teenagent.mmp", + "mmp/scummvm_mohawk.mmp", + "mmp/scummvm_hugo.mmp", + "mmp/scummvm_toon.mmp", # Target Platform Project Files - "S60/ScummVM_S60.mmp", - "S60v3/ScummVM_S60v3.mmp", - "S60v3/ScummVM_A0000658_S60v3.mmp", - "S80/ScummVM_S80.mmp", + "S60/ScummVM_S60.mmp", + "S60v3/ScummVM_S60v3.mmp", + "S60v3/ScummVM_A0000658_S60v3.mmp", + "S80/ScummVM_S80.mmp", "S90/ScummVM_S90.mmp", - "UIQ2/ScummVM_UIQ2.mmp", + "UIQ2/ScummVM_UIQ2.mmp", "UIQ3/ScummVM_UIQ3.mmp", - "UIQ3/ScummVM_A0000658_UIQ3.mmp" + "UIQ3/ScummVM_A0000658_UIQ3.mmp" ); @@ -75,7 +76,7 @@ my @sections_kyra = ("", "ENABLE_LOL"); # special sections for engine KYRA my @sections_agos = ("", "ENABLE_AGOS2"); # special sections for engine AGOS # files excluded from build, case insensitive, will be matched in filename string only -my @excludes_snd = ( +my @excludes_snd = ( "mt32.*", "fluidsynth.cpp", "i386.cpp", @@ -86,14 +87,14 @@ my @excludes_snd = ( "rate.*" # not really needed, USE_ARM_SOUND_ASM currently not parsed correctly, # "rate[_arm|_arm_asm].(cpp|s)" will be added later based on WINS/ARM build! # These #defines for compile time are set in portdefs.h -); +); -my @excludes_graphics = ( +my @excludes_graphics = ( "iff.cpp" -); +); -my @excludes_gui = ( -); +my @excludes_gui = ( +); # the USE_ARM_* defines not parsed correctly, exclude manually: my @excludes_scumm = ( @@ -138,6 +139,7 @@ ParseModule("_draci", "draci", \@section_empty); ParseModule("_teenagent","teenagent", \@section_empty); ParseModule("_mohawk" ,"mohawk", \@section_empty); ParseModule("_hugo" ,"hugo", \@section_empty); +ParseModule("_toon" ,"toon", \@section_empty); print " ======================================================================================= Done. Enjoy :P @@ -147,7 +149,7 @@ Done. Enjoy :P ################################################################################################################## ################################################################################################################## -# parses multiple sections per mmp/module +# parses multiple sections per mmp/module sub ParseModule { my ($mmp,$module,$sections,$exclusions) = @_; @@ -172,7 +174,7 @@ sub CheckForModuleMK if (-d $item) { #print "$item\n"; - + opendir DIR, $item; #my @Files = readdir DIR; my @Files = grep s/^([^\.].*)$/$1/, readdir DIR; @@ -191,7 +193,7 @@ sub CheckForModuleMK my $isenable; my $ObjectsSelected = 0; my $ObjectsTotal = 0; - + print "$item for section '$section' ... "; open FILE, $item; @@ -200,14 +202,14 @@ sub CheckForModuleMK my $count = @lines; print "$count lines"; - + A: foreach $line (@lines) { # all things we need are inside #ifdef sections, # there is nothing we need in #ifndef sections: so ignore these for now - - # found a section? reset - if ($line =~ /^ifdef (.*)/) + + # found a section? reset + if ($line =~ /^ifdef (.*)/) { $sec = $1; $isenable = 1; @@ -230,7 +232,7 @@ sub CheckForModuleMK $line =~ s/ \\//; # remove possible trailing ' \' $line =~ s/\//\\/g; # replace / with \ chop($line); # remove \n - + # do we need to skip this file? According to our own @exclusions array foreach $exclusion (@exclusions) { @@ -242,7 +244,7 @@ sub CheckForModuleMK next A; } } - + # do we need to do this file? According to MACROs in .MMPs my $found = 0; foreach $EnableDefine (@EnabledDefines) @@ -270,7 +272,7 @@ sub CheckForModuleMK $output .= "//SOURCE $line ($reason)\n"; next A; } - + $ObjectsSelected++; #print "\n $line"; $output .= "SOURCE $line\n"; @@ -293,7 +295,7 @@ sub UpdateProjectFile my $updated = " Updated @ ".localtime(); my $name; my @mmp_files_plus_one = @mmp_files; - unshift @mmp_files_plus_one, "mmp/scummvm_base.mmp"; + unshift @mmp_files_plus_one, "mmp/scummvm_base.mmp"; foreach $name (@mmp_files_plus_one) { @@ -302,23 +304,23 @@ sub UpdateProjectFile open FILE, "$file"; my @lines = ; close FILE; - + my $onestr = join("",@lines); - + if ($onestr =~ /$n/) { print " - $name @ $n updating ... "; - + $onestr =~ s/$a.*$b/$a$updated\n$output$b/s; open FILE, ">$file"; print FILE $onestr; close FILE; - + print "done.\n"; } } - + $output = ""; } @@ -328,7 +330,7 @@ sub UpdateSlaveMacros { my $updated = " Updated @ ".localtime(); - my $name = "mmp/scummvm_base.mmp"; + my $name = "mmp/scummvm_base.mmp"; my $file = "$buildDir/$name"; print "Reading master MACROS from backends/symbian/$name ... "; @@ -342,7 +344,7 @@ sub UpdateSlaveMacros my $b = "\/\/STOP_$n\/\/"; $onestr =~ /$a(.*)$b/s; my $macros = $1; - + my $libs_first = "\n// automagically enabled static libs from macros above\n"; my $libs_second = "STATICLIBRARY scummvm_base.lib // must be above USE_* .libs\n"; my $macro_counter = 0; @@ -355,7 +357,7 @@ sub UpdateSlaveMacros if ($line =~ /^.*MACRO\s*([0-9A-Z_]*)\s*\/\/\s*LIB\:(.*)$/) { my $macro = $1; my $lib = $2; - + # this macro enabled? then also add the .lib if ($line =~ /^\s*MACRO\s*$macro/m) { @@ -366,7 +368,7 @@ sub UpdateSlaveMacros if ($macro =~ /^ENABLE_/) { $libs_first .= "STATICLIBRARY $lib\n"; - + # add projects for BLD.INF's my $projectname = substr("$lib",0,-4); $projects .= "..\\mmp\\$projectname.mmp\n"; @@ -393,7 +395,7 @@ sub UpdateSlaveMacros push @DisabledDefines, $macro; # used in CheckForModuleMK()!! } } - } + } print "$macro_counter macro lines.\n"; @@ -404,23 +406,23 @@ sub UpdateSlaveMacros $m = "AUTO_PROJECTS"; $p = "\/\/START_$m\/\/"; $q = "\/\/STOP_$m\/\/"; - + foreach $name (@mmp_files) { $file = "$buildDir/$name"; $fileBLDINF = $buildDir .'/'. substr($name, 0, rindex($name, "/")) . "/BLD.INF"; print "Updating macros in $file ... "; #print "Updating macros in backends/symbian/$name ... "; - + open FILE, "$file"; @lines = ; close FILE; $onestr = join("",@lines); - + my $extralibs = ""; # output # slash in name means it's a phone specific build file: add LIBs $extralibs .= "$libs_first$libs_second" if (-e $fileBLDINF); - + $onestr =~ s/$a.*$b/$a$updated$macros2$extralibs$b/s; - + open FILE, ">$file"; print FILE $onestr; close FILE; my $count = @lines; @@ -434,13 +436,13 @@ sub UpdateSlaveMacros open FILE, "$fileBLDINF"; @lines = ; close FILE; $onestr = join("",@lines); - + $onestr =~ s/$p.*$q/$p$updated$projects$q/s; - + open FILE, ">$fileBLDINF"; print FILE $onestr; close FILE; } } -} +} ################################################################################################################## @@ -448,10 +450,10 @@ sub ResetProjectFiles() { my $onestr, @lines; my @mmp_files_plus_one = @mmp_files; -# unshift @mmp_files_plus_one, "mmp/scummvm_base.mmp"; - +# unshift @mmp_files_plus_one, "mmp/scummvm_base.mmp"; + print "Resetting project files: "; - + # we don't need to do mmp/scummvm_base.mmp", it was done in BuildPackageUpload.pl before the call to this script foreach $name (@mmp_files_plus_one) { @@ -471,7 +473,7 @@ sub ResetProjectFiles() $onestr = join("",@lines); open FILE, ">$fileBLDINF"; print FILE $onestr; close FILE; } - } + } print "... done.\n"; } diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl index 62fcef02756..3bdcede76a5 100644 --- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl +++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl @@ -17,7 +17,7 @@ $SDK_BuildDirs{'S60v3'} = "S60v3"; $SDK_BuildDirs{'S80'} = "S80"; $SDK_BuildDirs{'S90'} = "S90"; -# the target name inserted here: 'abld BUILD $SDK_TargetName UREL' +# the target name inserted here: 'abld BUILD $SDK_TargetName UREL' $SDK_TargetName{'UIQ2'} = "armi"; $SDK_TargetName{'UIQ3'} = "gcce"; $SDK_TargetName{'S60v1'}= "armi"; @@ -117,7 +117,7 @@ foreach $Library (sort keys(%PresentLibs)) # push @Packages, sprintf($file_tpl_sis, $version_tpl_sis, $SDK2, $Extra); # $PackagesQueued++; # } -# } +# } # } # else # { @@ -144,7 +144,7 @@ while( ($SDK, $Value) = each(%VariationSets) ) push @Packages, sprintf($file_tpl_sis, $version_tpl_sis, $SDK2, $Extra); $PackagesQueued++; } - } + } } else { @@ -170,7 +170,7 @@ Preparing to Build, Package & Upload $PackagesQueued SymbianOS ScummVM variation SDKs inst'd \t$SDKs ".( %SDK_LibraryDirs ? " LIBs inst'd \t$LIBs " : "" )." - $PackagesQueued Variations \t$PackagesStr + $PackagesQueued Variations \t$PackagesStr DIR base \t$base_dir build \t$build_dir output \t$output_dir @@ -178,7 +178,7 @@ Preparing to Build, Package & Upload $PackagesQueued SymbianOS ScummVM variation FTP host \t$FTP_Host user \t$FTP_User pass \t"."*" x length($FTP_Pass)." - dir \t$FTP_Dir + dir \t$FTP_Dir " : "" )." ======================================================================================= Press Ctrl-C to abort or enter to continue Build, Package & Upload $PackagesQueued Variations... @@ -194,7 +194,7 @@ unlink($build_log_out); unlink($build_log_err); # init _base.mmp now, so we can start changing it without affecting the CVS version _base.mmp.in! -my $name = "mmp/scummvm_base.mmp"; +my $name = "mmp/scummvm_base.mmp"; my $file = "$build_dir/$name"; open FILE, "$file.in"; @lines = ; close FILE; my $onestr = join("",@lines); @@ -219,7 +219,7 @@ while( ($SDK, $Value) = each(%SDK_LibraryDirs) ) $LibrariesQueued++; DoLibrary($SDK2, $Library, $Path); } - } + } } else { @@ -252,7 +252,7 @@ while( ($SDK, $VariationsHash) = each(%SDK_Variations) ) { DoVariation($SDK2, $Variation, $MacroBlock); } - } + } } else { @@ -277,7 +277,7 @@ while( ($SDK, $VariationsHash) = each(%VariationSets) ) { DoVariation($SDK2, $Variation, $MacroBlock); } - } + } } else { @@ -335,7 +335,7 @@ print " SumthinWicked wishes you a ridiculously good and optimally happy d sub MakeMppMacroDefs { my ($features) = @_; - + my %EnabledFeatures = (); foreach (split(/\W|\r|\n/, $features)) { @@ -398,14 +398,14 @@ sub MakeMppMacroDefs $MacroDefs .= "//MACRO ENABLE_$E\n"; } } - + #print "\n\n'$features' ==> $MacroDefs\n\n\n"; return $MacroDefs; } ################################################################################################################## -# Build, Package & Upload a single Variation +# Build, Package & Upload a single Variation sub DoLibrary { my ($SDK, $Library, $Path) = @_; @@ -435,23 +435,23 @@ my $header = " my $OK = 1; PrepSdkPaths($SDK); - + chdir($Path) or $OK=0; PrintErrorMessage("Changing to $Path failed!") if (!$OK); - return 0 if (!$OK); + return 0 if (!$OK); PrintMessage("Cleaning for $Target") if (!$ReallyQuiet); system("bldmake bldfiles > NUL 2> NUL"); PrintErrorMessage("'bldmake bldfiles' exited with value " . ($? >> 8)) if ($? >> 8); system("abld MAKEFILE $TargetName > NUL 2> NUL"); - PrintErrorMessage("'abld MAKEFILE $TargetName' exited with value " . ($? >> 8)) if ($? >> 8); + PrintErrorMessage("'abld MAKEFILE $TargetName' exited with value " . ($? >> 8)) if ($? >> 8); system("abld CLEAN $TargetName UREL > NUL 2> NUL"); - PrintErrorMessage("'abld CLEAN $TargetName urel' exited with value " . ($? >> 8)) if ($? >> 8); + PrintErrorMessage("'abld CLEAN $TargetName urel' exited with value " . ($? >> 8)) if ($? >> 8); # remove file so we are sure that after .lib generation we have a fresh copy! if (-e $TargetFilePath) { unlink($TargetFilePath) or PrintErrorMessage("Removing $TargetFilePath"); } - + my $Redirection = "OUT:file, ERR:".($RedirectSTDERR ? "file" : "screen"); my $Message = "Building $Target ($Redirection)"; PrintMessage($Message) if (!$ReallyQuiet); @@ -463,14 +463,14 @@ my $header = " $OK = 0 if ($? >> 8); # print " STDERR: ".((-s $build_log_err)-$OldSize)." bytes output written to $build_log_err\n+--------------------------------------------------------------------------------------\n" if ($OldSize != (-s $build_log_err)); PrintErrorMessage("'abld TARGET $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8); - return 0 if (!$OK); # ABLD always returns ok :( grr + return 0 if (!$OK); # ABLD always returns ok :( grr PrintMessage("Done.") if (!$ReallyQuiet); # did it work? :) if (-e $TargetFilePath) { $LibrariesSucceeded++; - + if ($TargetIntermediatePath ne '' && $TargetIntermediatePath =~ /\\EPOC32\\BUILD\\/i) # make really sure it's a valid path! { system("del /S /Q $TargetIntermediatePath > NUL"); @@ -491,12 +491,12 @@ my $header = " ################################################################################################################## -# Build, Package & Upload a single Variation +# Build, Package & Upload a single Variation sub DoVariation { my ($SDK, $Variation, $MacroBlock) = @_; my $Extra = ($Variation ne '' ? "_$Variation" : ""); - my $Package = sprintf($file_tpl_sis, $version_tpl_sis, $SDK, $Extra); + my $Package = sprintf($file_tpl_sis, $version_tpl_sis, $SDK, $Extra); if ($SkipExistingPackages && -f "$output_dir/$Package") { @@ -527,7 +527,7 @@ my $header = " if ($OK) { $OK = BuildVariation($SDK, $Variation, $Package, $MacroBlock); - + if ($OK && $FTP_Host ne '') { UploadVariation($SDK, $Variation, $Package); @@ -543,17 +543,17 @@ sub PrepVariation() my $OK = 1; PrepSdkPaths($SDK); - + chdir($build_dir) or $OK=0; PrintErrorMessage("Changing to $build_dir failed!") if (!$OK); - return 0 if (!$OK); + return 0 if (!$OK); # insert $MacroBlock into AUTO_MACRO_MASTER in scummvm_base.mmp PrintMessage("Setting new AUTO_MACROS_MASTER in scummvm_base.mmp for '$Variation'") if (!$ReallyQuiet); my $n = "AUTO_MACROS_MASTER"; my $a = "\/\/START_$n\/\/"; my $b = "\/\/STOP_$n\/\/"; - my $name = "scummvm_base.mmp"; + my $name = "scummvm_base.mmp"; my $file = "$build_dir/mmp/$name"; my $updated = " Updated @ ".localtime(); @@ -562,11 +562,11 @@ sub PrepVariation() return 0 if (!$OK); my @lines = ; close FILE; - + my $onestr = join("",@lines); $MacroBlock =~ s/^\s*//gm; $onestr =~ s/$a(.*)$b/$a$updated\n$ExtraMacros$MacroBlock$b/s; - + open FILE, ">$file" or $OK=0; PrintErrorMessage("Writing file '$file'") if (!$OK); return 0 if (!$OK); @@ -579,7 +579,7 @@ sub PrepVariation() $OK = 0 if ($? >> 8); PrintErrorMessage("'AdaptAllMMPs.pl' exited with value " . ($? >> 8)) if ($? >> 8); return 0 if (!$OK); - + # we are here: so all is ok :) return 1; } @@ -592,7 +592,7 @@ sub BuildVariation() my $TargetName = $SDK_TargetName{$SDK}; my $TargetDir = $SDK_TargetDir{$SDK}; my $OK = 1; - + my $dir = $build_dir."/".$SDK_BuildDirs{$SDK}; $dir =~ s#/#\\#g; chdir($dir); @@ -617,8 +617,8 @@ sub BuildVariation() PrintErrorMessage("'bldmake bldfiles' exited with value " . ($? >> 8)) if ($? >> 8); system("abld CLEAN $TargetName UREL 2> NUL > NUL"); - PrintErrorMessage("'abld CLEAN $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8); - + PrintErrorMessage("'abld CLEAN $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8); + my $Redirection = "OUT:file, ERR:".($RedirectSTDERR ? "file" : "screen"); my $Message = "Building $Package ($Redirection)"; PrintMessage($Message) if (!$ReallyQuiet); @@ -630,7 +630,7 @@ sub BuildVariation() $OK = 0 if ($? >> 8); print " STDERR: ".((-s $build_log_err)-$OldSize)." bytes output written to $build_log_err\n+--------------------------------------------------------------------------------------\n" if ($OldSize != (-s $build_log_err) && !$ReallyQuiet); PrintErrorMessage("'abld BUILD $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8); - return 0 if (!$OK); # ABLD always returns ok :( grr + return 0 if (!$OK); # ABLD always returns ok :( grr PrintMessage("Done.") if (!$ReallyQuiet); # do we have an override suffix for the package name? @@ -654,7 +654,7 @@ sub BuildVariation() if (-e "$output_dir/$Package") { $PackagesCreated++; - + if ($TargetIntermediatePath ne '' && $TargetIntermediatePath =~ /\\EPOC32\\BUILD\\/i) # make really sure it's a valid path! { #PrintMessage("Cleaning $TargetIntermediatePath"); @@ -677,7 +677,7 @@ sub UploadVariation() use Net::FTP; my $newerr; - + PrintMessage("Connecting to FTP $FTP_Host") if (!$ReallyQuiet); $ftp = Net::FTP->new($FTP_Host,Timeout=>240) or $newerr=1; @@ -692,7 +692,7 @@ sub UploadVariation() { PrintMessage("Changing to dir $FTP_Dir"); $ftp->cwd($FTP_Dir) or $newerr=1; - + if ($newerr) { PrintErrorMessage("Changing to dir $FTP_Dir! Aborting!"); @@ -704,20 +704,20 @@ sub UploadVariation() # leave this for possible auto-deletion of old files? # @files = $ftp->dir or $newerr=1; # push @ERRORS, "Can't get file list $!\n" if $newerr; -# print "Got file list\n"; +# print "Got file list\n"; # foreach(@files) { # print "$_\n"; # } - + PrintMessage("Uploading $Package (".(-s "$output_dir/$Package")." bytes)"); - + $ftp->binary; $ftp->put("$output_dir/$Package") or $newerr=1; PrintErrorMessage("Uploading package! Aborting!") if $newerr; $PackagesUploaded++ if (!$newerr); - } + } - $ftp->quit; + $ftp->quit; } } @@ -758,7 +758,7 @@ sub CleanupPath() { $path =~ s/\"\Q$ECompXL_BinDir\E\";//g; } - + while( ($SDK, $RootDir) = each(%SDK_RootDirs) ) { if ($SDK_RootDirs{$SDK} ne '') @@ -766,8 +766,8 @@ sub CleanupPath() my $path_component = "\"".$SDK_RootDirs{$SDK}."\\epoc32\\"; $path =~ s/\Q$path_component\E.*?\";//g; } - } - + } + return $path; } @@ -798,5 +798,5 @@ sub PrintMessage() } ################################################################################################################## - + diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl index b6ebbafe749..bf80c36a0e6 100644 --- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl +++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl @@ -2,26 +2,26 @@ ################################################################################################################## @WorkingEngines = qw( - scumm agos sky queen gob groovie saga drascula + scumm agos sky queen gob groovie saga drascula kyra lure agi touche parallaction cine - cruise made m4 tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo + cruise made m4 tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo toon ); - + @WorkingEngines_1st = qw( - scumm queen groovie saga drascula + scumm queen groovie saga drascula touche parallaction cine -? cruise made m4 tucker +? cruise made m4 tucker ); - + @WorkingEngines_2nd = qw( - agos sky gob + agos sky gob kyra lure agi tinsel - sword1 sword2 draci sci teenagent hugo + sword1 sword2 draci sci teenagent hugo toon ); @TestingEngines = qw( - - ); + + ); @EnablableEngines = (@WorkingEngines, @TestingEngines); @@ -36,16 +36,16 @@ #disabled subengines lol saga2 personal nightmare %UseableFeatures = ( - 'zlib' => 'zlib.lib', - 'mad' => 'libmad.lib', + 'zlib' => 'zlib.lib', + 'mad' => 'libmad.lib', 'tremor' => 'libtremor.lib', 'flac' => 'libflac.lib' ); - + # these are normally enabled for each variation #$DefaultFeatures = qw(zlib,mad); - $DefaultFeatures = qw(zlib,mad,tremor,flac); - + $DefaultFeatures = qw(zlib,mad,tremor,flac); + ################################################################################################################## ## ## General system information, based on $COMPUTERNAME, so this way @@ -62,13 +62,13 @@ $SkipExistingPackages = 0; $ReallyQuiet = 0; $DevBase = "C:\\S"; - + # specify an optional FTP server to upload to after each Build+Package (can leave empty) #$FTP_Host = "host.com"; $FTP_User = "something"; $FTP_Pass = "password"; $FTP_Dir = "cvsbuilds"; - + # What Platform SDKs are installed on this machine? # possible SDKs: ("UIQ2", UIQ3", "S60v1", "S60v2", "S60v3", "S80", "S90") # Note1: the \epoc32 directory needs to be in these rootdirs @@ -93,10 +93,10 @@ $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "$DevBase\\zlib-1.2.2\\epoc"; #$SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "$DevBase\\libmad-0.15.1b\\group"; $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "$DevBase\\tremor\\epoc"; - + ## SDL 1.2.12 / AnotherGuest / Symbian version my $SdlBase = "$DevBase\\SDL-1.2.12-ag\\Symbian"; - #$SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = "$SdlBase\\S60"; // unsupported? + #$SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = "$SdlBase\\S60"; // unsupported? #$SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = "$SdlBase\\S60v2"; $SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "$SdlBase\\S60v3"; #$SDK_LibraryDirs{'S80'}{'esdl.lib'} = "$SdlBase\\S80"; @@ -107,7 +107,7 @@ ## HardlySupported(TM) :P #$SDK_LibraryDirs{'ALL'}{'libmpeg2.lib'} = "$DevBase\\mpeg2dec-0.4.0\\epoc"; } - + # now you can add $VariationSets only built on this PC below this line :) #$VariationSets{'ALL'}{'scumm'} = "$DefaultFeatures scumm scumm_7_8 he"; @@ -296,14 +296,14 @@ # scummvm-051101-SymbianS90_queen.sis # NOTE: empty $VariationSets{''} string instead of 'ALL' = easy way to disable pkg! - + if (1) # all regular combo's { # the first one includes all SDKs & release-ready engines - + $VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines"; - $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines"; - $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines"; +# $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines"; +# $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines"; # now one for each ready-for-release engine if (0) { @@ -324,16 +324,16 @@ } } # below here you could specify weird & experimental combinations, non-ready engines - + # Separate version for the broken sword engines (1&2) #$VariationSets{'ALL'}{'brokensword'} = "$DefaultFeatures sword1 sword2"; - + # Separate version for Scumm games (COMI) since memory usage might be high - #$VariationSets{'ALL'}{'scumm'} = "$DefaultFeatures scumm scumm_7_8 he"; - + #$VariationSets{'ALL'}{'scumm'} = "$DefaultFeatures scumm scumm_7_8 he"; + # for mega-fast-testing only plz! Warning: contains to engines! #$VariationSets{'ALL'}{'fast_empty'} = ""; - + } # end quick-n-fast if (1|0) diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README index 630b539a5fb..ba7099ba328 100644 --- a/backends/platform/symbian/README +++ b/backends/platform/symbian/README @@ -24,7 +24,7 @@ About ScummVM The original ports (uptil 0.7.1) were made by Andreas Karlsson and Lars Persson. The main transition to 0.8.0CVS and all relevant changes were done by Jurgen Braam. Jurgen and Lars have successfully transfered all needed changes into CVS/SVN, with additional helpful tools for Symbian OS - + Release History: Release version: 1.1.0 * Nothing significant in the Symbian port, except SDL improvements. @@ -33,7 +33,7 @@ Release History: Release version: 1.0.0 * Nothing significant in the Symbian port, except SDL improvements. * See main readme for general ScummVM improvements, minor update - + Release version: 0.13.1 * Nothing significant in the Symbian port, except SDL improvements. * See main readme for general ScummVM improvements, minor update diff --git a/backends/platform/symbian/S60/BLD.INF.in b/backends/platform/symbian/S60/BLD.INF.in index b6cf8bbda65..c3c3decf1a8 100644 --- a/backends/platform/symbian/S60/BLD.INF.in +++ b/backends/platform/symbian/S60/BLD.INF.in @@ -5,7 +5,7 @@ PRJ_MMPFILES //START_AUTO_PROJECTS// // empty base file, will be updated by Perl build scripts - + //STOP_AUTO_PROJECTS// .\ScummVM_S60.mmp diff --git a/backends/platform/symbian/S60v3/BLD.INF.in b/backends/platform/symbian/S60v3/BLD.INF.in index 10f46ced615..78d130cb08c 100644 --- a/backends/platform/symbian/S60v3/BLD.INF.in +++ b/backends/platform/symbian/S60v3/BLD.INF.in @@ -5,7 +5,7 @@ PRJ_MMPFILES //START_AUTO_PROJECTS// // empty base file, will be updated by Perl build scripts - + //STOP_AUTO_PROJECTS// gnumakefile icons.mk .\ScummVM_A0000658_S60v3.mmp diff --git a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in index 2916d739387..d044b33bb04 100644 --- a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in @@ -97,6 +97,9 @@ SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE \epoc32\include\mw +SYSTEMINCLUDE \epoc32\include\platform +SYSTEMINCLUDE \epoc32\include\platform\mw SYSTEMINCLUDE ..\src // for portdefs.h // *** SOURCE files @@ -126,7 +129,7 @@ SOURCE gui\KeysDialog.cpp SOURCE gui\Actions.cpp SOURCE gui\Dialog.cpp -// Common error +// Common error source common\error.cpp // Special for graphics @@ -140,4 +143,4 @@ LIBRARY gdi.lib hal.lib bitgdi.lib LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib library avkon.lib bafl.lib -CAPABILITY LocalServices ReadUserData \ No newline at end of file +CAPABILITY LocalServices ReadUserData diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in index e95bb9ee218..bcc00017ab9 100644 --- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in @@ -97,6 +97,9 @@ SYSTEMINCLUDE \epoc32\include\ESDL SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version SYSTEMINCLUDE \epoc32\include\libc SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE \epoc32\include\mw +SYSTEMINCLUDE \epoc32\include\platform +SYSTEMINCLUDE \epoc32\include\platform\mw SYSTEMINCLUDE ..\src // for portdefs.h // *** SOURCE files @@ -126,7 +129,7 @@ SOURCE gui\KeysDialog.cpp SOURCE gui\Actions.cpp SOURCE gui\Dialog.cpp -// Common error +// Common error source common\error.cpp // Special for graphics @@ -140,4 +143,4 @@ LIBRARY gdi.lib hal.lib bitgdi.lib LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib library avkon.lib bafl.lib -CAPABILITY LocalServices ReadUserData \ No newline at end of file +CAPABILITY LocalServices ReadUserData diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg index a2c43d94e67..3f0fbbc5f18 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg @@ -36,7 +36,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM S60v3"},(0xA0000657),1,12,0 +#{"ScummVM S60v3"},(0xA0000657),1,13,0 ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} @@ -68,6 +68,7 @@ "..\..\..\..\dists\engine-data\m4.dat"-"c:\data\scummvm\m4.dat" "..\..\..\..\dists\engine-data\teenagent.dat"-"c:\data\scummvm\teenagent.dat" "..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\data\scummvm\vkeybd_default.zip" +"..\..\..\..\gui\themes\translations.dat"-"c:\data\scummvm\translations.dat" ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\data\scummvm\scummvm.ini",FILENULL diff --git a/backends/platform/symbian/S80/BLD.INF.in b/backends/platform/symbian/S80/BLD.INF.in index 75ef20be121..c25ee43a993 100644 --- a/backends/platform/symbian/S80/BLD.INF.in +++ b/backends/platform/symbian/S80/BLD.INF.in @@ -5,7 +5,7 @@ PRJ_MMPFILES //START_AUTO_PROJECTS// // empty base file, will be updated by Perl build scripts - + //STOP_AUTO_PROJECTS// .\ScummVM_S80.mmp diff --git a/backends/platform/symbian/S90/BLD.INF.in b/backends/platform/symbian/S90/BLD.INF.in index d6e1ece0122..4e333e5dae2 100644 --- a/backends/platform/symbian/S90/BLD.INF.in +++ b/backends/platform/symbian/S90/BLD.INF.in @@ -5,7 +5,7 @@ PRJ_MMPFILES //START_AUTO_PROJECTS// // empty base file, will be updated by Perl build scripts - + //STOP_AUTO_PROJECTS// .\ScummVM_S90.mmp diff --git a/backends/platform/symbian/UIQ2/BLD.INF.in b/backends/platform/symbian/UIQ2/BLD.INF.in index b607446a642..b8d8111e870 100644 --- a/backends/platform/symbian/UIQ2/BLD.INF.in +++ b/backends/platform/symbian/UIQ2/BLD.INF.in @@ -5,7 +5,7 @@ PRJ_MMPFILES //START_AUTO_PROJECTS// // empty base file, will be updated by Perl build scripts - + //STOP_AUTO_PROJECTS// .\ScummVM_UIQ2.mmp diff --git a/backends/platform/symbian/UIQ3/BLD.INF.in b/backends/platform/symbian/UIQ3/BLD.INF.in index e4b0bb306e4..ff12dbdd750 100644 --- a/backends/platform/symbian/UIQ3/BLD.INF.in +++ b/backends/platform/symbian/UIQ3/BLD.INF.in @@ -1,11 +1,11 @@ PRJ_PLATFORMS -GCCE WINSCW +GCCE WINSCW PRJ_MMPFILES //START_AUTO_PROJECTS// // empty base file, will be updated by Perl build scripts - + //STOP_AUTO_PROJECTS// .\ScummVM_A0000658_UIQ3.mmp .\ScummVM_UIQ3.mmp diff --git a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in index 99cbb264c2a..83ce9bc5990 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in @@ -127,7 +127,7 @@ SOURCE gui\KeysDialog.cpp SOURCE gui\Actions.cpp SOURCE gui\Dialog.cpp -// Common error +// Common error source common\error.cpp // Special for graphics diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in index 35097141521..3c8e41784af 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in @@ -127,7 +127,7 @@ SOURCE gui\KeysDialog.cpp SOURCE gui\Actions.cpp SOURCE gui\Dialog.cpp -// Common error +// Common error source common\error.cpp // Special for graphics diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg index 7e620485d5e..a55f4b6e378 100644 --- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg +++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg @@ -35,7 +35,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM UIQ3"},(0xA0000657),1,12,0 +#{"ScummVM UIQ3"},(0xA0000657),1,13,0 ; ProductID for UIQ 3.0 ; Product/platform version UID, Major, Minor, Build, Product ID @@ -65,6 +65,8 @@ "..\..\..\..\dists\engine-data\m4.dat"-"c:\shared\scummvm\m4.dat" "..\..\..\..\dists\engine-data\teenagent.dat"-"c:\shared\scummvm\teenagent.dat" "..\..\..\vkeybd\packs\vkeybd_default.zip"-"c:\shared\scummvm\vkeybd_default.zip" +"..\..\..\..\gui\themes\translations.dat"-"c:\shared\scummvm\translations.dat" + ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\shared\scummvm\scummvm.ini",FILENULL ""-"c:\shared\scummvm\scummvm.stdout.txt",FILENULL diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in index ceb62ec843f..8f51e3c7b5e 100644 --- a/backends/platform/symbian/mmp/scummvm_base.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in @@ -59,6 +59,9 @@ SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian alr SYSTEMINCLUDE \epoc32\include\libc SYSTEMINCLUDE \epoc32\include\tremor SYSTEMINCLUDE \epoc32\include +SYSTEMINCLUDE \epoc32\include\mw +SYSTEMINCLUDE \epoc32\include\platform +SYSTEMINCLUDE \epoc32\include\platform\mw SYSTEMINCLUDE ..\src // for portdefs.h // *** SOURCE files diff --git a/backends/platform/symbian/mmp/scummvm_toon.mmp.in b/backends/platform/symbian/mmp/scummvm_toon.mmp.in new file mode 100644 index 00000000000..7b907fd92f8 --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_toon.mmp.in @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL + * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System + * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer + * Copyright (C) 2005-2010 The ScummVM project + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_toon.lib +TARGETTYPE lib +OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp +OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings +OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char +ALWAYS_BUILD_AS_ARM + +//START_AUTO_MACROS_SLAVE// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_MACROS_SLAVE// + +// *** SOURCE files + +SOURCEPATH ..\..\..\..\engines\toon + +//START_AUTO_OBJECTS_TOON_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_TOON_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/res/scummvm.rss b/backends/platform/symbian/res/scummvm.rss index 0bb5dff0588..f7daf9bfc17 100644 --- a/backends/platform/symbian/res/scummvm.rss +++ b/backends/platform/symbian/res/scummvm.rss @@ -35,7 +35,6 @@ NAME SCUM #include #include "..\src\Scummvm.hrh" // Include the standard Eikon resource ids -#include RESOURCE RSS_SIGNATURE diff --git a/backends/platform/symbian/src/ScummApp.cpp b/backends/platform/symbian/src/ScummApp.cpp index a3ce6923686..01af5e7fd9b 100644 --- a/backends/platform/symbian/src/ScummApp.cpp +++ b/backends/platform/symbian/src/ScummApp.cpp @@ -27,7 +27,7 @@ #define _PAGESIZE_ 0x1000 -#if defined (__WINS__) && !defined (__SERIES60_30__) && !defined (UIQ3) +#if defined (__WINS__) && !defined (S60V3) && !defined (UIQ3) extern "C" int _chkstk(int /*a*/) { _asm { push ecx diff --git a/backends/platform/symbian/src/ScummApp.h b/backends/platform/symbian/src/ScummApp.h index 8cfdbdb92f3..cca8e2a7c94 100644 --- a/backends/platform/symbian/src/ScummApp.h +++ b/backends/platform/symbian/src/ScummApp.h @@ -22,8 +22,8 @@ * $Id$ */ -#ifndef ScummAPPH -#define ScummAPPH +#ifndef SCUMMAPP_H +#define SCUMMAPP_H #include #include diff --git a/backends/platform/symbian/src/ScummVMApp.h b/backends/platform/symbian/src/ScummVMApp.h index 6796024e1ea..aee098f9893 100644 --- a/backends/platform/symbian/src/ScummVMApp.h +++ b/backends/platform/symbian/src/ScummVMApp.h @@ -23,8 +23,8 @@ * */ -#ifndef ScummVMapph -#define ScummVMapph +#ifndef SCUMMVMAPP_H +#define SCUMMVMAPP_H #include #include diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index d63c9fe0445..50ab7e00b11 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -140,9 +140,6 @@ OSystem_SDL_Symbian::OSystem_SDL_Symbian() :_channels(0),_stereo_mix_buffer(0) { } void OSystem_SDL_Symbian::initBackend() { - // First set the extrapath (for installed dat files etc) - ConfMan.set("extrapath", Symbian::GetExecutablePath()); - // Calculate the default savepath Common::String savePath; savePath = Symbian::GetExecutablePath(); @@ -183,6 +180,13 @@ void OSystem_SDL_Symbian::initBackend() { initZones(); } +void OSystem_SDL_Symbian::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { + Common::FSNode pluginsNode(Symbian::GetExecutablePath()); + if (pluginsNode.exists() && pluginsNode.isDirectory()) { + s.add("SYMBIAN_DATAFOLDER", new Common::FSDirectory(Symbian::GetExecutablePath()), priority); + } +} + OSystem_SDL_Symbian::~OSystem_SDL_Symbian() { delete[] _stereo_mix_buffer; } diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h index 42929f80298..85b5e131dab 100644 --- a/backends/platform/symbian/src/SymbianOS.h +++ b/backends/platform/symbian/src/SymbianOS.h @@ -22,8 +22,8 @@ * $Id$ */ -#ifndef SDLSYMBIANH -#define SDLSYMBIANH +#ifndef SDLSYMBIAN_H +#define SDLSYMBIAN_H #include "backends/platform/sdl/sdl.h" @@ -61,6 +61,8 @@ public: // Returns reference to File session RFs& FsSession(); + + void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); protected: // // The mixer callback function. diff --git a/backends/platform/wii/options.cpp b/backends/platform/wii/options.cpp index 0a21b45561a..2a47958e3bc 100644 --- a/backends/platform/wii/options.cpp +++ b/backends/platform/wii/options.cpp @@ -183,7 +183,7 @@ void WiiOptionsDialog::handleTickle() { break; default: - label = String::printf(_("Network not initialsed (%d)"), status); + label = String::printf(_("Network not initialised (%d)"), status); break; } diff --git a/backends/platform/wince/CEActionsPocket.h b/backends/platform/wince/CEActionsPocket.h index ae0ed199758..0fe29a9e862 100644 --- a/backends/platform/wince/CEActionsPocket.h +++ b/backends/platform/wince/CEActionsPocket.h @@ -23,8 +23,8 @@ * */ -#ifndef CEACTIONSPOCKET -#define CEACTIONSPOCKET +#ifndef CEACTIONSPOCKET_H +#define CEACTIONSPOCKET_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEActionsSmartphone.h b/backends/platform/wince/CEActionsSmartphone.h index eacc571a67c..36797cd2c88 100644 --- a/backends/platform/wince/CEActionsSmartphone.h +++ b/backends/platform/wince/CEActionsSmartphone.h @@ -23,8 +23,8 @@ * */ -#ifndef CEACTIONSSMARTPHONE -#define CEACTIONSSMARTPHONE +#ifndef CEACTIONSSMARTPHONE_H +#define CEACTIONSSMARTPHONE_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEDevice.h b/backends/platform/wince/CEDevice.h index 9fee8497c27..ca2f908c6d5 100644 --- a/backends/platform/wince/CEDevice.h +++ b/backends/platform/wince/CEDevice.h @@ -23,8 +23,8 @@ * */ -#ifndef CEDEVICE -#define CEDEVICE +#ifndef CEDEVICE_H +#define CEDEVICE_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CELauncherDialog.h b/backends/platform/wince/CELauncherDialog.h index 7e86f808fc8..7755e33dcce 100644 --- a/backends/platform/wince/CELauncherDialog.h +++ b/backends/platform/wince/CELauncherDialog.h @@ -23,8 +23,8 @@ * */ -#ifndef CELAUNCHERDIALOG -#define CELAUNCHERDIALOG +#ifndef CELAUNCHERDIALOG_H +#define CELAUNCHERDIALOG_H #include "base/plugins.h" #include "common/fs.h" diff --git a/backends/platform/wince/CEScaler.h b/backends/platform/wince/CEScaler.h index c93e1c66ca0..4711f94bbae 100644 --- a/backends/platform/wince/CEScaler.h +++ b/backends/platform/wince/CEScaler.h @@ -23,8 +23,8 @@ * */ -#ifndef CESCALER -#define CESCALER +#ifndef CESCALER_H +#define CESCALER_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/GUIElement.h b/backends/platform/wince/CEgui/GUIElement.h index beb9d95047f..7e4572d3773 100644 --- a/backends/platform/wince/CEgui/GUIElement.h +++ b/backends/platform/wince/CEgui/GUIElement.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_GUIELEMENT -#define CEGUI_GUIELEMENT +#ifndef CEGUI_GUIELEMENT_H +#define CEGUI_GUIELEMENT_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/ItemAction.h b/backends/platform/wince/CEgui/ItemAction.h index e2cd5b2367c..74ed6bec4d1 100644 --- a/backends/platform/wince/CEgui/ItemAction.h +++ b/backends/platform/wince/CEgui/ItemAction.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_ITEMACTION -#define CEGUI_ITEMACTION +#ifndef CEGUI_ITEMACTION_H +#define CEGUI_ITEMACTION_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/ItemSwitch.h b/backends/platform/wince/CEgui/ItemSwitch.h index 1fa5732b6a1..8d03ee77cbb 100644 --- a/backends/platform/wince/CEgui/ItemSwitch.h +++ b/backends/platform/wince/CEgui/ItemSwitch.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_ITEMSWITCH -#define CEGUI_ITEMSWITCH +#ifndef CEGUI_ITEMSWITCH_H +#define CEGUI_ITEMSWITCH_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/Panel.h b/backends/platform/wince/CEgui/Panel.h index 0b55c00dee0..6626e418668 100644 --- a/backends/platform/wince/CEgui/Panel.h +++ b/backends/platform/wince/CEgui/Panel.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_PANEL -#define CEGUI_PANEL +#ifndef CEGUI_PANEL_H +#define CEGUI_PANEL_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/PanelItem.h b/backends/platform/wince/CEgui/PanelItem.h index 82e9b03e225..55920c304a5 100644 --- a/backends/platform/wince/CEgui/PanelItem.h +++ b/backends/platform/wince/CEgui/PanelItem.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_PANELITEM -#define CEGUI_PANELITEM +#ifndef CEGUI_PANELITEM_H +#define CEGUI_PANELITEM_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/PanelKeyboard.h b/backends/platform/wince/CEgui/PanelKeyboard.h index 5ef4adc73ee..f441e147718 100644 --- a/backends/platform/wince/CEgui/PanelKeyboard.h +++ b/backends/platform/wince/CEgui/PanelKeyboard.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_PANELKEYBOARD -#define CEGUI_PANELKEYBOARD +#ifndef CEGUI_PANELKEYBOARD_H +#define CEGUI_PANELKEYBOARD_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.h b/backends/platform/wince/CEgui/SDL_ImageResource.h index 140a11c3567..454237dd15a 100644 --- a/backends/platform/wince/CEgui/SDL_ImageResource.h +++ b/backends/platform/wince/CEgui/SDL_ImageResource.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_SDL_IMAGERESOURCE -#define CEGUI_SDL_IMAGERESOURCE +#ifndef CEGUI_SDL_IMAGERESOURCE_H +#define CEGUI_SDL_IMAGERESOURCE_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/Toolbar.h b/backends/platform/wince/CEgui/Toolbar.h index c23559d3152..3c48e6188a7 100644 --- a/backends/platform/wince/CEgui/Toolbar.h +++ b/backends/platform/wince/CEgui/Toolbar.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_TOOLBAR -#define CEGUI_TOOLBAR +#ifndef CEGUI_TOOLBAR_H +#define CEGUI_TOOLBAR_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEgui/ToolbarHandler.h b/backends/platform/wince/CEgui/ToolbarHandler.h index 30a299d1531..4a79ed1609a 100644 --- a/backends/platform/wince/CEgui/ToolbarHandler.h +++ b/backends/platform/wince/CEgui/ToolbarHandler.h @@ -23,8 +23,8 @@ * */ -#ifndef CEGUI_TOOLBARHANDLER -#define CEGUI_TOOLBARHANDLER +#ifndef CEGUI_TOOLBARHANDLER_H +#define CEGUI_TOOLBARHANDLER_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/CEkeys/EventsBuffer.h b/backends/platform/wince/CEkeys/EventsBuffer.h index 2e13770d252..44e1c66e473 100644 --- a/backends/platform/wince/CEkeys/EventsBuffer.h +++ b/backends/platform/wince/CEkeys/EventsBuffer.h @@ -23,8 +23,8 @@ * */ -#ifndef CEKEYS_EVENTSBUFFER -#define CEKEYS_EVENTSBUFFER +#ifndef CEKEYS_EVENTSBUFFER_H +#define CEKEYS_EVENTSBUFFER_H #include "common/scummsys.h" #include "common/system.h" diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index aef2117bd71..ac9be5df480 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -429,7 +429,7 @@ void OSystem_WINCE3::initBackend() { GUI::Actions::init(); GUI_Actions::Instance()->initInstanceMain(this); if (!GUI_Actions::Instance()->loadMapping()) { // error during loading means not present/wrong version - warning("Setting default action mappings."); + warning("Setting default action mappings"); GUI_Actions::Instance()->saveMapping(); // write defaults } @@ -987,11 +987,11 @@ void OSystem_WINCE3::check_mappings() { // Some games need to map the right click button, signal it here if it wasn't done if (instance->needsRightClickMapping()) { - GUI::KeysDialog *keysDialog = new GUI::KeysDialog("Map right click action"); + GUI::KeysDialog *keysDialog = new GUI::KeysDialog(_("Map right click action")); while (!instance->getMapping(POCKET_ACTION_RIGHTCLICK)) { keysDialog->runModal(); if (!instance->getMapping(POCKET_ACTION_RIGHTCLICK)) { - GUI::MessageDialog alert("You must map a key to the 'Right Click' action to play this game"); + GUI::MessageDialog alert(_("You must map a key to the 'Right Click' action to play this game")); alert.runModal(); } } @@ -1000,11 +1000,11 @@ void OSystem_WINCE3::check_mappings() { // Map the "hide toolbar" action if needed if (instance->needsHideToolbarMapping()) { - GUI::KeysDialog *keysDialog = new GUI::KeysDialog("Map hide toolbar action"); + GUI::KeysDialog *keysDialog = new GUI::KeysDialog(_("Map hide toolbar action")); while (!instance->getMapping(POCKET_ACTION_HIDE)) { keysDialog->runModal(); if (!instance->getMapping(POCKET_ACTION_HIDE)) { - GUI::MessageDialog alert("You must map a key to the 'Hide toolbar' action to play this game"); + GUI::MessageDialog alert(_("You must map a key to the 'Hide toolbar' action to play this game")); alert.runModal(); } } @@ -1013,10 +1013,10 @@ void OSystem_WINCE3::check_mappings() { // Map the "zoom" actions if needed if (instance->needsZoomMapping()) { - GUI::KeysDialog *keysDialog = new GUI::KeysDialog("Map Zoom Up action (optional)"); + GUI::KeysDialog *keysDialog = new GUI::KeysDialog(_("Map Zoom Up action (optional)")); keysDialog->runModal(); delete keysDialog; - keysDialog = new GUI::KeysDialog("Map Zoom Down action (optional)"); + keysDialog = new GUI::KeysDialog(_("Map Zoom Down action (optional)")); keysDialog->runModal(); delete keysDialog; } @@ -1024,7 +1024,7 @@ void OSystem_WINCE3::check_mappings() { // Extra warning for Zak Mc Kracken if (strncmp(gameid.c_str(), "zak", 3) == 0 && !GUI_Actions::Instance()->getMapping(POCKET_ACTION_HIDE)) { - GUI::MessageDialog alert("Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory"); + GUI::MessageDialog alert(_("Don't forget to map a key to 'Hide Toolbar' action to see the whole inventory")); alert.runModal(); } diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp index f8f1987b137..17a67f4d02e 100644 --- a/backends/plugins/elf/elf-loader.cpp +++ b/backends/plugins/elf/elf-loader.cpp @@ -166,7 +166,7 @@ bool DLObject::loadSegment(Elf32_Phdr *phdr) { warning("elfloader: Out of memory."); return false; } - + debug(2, "elfloader: Allocated segment @ %p", _segment); // Get offset to load segment into diff --git a/backends/plugins/elf/mips-loader.cpp b/backends/plugins/elf/mips-loader.cpp index a90e22cacd1..53ffc2f01b9 100644 --- a/backends/plugins/elf/mips-loader.cpp +++ b/backends/plugins/elf/mips-loader.cpp @@ -208,7 +208,7 @@ bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) *target = relocation; if (debugRelocs[6]++ < DEBUG_NUM) - debug("8, elfloader: R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x", + debug(8, "elfloader: R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x", i, a, origTarget, *target); } diff --git a/backends/plugins/sdl/sdl-provider.cpp b/backends/plugins/sdl/sdl-provider.cpp index be04b5a1eb8..6f8ca594f65 100644 --- a/backends/plugins/sdl/sdl-provider.cpp +++ b/backends/plugins/sdl/sdl-provider.cpp @@ -25,6 +25,9 @@ #if defined(DYNAMIC_MODULES) && defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/plugins/sdl/sdl-provider.h" #include "backends/plugins/dynamic-plugin.h" #include "common/fs.h" diff --git a/backends/timer/psp/timer.cpp b/backends/timer/psp/timer.cpp index 55b63ba4fd0..2b6bebe37c2 100644 --- a/backends/timer/psp/timer.cpp +++ b/backends/timer/psp/timer.cpp @@ -23,7 +23,7 @@ * */ -#if defined (__PSP__) +#if defined (__PSP__) #include #include "common/scummsys.h" @@ -38,7 +38,7 @@ bool PspTimer::start() { DEBUG_ENTER_FUNC(); - + if (!_interval || !_callback) return false; @@ -48,31 +48,31 @@ bool PspTimer::start() { PSP_ERROR("failed to create timer thread. Error code %d\n", _threadId); return false; } - + PspTimer *_this = this; // trick to get into context when the thread starts _init = true; - + if (sceKernelStartThread(_threadId, sizeof(uint32 *), &_this) < 0) { PSP_ERROR("failed to start thread %d\n", _threadId); return false; } - + PSP_DEBUG_PRINT("created timer thread[%x]\n", _threadId); - + return true; } int PspTimer::thread(SceSize, void *__this) { DEBUG_ENTER_FUNC(); PspTimer *_this = *(PspTimer **)__this; // get our this for the context - + _this->timerThread(); return 0; }; void PspTimer::timerThread() { DEBUG_ENTER_FUNC(); - + while (_init) { sceKernelDelayThread(_interval); PSP_DEBUG_PRINT("calling callback!\n"); diff --git a/backends/timer/psp/timer.h b/backends/timer/psp/timer.h index ec31addb727..01b1ca636e2 100644 --- a/backends/timer/psp/timer.h +++ b/backends/timer/psp/timer.h @@ -24,8 +24,8 @@ */ #ifndef PSP_TIMER_H -#define PSP_TIMER_H - +#define PSP_TIMER_H + class PspTimer { public: typedef void (* CallbackFunc)(void); @@ -44,4 +44,4 @@ private: bool _init; }; -#endif +#endif // PSP_TIMER_H diff --git a/backends/vkeybd/packs/vkeybdpack.py b/backends/vkeybd/packs/vkeybdpack.py index 130e4b737b8..b0cd4c45e99 100755 --- a/backends/vkeybd/packs/vkeybdpack.py +++ b/backends/vkeybd/packs/vkeybdpack.py @@ -16,9 +16,9 @@ def buildPack(packName): if not os.path.isdir(packName): print ("Invalid pack name: " + packName) return - + zf = zipfile.ZipFile(packName + ".zip", 'w') - + zf.compress_type = zipfile.ZIP_DEFLATED print ("Building '" + packName + "' pack:") @@ -28,9 +28,9 @@ def buildPack(packName): if os.path.isfile(filename) and not filename[0] == '.' and filename.endswith(PACK_FILE_EXTENSIONS): zf.write(filename, './' + filename, compress_type=compression) print (" Adding file: " + filename) - + os.chdir('../') - + zf.close() def buildAllPacks(): @@ -49,13 +49,13 @@ def printUsage(): print (" Builds the pack called 'packname'.\n") def main(): - + if len(sys.argv) == 2 and sys.argv[1] == "makeall": buildAllPacks() - + elif len(sys.argv) == 3 and sys.argv[1] == "make": buildPack(sys.argv[2]) - + else: printUsage() diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp index 6a644e0cdff..dd118662625 100644 --- a/backends/vkeybd/virtual-keyboard-parser.cpp +++ b/backends/vkeybd/virtual-keyboard-parser.cpp @@ -270,7 +270,7 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) { int r, g, b; if (node->values.contains("transparent_color")) { - if (!parseIntegerKey(node->values["transparent_color"].c_str(), 3, &r, &g, &b)) + if (!parseIntegerKey(node->values["transparent_color"], 3, &r, &g, &b)) return parserError("Could not parse color value"); } else { // default to purple @@ -281,7 +281,7 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) { _mode->transparentColor = format.RGBToColor(r, g, b); if (node->values.contains("display_font_color")) { - if (!parseIntegerKey(node->values["display_font_color"].c_str(), 3, &r, &g, &b)) + if (!parseIntegerKey(node->values["display_font_color"], 3, &r, &g, &b)) return parserError("Could not parse color value"); } else { r = g = b = 0; // default to black @@ -336,7 +336,7 @@ byte VirtualKeyboardParser::parseFlags(const String& flags) { bool VirtualKeyboardParser::parseRect(Rect &rect, const String& coords) { int x1, y1, x2, y2; - if (!parseIntegerKey(coords.c_str(), 4, &x1, &y1, &x2, &y2)) + if (!parseIntegerKey(coords, 4, &x1, &y1, &x2, &y2)) return parserError("Invalid coords for rect area"); rect.left = x1; rect.top = y1; diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 2f4e78fd80e..cf59ae6dfd3 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -219,6 +219,14 @@ void registerDefaults() { ConfMan.registerDefault("record_file_name", "record.bin"); ConfMan.registerDefault("record_temp_file_name", "record.tmp"); ConfMan.registerDefault("record_time_file_name", "record.time"); + +#if 0 + // NEW CODE TO HIDE CONSOLE FOR WIN32 +#ifdef WIN32 + // console hiding for win32 + ConfMan.registerDefault("show_console", false); +#endif +#endif } // @@ -546,6 +554,15 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha END_OPTION #endif +#if 0 + // NEW CODE TO HIDE CONSOLE FOR WIN32 +#ifdef WIN32 + // console hiding for win32 + DO_LONG_OPTION_BOOL("show-console") + END_OPTION +#endif +#endif + unknownOption: // If we get till here, the option is unhandled and hence unknown. usage("Unrecognized option '%s'", argv[i]); @@ -578,6 +595,10 @@ static void listTargets() { using namespace Common; const ConfigManager::DomainMap &domains = ConfMan.getGameDomains(); ConfigManager::DomainMap::const_iterator iter; + + Common::Array targets; + targets.reserve(domains.size()); + for (iter = domains.begin(); iter != domains.end(); ++iter) { Common::String name(iter->_key); Common::String description(iter->_value.getVal("description")); @@ -592,9 +613,13 @@ static void listTargets() { description = g.description(); } - printf("%-20s %s\n", name.c_str(), description.c_str()); - + targets.push_back(Common::String::printf("%-20s %s", name.c_str(), description.c_str())); } + + Common::sort(targets.begin(), targets.end()); + + for (Common::Array::const_iterator i = targets.begin(), end = targets.end(); i != end; ++i) + printf("%s\n", i->c_str()); } /** List all saves states for the given target. */ @@ -950,9 +975,9 @@ Common::Error processSettings(Common::String &command, Common::StringMap &settin if (dir && *dir && strlen(dir) < MAXPATHLEN) { Common::FSNode saveDir(dir); if (!saveDir.exists()) { - warning("Non-existent SCUMMVM_SAVEPATH save path. It will be ignored."); + warning("Non-existent SCUMMVM_SAVEPATH save path. It will be ignored"); } else if (!saveDir.isWritable()) { - warning("Non-writable SCUMMVM_SAVEPATH save path. It will be ignored."); + warning("Non-writable SCUMMVM_SAVEPATH save path. It will be ignored"); } else { settings["savepath"] = dir; } diff --git a/base/internal_version.h b/base/internal_version.h index 5fd0535142a..2b00ce60d2d 100644 --- a/base/internal_version.h +++ b/base/internal_version.h @@ -3,7 +3,7 @@ #endif #ifndef SCUMMVM_SVN_REVISION -#define SCUMMVM_SVN_REVISION +#define SCUMMVM_SVN_REVISION "" #endif #ifdef RELEASE_BUILD @@ -11,4 +11,4 @@ #define SCUMMVM_SVN_REVISION #endif -#define SCUMMVM_VERSION "1.2.0svn" SCUMMVM_SVN_REVISION +#define SCUMMVM_VERSION "1.3.0svn" SCUMMVM_SVN_REVISION diff --git a/base/internal_version.h.in b/base/internal_version.h.in index adf5f94d21c..dacaf72d404 100644 --- a/base/internal_version.h.in +++ b/base/internal_version.h.in @@ -3,7 +3,7 @@ #endif #ifndef SCUMMVM_SVN_REVISION -#define SCUMMVM_SVN_REVISION +#define SCUMMVM_SVN_REVISION "@SVN_REVISION@" #endif #ifdef RELEASE_BUILD diff --git a/base/main.cpp b/base/main.cpp index b925391a96c..37e100b49f8 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -315,7 +315,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { Common::StringMap settings; command = Base::parseCommandLine(settings, argc, argv); - // Load the config file (possibly overriden via command line): + // Load the config file (possibly overridden via command line): if (settings.contains("config")) { ConfMan.loadConfigFile(settings["config"]); settings.erase("config"); @@ -326,9 +326,6 @@ 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 // requested. @@ -440,9 +437,6 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { PluginManager::instance().loadPlugins(); #endif } else { - // A dialog would be nicer, but we don't have any - // screen to draw on yet. - 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")); } diff --git a/base/plugins.cpp b/base/plugins.cpp index 2e08dabc3f3..d2fad34579f 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -121,6 +121,9 @@ public: #if PLUGIN_ENABLED_STATIC(KYRA) LINK_PLUGIN(KYRA) #endif + #if PLUGIN_ENABLED_STATIC(LASTEXPRESS) + LINK_PLUGIN(LASTEXPRESS) + #endif #if PLUGIN_ENABLED_STATIC(LURE) LINK_PLUGIN(LURE) #endif @@ -154,12 +157,21 @@ public: #if PLUGIN_ENABLED_STATIC(SWORD2) LINK_PLUGIN(SWORD2) #endif + #if PLUGIN_ENABLED_STATIC(SWORD25) + LINK_PLUGIN(SWORD25) + #endif #if PLUGIN_ENABLED_STATIC(TEENAGENT) LINK_PLUGIN(TEENAGENT) #endif + #if PLUGIN_ENABLED_STATIC(TESTBED) + LINK_PLUGIN(TESTBED) + #endif #if PLUGIN_ENABLED_STATIC(TINSEL) LINK_PLUGIN(TINSEL) #endif + #if PLUGIN_ENABLED_STATIC(TOON) + LINK_PLUGIN(TOON) + #endif #if PLUGIN_ENABLED_STATIC(TOUCHE) LINK_PLUGIN(TOUCHE) #endif @@ -203,13 +215,14 @@ public: LINK_PLUGIN(ADLIB) LINK_PLUGIN(PCSPK) LINK_PLUGIN(PCJR) + LINK_PLUGIN(CMS) #ifndef DISABLE_SID LINK_PLUGIN(C64) #endif LINK_PLUGIN(AMIGA) LINK_PLUGIN(APPLEIIGS) LINK_PLUGIN(TOWNS) - #if defined (UNIX) + #if defined(USE_TIMIDITY) LINK_PLUGIN(TIMIDITY) #endif diff --git a/base/version.cpp b/base/version.cpp index 055067a6568..6967263f5c4 100644 --- a/base/version.cpp +++ b/base/version.cpp @@ -92,6 +92,10 @@ const char *gScummVMFeatures = "" "SEQ " #endif +#ifdef USE_TIMIDITY + "TiMidity " +#endif + #ifdef USE_RGB_COLOR "RGB " #endif @@ -107,5 +111,9 @@ const char *gScummVMFeatures = "" #ifdef USE_FLUIDSYNTH "FluidSynth " #endif + +#ifdef USE_THEORADEC + "Theora " +#endif ; diff --git a/common/algorithm.h b/common/algorithm.h index 9d22af40901..b34d6f852d5 100644 --- a/common/algorithm.h +++ b/common/algorithm.h @@ -242,13 +242,17 @@ void sort(T first, T last) { */ template T gcd(T a, T b) { - if (a <= 0) a = -a; - if (b <= 0) b = -b; + if (a <= 0) + a = -a; + if (b <= 0) + b = -b; + while (a > 0) { T tmp = a; a = b % a; b = tmp; } + return b; } diff --git a/common/array.h b/common/array.h index 4cc5369f9fe..e3aab66dc69 100644 --- a/common/array.h +++ b/common/array.h @@ -150,6 +150,12 @@ public: insert_aux(_storage + idx, &element, &element + 1); } + void insert_at(int idx, const Array &array) { + assert(idx >= 0 && (uint)idx <= _size); + insert_aux(_storage + idx, array.begin(), array.end()); + } + + T remove_at(int idx) { assert(idx >= 0 && (uint)idx < _size); T tmp = _storage[idx]; diff --git a/common/forbidden.h b/common/forbidden.h new file mode 100644 index 00000000000..cc71c367111 --- /dev/null +++ b/common/forbidden.h @@ -0,0 +1,147 @@ +/* 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_FORBIDDEN_H +#define COMMON_FORBIDDEN_H + + +// +// Backend files may #define FORBIDDEN_SYMBOL_ALLOW_ALL if they +// have to access functions like fopen, fread etc. +// Regular code, esp. code in engines/, should never do that. +// + +#ifndef FORBIDDEN_SYMBOL_ALLOW_ALL + +#define FORBIDDEN_SYMBOL_REPLACEMENT FORBIDDEN SYMBOL! + + +/* +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_printf +#undef printf +#define printf FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fprintf +#undef fprintf +#define fprintf FORBIDDEN_SYMBOL_REPLACEMENT +#endif +*/ + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_FILE +#undef FILE +#define FILE FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fopen +#undef fopen +#define fopen(a,b) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fclose +#undef fclose +#define fclose(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fread +#undef fread +#define fread(a,b,c,d) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fwrite +#undef fwrite +#define fwrite(a,b,c,d) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fseek +#undef fseek +#define fseek(a,b,c) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_ftell +#undef ftell +#define ftell(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_feof +#undef feof +#define feof(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fgetc +#undef fgetc +#define fgetc(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_fputc +#undef fputc +#define fputc(a,b) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_setjmp +#undef setjmp +#define setjmp(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_longjmp +#undef longjmp +#define longjmp(a,b) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + +#ifndef FORBIDDEN_SYMBOL_EXCEPTION_system +#undef system +#define system(a) FORBIDDEN_SYMBOL_REPLACEMENT +#endif + + +/* +time_t + +time + +difftime + +mktime + +localtime + +clock + +gmtime + +system + +remove + +setlocale + +setvbuf +*/ + +#endif + + +#endif diff --git a/common/hashmap.h b/common/hashmap.h index 0d4d7663f38..45192256a9b 100644 --- a/common/hashmap.h +++ b/common/hashmap.h @@ -42,7 +42,8 @@ namespace Common { // The sgi IRIX MIPSpro Compiler has difficulties with nested templates. // This and the other __sgi conditionals below work around these problems. -#if defined(__sgi) && !defined(__GNUC__) +// The Intel C++ Compiler suffers from the same problems. +#if (defined(__sgi) && !defined(__GNUC__)) || defined(__INTEL_COMPILER) template class IteratorImpl; #endif @@ -138,7 +139,7 @@ private: template class IteratorImpl { friend class HashMap; -#if defined(__sgi) && !defined(__GNUC__) +#if (defined(__sgi) && !defined(__GNUC__)) || defined(__INTEL_COMPILER) template friend class Common::IteratorImpl; #else template friend class IteratorImpl; diff --git a/common/macresman.cpp b/common/macresman.cpp index eb6a5939b6d..641702b5ece 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -110,6 +110,7 @@ bool MacResManager::open(Common::String filename) { _baseFileName = filename; return true; } + delete macResForkRawStream; #endif @@ -169,6 +170,7 @@ bool MacResManager::open(Common::FSNode path, Common::String filename) { _baseFileName = filename; return true; } + delete macResForkRawStream; #endif @@ -466,6 +468,28 @@ Common::SeekableReadStream *MacResManager::getResource(const Common::String &fil return 0; } +Common::SeekableReadStream *MacResManager::getResource(uint32 typeID, const Common::String &filename) { + for (uint32 i = 0; i < _resMap.numTypes; i++) { + if (_resTypes[i].id != typeID) + continue; + + for (uint32 j = 0; j < _resTypes[i].items; j++) { + if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) { + _stream->seek(_dataOffset + _resLists[i][j].dataOffset); + uint32 len = _stream->readUint32BE(); + + // Ignore resources with 0 length + if (!len) + return 0; + + return _stream->readStream(len); + } + } + } + + return 0; +} + void MacResManager::readMap() { _stream->seek(_mapOffset + 22); diff --git a/common/macresman.h b/common/macresman.h index 21682356707..d47b0ca329a 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -57,7 +57,7 @@ public: /** * Read resource from the Mac Binary file - * @param typeID FourCC with type ID + * @param typeID FourCC of the type * @param resID Resource ID to fetch * @return Pointer to a SeekableReadStream with loaded resource */ @@ -65,11 +65,20 @@ public: /** * Read resource from the Mac Binary file + * @note This will take the first resource that matches this name, regardless of type * @param filename filename of the resource * @return Pointer to a SeekableReadStream with loaded resource */ Common::SeekableReadStream *getResource(const Common::String &filename); + /** + * Read resource from the Mac Binary file + * @param typeID FourCC of the type + * @param filename filename of the resource + * @return Pointer to a SeekableReadStream with loaded resource + */ + Common::SeekableReadStream *getResource(uint32 typeID, const Common::String &filename); + Common::SeekableReadStream *getDataFork(); Common::String getResName(uint32 typeID, uint16 resID); uint32 getResForkSize(); diff --git a/common/memorypool.h b/common/memorypool.h index 7188e854f95..e19d9829137 100644 --- a/common/memorypool.h +++ b/common/memorypool.h @@ -66,7 +66,7 @@ public: * Constructor for a memory pool with the given chunk size. * @param chunkSize the chunk size of this memory pool */ - MemoryPool(size_t chunkSize); + explicit MemoryPool(size_t chunkSize); ~MemoryPool(); /** diff --git a/common/mutex.h b/common/mutex.h index ba5c45c30e7..3addaa6b188 100644 --- a/common/mutex.h +++ b/common/mutex.h @@ -49,8 +49,8 @@ class StackLock { void lock(); void unlock(); public: - StackLock(MutexRef mutex, const char *mutexName = NULL); - StackLock(const Mutex &mutex, const char *mutexName = NULL); + explicit StackLock(MutexRef mutex, const char *mutexName = NULL); + explicit StackLock(const Mutex &mutex, const char *mutexName = NULL); ~StackLock(); }; diff --git a/common/rational.cpp b/common/rational.cpp index 163044f349b..f55c2dcfe34 100644 --- a/common/rational.cpp +++ b/common/rational.cpp @@ -22,6 +22,7 @@ * $Id$ */ +#include "common/debug.h" #include "common/rational.h" #include "common/util.h" #include "common/algorithm.h" @@ -257,38 +258,34 @@ frac_t Rational::toFrac() const { return (_num * FRAC_ONE) / _denom; } -Rational::operator int() const { - return toInt(); -} - -Rational::operator double() const { - return toDouble(); -} - const Rational operator+(int left, const Rational &right) { - Rational tmp = right; - tmp += left; + Rational tmp(left); + tmp += right; return tmp; } const Rational operator-(int left, const Rational &right) { - Rational tmp = right; - tmp -= left; + Rational tmp(left); + tmp -= right; return tmp; } const Rational operator*(int left, const Rational &right) { - Rational tmp = right; - tmp *= left; + Rational tmp(left); + tmp *= right; return tmp; } const Rational operator/(int left, const Rational &right) { - Rational tmp = right; - tmp /= left; + Rational tmp(left); + tmp /= right; return tmp; } +void Rational::debugPrint(int debuglevel, const char *caption) const { + debug(debuglevel, "%s %d/%d", caption, _num, _denom); +} + bool operator==(int left, const Rational &right) { return right == left; } diff --git a/common/rational.h b/common/rational.h index 5ceac362091..bee09d8ddb1 100644 --- a/common/rational.h +++ b/common/rational.h @@ -76,9 +76,6 @@ public: bool operator>=(int right) const; bool operator<=(int right) const; - operator int() const; - operator double() const; - void invert(); Rational getInverse() const; @@ -86,6 +83,8 @@ public: double toDouble() const; frac_t toFrac() const; + void debugPrint(int debuglevel = 0, const char *caption = "Rational:") const; + private: int _num; int _denom; diff --git a/common/scummsys.h b/common/scummsys.h index df8b8e19015..d168544b188 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -243,7 +243,7 @@ #define SCUMM_NEED_ALIGNMENT #endif - // Very BAD hack following, used to avoid triggering an assert in uClibc dingux library + // Very BAD hack following, used to avoid triggering an assert in uClibc dingux library // "toupper" when pressing keyboard function keys. #if defined(DINGUX) #undef toupper @@ -315,6 +315,7 @@ #elif defined(__PSP__) #include + #include "backends/platform/psp/memory.h" #define scumm_stricmp strcasecmp #define scumm_strnicmp strncasecmp @@ -322,6 +323,9 @@ #define SCUMM_LITTLE_ENDIAN #define SCUMM_NEED_ALIGNMENT + /* to make an efficient, inlined memcpy implementation */ + #define memcpy(dst, src, size) psp_memcpy(dst, src, size) + #elif defined(__amigaos4__) #define scumm_stricmp strcasecmp @@ -433,5 +437,6 @@ typedef uint16 OverlayColor; #endif +#include #endif diff --git a/common/str.cpp b/common/str.cpp index 2961a0c61b9..c3c19adfe60 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -439,12 +439,20 @@ String String::printf(const char *fmt, ...) { int len = vsnprintf(output._str, _builtinCapacity, fmt, va); va_end(va); - if (len == -1) { - // MSVC doesn't return the size the full string would take up. - // Try increasing the size of the string until it fits. + if (len == -1 || len == _builtinCapacity - 1) { + // MSVC and IRIX don't return the size the full string would take up. + // MSVC returns -1, IRIX returns the number of characters actually written, + // which is at the most the size of the buffer minus one, as the string is + // truncated to fit. // We assume MSVC failed to output the correct, null-terminated string // if the return value is either -1 or size. + // For IRIX, because we lack a better mechanism, we assume failure + // if the return value equals size - 1. + // The downside to this is that whenever we try to format a string where the + // size is 1 below the built-in capacity, the size is needlessly increased. + + // Try increasing the size of the string until it fits. int size = _builtinCapacity; do { size *= 2; @@ -455,7 +463,7 @@ String String::printf(const char *fmt, ...) { va_start(va, fmt); len = vsnprintf(output._str, size, fmt, va); va_end(va); - } while (len == -1 || len >= size); + } while (len == -1 || len >= size - 1); output._size = len; } else if (len < (int)_builtinCapacity) { // vsnprintf succeeded @@ -691,9 +699,18 @@ bool matchString(const char *str, const char *pat, bool ignoreCase, bool pathMod switch (*pat) { case '*': - // Record pattern / string position for backtracking - p = ++pat; - q = str; + if (*str) { + // Record pattern / string position for backtracking + p = ++pat; + q = str; + } else { + // If we've reached the end of str, we can't backtrack further + // NB: We can't simply check if pat also ended here, because + // the pattern might end with any number of *s. + ++pat; + p = 0; + q = 0; + } // If pattern ended with * -> match if (!*pat) return true; diff --git a/common/stream.cpp b/common/stream.cpp index 718c806ff3a..9f8f6127f1d 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -231,21 +231,13 @@ BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize, _realBufSize(bufSize) { assert(parentStream); - allocBuf(bufSize); - assert(_buf); -} - -void BufferedReadStream::allocBuf(uint32 bufSize) { _buf = new byte[bufSize]; + assert(_buf); } BufferedReadStream::~BufferedReadStream() { if (_disposeParentStream) delete _parentStream; - deallocBuf(); -} - -void BufferedReadStream::deallocBuf() { delete[] _buf; } @@ -294,7 +286,7 @@ uint32 BufferedReadStream::read(void *dataPtr, uint32 dataSize) { // Satisfy the request from the buffer memcpy(dataPtr, _buf + _pos, dataSize); _pos += dataSize; - } + } return alreadyRead + dataSize; } @@ -309,7 +301,7 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) { // Note: We could try to handle SEEK_END and SEEK_SET, too, but // since they are rarely used, it seems not worth the effort. _eos = false; // seeking always cancels EOS - + if (whence == SEEK_CUR && (int)_pos + offset >= 0 && _pos + offset <= _bufSize) { _pos += offset; @@ -334,24 +326,16 @@ BufferedWriteStream::BufferedWriteStream(WriteStream *parentStream, uint32 bufSi _bufSize(bufSize) { assert(parentStream); - allocBuf(bufSize); + _buf = new byte[bufSize]; assert(_buf); } BufferedWriteStream::~BufferedWriteStream() { assert(flush()); - + if (_disposeParentStream) delete _parentStream; - - deallocBuf(); -} -void BufferedWriteStream::allocBuf(uint32 bufSize) { - _buf = new byte[bufSize]; -} - -void BufferedWriteStream::deallocBuf() { delete[] _buf; } @@ -359,7 +343,7 @@ uint32 BufferedWriteStream::write(const void *dataPtr, uint32 dataSize) { // check if we have enough space for writing to the buffer if (_bufSize - _pos >= dataSize) { memcpy(_buf + _pos, dataPtr, dataSize); - _pos += dataSize; + _pos += dataSize; } else if (_bufSize >= dataSize) { // check if we can flush the buffer and load the data // flush the buffer assert(flushBuffer()); @@ -367,7 +351,7 @@ uint32 BufferedWriteStream::write(const void *dataPtr, uint32 dataSize) { _pos += dataSize; } else { // too big for our buffer // flush the buffer - assert(flushBuffer()); + assert(flushBuffer()); return _parentStream->write(dataPtr, dataSize); } return dataSize; @@ -375,7 +359,7 @@ uint32 BufferedWriteStream::write(const void *dataPtr, uint32 dataSize) { bool BufferedWriteStream::flushBuffer() { uint32 bytesToWrite = _pos; - + if (bytesToWrite) { _pos = 0; if (_parentStream->write(_buf, bytesToWrite) != bytesToWrite) diff --git a/common/stream.h b/common/stream.h index 4d673d1539f..c6605cb42dc 100644 --- a/common/stream.h +++ b/common/stream.h @@ -497,8 +497,6 @@ protected: bool _eos; // end of stream uint32 _bufSize; uint32 _realBufSize; - virtual void allocBuf(uint32 bufSize); // virtual functions to allocate/deallocate the buffer - virtual void deallocBuf(); public: BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO); @@ -538,13 +536,11 @@ protected: uint32 _pos; uint32 _bufSize; bool flushBuffer(); // write out the data in the buffer - virtual void allocBuf(uint32 bufSize); // virtual functions to allocate/deallocate the buffer - virtual void deallocBuf(); public: BufferedWriteStream(WriteStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO); virtual ~BufferedWriteStream(); - + virtual uint32 write(const void *dataPtr, uint32 dataSize); virtual bool flush(); }; diff --git a/common/translation.cpp b/common/translation.cpp index 1328ed62d2d..a33e1a52436 100644 --- a/common/translation.cpp +++ b/common/translation.cpp @@ -213,6 +213,12 @@ const char *TranslationManager::getCurrentCharset() { return _currentCharset.c_str(); } +const char *TranslationManager::getCurrentLanguage() { + if (_currentLang == -1) + return "C"; + return _langs[_currentLang].c_str(); +} + String TranslationManager::getTranslation(const String &message) { return getTranslation(message.c_str()); } @@ -264,18 +270,18 @@ bool TranslationManager::openTranslationsFile(File& inFile) { // First try to open it directly (i.e. using the SearchMan). if (inFile.open("translations.dat")) return true; - + // Then look in the Themepath if we can find the file. if (ConfMan.hasKey("themepath")) return openTranslationsFile(FSNode(ConfMan.get("themepath")), inFile); - + return false; } bool TranslationManager::openTranslationsFile(const FSNode &node, File& inFile, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return false; - + // Check if we can find the file in this directory // Since File::open(FSNode) makes all the needed tests, it is not really // necessary to make them here. But it avoid printing warnings. @@ -284,21 +290,21 @@ bool TranslationManager::openTranslationsFile(const FSNode &node, File& inFile, if (inFile.open(fileNode)) return true; } - + // Check if we exceeded the given recursion depth if (depth - 1 == -1) - return false; - + return false; + // Otherwise look for it in sub-directories FSList fileList; if (!node.getChildren(fileList, FSNode::kListDirectoriesOnly)) return false; - + for (FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { if (openTranslationsFile(*i, inFile, depth == -1 ? - 1 : depth - 1)) return true; } - + // Not found in this directory or its sub-directories return false; } @@ -318,7 +324,7 @@ void TranslationManager::loadTranslationsInfoDat() { // Get number of translations int nbTranslations = in.readUint16BE(); - + // Skip all the block sizes for (int i = 0; i < nbTranslations + 2; ++i) in.readUint16BE(); @@ -467,12 +473,15 @@ String TranslationManager::getTranslation(const String &message, const String &) const TLangArray TranslationManager::getSupportedLanguageNames() const { return TLangArray(); } - + const char *TranslationManager::getCurrentCharset() { return "ASCII"; } +const char *TranslationManager::getCurrentLanguage() { + return "C"; +} + #endif // USE_TRANSLATION } // End of namespace Common - diff --git a/common/translation.h b/common/translation.h index 57c4cc2ac82..ff0a8a2acf2 100644 --- a/common/translation.h +++ b/common/translation.h @@ -116,7 +116,7 @@ public: * it returns the original untranslated message. */ String getTranslation(const String &message); - + /** * Returns the translation into the current language of the parameter * message. In case the message isn't found in the translation catalog, @@ -127,7 +127,7 @@ public: * massage without a context or with a different context. */ const char *getTranslation(const char *message, const char *context); - + /** * Returns the translation into the current language of the parameter * message. In case the message isn't found in the translation catalog, @@ -151,6 +151,11 @@ public: */ const char *getCurrentCharset(); + /** + * Returns currently selected translation language + */ + const char *getCurrentLanguage(); + private: #ifdef USE_TRANSLATION /** @@ -208,6 +213,6 @@ private: #define _s(str) str #define _sc(str, ctxt) str -#define DECLARE_TRANSLATION_ADDITIONAL_CONTEXT(str, ctxt) +#define DECLARE_TRANSLATION_ADDITIONAL_CONTEXT(str, ctxt) #endif diff --git a/common/unzip.cpp b/common/unzip.cpp index 6df2ed48486..3f084ad8610 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -373,7 +373,7 @@ typedef struct { unz_file_info_internal cur_file_info_internal; /* private info about it*/ } cached_file_in_zip; -typedef Common::HashMap ZipHash; /* unz_s contain internal information about the zipfile @@ -401,7 +401,7 @@ typedef struct { /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. - IN assertion: the stream s has been sucessfully opened for reading. + IN assertion: the stream s has been successfully opened for reading. */ diff --git a/common/util.h b/common/util.h index 52e4295bbbc..699653918a4 100644 --- a/common/util.h +++ b/common/util.h @@ -63,6 +63,20 @@ template inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; } #define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0]))) +/** + * @def SCUMMVM_CURRENT_FUNCTION + * This macro evaluates to the current function's name on compilers supporting this. + */ +#if defined(__GNUC__) +# define SCUMMVM_CURRENT_FUNCTION __PRETTY_FUNCTION__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) +# define SCUMMVM_CURRENT_FUNCTION __func__ +#elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define SCUMMVM_CURRENT_FUNCTION __FUNCTION__ +#else +# define SCUMMVM_CURRENT_FUNCTION "" +#endif + namespace Common { /** diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp index 1c652fa19da..ab56ba37510 100644 --- a/common/xmlparser.cpp +++ b/common/xmlparser.cpp @@ -229,6 +229,47 @@ bool XMLParser::parseKeyValue(Common::String keyName) { return true; } +bool XMLParser::parseIntegerKey(const char *key, int count, ...) { + bool result; + va_list args; + va_start(args, count); + result = vparseIntegerKey(key, count, args); + va_end(args); + return result; +} + +bool XMLParser::parseIntegerKey(const Common::String &key, int count, ...) { + bool result; + va_list args; + va_start(args, count); + result = vparseIntegerKey(key.c_str(), count, args); + va_end(args); + return result; +} + +bool XMLParser::vparseIntegerKey(const char *key, int count, va_list args) { + char *parseEnd; + int *num_ptr; + + while (count--) { + while (isspace(*key)) + key++; + + num_ptr = va_arg(args, int*); + *num_ptr = strtol(key, &parseEnd, 10); + + key = parseEnd; + + while (isspace(*key)) + key++; + + if (count && *key++ != ',') + return false; + } + + return (*key == 0); +} + bool XMLParser::closeKey() { bool ignore = false; bool result = true; @@ -410,5 +451,61 @@ bool XMLParser::parse() { return true; } +bool XMLParser::skipSpaces() { + if (!isspace(_char)) + return false; + + while (_char && isspace(_char)) + _char = _stream->readByte(); + + return true; } +bool XMLParser::skipComments() { + if (_char == '<') { + _char = _stream->readByte(); + + if (_char != '!') { + _stream->seek(-1, SEEK_CUR); + _char = '<'; + return false; + } + + if (_stream->readByte() != '-' || _stream->readByte() != '-') + return parserError("Malformed comment syntax."); + + _char = _stream->readByte(); + + while (_char) { + if (_char == '-') { + if (_stream->readByte() == '-') { + + if (_stream->readByte() != '>') + return parserError("Malformed comment (double-hyphen inside comment body)."); + + _char = _stream->readByte(); + return true; + } + } + + _char = _stream->readByte(); + } + + return parserError("Comment has no closure."); + } + + return false; +} + +bool XMLParser::parseToken() { + _token.clear(); + + while (isValidNameChar(_char)) { + _token += _char; + _char = _stream->readByte(); + } + + return isspace(_char) != 0 || _char == '>' || _char == '=' || _char == '/'; +} + +} // End of namespace Common diff --git a/common/xmlparser.h b/common/xmlparser.h index 52719179273..c8cc349a6cf 100644 --- a/common/xmlparser.h +++ b/common/xmlparser.h @@ -293,65 +293,22 @@ protected: /** * Prints an error message when parsing fails and stops the parser. - * Parser error always returns "false" so we can pass the return value directly - * and break down the parsing. + * Parser error always returns "false" so we can pass the return value + * directly and break down the parsing. */ bool parserError(const char *errorString, ...) GCC_PRINTF(2, 3); /** - * Skips spaces/whitelines etc. Returns true if any spaces were skipped. + * Skips spaces/whitelines etc. + * @return true if any spaces were skipped. */ - bool skipSpaces() { - if (!isspace(_char)) - return false; - - while (_char && isspace(_char)) - _char = _stream->readByte(); - - return true; - } + bool skipSpaces(); /** * Skips comment blocks and comment lines. - * Returns true if any comments were skipped. - * Overload this if you want to disable comments on your XML syntax - * or to change the commenting syntax. + * @return true if any comments were skipped. */ - virtual bool skipComments() { - if (_char == '<') { - _char = _stream->readByte(); - - if (_char != '!') { - _stream->seek(-1, SEEK_CUR); - _char = '<'; - return false; - } - - if (_stream->readByte() != '-' || _stream->readByte() != '-') - return parserError("Malformed comment syntax."); - - _char = _stream->readByte(); - - while (_char) { - if (_char == '-') { - if (_stream->readByte() == '-') { - - if (_stream->readByte() != '>') - return parserError("Malformed comment (double-hyphen inside comment body)."); - - _char = _stream->readByte(); - return true; - } - } - - _char = _stream->readByte(); - } - - return parserError("Comment has no closure."); - } - - return false; - } + bool skipComments(); /** * Check if a given character can be part of a KEY or VALUE name. @@ -364,18 +321,8 @@ protected: /** * Parses a the first textual token found. - * There's no reason to overload this. */ - bool parseToken() { - _token.clear(); - - while (isValidNameChar(_char)) { - _token += _char; - _char = _stream->readByte(); - } - - return isspace(_char) != 0 || _char == '>' || _char == '=' || _char == '/'; - } + bool parseToken(); /** * Parses the values inside an integer key. @@ -395,32 +342,9 @@ protected: * by reference. * @returns True if the parsing succeeded. */ - bool parseIntegerKey(const char *key, int count, ...) { - char *parseEnd; - int *num_ptr; - - va_list args; - va_start(args, count); - - while (count--) { - while (isspace(*key)) - key++; - - num_ptr = va_arg(args, int*); - *num_ptr = strtol(key, &parseEnd, 10); - - key = parseEnd; - - while (isspace(*key)) - key++; - - if (count && *key++ != ',') - return false; - } - - va_end(args); - return (*key == 0); - } + bool parseIntegerKey(const char *key, int count, ...); + bool parseIntegerKey(const Common::String &keyStr, int count, ...); + bool vparseIntegerKey(const char *key, int count, va_list args); bool parseXMLHeader(ParserNode *node); @@ -446,6 +370,6 @@ private: Common::Stack _activeKey; /** Node stack of the parsed keys */ }; -} +} // End of namespace Common #endif diff --git a/configure b/configure index a341a871371..bce4e659339 100755 --- a/configure +++ b/configure @@ -91,6 +91,7 @@ add_engine groovie2 "Groovie 2 games" no add_engine hugo "Hugo Trilogy" no add_engine kyra "Legend of Kyrandia" yes "lol" add_engine lol "Lands of Lore" no +add_engine lastexpress "The Last Express" no add_engine lure "Lure of the Temptress" yes add_engine m4 "M4/MADS" no add_engine made "MADE" yes @@ -105,8 +106,11 @@ add_engine sci32 "SCI32 games" no add_engine sky "Beneath a Steel Sky" yes add_engine sword1 "Broken Sword" yes add_engine sword2 "Broken Sword II" yes +add_engine sword25 "Broken Sword 2.5" no add_engine teenagent "Teen Agent" yes +add_engine testbed "TestBed: the Testing framework" no add_engine tinsel "Tinsel" yes +add_engine toon "Toonstruck" no add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes add_engine tucker "Bud Tucker in Double Trouble" yes @@ -121,8 +125,11 @@ _flac=auto _mad=auto _alsa=auto _seq_midi=auto +_timidity=auto _zlib=auto _mpeg2=no +_png=auto +_theoradec=auto _fluidsynth=auto _16bit=auto _readline=auto @@ -174,15 +181,15 @@ NASM="" # to make it possible to change e.g. the location of the # man pages independently of that of the engine data files, # which are placed inside $datadir/scummvm -exec_prefix=NONE prefix=NONE +exec_prefix=NONE bindir='${exec_prefix}/bin' +libdir='${exec_prefix}/lib' datarootdir='${prefix}/share' datadir='${datarootdir}/scummvm' -docdir='${datarootdir}/doc/scummvm' -libdir='${exec_prefix}/lib' -#localedir='${datarootdir}/locale' mandir='${datarootdir}/man' +docdir='${datarootdir}/doc/scummvm' +#localedir='${datarootdir}/locale' # For cross compiling _host="" @@ -194,12 +201,8 @@ _host_alias="" _srcdir=`dirname $0` _port_mk="ports.mk" -# Determine a tmp file name, using mktemp(1) when available. -if type mktemp > /dev/null 2>&1 ; then - TMPO=`mktemp /tmp/scummvm-conf.XXXXXXXXXX` -else - TMPO=./scummvm-conf -fi +# Use temp files in the build directory +TMPO=./scummvm-conf TMPC=${TMPO}.cpp TMPLOG=config.log @@ -365,17 +368,11 @@ get_system_exe_extension() { arm-riscos) _exeext=",ff8" ;; - caanoo-linux) - _exeext=".caanoo" - ;; dreamcast | ds | gamecube | n64 | ps2 | psp | wii) _exeext=".elf" ;; - gp2x-linux) - _exeext=".gp2x" - ;; - gp2xwiz-linux) - _exeext=".wiz" + gph-linux) + _exeext=".gph" ;; mingw* | *os2-emx | wince) _exeext=".exe" @@ -651,9 +648,9 @@ Usage: $0 [OPTIONS]... Configuration: -h, --help display this help and exit - --backend=BACKEND backend to build (caanoo, dc, gp2x, gp2xwiz, iphone, - linuxmoto, ds, null, ps2, psp, sdl, wii, wince) - [sdl] + --backend=BACKEND backend to build (android, dc, dingux, ds, gp2x, gph, + iphone, linuxmoto, maemo, n64, null, openpandora, ps2, + psp, samsungtv, sdl, symbian, wii, wince) [sdl] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX @@ -672,19 +669,30 @@ Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --libdir=DIR object code libraries [EPREFIX/lib] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR/scummvm] + --datadir=DIR read-only architecture-independent data + [DATAROOTDIR/scummvm] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/scummvm] Special configuration feature: --host=HOST cross-compile to target HOST (arm-linux, ...) - special targets: dreamcast for Sega Dreamcast + special targets: android for Android + caanoo for Caanoo + dingux for Dingux + dreamcast for Sega Dreamcast + ds for Nintendo DS gamecube for Nintendo GameCube + gp2x for GP2X + gp2xwiz for GP2X Wiz iphone for Apple iPhone linupy for Yopy PDA - ds for Nintendo DS + motoezx for MotoEZX + motomagx for MotoMAGX + n64 for Nintendo 64 + openpandora for OpenPandora ps2 for PlayStation 2 psp for PlayStation Portable + samsungtv for Samsung TV wii for Nintendo Wii wince for Windows CE @@ -695,7 +703,8 @@ $engines_help Optional Features: --disable-debug disable building with debugging symbols --enable-Werror treat warnings as errors - --enable-release enable building in release mode (this activates optimizations) + --enable-release enable building in release mode (this activates + optimizations) --enable-profiling enable profiling --enable-plugins enable the support for dynamic plugins --default-dynamic make plugins dynamic by default @@ -705,7 +714,8 @@ Optional Features: --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 + --enable-verbose-build enable regular echoing of commands during build + process Optional Libraries: --with-alsa-prefix=DIR Prefix where alsa is installed (optional) @@ -732,10 +742,18 @@ Optional Libraries: --disable-indeo3 disable Indeo3 decoder [autodetect] - --with-fluidsynth-prefix=DIR Prefix where libfluidsynth is installed (optional) + --with-png-prefix=DIR Prefix where libpng is installed (optional) + --disable-png disable PNG decoder [autodetect] + + --with-theoradec-prefix=DIR Prefix where libtheoradec is installed (optional) + --disable-theoradec disable Theora decoder [autodetect] + + --with-fluidsynth-prefix=DIR Prefix where libfluidsynth is + installed (optional) --disable-fluidsynth disable fluidsynth MIDI driver [autodetect] - --with-sdl-prefix=DIR Prefix where the sdl-config script is installed (optional) + --with-sdl-prefix=DIR Prefix where the sdl-config script is + installed (optional) --with-nasm-prefix=DIR Prefix where nasm executable is installed (optional) --disable-nasm disable assembly language optimizations [autodetect] @@ -765,8 +783,10 @@ for ac_option in $@; do --disable-hq-scalers) _build_hq_scalers=no ;; --enable-alsa) _alsa=yes ;; --disable-alsa) _alsa=no ;; - --enable-seq-midi) _seq_midi=yes ;; - --disable-seq-midi) _seq_midi=no ;; + --enable-seq-midi) _seq_midi=yes ;; + --disable-seq-midi) _seq_midi=no ;; + --enable-timidity) _timidity=yes ;; + --disable-timidity) _timidity=no ;; --enable-vorbis) _vorbis=yes ;; --disable-vorbis) _vorbis=no ;; --enable-tremor) _tremor=yes ;; @@ -782,6 +802,10 @@ for ac_option in $@; do --enable-mpeg2) _mpeg2=yes ;; --disable-indeo3) _indeo3=no ;; --enable-indeo3) _indeo3=yes ;; + --disable-png) _png=no ;; + --enable-png) _png=yes ;; + --disable-theoradec) _theoradec=no ;; + --enable-theoradec) _theoradec=yes ;; --disable-fluidsynth) _fluidsynth=no ;; --enable-readline) _readline=yes ;; --disable-readline) _readline=no ;; @@ -838,6 +862,16 @@ for ac_option in $@; do MAD_CFLAGS="-I$arg/include" MAD_LIBS="-L$arg/lib" ;; + --with-png-prefix=*) + arg=`echo $ac_option | cut -d '=' -f 2` + PNG_CFLAGS="-I$arg/include" + PNG_LIBS="-L$arg/lib" + ;; + --with-theoradec-prefix=*) + arg=`echo $ac_option | cut -d '=' -f 2` + THEORADEC_CFLAGS="-I$arg/include" + THEORADEC_LIBS="-L$arg/lib" + ;; --with-zlib-prefix=*) arg=`echo $ac_option | cut -d '=' -f 2` ZLIB_CFLAGS="-I$arg/include" @@ -883,17 +917,17 @@ for ac_option in $@; do --host=*) _host=`echo $ac_option | cut -d '=' -f 2` ;; - --exec-prefix=*) - exec_prefix=`echo $ac_option | cut -d '=' -f 2` - ;; --prefix=*) prefix=`echo $ac_option | cut -d '=' -f 2` ;; + --exec-prefix=*) + exec_prefix=`echo $ac_option | cut -d '=' -f 2` + ;; --bindir=*) bindir=`echo $ac_option | cut -d '=' -f 2` ;; - --mandir=*) - mandir=`echo $ac_option | cut -d '=' -f 2` + --libdir=*) + libdir=`echo $ac_option | cut -d '=' -f 2` ;; --datarootdir=*) datarootdir=`echo $ac_option | cut -d '=' -f 2` @@ -901,8 +935,11 @@ for ac_option in $@; do --datadir=*) datadir=`echo $ac_option | cut -d '=' -f 2` ;; - --libdir=*) - libdir=`echo $ac_option | cut -d '=' -f 2` + --mandir=*) + mandir=`echo $ac_option | cut -d '=' -f 2` + ;; + --docdir=*) + docdir=`echo $ac_option | cut -d '=' -f 2` ;; --enable-all-engines) engine_enable_all @@ -937,9 +974,18 @@ arm-riscos) _host_cpu=arm ;; caanoo) - _host_os=caanoo-linux + _host_os=gph-linux _host_cpu=arm _host_alias=arm-none-linux-gnueabi + if test "$_debug_build" = auto; then + # If you want to debug on the Caanoo use '--disable-release --enable-debug' + _debug_build=no + fi + + if test "$_release_build" = auto; then + # Enable release build by default. + _release_build=yes + fi ;; dingux) _host_os=linux @@ -964,14 +1010,32 @@ gamecube) _host_alias=powerpc-gekko ;; gp2x) - _host_os=gp2x-linux + _host_os=gph-linux _host_cpu=arm _host_alias=arm-open2x-linux + if test "$_debug_build" = auto; then + # If you want to debug on the GP2X use '--disable-release --enable-debug' + _debug_build=no + fi + + if test "$_release_build" = auto; then + # Enable release build by default. + _release_build=yes + fi ;; gp2xwiz) - _host_os=gp2xwiz-linux + _host_os=gph-linux _host_cpu=arm _host_alias=arm-open2x-linux + if test "$_debug_build" = auto; then + # If you want to debug on the GP2XWiz use '--disable-release --enable-debug' + _debug_build=no + fi + + if test "$_release_build" = auto; then + # Enable release build by default. + _release_build=yes + fi ;; i586-mingw32msvc) _host_os=mingw32msvc @@ -996,7 +1060,7 @@ motomagx) _host_cpu=arm _host_alias=arm-linux-gnueabi ;; -n64) +n64) _host_os=n64 _host_cpu=mips _host_alias=mips64 @@ -1005,6 +1069,20 @@ neuros) _host_os=linux _host_cpu=arm ;; +openpandora) + _host_os=linux + _host_cpu=arm + _host_alias=arm-angstrom-linux-gnueabi + if test "$_debug_build" = auto; then + # If you want to debug on the OP use '--disable-release --enable-debug' + _debug_build=no + fi + + if test "$_release_build" = auto; then + # Enable release build by default. + _release_build=yes + fi + ;; ppc-amigaos) _host_os=amigaos _host_cpu=ppc @@ -1100,10 +1178,10 @@ HOSTEXEEXT=$_exeext # Determine separator used for $PATH # case $_host_os in -os2-emx* ) +os2-emx*) SEPARATOR=";" ;; -* ) +*) SEPARATOR=":" ;; esac @@ -1186,12 +1264,12 @@ else CXX= for compiler in $compilers; do if test_compiler $compiler; then - echo "success testing compiler: $1" >> "$TMPLOG" + echo "success testing compiler: $compiler" >> "$TMPLOG" CXX=$compiler echo $CXX break else - echo "failure testing compiler: $1" >> "$TMPLOG" + echo "failure testing compiler: $compiler" >> "$TMPLOG" fi done fi @@ -1487,6 +1565,7 @@ case $_host_os in DEFINES="$DEFINES -D__N64__ -DLIMIT_FPS -DNONSTANDARD_PORT" DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_COMMAND_LINE" DEFINES="$DEFINES -DDISABLE_FANCY_THEMES -DDISABLE_DOSBOX_OPL -DDISABLE_SID -DDISABLE_NES_APU" + DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE" ;; os2-emx*) _unix=yes # FIXME??? Why?? @@ -1565,7 +1644,15 @@ if test -n "$_host"; then _need_memalign=yes ;; caanoo) - DEFINES="$DEFINES -DGP2XWIZ -DCAANOO -DNDEBUG" + # This uses the GPH backend. + DEFINES="$DEFINES -DGPH_DEVICE" + DEFINES="$DEFINES -DCAANOO -DREDUCE_MEMORY_USAGE" + if test "$_debug_build" = yes; then + DEFINES="$DEFINES -DGPH_DEBUG" + else + # Use -O3 on the Caanoo for non-debug builds. + CXXFLAGS="$CXXFLAGS -O3" + fi CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s" ASFLAGS="$ASFLAGS" _unix=yes @@ -1575,19 +1662,19 @@ if test -n "$_host"; then 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="gp2xwiz" + _backend="gph" _build_hq_scalers=no _mt32emu=no _vkeybd=yes _seq_midi=no - _port_mk="backends/platform/gp2xwiz/caanoo/caanoo-bundle.mk" - ;; + _port_mk="backends/platform/gph/caanoo-bundle.mk" + ;; *darwin*) _ranlib=$_host-ranlib _strip=$_host-strip ;; dingux) - DEFINES="$DEFINES -DUNIX -DDINGUX -DDISABLE_DOSBOX_OPL" + DEFINES="$DEFINES -DUNIX -DDINGUX -DDISABLE_DOSBOX_OPL -DREDUCE_MEMORY_USAGE" ASFLAGS="$ASFLAGS" CXXFLAGS="$CXXFLAGS -msoft-float -mips32" _need_memalign=yes @@ -1600,6 +1687,7 @@ if test -n "$_host"; then _vorbis=no # Force disable seq on dingux, no way to use it and it would get enabled by default with configure _seq_midi=no + _port_mk="backends/platform/dingux/dingux.mk" ;; dreamcast) DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE" @@ -1647,7 +1735,12 @@ if test -n "$_host"; then add_line_to_config_h "#define USE_WII_DI" ;; gp2x) - DEFINES="$DEFINES -DGP2X -DNDEBUG" + # This uses the GPH backend. + DEFINES="$DEFINES -DGPH_DEVICE" + DEFINES="$DEFINES -DGP2X -DREDUCE_MEMORY_USAGE" + if test "$_debug_build" = yes; then + DEFINES="$DEFINES -DGPH_DEBUG" + fi CXXFLAGS="$CXXFLAGS -march=armv4t" ASFLAGS="$ASFLAGS -mfloat-abi=soft" LDFLAGS="$LDFLAGS -static" @@ -1666,7 +1759,12 @@ if test -n "$_host"; then _port_mk="backends/platform/gp2x/gp2x-bundle.mk" ;; gp2xwiz) - DEFINES="$DEFINES -DGP2XWIZ -DNDEBUG" + # This uses the GPH backend. + DEFINES="$DEFINES -DGPH_DEVICE" + DEFINES="$DEFINES -DGP2XWIZ -DREDUCE_MEMORY_USAGE" + if test "$_debug_build" = yes; then + DEFINES="$DEFINES -DGPH_DEBUG" + fi CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s" ASFLAGS="$ASFLAGS -mfloat-abi=soft" _unix=yes @@ -1676,12 +1774,12 @@ if test -n "$_host"; then 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="gp2xwiz" + _backend="gph" _build_hq_scalers=no _mt32emu=no _vkeybd=yes _seq_midi=no - _port_mk="backends/platform/gp2xwiz/gp2xwiz-bundle.mk" + _port_mk="backends/platform/gph/gp2xwiz-bundle.mk" ;; iphone) DEFINES="$DEFINES -DIPHONE" @@ -1709,6 +1807,8 @@ if test -n "$_host"; then _ranlib=$_host-ranlib ;; mips-sgi*) + LDFLAGS="$LDFLAGS -static-libgcc" + LIBS="$LIBS -laudio" _endian=big _need_memalign=yes ;; @@ -1767,6 +1867,7 @@ if test -n "$_host"; then _mad=yes _tremor=yes _zlib=yes + _port_mk="backends/platform/n64/n64.mk" ;; neuros) DEFINES="$DEFINES -DNEUROS" @@ -1776,6 +1877,30 @@ if test -n "$_host"; then _build_hq_scalers=no _mt32emu=no ;; + openpandora) + DEFINES="$DEFINES -DOPENPANDORA -DREDUCE_MEMORY_USAGE" + if test "$_release_build" = no; then + DEFINES="$DEFINES -DOP_DEBUG" + else + # Use -O3 on the OpenPandora for non-debug builds. + CXXFLAGS="$CXXFLAGS -O3" + fi + CXXFLAGS="$CXXFLAGS -march=armv7-a -mtune=cortex-a8 -mfpu=neon" + ASFLAGS="$ASFLAGS -mfloat-abi=soft" + _unix=yes + _need_memalign=yes + add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1' + add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1' + add_line_to_config_mk 'USE_ARM_GFX_ASM = 1' + add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1' + add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1' + _backend="openpandora" + _build_hq_scalers=yes + _mt32emu=no + _vkeybd=no + _seq_midi=no + _port_mk="backends/platform/openpandora/op-bundle.mk" + ;; ppc-amigaos) _endian=big _need_memalign=yes @@ -1918,7 +2043,7 @@ fi # Enable 16bit support only for backends which support it # case $_backend in - dreamcast | dingux | samsungtv | sdl | wii | psp) + dingux | dreamcast | gph | openpandora | psp | samsungtv | sdl | wii) if test "$_16bit" = auto ; then _16bit=yes else @@ -2036,6 +2161,24 @@ POST_OBJS_FLAGS := -Wl,-no-whole-archive DEFINES="$DEFINES -DPPC_TARGET -DELF_LOADER_CXA_ATEXIT -DONE_PLUGIN_AT_A_TIME" _mak_plugins=' PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/wii/plugin.ld +' + ;; + gph*) +_def_plugin=' +#define PLUGIN_PREFIX "" +#define PLUGIN_SUFFIX ".plugin" +' +_mak_plugins=' +DYNAMIC_MODULES := 1 +PLUGIN_PREFIX := +PLUGIN_SUFFIX := .plugin +PLUGIN_EXTRA_DEPS = $(EXECUTABLE) +CXXFLAGS += -DDYNAMIC_MODULES +CXXFLAGS += -fpic +PLUGIN_LDFLAGS += -shared +PRE_OBJS_FLAGS := -Wl,-export-dynamic -Wl,-whole-archive +POST_OBJS_FLAGS := -Wl,-no-whole-archive +LIBS += -ldl ' ;; linux*|android) @@ -2085,7 +2228,7 @@ PLUGIN_LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-T$(srcdir)/backend DEFINES="$DEFINES -DMIPS_TARGET -DELF_LOADER_CXA_ATEXIT" _mak_plugins=' LDFLAGS += -Wl,-T$(srcdir)/backends/platform/psp/main_prog.ld -PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/psp/plugin.ld -lc -Wl,--wrap,memcpy +PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/psp/plugin.ld -lc ' ;; *) @@ -2274,6 +2417,62 @@ fi define_in_config_h_if_yes "$_alsa" 'USE_ALSA' echo "$_alsa" +# +# Check for PNG +# +echocheck "PNG >= 1.2.8" +if test "$_png" = auto ; then + _png=no + cat > $TMPC << EOF +#include +int main(void) { +#if PNG_LIBPNG_VER >= 10208 +#else + syntax error +#endif + return 0; +} +EOF + cc_check $PNG_CFLAGS $PNG_LIBS -lpng && _png=yes +fi +if test "$_png" = yes ; then + LIBS="$LIBS $PNG_LIBS -lpng" + INCLUDES="$INCLUDES $PNG_CFLAGS" +fi +define_in_config_if_yes "$_png" 'USE_PNG' +echo "$_png" + +if test `get_engine_build sword25` = yes && test ! "$_png" = yes ; then + echo "...disabling Broken Sword 2.5 engine. PNG is required" + engine_disable sword25 +fi + +# +# Check for Theora Decoder +# +echocheck "libtheoradec >= 1.0" +if test "$_vorbis" = no ; then + echo "skipping. no vorbis" + _theoradec=notsupported +fi +if test "$_theoradec" = auto ; then + _theoradec=no + cat > $TMPC << EOF +#include +#include +int main(void) { th_ycbcr_buffer yuv; th_decode_ycbcr_out(NULL, yuv); } +EOF + cc_check $THEORADEC_CFLAGS $THEORADEC_LIBS -ltheoradec && _theoradec=yes +fi +if test "$_theoradec" = yes ; then + LIBS="$LIBS $THEORADEC_LIBS -ltheoradec" + INCLUDES="$INCLUDES $THEORADEC_CFLAGS" +fi +define_in_config_if_yes "$_theoradec" 'USE_THEORADEC' +if test ! "$_theoradec" = notsupported ; then + echo "$_theoradec" +fi + # # Check for SEQ MIDI # @@ -2287,6 +2486,19 @@ fi define_in_config_h_if_yes "$_seq_midi" 'USE_SEQ_MIDI' echo "$_seq_midi" +# +# Check for TiMidity(++) +# +echocheck "TiMidity" +if test "$_timidity" = auto ; then + # TODO: Is there a good possibility of auto detecting whether we + # should include TiMidity support? It can only be used on Unix + # currently so we use that as "detection" for now. + _timidity="$_unix" +fi +define_in_config_h_if_yes "$_timidity" 'USE_TIMIDITY' +echo "$_timidity" + # # Check for ZLib # @@ -2452,14 +2664,14 @@ if test "$_have_x86" = yes ; then _nasm=no else case $_host_os in - os2-emx*) - NASMFLAGS="$NASMFLAGS -f aout" + darwin*) + NASMFLAGS="$NASMFLAGS -f macho" ;; mingw*) NASMFLAGS="$NASMFLAGS -f win32" ;; - darwin*) - NASMFLAGS="$NASMFLAGS -f macho" + os2-emx*) + NASMFLAGS="$NASMFLAGS -f aout" ;; *) NASMFLAGS="$NASMFLAGS -f elf" @@ -2513,8 +2725,16 @@ test "x$prefix" = xNONE && prefix=/usr/local test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFINES="$DEFINES -DDATA_PATH=\\\"$datadir\\\"" -DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"$libdir/scummvm\\\"" +case $_backend in + openpandora) + # Add ../plugins as a path so plugins can be found when running from a .PND. + DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"../plugins\\\"" + ;; + *) + DEFINES="$DEFINES -DPLUGIN_DIRECTORY=\\\"$libdir/scummvm\\\"" + ;; +esac # # Set variables for profiling. @@ -2603,13 +2823,6 @@ case $_backend in add_line_to_config_mk 'PLUGIN_LDFLAGS += -Lbuild.tmp -lscummvm' add_line_to_config_mk 'PLUGIN_EXTRA_DEPS += build.tmp/libscummvm.so' ;; - caanoo) - find_sdlconfig - INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`" - LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`" - LDFLAGS="$LDFLAGS" - CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s" - ;; dc) INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc -isystem $(ronindir)/include' LDFLAGS="$LDFLAGS -Wl,-Ttext,0x8c010000 -nostartfiles "'$(ronindir)/lib/crt0.o -L$(ronindir)/lib' @@ -2633,15 +2846,13 @@ case $_backend in find_sdlconfig INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`" LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`" - LDFLAGS="$LDFLAGS -static" - CXXFLAGS="$CXXFLAGS -march=armv4t" + LDFLAGS="$LDFLAGS" ;; - gp2xwiz) + gph) find_sdlconfig INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`" LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`" LDFLAGS="$LDFLAGS" - CXXFLAGS="$CXXFLAGS -mcpu=arm926ej-s -mtune=arm926ej-s" ;; iphone) OBJCFLAGS="$OBJCFLAGS --std=c99" @@ -2663,6 +2874,12 @@ case $_backend in null) DEFINES="$DEFINES -DUSE_NULL_DRIVER" ;; + openpandora) + find_sdlconfig + INCLUDES="$INCLUDES `$_sdlconfig --prefix="$_sdlpath" --cflags`" + LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`" + LDFLAGS="$LDFLAGS" + ;; ps2) # TODO ps2 DEFINES="$DEFINES -D_EE -DFORCE_RTL" @@ -2674,9 +2891,8 @@ case $_backend in LIBS="$LIBS -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lm -lc -lfileXio -lkernel -lstdc++ " ;; psp) - DEFINES="$DEFINES -D__PSP__ -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL" + DEFINES="$DEFINES -D__PSP__ -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL" LIBS="$LIBS -lpng -Wl,-Map,mapfile.txt" - LDFLAGS="$LDFLAGS -Wl,--wrap,memcpy" ;; samsungtv) find_sdlconfig @@ -2722,7 +2938,7 @@ if test "$have_gcc" = yes ; then case $_host_os in # newlib-based system include files suppress non-C89 function # declarations under __STRICT_ANSI__ - amigaos* | android | ds | dreamcast | gamecube | mingw* | n64 | psp | wii | wince ) + amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | wii | wince ) CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter" ;; *) @@ -2886,11 +3102,11 @@ NASMFLAGS := $NASMFLAGS prefix = $prefix exec_prefix = $exec_prefix bindir = $bindir +libdir = $libdir datarootdir = $datarootdir datadir = $datadir -docdir = $docdir -libdir = $libdir mandir = $mandir +docdir = $docdir $_config_mk_data diff --git a/dists/android/AndroidManifest.xml b/dists/android/AndroidManifest.xml index 55e3bf2f38b..3b69c9f1f3c 100644 --- a/dists/android/AndroidManifest.xml +++ b/dists/android/AndroidManifest.xml @@ -2,11 +2,11 @@ - diff --git a/dists/engine-data/create-testbed-data.sh b/dists/engine-data/create-testbed-data.sh new file mode 100755 index 00000000000..754ec4d6839 --- /dev/null +++ b/dists/engine-data/create-testbed-data.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +# Create the directory structure +# Avoided bash shortcuts / file-seperators in interest of portability + +if [ -e testbed ]; then + echo "Game-data already present as testbed/" + echo "To regenerate, remove and rerun" + exit 0 +fi + +mkdir testbed + +cd testbed + +# For game detection +echo "ScummVM rocks!" > TESTBED + +mkdir test1 +mkdir Test2 +mkdir TEST3 +mkdir tEST4 +mkdir test5 + + +cd test1 +echo "It works!" > file.txt +cd .. + +cd Test2 +echo "It works!" > File.txt +cd .. + +cd TEST3 +echo "It works!" > FILE.txt +cd .. + +cd tEST4 +echo "It works!" > fILe.txt +cd .. + +cd test5 +echo "It works!" > file. +cd .. + +# back to the top +cd .. + +# move the audiocd data to newly created directory +cp -r testbed-audiocd-files testbed/audiocd-files +mv testbed/audiocd-files/music.mid testbed/ +echo "Game data created" diff --git a/dists/engine-data/drascula.dat b/dists/engine-data/drascula.dat index 646da84aead..feecda80a22 100644 Binary files a/dists/engine-data/drascula.dat and b/dists/engine-data/drascula.dat differ diff --git a/dists/engine-data/hugo.dat b/dists/engine-data/hugo.dat index 348339bddae..8fda3fb2f4b 100644 Binary files a/dists/engine-data/hugo.dat and b/dists/engine-data/hugo.dat differ diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat index d8cb28076a1..23e866c62e0 100644 Binary files a/dists/engine-data/kyra.dat and b/dists/engine-data/kyra.dat differ diff --git a/dists/engine-data/testbed-audiocd-files/music.mid b/dists/engine-data/testbed-audiocd-files/music.mid new file mode 100644 index 00000000000..35e0f770739 Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/music.mid differ diff --git a/dists/engine-data/testbed-audiocd-files/track01.mp3 b/dists/engine-data/testbed-audiocd-files/track01.mp3 new file mode 100644 index 00000000000..53d057ee96f Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/track01.mp3 differ diff --git a/dists/engine-data/testbed-audiocd-files/track02.mp3 b/dists/engine-data/testbed-audiocd-files/track02.mp3 new file mode 100644 index 00000000000..daf8e4860d5 Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/track02.mp3 differ diff --git a/dists/engine-data/testbed-audiocd-files/track03.mp3 b/dists/engine-data/testbed-audiocd-files/track03.mp3 new file mode 100644 index 00000000000..1ef385d6402 Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/track03.mp3 differ diff --git a/dists/engine-data/testbed-audiocd-files/track04.mp3 b/dists/engine-data/testbed-audiocd-files/track04.mp3 new file mode 100644 index 00000000000..7607087f083 Binary files /dev/null and b/dists/engine-data/testbed-audiocd-files/track04.mp3 differ diff --git a/dists/engine-data/toon.dat b/dists/engine-data/toon.dat new file mode 100644 index 00000000000..82354c42397 Binary files /dev/null and b/dists/engine-data/toon.dat differ diff --git a/dists/iphone/Info.plist b/dists/iphone/Info.plist index a042504b9f9..9fc4debc92d 100644 --- a/dists/iphone/Info.plist +++ b/dists/iphone/Info.plist @@ -1,5 +1,5 @@ - + CFBundleDevelopmentRegion @@ -15,19 +15,18 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.0 + 1.3.0svn CFBundleSignature ???? - CFBundleShortVersionString - 1.2.0svn CFBundleVersion - svn + 1.3.0svn CFBundleIconFile icon.png CFBundleIconFiles icon.png icon-72.png + icon4.png UIPrerenderedIcon diff --git a/dists/iphone/Info.plist.in b/dists/iphone/Info.plist.in index 7792857f407..efb93832e76 100644 --- a/dists/iphone/Info.plist.in +++ b/dists/iphone/Info.plist.in @@ -1,5 +1,5 @@ - + CFBundleDevelopmentRegion @@ -15,15 +15,19 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0.0 + @VERSION@ CFBundleSignature ???? - CFBundleShortVersionString - @VERSION@ CFBundleVersion - svn + @VERSION@ CFBundleIconFile icon.png + CFBundleIconFiles + + icon.png + icon-72.png + icon4.png + UIPrerenderedIcon UIDeviceFamily diff --git a/dists/iphone/icon4.png b/dists/iphone/icon4.png new file mode 100644 index 00000000000..5abe16ed51d Binary files /dev/null and b/dists/iphone/icon4.png differ diff --git a/dists/iphone/scummvm.xcodeproj/project.pbxproj b/dists/iphone/scummvm.xcodeproj/project.pbxproj index 55123189188..a2c28f8c662 100755 --- a/dists/iphone/scummvm.xcodeproj/project.pbxproj +++ b/dists/iphone/scummvm.xcodeproj/project.pbxproj @@ -7,6 +7,189 @@ objects = { /* Begin PBXBuildFile section */ + 8CB5A9C11253FD6900CB6BC7 /* m4_scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9B71253FD6800CB6BC7 /* m4_scene.cpp */; }; + 8CB5A9C21253FD6900CB6BC7 /* mads_logic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9B91253FD6800CB6BC7 /* mads_logic.cpp */; }; + 8CB5A9C31253FD6900CB6BC7 /* mads_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BB1253FD6800CB6BC7 /* mads_player.cpp */; }; + 8CB5A9C41253FD6900CB6BC7 /* mads_scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BD1253FD6800CB6BC7 /* mads_scene.cpp */; }; + 8CB5A9C51253FD6900CB6BC7 /* mads_views.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BF1253FD6900CB6BC7 /* mads_views.cpp */; }; + 8CB5A9C61253FD6900CB6BC7 /* m4_scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9B71253FD6800CB6BC7 /* m4_scene.cpp */; }; + 8CB5A9C71253FD6900CB6BC7 /* mads_logic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9B91253FD6800CB6BC7 /* mads_logic.cpp */; }; + 8CB5A9C81253FD6900CB6BC7 /* mads_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BB1253FD6800CB6BC7 /* mads_player.cpp */; }; + 8CB5A9C91253FD6900CB6BC7 /* mads_scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BD1253FD6800CB6BC7 /* mads_scene.cpp */; }; + 8CB5A9CA1253FD6900CB6BC7 /* mads_views.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BF1253FD6900CB6BC7 /* mads_views.cpp */; }; + 8CB5A9CB1253FD6900CB6BC7 /* m4_scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9B71253FD6800CB6BC7 /* m4_scene.cpp */; }; + 8CB5A9CC1253FD6900CB6BC7 /* mads_logic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9B91253FD6800CB6BC7 /* mads_logic.cpp */; }; + 8CB5A9CD1253FD6900CB6BC7 /* mads_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BB1253FD6800CB6BC7 /* mads_player.cpp */; }; + 8CB5A9CE1253FD6900CB6BC7 /* mads_scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BD1253FD6800CB6BC7 /* mads_scene.cpp */; }; + 8CB5A9CF1253FD6900CB6BC7 /* mads_views.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CB5A9BF1253FD6900CB6BC7 /* mads_views.cpp */; }; + 8CB5A9D91253FDF500CB6BC7 /* drascula.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D51253FDF400CB6BC7 /* drascula.dat */; }; + 8CB5A9DA1253FDF500CB6BC7 /* hugo.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D61253FDF500CB6BC7 /* hugo.dat */; }; + 8CB5A9DB1253FDF500CB6BC7 /* m4.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D71253FDF500CB6BC7 /* m4.dat */; }; + 8CB5A9DC1253FDF500CB6BC7 /* teenagent.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D81253FDF500CB6BC7 /* teenagent.dat */; }; + 8CB5A9DD1253FDF500CB6BC7 /* drascula.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D51253FDF400CB6BC7 /* drascula.dat */; }; + 8CB5A9DE1253FDF500CB6BC7 /* hugo.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D61253FDF500CB6BC7 /* hugo.dat */; }; + 8CB5A9DF1253FDF500CB6BC7 /* m4.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D71253FDF500CB6BC7 /* m4.dat */; }; + 8CB5A9E01253FDF500CB6BC7 /* teenagent.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D81253FDF500CB6BC7 /* teenagent.dat */; }; + 8CB5A9E11253FDF500CB6BC7 /* drascula.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D51253FDF400CB6BC7 /* drascula.dat */; }; + 8CB5A9E21253FDF500CB6BC7 /* hugo.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D61253FDF500CB6BC7 /* hugo.dat */; }; + 8CB5A9E31253FDF500CB6BC7 /* m4.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D71253FDF500CB6BC7 /* m4.dat */; }; + 8CB5A9E41253FDF500CB6BC7 /* teenagent.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CB5A9D81253FDF500CB6BC7 /* teenagent.dat */; }; + 8CD1ED0B126202AB00FA198C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC6126202AA00FA198C /* detection.cpp */; }; + 8CD1ED0C126202AB00FA198C /* display.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC7126202AA00FA198C /* display.cpp */; }; + 8CD1ED0D126202AB00FA198C /* engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC9126202AA00FA198C /* engine.cpp */; }; + 8CD1ED0E126202AB00FA198C /* file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECCB126202AA00FA198C /* file.cpp */; }; + 8CD1ED0F126202AB00FA198C /* hugo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECCF126202AA00FA198C /* hugo.cpp */; }; + 8CD1ED10126202AB00FA198C /* intro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD1126202AA00FA198C /* intro.cpp */; }; + 8CD1ED11126202AB00FA198C /* inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD3126202AA00FA198C /* inventory.cpp */; }; + 8CD1ED14126202AB00FA198C /* mouse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD7126202AA00FA198C /* mouse.cpp */; }; + 8CD1ED15126202AB00FA198C /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD9126202AA00FA198C /* parser.cpp */; }; + 8CD1ED16126202AB00FA198C /* route.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDB126202AA00FA198C /* route.cpp */; }; + 8CD1ED17126202AB00FA198C /* schedule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDD126202AA00FA198C /* schedule.cpp */; }; + 8CD1ED18126202AB00FA198C /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDF126202AA00FA198C /* sound.cpp */; }; + 8CD1ED19126202AB00FA198C /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE1126202AA00FA198C /* util.cpp */; }; + 8CD1ED1A126202AB00FA198C /* anim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE4126202AA00FA198C /* anim.cpp */; }; + 8CD1ED1B126202AB00FA198C /* audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE6126202AA00FA198C /* audio.cpp */; }; + 8CD1ED1C126202AB00FA198C /* character.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE8126202AA00FA198C /* character.cpp */; }; + 8CD1ED1D126202AB00FA198C /* conversation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEA126202AA00FA198C /* conversation.cpp */; }; + 8CD1ED1E126202AB00FA198C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEC126202AA00FA198C /* detection.cpp */; }; + 8CD1ED1F126202AB00FA198C /* drew.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECED126202AA00FA198C /* drew.cpp */; }; + 8CD1ED20126202AB00FA198C /* flux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEF126202AA00FA198C /* flux.cpp */; }; + 8CD1ED21126202AB00FA198C /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF1126202AA00FA198C /* font.cpp */; }; + 8CD1ED22126202AB00FA198C /* hotspot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF3126202AA00FA198C /* hotspot.cpp */; }; + 8CD1ED25126202AB00FA198C /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF7126202AA00FA198C /* movie.cpp */; }; + 8CD1ED26126202AB00FA198C /* path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF9126202AA00FA198C /* path.cpp */; }; + 8CD1ED27126202AB00FA198C /* picture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFB126202AA00FA198C /* picture.cpp */; }; + 8CD1ED28126202AB00FA198C /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFD126202AA00FA198C /* resource.cpp */; }; + 8CD1ED29126202AB00FA198C /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFF126202AA00FA198C /* script.cpp */; }; + 8CD1ED2A126202AB00FA198C /* script_func.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED01126202AA00FA198C /* script_func.cpp */; }; + 8CD1ED2B126202AB00FA198C /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED03126202AA00FA198C /* state.cpp */; }; + 8CD1ED2C126202AB00FA198C /* text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED05126202AA00FA198C /* text.cpp */; }; + 8CD1ED2D126202AB00FA198C /* tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED07126202AA00FA198C /* tools.cpp */; }; + 8CD1ED2E126202AB00FA198C /* toon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED09126202AA00FA198C /* toon.cpp */; }; + 8CD1ED2F126202AB00FA198C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC6126202AA00FA198C /* detection.cpp */; }; + 8CD1ED30126202AB00FA198C /* display.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC7126202AA00FA198C /* display.cpp */; }; + 8CD1ED31126202AB00FA198C /* engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC9126202AA00FA198C /* engine.cpp */; }; + 8CD1ED32126202AB00FA198C /* file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECCB126202AA00FA198C /* file.cpp */; }; + 8CD1ED33126202AB00FA198C /* hugo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECCF126202AA00FA198C /* hugo.cpp */; }; + 8CD1ED34126202AB00FA198C /* intro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD1126202AA00FA198C /* intro.cpp */; }; + 8CD1ED35126202AB00FA198C /* inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD3126202AA00FA198C /* inventory.cpp */; }; + 8CD1ED38126202AB00FA198C /* mouse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD7126202AA00FA198C /* mouse.cpp */; }; + 8CD1ED39126202AB00FA198C /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD9126202AA00FA198C /* parser.cpp */; }; + 8CD1ED3A126202AB00FA198C /* route.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDB126202AA00FA198C /* route.cpp */; }; + 8CD1ED3B126202AB00FA198C /* schedule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDD126202AA00FA198C /* schedule.cpp */; }; + 8CD1ED3C126202AB00FA198C /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDF126202AA00FA198C /* sound.cpp */; }; + 8CD1ED3D126202AB00FA198C /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE1126202AA00FA198C /* util.cpp */; }; + 8CD1ED3E126202AB00FA198C /* anim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE4126202AA00FA198C /* anim.cpp */; }; + 8CD1ED3F126202AB00FA198C /* audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE6126202AA00FA198C /* audio.cpp */; }; + 8CD1ED40126202AB00FA198C /* character.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE8126202AA00FA198C /* character.cpp */; }; + 8CD1ED41126202AB00FA198C /* conversation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEA126202AA00FA198C /* conversation.cpp */; }; + 8CD1ED42126202AB00FA198C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEC126202AA00FA198C /* detection.cpp */; }; + 8CD1ED43126202AB00FA198C /* drew.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECED126202AA00FA198C /* drew.cpp */; }; + 8CD1ED44126202AB00FA198C /* flux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEF126202AA00FA198C /* flux.cpp */; }; + 8CD1ED45126202AB00FA198C /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF1126202AA00FA198C /* font.cpp */; }; + 8CD1ED46126202AB00FA198C /* hotspot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF3126202AA00FA198C /* hotspot.cpp */; }; + 8CD1ED49126202AB00FA198C /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF7126202AA00FA198C /* movie.cpp */; }; + 8CD1ED4A126202AB00FA198C /* path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF9126202AA00FA198C /* path.cpp */; }; + 8CD1ED4B126202AB00FA198C /* picture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFB126202AA00FA198C /* picture.cpp */; }; + 8CD1ED4C126202AB00FA198C /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFD126202AA00FA198C /* resource.cpp */; }; + 8CD1ED4D126202AB00FA198C /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFF126202AA00FA198C /* script.cpp */; }; + 8CD1ED4E126202AB00FA198C /* script_func.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED01126202AA00FA198C /* script_func.cpp */; }; + 8CD1ED4F126202AB00FA198C /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED03126202AA00FA198C /* state.cpp */; }; + 8CD1ED50126202AB00FA198C /* text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED05126202AA00FA198C /* text.cpp */; }; + 8CD1ED51126202AB00FA198C /* tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED07126202AA00FA198C /* tools.cpp */; }; + 8CD1ED52126202AB00FA198C /* toon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED09126202AA00FA198C /* toon.cpp */; }; + 8CD1ED53126202AB00FA198C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC6126202AA00FA198C /* detection.cpp */; }; + 8CD1ED54126202AB00FA198C /* display.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC7126202AA00FA198C /* display.cpp */; }; + 8CD1ED55126202AB00FA198C /* engine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECC9126202AA00FA198C /* engine.cpp */; }; + 8CD1ED56126202AB00FA198C /* file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECCB126202AA00FA198C /* file.cpp */; }; + 8CD1ED57126202AB00FA198C /* hugo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECCF126202AA00FA198C /* hugo.cpp */; }; + 8CD1ED58126202AB00FA198C /* intro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD1126202AA00FA198C /* intro.cpp */; }; + 8CD1ED59126202AB00FA198C /* inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD3126202AA00FA198C /* inventory.cpp */; }; + 8CD1ED5C126202AB00FA198C /* mouse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD7126202AA00FA198C /* mouse.cpp */; }; + 8CD1ED5D126202AB00FA198C /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECD9126202AA00FA198C /* parser.cpp */; }; + 8CD1ED5E126202AB00FA198C /* route.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDB126202AA00FA198C /* route.cpp */; }; + 8CD1ED5F126202AB00FA198C /* schedule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDD126202AA00FA198C /* schedule.cpp */; }; + 8CD1ED60126202AB00FA198C /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECDF126202AA00FA198C /* sound.cpp */; }; + 8CD1ED61126202AB00FA198C /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE1126202AA00FA198C /* util.cpp */; }; + 8CD1ED62126202AB00FA198C /* anim.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE4126202AA00FA198C /* anim.cpp */; }; + 8CD1ED63126202AB00FA198C /* audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE6126202AA00FA198C /* audio.cpp */; }; + 8CD1ED64126202AB00FA198C /* character.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECE8126202AA00FA198C /* character.cpp */; }; + 8CD1ED65126202AB00FA198C /* conversation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEA126202AA00FA198C /* conversation.cpp */; }; + 8CD1ED66126202AB00FA198C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEC126202AA00FA198C /* detection.cpp */; }; + 8CD1ED67126202AB00FA198C /* drew.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECED126202AA00FA198C /* drew.cpp */; }; + 8CD1ED68126202AB00FA198C /* flux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECEF126202AA00FA198C /* flux.cpp */; }; + 8CD1ED69126202AB00FA198C /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF1126202AA00FA198C /* font.cpp */; }; + 8CD1ED6A126202AB00FA198C /* hotspot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF3126202AA00FA198C /* hotspot.cpp */; }; + 8CD1ED6D126202AB00FA198C /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF7126202AA00FA198C /* movie.cpp */; }; + 8CD1ED6E126202AB00FA198C /* path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECF9126202AA00FA198C /* path.cpp */; }; + 8CD1ED6F126202AB00FA198C /* picture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFB126202AA00FA198C /* picture.cpp */; }; + 8CD1ED70126202AB00FA198C /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFD126202AA00FA198C /* resource.cpp */; }; + 8CD1ED71126202AB00FA198C /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ECFF126202AA00FA198C /* script.cpp */; }; + 8CD1ED72126202AB00FA198C /* script_func.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED01126202AA00FA198C /* script_func.cpp */; }; + 8CD1ED73126202AB00FA198C /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED03126202AA00FA198C /* state.cpp */; }; + 8CD1ED74126202AB00FA198C /* text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED05126202AA00FA198C /* text.cpp */; }; + 8CD1ED75126202AB00FA198C /* tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED07126202AA00FA198C /* tools.cpp */; }; + 8CD1ED76126202AB00FA198C /* toon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD1ED09126202AA00FA198C /* toon.cpp */; }; + 8CD1ED881262030100FA198C /* toon.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CD1ED871262030100FA198C /* toon.dat */; }; + 8CD1ED891262030100FA198C /* toon.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CD1ED871262030100FA198C /* toon.dat */; }; + 8CD1ED8A1262030100FA198C /* toon.dat in Resources */ = {isa = PBXBuildFile; fileRef = 8CD1ED871262030100FA198C /* toon.dat */; }; + 8CD80C8B126271A9001C6C87 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80C89126271A9001C6C87 /* surface.cpp */; }; + 8CD80C8C126271A9001C6C87 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80C89126271A9001C6C87 /* surface.cpp */; }; + 8CD80C8D126271A9001C6C87 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80C89126271A9001C6C87 /* surface.cpp */; }; + 8CD80C91126271BD001C6C87 /* gfx_towns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80C90126271BD001C6C87 /* gfx_towns.cpp */; }; + 8CD80C92126271BD001C6C87 /* gfx_towns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80C90126271BD001C6C87 /* gfx_towns.cpp */; }; + 8CD80C93126271BD001C6C87 /* gfx_towns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80C90126271BD001C6C87 /* gfx_towns.cpp */; }; + 8CD80CE0126272A0001C6C87 /* actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CBF1262729F001C6C87 /* actor.cpp */; }; + 8CD80CE1126272A0001C6C87 /* animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC11262729F001C6C87 /* animation.cpp */; }; + 8CD80CE2126272A0001C6C87 /* callbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC31262729F001C6C87 /* callbacks.cpp */; }; + 8CD80CE3126272A0001C6C87 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC41262729F001C6C87 /* console.cpp */; }; + 8CD80CE4126272A0001C6C87 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC61262729F001C6C87 /* detection.cpp */; }; + 8CD80CE5126272A0001C6C87 /* dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC71262729F001C6C87 /* dialog.cpp */; }; + 8CD80CE6126272A0001C6C87 /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC91262729F001C6C87 /* font.cpp */; }; + 8CD80CE7126272A0001C6C87 /* inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CCB1262729F001C6C87 /* inventory.cpp */; }; + 8CD80CE9126272A0001C6C87 /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CCE1262729F001C6C87 /* music.cpp */; }; + 8CD80CEA126272A0001C6C87 /* objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD01262729F001C6C87 /* objects.cpp */; }; + 8CD80CEB126272A0001C6C87 /* pack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD21262729F001C6C87 /* pack.cpp */; }; + 8CD80CEC126272A0001C6C87 /* resources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD4126272A0001C6C87 /* resources.cpp */; }; + 8CD80CED126272A0001C6C87 /* scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD6126272A0001C6C87 /* scene.cpp */; }; + 8CD80CEE126272A0001C6C87 /* segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD8126272A0001C6C87 /* segment.cpp */; }; + 8CD80CEF126272A0001C6C87 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDA126272A0001C6C87 /* surface.cpp */; }; + 8CD80CF0126272A0001C6C87 /* surface_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDC126272A0001C6C87 /* surface_list.cpp */; }; + 8CD80CF1126272A0001C6C87 /* teenagent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDE126272A0001C6C87 /* teenagent.cpp */; }; + 8CD80CF2126272A0001C6C87 /* actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CBF1262729F001C6C87 /* actor.cpp */; }; + 8CD80CF3126272A0001C6C87 /* animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC11262729F001C6C87 /* animation.cpp */; }; + 8CD80CF4126272A0001C6C87 /* callbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC31262729F001C6C87 /* callbacks.cpp */; }; + 8CD80CF5126272A0001C6C87 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC41262729F001C6C87 /* console.cpp */; }; + 8CD80CF6126272A0001C6C87 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC61262729F001C6C87 /* detection.cpp */; }; + 8CD80CF7126272A0001C6C87 /* dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC71262729F001C6C87 /* dialog.cpp */; }; + 8CD80CF8126272A0001C6C87 /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC91262729F001C6C87 /* font.cpp */; }; + 8CD80CF9126272A0001C6C87 /* inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CCB1262729F001C6C87 /* inventory.cpp */; }; + 8CD80CFB126272A0001C6C87 /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CCE1262729F001C6C87 /* music.cpp */; }; + 8CD80CFC126272A0001C6C87 /* objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD01262729F001C6C87 /* objects.cpp */; }; + 8CD80CFD126272A0001C6C87 /* pack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD21262729F001C6C87 /* pack.cpp */; }; + 8CD80CFE126272A0001C6C87 /* resources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD4126272A0001C6C87 /* resources.cpp */; }; + 8CD80CFF126272A0001C6C87 /* scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD6126272A0001C6C87 /* scene.cpp */; }; + 8CD80D00126272A0001C6C87 /* segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD8126272A0001C6C87 /* segment.cpp */; }; + 8CD80D01126272A0001C6C87 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDA126272A0001C6C87 /* surface.cpp */; }; + 8CD80D02126272A0001C6C87 /* surface_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDC126272A0001C6C87 /* surface_list.cpp */; }; + 8CD80D03126272A0001C6C87 /* teenagent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDE126272A0001C6C87 /* teenagent.cpp */; }; + 8CD80D04126272A0001C6C87 /* actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CBF1262729F001C6C87 /* actor.cpp */; }; + 8CD80D05126272A0001C6C87 /* animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC11262729F001C6C87 /* animation.cpp */; }; + 8CD80D06126272A0001C6C87 /* callbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC31262729F001C6C87 /* callbacks.cpp */; }; + 8CD80D07126272A0001C6C87 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC41262729F001C6C87 /* console.cpp */; }; + 8CD80D08126272A0001C6C87 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC61262729F001C6C87 /* detection.cpp */; }; + 8CD80D09126272A0001C6C87 /* dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC71262729F001C6C87 /* dialog.cpp */; }; + 8CD80D0A126272A0001C6C87 /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CC91262729F001C6C87 /* font.cpp */; }; + 8CD80D0B126272A0001C6C87 /* inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CCB1262729F001C6C87 /* inventory.cpp */; }; + 8CD80D0D126272A0001C6C87 /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CCE1262729F001C6C87 /* music.cpp */; }; + 8CD80D0E126272A0001C6C87 /* objects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD01262729F001C6C87 /* objects.cpp */; }; + 8CD80D0F126272A0001C6C87 /* pack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD21262729F001C6C87 /* pack.cpp */; }; + 8CD80D10126272A0001C6C87 /* resources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD4126272A0001C6C87 /* resources.cpp */; }; + 8CD80D11126272A0001C6C87 /* scene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD6126272A0001C6C87 /* scene.cpp */; }; + 8CD80D12126272A0001C6C87 /* segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CD8126272A0001C6C87 /* segment.cpp */; }; + 8CD80D13126272A0001C6C87 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDA126272A0001C6C87 /* surface.cpp */; }; + 8CD80D14126272A0001C6C87 /* surface_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDC126272A0001C6C87 /* surface_list.cpp */; }; + 8CD80D15126272A0001C6C87 /* teenagent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD80CDE126272A0001C6C87 /* teenagent.cpp */; }; DF093E5F0F63CAD4002D821E /* pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5C0F63CAD4002D821E /* pn.cpp */; }; DF093E600F63CAD4002D821E /* script_pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5D0F63CAD4002D821E /* script_pn.cpp */; }; DF093E610F63CAD4002D821E /* vga_pn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF093E5E0F63CAD4002D821E /* vga_pn.cpp */; }; @@ -246,7 +429,6 @@ DF093F720F63CB26002D821E /* draw_bargon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421200E7BA6A700F5680E /* draw_bargon.cpp */; }; DF093F730F63CB26002D821E /* draw_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421210E7BA6A700F5680E /* draw_v1.cpp */; }; DF093F740F63CB26002D821E /* draw_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421220E7BA6A700F5680E /* draw_v2.cpp */; }; - DF093F750F63CB26002D821E /* driver_vga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421230E7BA6A700F5680E /* driver_vga.cpp */; }; DF093F760F63CB26002D821E /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421250E7BA6A700F5680E /* game.cpp */; }; DF093F790F63CB26002D821E /* global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421290E7BA6A700F5680E /* global.cpp */; }; DF093F7A0F63CB26002D821E /* gob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84212B0E7BA6A700F5680E /* gob.cpp */; }; @@ -558,7 +740,6 @@ DF0940D80F63CB26002D821E /* insane_enemy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D50E7BA6AA00F5680E /* insane_enemy.cpp */; }; DF0940D90F63CB26002D821E /* insane_iact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D60E7BA6AA00F5680E /* insane_iact.cpp */; }; DF0940DA0F63CB26002D821E /* insane_scenes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D70E7BA6AA00F5680E /* insane_scenes.cpp */; }; - DF0940DB0F63CB26002D821E /* midiparser_eup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D90E7BA6AA00F5680E /* midiparser_eup.cpp */; }; DF0940DC0F63CB26002D821E /* midiparser_ro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DA0E7BA6AA00F5680E /* midiparser_ro.cpp */; }; DF0940DD0F63CB26002D821E /* nut_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DD0E7BA6AA00F5680E /* nut_renderer.cpp */; }; DF0940DE0F63CB26002D821E /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DF0E7BA6AA00F5680E /* object.cpp */; }; @@ -845,6 +1026,12 @@ DF09CC290FAC4EAB00A5AFD7 /* script_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */; }; DF09CC2A0FAC4EAB00A5AFD7 /* script_v3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */; }; DF09CC2B0FAC4EAB00A5AFD7 /* script_v4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */; }; + DF0E303A1252C5BD0082D593 /* cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E30391252C5BD0082D593 /* cms.cpp */; }; + DF0E303B1252C5BD0082D593 /* cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E30391252C5BD0082D593 /* cms.cpp */; }; + DF0E303C1252C5BD0082D593 /* cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E30391252C5BD0082D593 /* cms.cpp */; }; + DF0E30411252C6090082D593 /* cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E303F1252C6090082D593 /* cms.cpp */; }; + DF0E30421252C6090082D593 /* cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E303F1252C6090082D593 /* cms.cpp */; }; + DF0E30431252C6090082D593 /* cms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF0E303F1252C6090082D593 /* cms.cpp */; }; DF224E040FB23BC500C8E453 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF224E020FB23BC500C8E453 /* OpenGLES.framework */; }; DF224E050FB23BC500C8E453 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF224E020FB23BC500C8E453 /* OpenGLES.framework */; }; DF2EC3E510E6490800765801 /* browser_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF2EC3E410E6490800765801 /* browser_osx.mm */; }; @@ -962,12 +1149,10 @@ DF45B1D4116628A5009B85CC /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18B116628A5009B85CC /* menu.cpp */; }; DF45B1D5116628A5009B85CC /* paint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18D116628A5009B85CC /* paint.cpp */; }; DF45B1D6116628A5009B85CC /* paint16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18F116628A5009B85CC /* paint16.cpp */; }; - DF45B1D7116628A5009B85CC /* paint32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B191116628A5009B85CC /* paint32.cpp */; }; DF45B1D8116628A5009B85CC /* palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B193116628A5009B85CC /* palette.cpp */; }; DF45B1D9116628A5009B85CC /* picture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B195116628A5009B85CC /* picture.cpp */; }; DF45B1DA116628A5009B85CC /* portrait.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B197116628A5009B85CC /* portrait.cpp */; }; DF45B1DB116628A5009B85CC /* ports.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B199116628A5009B85CC /* ports.cpp */; }; - DF45B1DC116628A5009B85CC /* robot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19B116628A5009B85CC /* robot.cpp */; }; DF45B1DD116628A5009B85CC /* screen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19D116628A5009B85CC /* screen.cpp */; }; DF45B1DE116628A5009B85CC /* text16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19F116628A5009B85CC /* text16.cpp */; }; DF45B1DF116628A5009B85CC /* transitions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1A1116628A5009B85CC /* transitions.cpp */; }; @@ -984,7 +1169,6 @@ DF45B1F0116628A5009B85CC /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C1116628A5009B85CC /* music.cpp */; }; DF45B1F1116628A5009B85CC /* soundcmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C3116628A5009B85CC /* soundcmd.cpp */; }; DF45B1F2116628A5009B85CC /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C6116628A5009B85CC /* seq_decoder.cpp */; }; - DF45B1F3116628A5009B85CC /* vmd_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C8116628A5009B85CC /* vmd_decoder.cpp */; }; DF45B1F4116628A5009B85CC /* animate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B176116628A5009B85CC /* animate.cpp */; }; DF45B1F5116628A5009B85CC /* cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B178116628A5009B85CC /* cache.cpp */; }; DF45B1F6116628A5009B85CC /* compare.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B17A116628A5009B85CC /* compare.cpp */; }; @@ -995,12 +1179,10 @@ DF45B1FE116628A5009B85CC /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18B116628A5009B85CC /* menu.cpp */; }; DF45B1FF116628A5009B85CC /* paint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18D116628A5009B85CC /* paint.cpp */; }; DF45B200116628A5009B85CC /* paint16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18F116628A5009B85CC /* paint16.cpp */; }; - DF45B201116628A5009B85CC /* paint32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B191116628A5009B85CC /* paint32.cpp */; }; DF45B202116628A5009B85CC /* palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B193116628A5009B85CC /* palette.cpp */; }; DF45B203116628A5009B85CC /* picture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B195116628A5009B85CC /* picture.cpp */; }; DF45B204116628A5009B85CC /* portrait.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B197116628A5009B85CC /* portrait.cpp */; }; DF45B205116628A5009B85CC /* ports.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B199116628A5009B85CC /* ports.cpp */; }; - DF45B206116628A5009B85CC /* robot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19B116628A5009B85CC /* robot.cpp */; }; DF45B207116628A5009B85CC /* screen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19D116628A5009B85CC /* screen.cpp */; }; DF45B208116628A5009B85CC /* text16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19F116628A5009B85CC /* text16.cpp */; }; DF45B209116628A5009B85CC /* transitions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1A1116628A5009B85CC /* transitions.cpp */; }; @@ -1017,7 +1199,6 @@ DF45B21A116628A5009B85CC /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C1116628A5009B85CC /* music.cpp */; }; DF45B21B116628A5009B85CC /* soundcmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C3116628A5009B85CC /* soundcmd.cpp */; }; DF45B21C116628A5009B85CC /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C6116628A5009B85CC /* seq_decoder.cpp */; }; - DF45B21D116628A5009B85CC /* vmd_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C8116628A5009B85CC /* vmd_decoder.cpp */; }; DF45B21E116628A5009B85CC /* animate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B176116628A5009B85CC /* animate.cpp */; }; DF45B21F116628A5009B85CC /* cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B178116628A5009B85CC /* cache.cpp */; }; DF45B220116628A5009B85CC /* compare.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B17A116628A5009B85CC /* compare.cpp */; }; @@ -1028,12 +1209,10 @@ DF45B228116628A5009B85CC /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18B116628A5009B85CC /* menu.cpp */; }; DF45B229116628A5009B85CC /* paint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18D116628A5009B85CC /* paint.cpp */; }; DF45B22A116628A5009B85CC /* paint16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B18F116628A5009B85CC /* paint16.cpp */; }; - DF45B22B116628A5009B85CC /* paint32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B191116628A5009B85CC /* paint32.cpp */; }; DF45B22C116628A5009B85CC /* palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B193116628A5009B85CC /* palette.cpp */; }; DF45B22D116628A5009B85CC /* picture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B195116628A5009B85CC /* picture.cpp */; }; DF45B22E116628A5009B85CC /* portrait.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B197116628A5009B85CC /* portrait.cpp */; }; DF45B22F116628A5009B85CC /* ports.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B199116628A5009B85CC /* ports.cpp */; }; - DF45B230116628A5009B85CC /* robot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19B116628A5009B85CC /* robot.cpp */; }; DF45B231116628A5009B85CC /* screen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19D116628A5009B85CC /* screen.cpp */; }; DF45B232116628A5009B85CC /* text16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B19F116628A5009B85CC /* text16.cpp */; }; DF45B233116628A5009B85CC /* transitions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1A1116628A5009B85CC /* transitions.cpp */; }; @@ -1050,7 +1229,6 @@ DF45B244116628A5009B85CC /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C1116628A5009B85CC /* music.cpp */; }; DF45B245116628A5009B85CC /* soundcmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C3116628A5009B85CC /* soundcmd.cpp */; }; DF45B246116628A5009B85CC /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C6116628A5009B85CC /* seq_decoder.cpp */; }; - DF45B247116628A5009B85CC /* vmd_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF45B1C8116628A5009B85CC /* vmd_decoder.cpp */; }; DF573C080F5A81EA00961A72 /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573C010F5A81EA00961A72 /* state.cpp */; }; DF573CBB0F5A85B300961A72 /* exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBA0F5A85B300961A72 /* exec.cpp */; }; DF573CBE0F5A85E100961A72 /* timer_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF573CBD0F5A85E100961A72 /* timer_lol.cpp */; }; @@ -1075,18 +1253,12 @@ DF6118550FE3A8990042AD3F /* disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118540FE3A8990042AD3F /* disk.cpp */; }; DF6118560FE3A8990042AD3F /* disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118540FE3A8990042AD3F /* disk.cpp */; }; DF6118570FE3A8990042AD3F /* disk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118540FE3A8990042AD3F /* disk.cpp */; }; - DF6118660FE3A9410042AD3F /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */; }; - DF6118670FE3A9410042AD3F /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185E0FE3A9410042AD3F /* indeo3.cpp */; }; DF6118680FE3A9410042AD3F /* dxa_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */; }; DF6118690FE3A9410042AD3F /* flic_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118620FE3A9410042AD3F /* flic_decoder.cpp */; }; DF61186A0FE3A9410042AD3F /* smk_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118640FE3A9410042AD3F /* smk_decoder.cpp */; }; - DF61186B0FE3A9410042AD3F /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */; }; - DF61186C0FE3A9410042AD3F /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185E0FE3A9410042AD3F /* indeo3.cpp */; }; DF61186D0FE3A9410042AD3F /* dxa_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */; }; DF61186E0FE3A9410042AD3F /* flic_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118620FE3A9410042AD3F /* flic_decoder.cpp */; }; DF61186F0FE3A9410042AD3F /* smk_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118640FE3A9410042AD3F /* smk_decoder.cpp */; }; - DF6118700FE3A9410042AD3F /* coktelvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */; }; - DF6118710FE3A9410042AD3F /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61185E0FE3A9410042AD3F /* indeo3.cpp */; }; DF6118720FE3A9410042AD3F /* dxa_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */; }; DF6118730FE3A9410042AD3F /* flic_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118620FE3A9410042AD3F /* flic_decoder.cpp */; }; DF6118740FE3A9410042AD3F /* smk_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118640FE3A9410042AD3F /* smk_decoder.cpp */; }; @@ -1233,9 +1405,6 @@ DF7E8C110ED5FCC2001CB19F /* xmlparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7E8C0F0ED5FCC2001CB19F /* xmlparser.cpp */; }; DF7E8C530ED60067001CB19F /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7E8C510ED60067001CB19F /* game.cpp */; }; DF7E8C810ED60271001CB19F /* scummmodern.zip in Resources */ = {isa = PBXBuildFile; fileRef = DF7E8C7A0ED601E5001CB19F /* scummmodern.zip */; }; - DF7F285D11FF23B700159131 /* frameout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F285C11FF23B700159131 /* frameout.cpp */; }; - DF7F285E11FF23B700159131 /* frameout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F285C11FF23B700159131 /* frameout.cpp */; }; - DF7F285F11FF23B700159131 /* frameout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F285C11FF23B700159131 /* frameout.cpp */; }; DF7F286111FF23D500159131 /* amigamac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286011FF23D500159131 /* amigamac.cpp */; }; DF7F286211FF23D500159131 /* amigamac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286011FF23D500159131 /* amigamac.cpp */; }; DF7F286311FF23D500159131 /* amigamac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF7F286011FF23D500159131 /* amigamac.cpp */; }; @@ -1420,7 +1589,6 @@ DF8425E00E7BA6AC00F5680E /* draw_bargon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421200E7BA6A700F5680E /* draw_bargon.cpp */; }; DF8425E10E7BA6AC00F5680E /* draw_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421210E7BA6A700F5680E /* draw_v1.cpp */; }; DF8425E20E7BA6AC00F5680E /* draw_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421220E7BA6A700F5680E /* draw_v2.cpp */; }; - DF8425E30E7BA6AC00F5680E /* driver_vga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421230E7BA6A700F5680E /* driver_vga.cpp */; }; DF8425E40E7BA6AC00F5680E /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421250E7BA6A700F5680E /* game.cpp */; }; DF8425E70E7BA6AC00F5680E /* global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421290E7BA6A700F5680E /* global.cpp */; }; DF8425E80E7BA6AC00F5680E /* gob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84212B0E7BA6A700F5680E /* gob.cpp */; }; @@ -1732,7 +1900,6 @@ DF8427AD0E7BA6AC00F5680E /* insane_enemy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D50E7BA6AA00F5680E /* insane_enemy.cpp */; }; DF8427AE0E7BA6AC00F5680E /* insane_iact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D60E7BA6AA00F5680E /* insane_iact.cpp */; }; DF8427AF0E7BA6AC00F5680E /* insane_scenes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D70E7BA6AA00F5680E /* insane_scenes.cpp */; }; - DF8427B00E7BA6AC00F5680E /* midiparser_eup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D90E7BA6AA00F5680E /* midiparser_eup.cpp */; }; DF8427B10E7BA6AC00F5680E /* midiparser_ro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DA0E7BA6AA00F5680E /* midiparser_ro.cpp */; }; DF8427B30E7BA6AC00F5680E /* nut_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DD0E7BA6AA00F5680E /* nut_renderer.cpp */; }; DF8427B40E7BA6AC00F5680E /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DF0E7BA6AA00F5680E /* object.cpp */; }; @@ -1901,6 +2068,57 @@ DF842A490E7BBBB400F5680E /* unarj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF842A450E7BBBB400F5680E /* unarj.cpp */; }; DF842A6D0E7BBD5700F5680E /* stdiostream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF842A6B0E7BBD5700F5680E /* stdiostream.cpp */; }; DF842A710E7BBDB200F5680E /* musicplugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF842A6F0E7BBDB200F5680E /* musicplugin.cpp */; }; + DF895BFE124C24350077F6E8 /* coktel_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895BFC124C24350077F6E8 /* coktel_decoder.cpp */; }; + DF895BFF124C24350077F6E8 /* coktel_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895BFC124C24350077F6E8 /* coktel_decoder.cpp */; }; + DF895C00124C24350077F6E8 /* coktel_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895BFC124C24350077F6E8 /* coktel_decoder.cpp */; }; + DF895C03124C24680077F6E8 /* player_towns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C01124C24680077F6E8 /* player_towns.cpp */; }; + DF895C04124C24680077F6E8 /* player_towns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C01124C24680077F6E8 /* player_towns.cpp */; }; + DF895C05124C24680077F6E8 /* player_towns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C01124C24680077F6E8 /* player_towns.cpp */; }; + DF895C09124C24B60077F6E8 /* appleiigs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C08124C24B50077F6E8 /* appleiigs.cpp */; }; + DF895C0A124C24B60077F6E8 /* appleiigs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C08124C24B50077F6E8 /* appleiigs.cpp */; }; + DF895C0B124C24B60077F6E8 /* appleiigs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C08124C24B50077F6E8 /* appleiigs.cpp */; }; + DF895C15124C24C10077F6E8 /* towns_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C0D124C24C00077F6E8 /* towns_audio.cpp */; }; + DF895C16124C24C10077F6E8 /* towns_euphony.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C0F124C24C00077F6E8 /* towns_euphony.cpp */; }; + DF895C17124C24C10077F6E8 /* towns_pc98_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C11124C24C00077F6E8 /* towns_pc98_driver.cpp */; }; + DF895C18124C24C10077F6E8 /* towns_pc98_fmsynth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C13124C24C00077F6E8 /* towns_pc98_fmsynth.cpp */; }; + DF895C19124C24C10077F6E8 /* towns_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C0D124C24C00077F6E8 /* towns_audio.cpp */; }; + DF895C1A124C24C10077F6E8 /* towns_euphony.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C0F124C24C00077F6E8 /* towns_euphony.cpp */; }; + DF895C1B124C24C10077F6E8 /* towns_pc98_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C11124C24C00077F6E8 /* towns_pc98_driver.cpp */; }; + DF895C1C124C24C10077F6E8 /* towns_pc98_fmsynth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C13124C24C00077F6E8 /* towns_pc98_fmsynth.cpp */; }; + DF895C1D124C24C10077F6E8 /* towns_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C0D124C24C00077F6E8 /* towns_audio.cpp */; }; + DF895C1E124C24C10077F6E8 /* towns_euphony.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C0F124C24C00077F6E8 /* towns_euphony.cpp */; }; + DF895C1F124C24C10077F6E8 /* towns_pc98_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C11124C24C00077F6E8 /* towns_pc98_driver.cpp */; }; + DF895C20124C24C10077F6E8 /* towns_pc98_fmsynth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C13124C24C00077F6E8 /* towns_pc98_fmsynth.cpp */; }; + DF895C25124C25150077F6E8 /* init_fascin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C24124C25150077F6E8 /* init_fascin.cpp */; }; + DF895C26124C25150077F6E8 /* init_fascin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C24124C25150077F6E8 /* init_fascin.cpp */; }; + DF895C27124C25150077F6E8 /* init_fascin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C24124C25150077F6E8 /* init_fascin.cpp */; }; + DF895C2A124C25350077F6E8 /* script_patches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C29124C25350077F6E8 /* script_patches.cpp */; }; + DF895C2B124C25350077F6E8 /* script_patches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C29124C25350077F6E8 /* script_patches.cpp */; }; + DF895C2C124C25350077F6E8 /* script_patches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895C29124C25350077F6E8 /* script_patches.cpp */; }; + DF895C34124C26660077F6E8 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = DF895C33124C26660077F6E8 /* icon-72.png */; }; + DF895C35124C26660077F6E8 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = DF895C33124C26660077F6E8 /* icon-72.png */; }; + DF895C36124C26660077F6E8 /* icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = DF895C33124C26660077F6E8 /* icon-72.png */; }; + DF895C41124C271F0077F6E8 /* icon4.png in Resources */ = {isa = PBXBuildFile; fileRef = DF895C40124C271F0077F6E8 /* icon4.png */; }; + DF895C42124C271F0077F6E8 /* icon4.png in Resources */ = {isa = PBXBuildFile; fileRef = DF895C40124C271F0077F6E8 /* icon4.png */; }; + DF895C43124C271F0077F6E8 /* icon4.png in Resources */ = {isa = PBXBuildFile; fileRef = DF895C40124C271F0077F6E8 /* icon4.png */; }; + DF895CB8124E58980077F6E8 /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAB124E58980077F6E8 /* indeo3.cpp */; }; + DF895CB9124E58980077F6E8 /* mjpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAD124E58980077F6E8 /* mjpeg.cpp */; }; + DF895CBA124E58980077F6E8 /* qdm2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAF124E58980077F6E8 /* qdm2.cpp */; }; + DF895CBB124E58980077F6E8 /* qtrle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB2124E58980077F6E8 /* qtrle.cpp */; }; + DF895CBC124E58980077F6E8 /* rpza.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB4124E58980077F6E8 /* rpza.cpp */; }; + DF895CBD124E58990077F6E8 /* smc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB6124E58980077F6E8 /* smc.cpp */; }; + DF895CBE124E58990077F6E8 /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAB124E58980077F6E8 /* indeo3.cpp */; }; + DF895CBF124E58990077F6E8 /* mjpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAD124E58980077F6E8 /* mjpeg.cpp */; }; + DF895CC0124E58990077F6E8 /* qdm2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAF124E58980077F6E8 /* qdm2.cpp */; }; + DF895CC1124E58990077F6E8 /* qtrle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB2124E58980077F6E8 /* qtrle.cpp */; }; + DF895CC2124E58990077F6E8 /* rpza.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB4124E58980077F6E8 /* rpza.cpp */; }; + DF895CC3124E58990077F6E8 /* smc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB6124E58980077F6E8 /* smc.cpp */; }; + DF895CC4124E58990077F6E8 /* indeo3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAB124E58980077F6E8 /* indeo3.cpp */; }; + DF895CC5124E58990077F6E8 /* mjpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAD124E58980077F6E8 /* mjpeg.cpp */; }; + DF895CC6124E58990077F6E8 /* qdm2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CAF124E58980077F6E8 /* qdm2.cpp */; }; + DF895CC7124E58990077F6E8 /* qtrle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB2124E58980077F6E8 /* qtrle.cpp */; }; + DF895CC8124E58990077F6E8 /* rpza.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB4124E58980077F6E8 /* rpza.cpp */; }; + DF895CC9124E58990077F6E8 /* smc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF895CB6124E58980077F6E8 /* smc.cpp */; }; DF89C2880F62D55C00D756B6 /* sprites_lol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */; }; DF89C2A40F62D79E00D756B6 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2A30F62D79E00D756B6 /* script.cpp */; }; DF89C2BB0F62D91000D756B6 /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF89C2B80F62D91000D756B6 /* timestamp.cpp */; }; @@ -2350,7 +2568,6 @@ DFF95A080FB22D5700A3EC78 /* draw_bargon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421200E7BA6A700F5680E /* draw_bargon.cpp */; }; DFF95A090FB22D5700A3EC78 /* draw_v1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421210E7BA6A700F5680E /* draw_v1.cpp */; }; DFF95A0A0FB22D5700A3EC78 /* draw_v2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421220E7BA6A700F5680E /* draw_v2.cpp */; }; - DFF95A0B0FB22D5700A3EC78 /* driver_vga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421230E7BA6A700F5680E /* driver_vga.cpp */; }; DFF95A0C0FB22D5700A3EC78 /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421250E7BA6A700F5680E /* game.cpp */; }; DFF95A0F0FB22D5700A3EC78 /* global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8421290E7BA6A700F5680E /* global.cpp */; }; DFF95A100FB22D5700A3EC78 /* gob.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF84212B0E7BA6A700F5680E /* gob.cpp */; }; @@ -2662,7 +2879,6 @@ DFF95B6D0FB22D5700A3EC78 /* insane_enemy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D50E7BA6AA00F5680E /* insane_enemy.cpp */; }; DFF95B6E0FB22D5700A3EC78 /* insane_iact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D60E7BA6AA00F5680E /* insane_iact.cpp */; }; DFF95B6F0FB22D5700A3EC78 /* insane_scenes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D70E7BA6AA00F5680E /* insane_scenes.cpp */; }; - DFF95B700FB22D5700A3EC78 /* midiparser_eup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423D90E7BA6AA00F5680E /* midiparser_eup.cpp */; }; DFF95B710FB22D5700A3EC78 /* midiparser_ro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DA0E7BA6AA00F5680E /* midiparser_ro.cpp */; }; DFF95B720FB22D5700A3EC78 /* nut_renderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DD0E7BA6AA00F5680E /* nut_renderer.cpp */; }; DFF95B730FB22D5700A3EC78 /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF8423DF0E7BA6AA00F5680E /* object.cpp */; }; @@ -2970,6 +3186,120 @@ /* Begin PBXFileReference section */ 1D6058910D05DD3D006BFB54 /* ScummVM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ScummVM.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8CB5A9B71253FD6800CB6BC7 /* m4_scene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = m4_scene.cpp; sourceTree = ""; }; + 8CB5A9B81253FD6800CB6BC7 /* m4_scene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m4_scene.h; sourceTree = ""; }; + 8CB5A9B91253FD6800CB6BC7 /* mads_logic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mads_logic.cpp; sourceTree = ""; }; + 8CB5A9BA1253FD6800CB6BC7 /* mads_logic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mads_logic.h; sourceTree = ""; }; + 8CB5A9BB1253FD6800CB6BC7 /* mads_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mads_player.cpp; sourceTree = ""; }; + 8CB5A9BC1253FD6800CB6BC7 /* mads_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mads_player.h; sourceTree = ""; }; + 8CB5A9BD1253FD6800CB6BC7 /* mads_scene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mads_scene.cpp; sourceTree = ""; }; + 8CB5A9BE1253FD6800CB6BC7 /* mads_scene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mads_scene.h; sourceTree = ""; }; + 8CB5A9BF1253FD6900CB6BC7 /* mads_views.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mads_views.cpp; sourceTree = ""; }; + 8CB5A9C01253FD6900CB6BC7 /* mads_views.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mads_views.h; sourceTree = ""; }; + 8CB5A9D51253FDF400CB6BC7 /* drascula.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = drascula.dat; sourceTree = ""; }; + 8CB5A9D61253FDF500CB6BC7 /* hugo.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = hugo.dat; sourceTree = ""; }; + 8CB5A9D71253FDF500CB6BC7 /* m4.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = m4.dat; sourceTree = ""; }; + 8CB5A9D81253FDF500CB6BC7 /* teenagent.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = teenagent.dat; sourceTree = ""; }; + 8CD1ECC6126202AA00FA198C /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = ""; }; + 8CD1ECC7126202AA00FA198C /* display.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = display.cpp; sourceTree = ""; }; + 8CD1ECC8126202AA00FA198C /* display.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = display.h; sourceTree = ""; }; + 8CD1ECC9126202AA00FA198C /* engine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = engine.cpp; sourceTree = ""; }; + 8CD1ECCA126202AA00FA198C /* engine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = engine.h; sourceTree = ""; }; + 8CD1ECCB126202AA00FA198C /* file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file.cpp; sourceTree = ""; }; + 8CD1ECCC126202AA00FA198C /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = ""; }; + 8CD1ECCD126202AA00FA198C /* game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = game.h; sourceTree = ""; }; + 8CD1ECCE126202AA00FA198C /* global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = global.h; sourceTree = ""; }; + 8CD1ECCF126202AA00FA198C /* hugo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hugo.cpp; sourceTree = ""; }; + 8CD1ECD0126202AA00FA198C /* hugo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hugo.h; sourceTree = ""; }; + 8CD1ECD1126202AA00FA198C /* intro.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intro.cpp; sourceTree = ""; }; + 8CD1ECD2126202AA00FA198C /* intro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intro.h; sourceTree = ""; }; + 8CD1ECD3126202AA00FA198C /* inventory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inventory.cpp; sourceTree = ""; }; + 8CD1ECD4126202AA00FA198C /* inventory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inventory.h; sourceTree = ""; }; + 8CD1ECD7126202AA00FA198C /* mouse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mouse.cpp; sourceTree = ""; }; + 8CD1ECD8126202AA00FA198C /* mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mouse.h; sourceTree = ""; }; + 8CD1ECD9126202AA00FA198C /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = ""; }; + 8CD1ECDA126202AA00FA198C /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; }; + 8CD1ECDB126202AA00FA198C /* route.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = route.cpp; sourceTree = ""; }; + 8CD1ECDC126202AA00FA198C /* route.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = route.h; sourceTree = ""; }; + 8CD1ECDD126202AA00FA198C /* schedule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = schedule.cpp; sourceTree = ""; }; + 8CD1ECDE126202AA00FA198C /* schedule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = schedule.h; sourceTree = ""; }; + 8CD1ECDF126202AA00FA198C /* sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound.cpp; sourceTree = ""; }; + 8CD1ECE0126202AA00FA198C /* sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound.h; sourceTree = ""; }; + 8CD1ECE1126202AA00FA198C /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = ""; }; + 8CD1ECE2126202AA00FA198C /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + 8CD1ECE4126202AA00FA198C /* anim.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = anim.cpp; sourceTree = ""; }; + 8CD1ECE5126202AA00FA198C /* anim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anim.h; sourceTree = ""; }; + 8CD1ECE6126202AA00FA198C /* audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audio.cpp; sourceTree = ""; }; + 8CD1ECE7126202AA00FA198C /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = ""; }; + 8CD1ECE8126202AA00FA198C /* character.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = character.cpp; sourceTree = ""; }; + 8CD1ECE9126202AA00FA198C /* character.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = character.h; sourceTree = ""; }; + 8CD1ECEA126202AA00FA198C /* conversation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = conversation.cpp; sourceTree = ""; }; + 8CD1ECEB126202AA00FA198C /* conversation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = conversation.h; sourceTree = ""; }; + 8CD1ECEC126202AA00FA198C /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = ""; }; + 8CD1ECED126202AA00FA198C /* drew.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drew.cpp; sourceTree = ""; }; + 8CD1ECEE126202AA00FA198C /* drew.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drew.h; sourceTree = ""; }; + 8CD1ECEF126202AA00FA198C /* flux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flux.cpp; sourceTree = ""; }; + 8CD1ECF0126202AA00FA198C /* flux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flux.h; sourceTree = ""; }; + 8CD1ECF1126202AA00FA198C /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = ""; }; + 8CD1ECF2126202AA00FA198C /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = ""; }; + 8CD1ECF3126202AA00FA198C /* hotspot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hotspot.cpp; sourceTree = ""; }; + 8CD1ECF4126202AA00FA198C /* hotspot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hotspot.h; sourceTree = ""; }; + 8CD1ECF7126202AA00FA198C /* movie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = movie.cpp; sourceTree = ""; }; + 8CD1ECF8126202AA00FA198C /* movie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = movie.h; sourceTree = ""; }; + 8CD1ECF9126202AA00FA198C /* path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path.cpp; sourceTree = ""; }; + 8CD1ECFA126202AA00FA198C /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = path.h; sourceTree = ""; }; + 8CD1ECFB126202AA00FA198C /* picture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = picture.cpp; sourceTree = ""; }; + 8CD1ECFC126202AA00FA198C /* picture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = picture.h; sourceTree = ""; }; + 8CD1ECFD126202AA00FA198C /* resource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource.cpp; sourceTree = ""; }; + 8CD1ECFE126202AA00FA198C /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; + 8CD1ECFF126202AA00FA198C /* script.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script.cpp; sourceTree = ""; }; + 8CD1ED00126202AA00FA198C /* script.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = script.h; sourceTree = ""; }; + 8CD1ED01126202AA00FA198C /* script_func.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script_func.cpp; sourceTree = ""; }; + 8CD1ED02126202AA00FA198C /* script_func.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = script_func.h; sourceTree = ""; }; + 8CD1ED03126202AA00FA198C /* state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = state.cpp; sourceTree = ""; }; + 8CD1ED04126202AA00FA198C /* state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = state.h; sourceTree = ""; }; + 8CD1ED05126202AA00FA198C /* text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = text.cpp; sourceTree = ""; }; + 8CD1ED06126202AA00FA198C /* text.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = text.h; sourceTree = ""; }; + 8CD1ED07126202AA00FA198C /* tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tools.cpp; sourceTree = ""; }; + 8CD1ED08126202AA00FA198C /* tools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tools.h; sourceTree = ""; }; + 8CD1ED09126202AA00FA198C /* toon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = toon.cpp; sourceTree = ""; }; + 8CD1ED0A126202AA00FA198C /* toon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = toon.h; sourceTree = ""; }; + 8CD1ED871262030100FA198C /* toon.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = toon.dat; sourceTree = ""; }; + 8CD80C89126271A9001C6C87 /* surface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = surface.cpp; sourceTree = ""; }; + 8CD80C8A126271A9001C6C87 /* surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = surface.h; sourceTree = ""; }; + 8CD80C90126271BD001C6C87 /* gfx_towns.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gfx_towns.cpp; sourceTree = ""; }; + 8CD80CBF1262729F001C6C87 /* actor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = actor.cpp; sourceTree = ""; }; + 8CD80CC01262729F001C6C87 /* actor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = actor.h; sourceTree = ""; }; + 8CD80CC11262729F001C6C87 /* animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = animation.cpp; sourceTree = ""; }; + 8CD80CC21262729F001C6C87 /* animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = animation.h; sourceTree = ""; }; + 8CD80CC31262729F001C6C87 /* callbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = callbacks.cpp; sourceTree = ""; }; + 8CD80CC41262729F001C6C87 /* console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = console.cpp; sourceTree = ""; }; + 8CD80CC51262729F001C6C87 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = ""; }; + 8CD80CC61262729F001C6C87 /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = ""; }; + 8CD80CC71262729F001C6C87 /* dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dialog.cpp; sourceTree = ""; }; + 8CD80CC81262729F001C6C87 /* dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dialog.h; sourceTree = ""; }; + 8CD80CC91262729F001C6C87 /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = ""; }; + 8CD80CCA1262729F001C6C87 /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = ""; }; + 8CD80CCB1262729F001C6C87 /* inventory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inventory.cpp; sourceTree = ""; }; + 8CD80CCC1262729F001C6C87 /* inventory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inventory.h; sourceTree = ""; }; + 8CD80CCE1262729F001C6C87 /* music.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = music.cpp; sourceTree = ""; }; + 8CD80CCF1262729F001C6C87 /* music.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music.h; sourceTree = ""; }; + 8CD80CD01262729F001C6C87 /* objects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = objects.cpp; sourceTree = ""; }; + 8CD80CD11262729F001C6C87 /* objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = objects.h; sourceTree = ""; }; + 8CD80CD21262729F001C6C87 /* pack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pack.cpp; sourceTree = ""; }; + 8CD80CD3126272A0001C6C87 /* pack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pack.h; sourceTree = ""; }; + 8CD80CD4126272A0001C6C87 /* resources.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resources.cpp; sourceTree = ""; }; + 8CD80CD5126272A0001C6C87 /* resources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resources.h; sourceTree = ""; }; + 8CD80CD6126272A0001C6C87 /* scene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scene.cpp; sourceTree = ""; }; + 8CD80CD7126272A0001C6C87 /* scene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scene.h; sourceTree = ""; }; + 8CD80CD8126272A0001C6C87 /* segment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = segment.cpp; sourceTree = ""; }; + 8CD80CD9126272A0001C6C87 /* segment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = segment.h; sourceTree = ""; }; + 8CD80CDA126272A0001C6C87 /* surface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = surface.cpp; sourceTree = ""; }; + 8CD80CDB126272A0001C6C87 /* surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = surface.h; sourceTree = ""; }; + 8CD80CDC126272A0001C6C87 /* surface_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = surface_list.cpp; sourceTree = ""; }; + 8CD80CDD126272A0001C6C87 /* surface_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = surface_list.h; sourceTree = ""; }; + 8CD80CDE126272A0001C6C87 /* teenagent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = teenagent.cpp; sourceTree = ""; }; + 8CD80CDF126272A0001C6C87 /* teenagent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = teenagent.h; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DF093E5C0F63CAD4002D821E /* pn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pn.cpp; sourceTree = ""; }; DF093E5D0F63CAD4002D821E /* script_pn.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script_pn.cpp; sourceTree = ""; }; @@ -3008,6 +3338,9 @@ DF09CC240FAC4E6200A5AFD7 /* scumm_v8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scumm_v8.h; sourceTree = ""; }; DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script_v3.cpp; sourceTree = ""; }; DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script_v4.cpp; sourceTree = ""; }; + DF0E30391252C5BD0082D593 /* cms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cms.cpp; sourceTree = ""; }; + DF0E303F1252C6090082D593 /* cms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cms.cpp; sourceTree = ""; }; + DF0E30401252C6090082D593 /* cms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cms.h; sourceTree = ""; }; DF224E020FB23BC500C8E453 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; DF2EC3E410E6490800765801 /* browser_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = browser_osx.mm; sourceTree = ""; }; DF2EC3F610E64C0C00765801 /* dialogs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dialogs.cpp; sourceTree = ""; }; @@ -3190,8 +3523,6 @@ DF45B1C4116628A5009B85CC /* soundcmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = soundcmd.h; sourceTree = ""; }; DF45B1C6116628A5009B85CC /* seq_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = seq_decoder.cpp; sourceTree = ""; }; DF45B1C7116628A5009B85CC /* seq_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seq_decoder.h; sourceTree = ""; }; - DF45B1C8116628A5009B85CC /* vmd_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vmd_decoder.cpp; sourceTree = ""; }; - DF45B1C9116628A5009B85CC /* vmd_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmd_decoder.h; sourceTree = ""; }; DF573BFE0F5A81EA00961A72 /* kernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel.h; sourceTree = ""; }; DF573BFF0F5A81EA00961A72 /* script.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = script.h; sourceTree = ""; }; DF573C000F5A81EA00961A72 /* seg_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seg_manager.h; sourceTree = ""; }; @@ -3216,10 +3547,6 @@ DF6118460FE3A8250042AD3F /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; DF6118540FE3A8990042AD3F /* disk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = disk.cpp; sourceTree = ""; }; DF6118590FE3A9020042AD3F /* helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = helper.h; sourceTree = ""; }; - DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coktelvideo.cpp; sourceTree = ""; }; - DF61185D0FE3A9410042AD3F /* coktelvideo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coktelvideo.h; sourceTree = ""; }; - DF61185E0FE3A9410042AD3F /* indeo3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = indeo3.cpp; sourceTree = ""; }; - DF61185F0FE3A9410042AD3F /* indeo3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indeo3.h; sourceTree = ""; }; DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dxa_decoder.cpp; sourceTree = ""; }; DF6118610FE3A9410042AD3F /* dxa_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dxa_decoder.h; sourceTree = ""; }; DF6118620FE3A9410042AD3F /* flic_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flic_decoder.cpp; sourceTree = ""; }; @@ -3562,8 +3889,6 @@ DF8421200E7BA6A700F5680E /* draw_bargon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw_bargon.cpp; sourceTree = ""; }; DF8421210E7BA6A700F5680E /* draw_v1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw_v1.cpp; sourceTree = ""; }; DF8421220E7BA6A700F5680E /* draw_v2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw_v2.cpp; sourceTree = ""; }; - DF8421230E7BA6A700F5680E /* driver_vga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = driver_vga.cpp; sourceTree = ""; }; - DF8421240E7BA6A700F5680E /* driver_vga.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = driver_vga.h; sourceTree = ""; }; DF8421250E7BA6A700F5680E /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game.cpp; sourceTree = ""; }; DF8421260E7BA6A700F5680E /* game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = game.h; sourceTree = ""; }; DF8421290E7BA6A700F5680E /* global.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = global.cpp; sourceTree = ""; }; @@ -4083,7 +4408,6 @@ DF8423D50E7BA6AA00F5680E /* insane_enemy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = insane_enemy.cpp; sourceTree = ""; }; DF8423D60E7BA6AA00F5680E /* insane_iact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = insane_iact.cpp; sourceTree = ""; }; DF8423D70E7BA6AA00F5680E /* insane_scenes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = insane_scenes.cpp; sourceTree = ""; }; - DF8423D90E7BA6AA00F5680E /* midiparser_eup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = midiparser_eup.cpp; sourceTree = ""; }; DF8423DA0E7BA6AA00F5680E /* midiparser_ro.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = midiparser_ro.cpp; sourceTree = ""; }; DF8423DC0E7BA6AA00F5680E /* music.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music.h; sourceTree = ""; }; DF8423DD0E7BA6AA00F5680E /* nut_renderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nut_renderer.cpp; sourceTree = ""; }; @@ -4383,6 +4707,38 @@ DF842A6C0E7BBD5700F5680E /* stdiostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdiostream.h; sourceTree = ""; }; DF842A6F0E7BBDB200F5680E /* musicplugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = musicplugin.cpp; sourceTree = ""; }; DF842A700E7BBDB200F5680E /* musicplugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = musicplugin.h; sourceTree = ""; }; + DF895BFC124C24350077F6E8 /* coktel_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coktel_decoder.cpp; sourceTree = ""; }; + DF895BFD124C24350077F6E8 /* coktel_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coktel_decoder.h; sourceTree = ""; }; + DF895C01124C24680077F6E8 /* player_towns.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = player_towns.cpp; sourceTree = ""; }; + DF895C02124C24680077F6E8 /* player_towns.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = player_towns.h; sourceTree = ""; }; + DF895C08124C24B50077F6E8 /* appleiigs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = appleiigs.cpp; sourceTree = ""; }; + DF895C0D124C24C00077F6E8 /* towns_audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = towns_audio.cpp; sourceTree = ""; }; + DF895C0E124C24C00077F6E8 /* towns_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = towns_audio.h; sourceTree = ""; }; + DF895C0F124C24C00077F6E8 /* towns_euphony.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = towns_euphony.cpp; sourceTree = ""; }; + DF895C10124C24C00077F6E8 /* towns_euphony.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = towns_euphony.h; sourceTree = ""; }; + DF895C11124C24C00077F6E8 /* towns_pc98_driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = towns_pc98_driver.cpp; sourceTree = ""; }; + DF895C12124C24C00077F6E8 /* towns_pc98_driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = towns_pc98_driver.h; sourceTree = ""; }; + DF895C13124C24C00077F6E8 /* towns_pc98_fmsynth.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = towns_pc98_fmsynth.cpp; sourceTree = ""; }; + DF895C14124C24C00077F6E8 /* towns_pc98_fmsynth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = towns_pc98_fmsynth.h; sourceTree = ""; }; + DF895C23124C25150077F6E8 /* detection_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = detection_tables.h; sourceTree = ""; }; + DF895C24124C25150077F6E8 /* init_fascin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = init_fascin.cpp; sourceTree = ""; }; + DF895C28124C25350077F6E8 /* kernel_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_tables.h; sourceTree = ""; }; + DF895C29124C25350077F6E8 /* script_patches.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script_patches.cpp; sourceTree = ""; }; + DF895C33124C26660077F6E8 /* icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-72.png"; sourceTree = ""; }; + DF895C40124C271F0077F6E8 /* icon4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon4.png; sourceTree = ""; }; + DF895CAB124E58980077F6E8 /* indeo3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = indeo3.cpp; sourceTree = ""; }; + DF895CAC124E58980077F6E8 /* indeo3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indeo3.h; sourceTree = ""; }; + DF895CAD124E58980077F6E8 /* mjpeg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mjpeg.cpp; sourceTree = ""; }; + DF895CAE124E58980077F6E8 /* mjpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mjpeg.h; sourceTree = ""; }; + DF895CAF124E58980077F6E8 /* qdm2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = qdm2.cpp; sourceTree = ""; }; + DF895CB0124E58980077F6E8 /* qdm2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qdm2.h; sourceTree = ""; }; + DF895CB1124E58980077F6E8 /* qdm2data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qdm2data.h; sourceTree = ""; }; + DF895CB2124E58980077F6E8 /* qtrle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = qtrle.cpp; sourceTree = ""; }; + DF895CB3124E58980077F6E8 /* qtrle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qtrle.h; sourceTree = ""; }; + DF895CB4124E58980077F6E8 /* rpza.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rpza.cpp; sourceTree = ""; }; + DF895CB5124E58980077F6E8 /* rpza.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rpza.h; sourceTree = ""; }; + DF895CB6124E58980077F6E8 /* smc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = smc.cpp; sourceTree = ""; }; + DF895CB7124E58980077F6E8 /* smc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = smc.h; sourceTree = ""; }; DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sprites_lol.cpp; sourceTree = ""; }; DF89C2A30F62D79E00D756B6 /* script.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script.cpp; sourceTree = ""; }; DF89C2B80F62D91000D756B6 /* timestamp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = timestamp.cpp; sourceTree = ""; }; @@ -4652,10 +5008,10 @@ DFE478220D81F4E900B6D1FB /* pcspk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pcspk.h; sourceTree = ""; }; DFE478230D81F4E900B6D1FB /* ym2612.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ym2612.cpp; sourceTree = ""; }; DFE478240D81F4E900B6D1FB /* ym2612.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ym2612.h; sourceTree = ""; }; - DFE47C810D81F86900B6D1FB /* kyra.dat */ = {isa = PBXFileReference; lastKnownFileType = file; name = kyra.dat; path = "../engine-data/kyra.dat"; sourceTree = ""; }; - DFE47C820D81F86900B6D1FB /* lure.dat */ = {isa = PBXFileReference; lastKnownFileType = file; name = lure.dat; path = "../engine-data/lure.dat"; sourceTree = ""; }; - DFE47C830D81F86900B6D1FB /* queen.tbl */ = {isa = PBXFileReference; lastKnownFileType = file; name = queen.tbl; path = "../engine-data/queen.tbl"; sourceTree = ""; }; - DFE47C850D81F86900B6D1FB /* sky.cpt */ = {isa = PBXFileReference; lastKnownFileType = file; name = sky.cpt; path = "../engine-data/sky.cpt"; sourceTree = ""; }; + DFE47C810D81F86900B6D1FB /* kyra.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = kyra.dat; sourceTree = ""; }; + DFE47C820D81F86900B6D1FB /* lure.dat */ = {isa = PBXFileReference; lastKnownFileType = file; path = lure.dat; sourceTree = ""; }; + DFE47C830D81F86900B6D1FB /* queen.tbl */ = {isa = PBXFileReference; lastKnownFileType = file; path = queen.tbl; sourceTree = ""; }; + DFE47C850D81F86900B6D1FB /* sky.cpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = sky.cpt; sourceTree = ""; }; DFE88C440F874A1100C555C5 /* sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound.cpp; sourceTree = ""; }; DFE88C450F874A1100C555C5 /* sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound.h; sourceTree = ""; }; DFEC5D0A1166C5CF00C90552 /* random.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = random.cpp; sourceTree = ""; }; @@ -4774,11 +5130,11 @@ DFD6476A0F49F7D2008E18EF /* libs */, DF841FF50E7BA6A600F5680E /* engines */, DFE470D50D81F4E700B6D1FB /* backends */, + DFE470C00D81F4BA00B6D1FB /* base */, DFE473950D81F4E800B6D1FB /* common */, DFE477520D81F4E900B6D1FB /* graphics */, DFE477880D81F4E900B6D1FB /* gui */, DFE477C60D81F4E900B6D1FB /* sound */, - DFE470C00D81F4BA00B6D1FB /* base */, 29B97317FDCFA39411CA2CEA /* Resources */, DFA2A57A118E433A00344DFD /* Resources-iPad */, 29B97323FDCFA39411CA2CEA /* Frameworks */, @@ -4790,14 +5146,13 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + 8CB5A9D21253FD9100CB6BC7 /* engine-data */, + DF895C40124C271F0077F6E8 /* icon4.png */, + DF895C33124C26660077F6E8 /* icon-72.png */, DF0944B00F6430ED002D821E /* scummvm.icns */, DFF4DFFC0F4B449F00C50BC7 /* Info.plist.in */, DF2FFD290F48717F0006E566 /* Default.png */, DF2FFD2A0F48717F0006E566 /* icon.png */, - DFE47C810D81F86900B6D1FB /* kyra.dat */, - DFE47C820D81F86900B6D1FB /* lure.dat */, - DFE47C830D81F86900B6D1FB /* queen.tbl */, - DFE47C850D81F86900B6D1FB /* sky.cpt */, 8D1107310486CEB800E47090 /* Info.plist */, ); name = Resources; @@ -4812,6 +5167,140 @@ name = Frameworks; sourceTree = ""; }; + 8CB5A9D21253FD9100CB6BC7 /* engine-data */ = { + isa = PBXGroup; + children = ( + 8CB5A9D51253FDF400CB6BC7 /* drascula.dat */, + 8CB5A9D61253FDF500CB6BC7 /* hugo.dat */, + DFE47C810D81F86900B6D1FB /* kyra.dat */, + DFE47C820D81F86900B6D1FB /* lure.dat */, + 8CB5A9D71253FDF500CB6BC7 /* m4.dat */, + DFE47C830D81F86900B6D1FB /* queen.tbl */, + DFE47C850D81F86900B6D1FB /* sky.cpt */, + 8CB5A9D81253FDF500CB6BC7 /* teenagent.dat */, + 8CD1ED871262030100FA198C /* toon.dat */, + ); + name = "engine-data"; + path = "../engine-data"; + sourceTree = ""; + }; + 8CD1ECC5126202AA00FA198C /* hugo */ = { + isa = PBXGroup; + children = ( + 8CD1ECC6126202AA00FA198C /* detection.cpp */, + 8CD1ECC7126202AA00FA198C /* display.cpp */, + 8CD1ECC8126202AA00FA198C /* display.h */, + 8CD1ECC9126202AA00FA198C /* engine.cpp */, + 8CD1ECCA126202AA00FA198C /* engine.h */, + 8CD1ECCB126202AA00FA198C /* file.cpp */, + 8CD1ECCC126202AA00FA198C /* file.h */, + 8CD1ECCD126202AA00FA198C /* game.h */, + 8CD1ECCE126202AA00FA198C /* global.h */, + 8CD1ECCF126202AA00FA198C /* hugo.cpp */, + 8CD1ECD0126202AA00FA198C /* hugo.h */, + 8CD1ECD1126202AA00FA198C /* intro.cpp */, + 8CD1ECD2126202AA00FA198C /* intro.h */, + 8CD1ECD3126202AA00FA198C /* inventory.cpp */, + 8CD1ECD4126202AA00FA198C /* inventory.h */, + 8CD1ECD7126202AA00FA198C /* mouse.cpp */, + 8CD1ECD8126202AA00FA198C /* mouse.h */, + 8CD1ECD9126202AA00FA198C /* parser.cpp */, + 8CD1ECDA126202AA00FA198C /* parser.h */, + 8CD1ECDB126202AA00FA198C /* route.cpp */, + 8CD1ECDC126202AA00FA198C /* route.h */, + 8CD1ECDD126202AA00FA198C /* schedule.cpp */, + 8CD1ECDE126202AA00FA198C /* schedule.h */, + 8CD1ECDF126202AA00FA198C /* sound.cpp */, + 8CD1ECE0126202AA00FA198C /* sound.h */, + 8CD1ECE1126202AA00FA198C /* util.cpp */, + 8CD1ECE2126202AA00FA198C /* util.h */, + ); + path = hugo; + sourceTree = ""; + }; + 8CD1ECE3126202AA00FA198C /* toon */ = { + isa = PBXGroup; + children = ( + 8CD1ECE4126202AA00FA198C /* anim.cpp */, + 8CD1ECE5126202AA00FA198C /* anim.h */, + 8CD1ECE6126202AA00FA198C /* audio.cpp */, + 8CD1ECE7126202AA00FA198C /* audio.h */, + 8CD1ECE8126202AA00FA198C /* character.cpp */, + 8CD1ECE9126202AA00FA198C /* character.h */, + 8CD1ECEA126202AA00FA198C /* conversation.cpp */, + 8CD1ECEB126202AA00FA198C /* conversation.h */, + 8CD1ECEC126202AA00FA198C /* detection.cpp */, + 8CD1ECED126202AA00FA198C /* drew.cpp */, + 8CD1ECEE126202AA00FA198C /* drew.h */, + 8CD1ECEF126202AA00FA198C /* flux.cpp */, + 8CD1ECF0126202AA00FA198C /* flux.h */, + 8CD1ECF1126202AA00FA198C /* font.cpp */, + 8CD1ECF2126202AA00FA198C /* font.h */, + 8CD1ECF3126202AA00FA198C /* hotspot.cpp */, + 8CD1ECF4126202AA00FA198C /* hotspot.h */, + 8CD1ECF7126202AA00FA198C /* movie.cpp */, + 8CD1ECF8126202AA00FA198C /* movie.h */, + 8CD1ECF9126202AA00FA198C /* path.cpp */, + 8CD1ECFA126202AA00FA198C /* path.h */, + 8CD1ECFB126202AA00FA198C /* picture.cpp */, + 8CD1ECFC126202AA00FA198C /* picture.h */, + 8CD1ECFD126202AA00FA198C /* resource.cpp */, + 8CD1ECFE126202AA00FA198C /* resource.h */, + 8CD1ECFF126202AA00FA198C /* script.cpp */, + 8CD1ED00126202AA00FA198C /* script.h */, + 8CD1ED01126202AA00FA198C /* script_func.cpp */, + 8CD1ED02126202AA00FA198C /* script_func.h */, + 8CD1ED03126202AA00FA198C /* state.cpp */, + 8CD1ED04126202AA00FA198C /* state.h */, + 8CD1ED05126202AA00FA198C /* text.cpp */, + 8CD1ED06126202AA00FA198C /* text.h */, + 8CD1ED07126202AA00FA198C /* tools.cpp */, + 8CD1ED08126202AA00FA198C /* tools.h */, + 8CD1ED09126202AA00FA198C /* toon.cpp */, + 8CD1ED0A126202AA00FA198C /* toon.h */, + ); + path = toon; + sourceTree = ""; + }; + 8CD80CBE1262729F001C6C87 /* teenagent */ = { + isa = PBXGroup; + children = ( + 8CD80CBF1262729F001C6C87 /* actor.cpp */, + 8CD80CC01262729F001C6C87 /* actor.h */, + 8CD80CC11262729F001C6C87 /* animation.cpp */, + 8CD80CC21262729F001C6C87 /* animation.h */, + 8CD80CC31262729F001C6C87 /* callbacks.cpp */, + 8CD80CC41262729F001C6C87 /* console.cpp */, + 8CD80CC51262729F001C6C87 /* console.h */, + 8CD80CC61262729F001C6C87 /* detection.cpp */, + 8CD80CC71262729F001C6C87 /* dialog.cpp */, + 8CD80CC81262729F001C6C87 /* dialog.h */, + 8CD80CC91262729F001C6C87 /* font.cpp */, + 8CD80CCA1262729F001C6C87 /* font.h */, + 8CD80CCB1262729F001C6C87 /* inventory.cpp */, + 8CD80CCC1262729F001C6C87 /* inventory.h */, + 8CD80CCE1262729F001C6C87 /* music.cpp */, + 8CD80CCF1262729F001C6C87 /* music.h */, + 8CD80CD01262729F001C6C87 /* objects.cpp */, + 8CD80CD11262729F001C6C87 /* objects.h */, + 8CD80CD21262729F001C6C87 /* pack.cpp */, + 8CD80CD3126272A0001C6C87 /* pack.h */, + 8CD80CD4126272A0001C6C87 /* resources.cpp */, + 8CD80CD5126272A0001C6C87 /* resources.h */, + 8CD80CD6126272A0001C6C87 /* scene.cpp */, + 8CD80CD7126272A0001C6C87 /* scene.h */, + 8CD80CD8126272A0001C6C87 /* segment.cpp */, + 8CD80CD9126272A0001C6C87 /* segment.h */, + 8CD80CDA126272A0001C6C87 /* surface.cpp */, + 8CD80CDB126272A0001C6C87 /* surface.h */, + 8CD80CDC126272A0001C6C87 /* surface_list.cpp */, + 8CD80CDD126272A0001C6C87 /* surface_list.h */, + 8CD80CDE126272A0001C6C87 /* teenagent.cpp */, + 8CD80CDF126272A0001C6C87 /* teenagent.h */, + ); + path = teenagent; + sourceTree = ""; + }; DF09422F0F63CB9A002D821E /* sdl */ = { isa = PBXGroup; children = ( @@ -4841,22 +5330,23 @@ DF2FFB940F485D950006E566 /* video */ = { isa = PBXGroup; children = ( - DFB0576211B753AF0015AE65 /* mpeg_player.cpp */, - DFB0576311B753AF0015AE65 /* mpeg_player.h */, - DFB0576411B753AF0015AE65 /* qt_decoder.cpp */, - DFB0576511B753AF0015AE65 /* qt_decoder.h */, - DFB0576611B753AF0015AE65 /* video_decoder.cpp */, - DFB0576711B753AF0015AE65 /* video_decoder.h */, - DF90EABF10B023F300C8F93F /* codecs */, DF90EAB610B023D100C8F93F /* avi_decoder.cpp */, DF90EAB710B023D100C8F93F /* avi_decoder.h */, - DF61185B0FE3A9410042AD3F /* coktelvideo */, + DF90EABF10B023F300C8F93F /* codecs */, + DF895BFC124C24350077F6E8 /* coktel_decoder.cpp */, + DF895BFD124C24350077F6E8 /* coktel_decoder.h */, DF6118600FE3A9410042AD3F /* dxa_decoder.cpp */, DF6118610FE3A9410042AD3F /* dxa_decoder.h */, DF6118620FE3A9410042AD3F /* flic_decoder.cpp */, DF6118630FE3A9410042AD3F /* flic_decoder.h */, + DFB0576211B753AF0015AE65 /* mpeg_player.cpp */, + DFB0576311B753AF0015AE65 /* mpeg_player.h */, + DFB0576411B753AF0015AE65 /* qt_decoder.cpp */, + DFB0576511B753AF0015AE65 /* qt_decoder.h */, DF6118640FE3A9410042AD3F /* smk_decoder.cpp */, DF6118650FE3A9410042AD3F /* smk_decoder.h */, + DFB0576611B753AF0015AE65 /* video_decoder.cpp */, + DFB0576711B753AF0015AE65 /* video_decoder.h */, ); path = video; sourceTree = ""; @@ -4926,8 +5416,6 @@ DF45B0EB116627D9009B85CC /* decoders */ = { isa = PBXGroup; children = ( - DF7F289E11FF24B000159131 /* mac_snd.cpp */, - DF7F289F11FF24B000159131 /* mac_snd.h */, DF45B0F7116627DA009B85CC /* adpcm.cpp */, DF45B0F8116627DA009B85CC /* adpcm.h */, DF45B0FA116627DA009B85CC /* aiff.cpp */, @@ -4936,6 +5424,8 @@ DF45B0FE116627DA009B85CC /* flac.h */, DF45B100116627DA009B85CC /* iff_sound.cpp */, DF45B101116627DA009B85CC /* iff_sound.h */, + DF7F289E11FF24B000159131 /* mac_snd.cpp */, + DF7F289F11FF24B000159131 /* mac_snd.h */, DF45B103116627DA009B85CC /* mp3.cpp */, DF45B104116627DA009B85CC /* mp3.h */, DF45B106116627DA009B85CC /* raw.cpp */, @@ -4955,11 +5445,6 @@ DF45B175116628A5009B85CC /* graphics */ = { isa = PBXGroup; children = ( - DF7F285C11FF23B700159131 /* frameout.cpp */, - DFB0578811B754570015AE65 /* maciconbar.cpp */, - DFB0578911B754570015AE65 /* maciconbar.h */, - DF9B924F118E46A00069C19D /* fontsjis.cpp */, - DF9B9250118E46A00069C19D /* fontsjis.h */, DF45B176116628A5009B85CC /* animate.cpp */, DF45B177116628A5009B85CC /* animate.h */, DF45B178116628A5009B85CC /* cache.cpp */, @@ -4974,8 +5459,13 @@ DF45B181116628A5009B85CC /* cursor.h */, DF45B182116628A5009B85CC /* font.cpp */, DF45B183116628A5009B85CC /* font.h */, + DF9B924F118E46A00069C19D /* fontsjis.cpp */, + DF9B9250118E46A00069C19D /* fontsjis.h */, + DF7F285C11FF23B700159131 /* frameout.cpp */, DF45B185116628A5009B85CC /* frameout.h */, DF45B18A116628A5009B85CC /* helpers.h */, + DFB0578811B754570015AE65 /* maciconbar.cpp */, + DFB0578911B754570015AE65 /* maciconbar.h */, DF45B18B116628A5009B85CC /* menu.cpp */, DF45B18C116628A5009B85CC /* menu.h */, DF45B18D116628A5009B85CC /* paint.cpp */, @@ -5023,7 +5513,6 @@ DF45B1AC116628A5009B85CC /* audio.cpp */, DF45B1AD116628A5009B85CC /* audio.h */, DF45B1AE116628A5009B85CC /* drivers */, - DF45B1B6116628A5009B85CC /* iterator */, DF45B1BF116628A5009B85CC /* midiparser_sci.cpp */, DF45B1C0116628A5009B85CC /* midiparser_sci.h */, DF45B1C1116628A5009B85CC /* music.cpp */, @@ -5037,6 +5526,7 @@ DF45B1AE116628A5009B85CC /* drivers */ = { isa = PBXGroup; children = ( + DF0E30391252C5BD0082D593 /* cms.cpp */, DF7F286011FF23D500159131 /* amigamac.cpp */, DF45B1AF116628A5009B85CC /* adlib.cpp */, DF45B1B1116628A5009B85CC /* fb01.cpp */, @@ -5048,35 +5538,15 @@ path = drivers; sourceTree = ""; }; - DF45B1B6116628A5009B85CC /* iterator */ = { - isa = PBXGroup; - children = ( - ); - path = iterator; - sourceTree = ""; - }; DF45B1C5116628A5009B85CC /* video */ = { isa = PBXGroup; children = ( DF45B1C6116628A5009B85CC /* seq_decoder.cpp */, DF45B1C7116628A5009B85CC /* seq_decoder.h */, - DF45B1C8116628A5009B85CC /* vmd_decoder.cpp */, - DF45B1C9116628A5009B85CC /* vmd_decoder.h */, ); path = video; sourceTree = ""; }; - DF61185B0FE3A9410042AD3F /* coktelvideo */ = { - isa = PBXGroup; - children = ( - DF61185C0FE3A9410042AD3F /* coktelvideo.cpp */, - DF61185D0FE3A9410042AD3F /* coktelvideo.h */, - DF61185E0FE3A9410042AD3F /* indeo3.cpp */, - DF61185F0FE3A9410042AD3F /* indeo3.h */, - ); - path = coktelvideo; - sourceTree = ""; - }; DF6118780FE3A9AA0042AD3F /* save */ = { isa = PBXGroup; children = ( @@ -5105,14 +5575,8 @@ DF841FF50E7BA6A600F5680E /* engines */ = { isa = PBXGroup; children = ( - DFEC5D341166C67300C90552 /* savestate.cpp */, - DFEC5D351166C67300C90552 /* savestate.h */, - DF2FFD040F4870E50006E566 /* tucker */, - DF2FFCBC0F4870690006E566 /* groovie */, DF2FFC4C0F4863560006E566 /* advancedDetector.cpp */, DF2FFC4D0F4863560006E566 /* advancedDetector.h */, - DF7E8C510ED60067001CB19F /* game.cpp */, - DF7E8C520ED60067001CB19F /* game.h */, DF841FF60E7BA6A600F5680E /* agi */, DF84202D0E7BA6A600F5680E /* agos */, DF8420640E7BA6A600F5680E /* cine */, @@ -5122,22 +5586,31 @@ DF8421040E7BA6A700F5680E /* drascula */, DF8421140E7BA6A700F5680E /* engine.cpp */, DF8421150E7BA6A700F5680E /* engine.h */, + DF7E8C510ED60067001CB19F /* game.cpp */, + DF7E8C520ED60067001CB19F /* game.h */, DF8421170E7BA6A700F5680E /* gob */, + DF2FFCBC0F4870690006E566 /* groovie */, + 8CD1ECC5126202AA00FA198C /* hugo */, DF8421A30E7BA6A800F5680E /* kyra */, DF8422200E7BA6A800F5680E /* lure */, DF84224E0E7BA6A800F5680E /* m4 */, DF8422C90E7BA6A900F5680E /* made */, DF8422E40E7BA6A900F5680E /* metaengine.h */, - DFC830190F48AF18005EF03C /* sci */, DF8422E60E7BA6A900F5680E /* parallaction */, DF8423120E7BA6A900F5680E /* queen */, DF84233E0E7BA6AA00F5680E /* saga */, + DFEC5D341166C67300C90552 /* savestate.cpp */, + DFEC5D351166C67300C90552 /* savestate.h */, + DFC830190F48AF18005EF03C /* sci */, DF84237B0E7BA6AA00F5680E /* scumm */, DF8424200E7BA6AB00F5680E /* sky */, DF84244E0E7BA6AB00F5680E /* sword1 */, DF8424770E7BA6AB00F5680E /* sword2 */, + 8CD80CBE1262729F001C6C87 /* teenagent */, DF8424AA0E7BA6AB00F5680E /* tinsel */, + 8CD1ECE3126202AA00FA198C /* toon */, DF8424FC0E7BA6AB00F5680E /* touche */, + DF2FFD040F4870E50006E566 /* tucker */, ); name = engines; path = ../../engines; @@ -5146,17 +5619,6 @@ DF841FF60E7BA6A600F5680E /* agi */ = { isa = PBXGroup; children = ( - DF7F286F11FF243A00159131 /* detection_tables.h */, - DF7F287011FF243A00159131 /* sound_2gs.cpp */, - DF7F287111FF243A00159131 /* sound_2gs.h */, - DF7F287211FF243B00159131 /* sound_coco3.cpp */, - DF7F287311FF243B00159131 /* sound_coco3.h */, - DF7F287411FF243B00159131 /* sound_midi.cpp */, - DF7F287511FF243B00159131 /* sound_midi.h */, - DF7F287611FF243B00159131 /* sound_pcjr.cpp */, - DF7F287711FF243B00159131 /* sound_pcjr.h */, - DF7F287811FF243B00159131 /* sound_sarien.cpp */, - DF7F287911FF243B00159131 /* sound_sarien.h */, DF841FF70E7BA6A600F5680E /* agi.cpp */, DF841FF80E7BA6A600F5680E /* agi.h */, DF841FF90E7BA6A600F5680E /* checks.cpp */, @@ -5164,6 +5626,7 @@ DF841FFB0E7BA6A600F5680E /* console.h */, DF841FFC0E7BA6A600F5680E /* cycle.cpp */, DF841FFD0E7BA6A600F5680E /* detection.cpp */, + DF7F286F11FF243A00159131 /* detection_tables.h */, DF841FFE0E7BA6A600F5680E /* font.h */, DF841FFF0E7BA6A600F5680E /* global.cpp */, DF8420000E7BA6A600F5680E /* graphics.cpp */, @@ -5202,6 +5665,16 @@ DF8420220E7BA6A600F5680E /* saveload.cpp */, DF8420230E7BA6A600F5680E /* sound.cpp */, DF8420240E7BA6A600F5680E /* sound.h */, + DF7F287011FF243A00159131 /* sound_2gs.cpp */, + DF7F287111FF243A00159131 /* sound_2gs.h */, + DF7F287211FF243B00159131 /* sound_coco3.cpp */, + DF7F287311FF243B00159131 /* sound_coco3.h */, + DF7F287411FF243B00159131 /* sound_midi.cpp */, + DF7F287511FF243B00159131 /* sound_midi.h */, + DF7F287611FF243B00159131 /* sound_pcjr.cpp */, + DF7F287711FF243B00159131 /* sound_pcjr.h */, + DF7F287811FF243B00159131 /* sound_sarien.cpp */, + DF7F287911FF243B00159131 /* sound_sarien.h */, DF8420250E7BA6A600F5680E /* sprite.cpp */, DF8420260E7BA6A600F5680E /* sprite.h */, DF8420270E7BA6A600F5680E /* text.cpp */, @@ -5217,13 +5690,6 @@ DF84202D0E7BA6A600F5680E /* agos */ = { isa = PBXGroup; children = ( - DF6BF4D510529DE90069811F /* input_pn.cpp */, - DF6BF4D610529DE90069811F /* string_pn.cpp */, - DF6BF4D710529DE90069811F /* verb_pn.cpp */, - DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */, - DF093E5C0F63CAD4002D821E /* pn.cpp */, - DF093E5D0F63CAD4002D821E /* script_pn.cpp */, - DF093E5E0F63CAD4002D821E /* vga_pn.cpp */, DF84202E0E7BA6A600F5680E /* agos.cpp */, DF84202F0E7BA6A600F5680E /* agos.h */, DF8420300E7BA6A600F5680E /* animation.cpp */, @@ -5240,9 +5706,11 @@ DF84203B0E7BA6A600F5680E /* detection_tables.h */, DF84203C0E7BA6A600F5680E /* draw.cpp */, DF84203D0E7BA6A600F5680E /* event.cpp */, + DF6118AE0FE3A9EA0042AD3F /* feeble.cpp */, DF84203E0E7BA6A600F5680E /* gfx.cpp */, DF84203F0E7BA6A600F5680E /* icons.cpp */, DF8420400E7BA6A600F5680E /* input.cpp */, + DF6BF4D510529DE90069811F /* input_pn.cpp */, DF8420410E7BA6A600F5680E /* intern.h */, DF8420420E7BA6A600F5680E /* items.cpp */, DF8420430E7BA6A600F5680E /* menus.cpp */, @@ -5250,6 +5718,7 @@ DF8420450E7BA6A600F5680E /* midi.h */, DF8420460E7BA6A600F5680E /* midiparser_s1d.cpp */, DF8420480E7BA6A600F5680E /* oracle.cpp */, + DF093E5C0F63CAD4002D821E /* pn.cpp */, DF8420490E7BA6A600F5680E /* res.cpp */, DF84204A0E7BA6A600F5680E /* res_ami.cpp */, DF84204B0E7BA6A600F5680E /* res_snd.cpp */, @@ -5259,6 +5728,7 @@ DF84204F0E7BA6A600F5680E /* script_e1.cpp */, DF8420500E7BA6A600F5680E /* script_e2.cpp */, DF8420510E7BA6A600F5680E /* script_ff.cpp */, + DF093E5D0F63CAD4002D821E /* script_pn.cpp */, DF8420520E7BA6A600F5680E /* script_pp.cpp */, DF8420530E7BA6A600F5680E /* script_s1.cpp */, DF8420540E7BA6A600F5680E /* script_s2.cpp */, @@ -5266,12 +5736,15 @@ DF8420560E7BA6A600F5680E /* sound.cpp */, DF8420570E7BA6A600F5680E /* sound.h */, DF8420580E7BA6A600F5680E /* string.cpp */, + DF6BF4D610529DE90069811F /* string_pn.cpp */, DF8420590E7BA6A600F5680E /* subroutine.cpp */, DF84205A0E7BA6A600F5680E /* verb.cpp */, + DF6BF4D710529DE90069811F /* verb_pn.cpp */, DF84205B0E7BA6A600F5680E /* vga.cpp */, DF84205C0E7BA6A600F5680E /* vga.h */, DF84205D0E7BA6A600F5680E /* vga_e2.cpp */, DF84205E0E7BA6A600F5680E /* vga_ff.cpp */, + DF093E5E0F63CAD4002D821E /* vga_pn.cpp */, DF84205F0E7BA6A600F5680E /* vga_s1.cpp */, DF8420600E7BA6A600F5680E /* vga_s2.cpp */, DF8420610E7BA6A600F5680E /* vga_ww.cpp */, @@ -5284,8 +5757,6 @@ DF8420640E7BA6A600F5680E /* cine */ = { isa = PBXGroup; children = ( - DFAAAFF50F0112AD003E9390 /* saveload.cpp */, - DFAAAFF60F0112AD003E9390 /* saveload.h */, DF8420650E7BA6A600F5680E /* anim.cpp */, DF8420660E7BA6A600F5680E /* anim.h */, DF8420670E7BA6A600F5680E /* bg.cpp */, @@ -5311,6 +5782,8 @@ DF84207C0E7BA6A600F5680E /* prc.h */, DF84207D0E7BA6A600F5680E /* rel.cpp */, DF84207E0E7BA6A600F5680E /* rel.h */, + DFAAAFF50F0112AD003E9390 /* saveload.cpp */, + DFAAAFF60F0112AD003E9390 /* saveload.h */, DF84207F0E7BA6A600F5680E /* script.h */, DF8420800E7BA6A600F5680E /* script_fw.cpp */, DF8420810E7BA6A600F5680E /* script_os.cpp */, @@ -5329,12 +5802,6 @@ DF84208B0E7BA6A600F5680E /* cruise */ = { isa = PBXGroup; children = ( - DFE88C440F874A1100C555C5 /* sound.cpp */, - DFE88C450F874A1100C555C5 /* sound.h */, - DF2FFC700F4867910006E566 /* debugger.cpp */, - DF2FFC710F4867910006E566 /* debugger.h */, - DF2FFC720F4867910006E566 /* staticres.cpp */, - DF2FFC730F4867910006E566 /* staticres.h */, DF8420AB0E7BA6A600F5680E /* actor.cpp */, DF8420AC0E7BA6A600F5680E /* actor.h */, DF8420AE0E7BA6A600F5680E /* background.cpp */, @@ -5351,6 +5818,8 @@ DF8420BE0E7BA6A700F5680E /* ctp.h */, DF8420C00E7BA6A700F5680E /* dataLoader.cpp */, DF8420C10E7BA6A700F5680E /* dataLoader.h */, + DF2FFC700F4867910006E566 /* debugger.cpp */, + DF2FFC710F4867910006E566 /* debugger.h */, DF8420C30E7BA6A700F5680E /* decompiler.cpp */, DF8420C50E7BA6A700F5680E /* delphine-unpack.cpp */, DF8420C70E7BA6A700F5680E /* detection.cpp */, @@ -5380,8 +5849,12 @@ DF8420F00E7BA6A700F5680E /* saveload.h */, DF8420F20E7BA6A700F5680E /* script.cpp */, DF8420F30E7BA6A700F5680E /* script.h */, + DFE88C440F874A1100C555C5 /* sound.cpp */, + DFE88C450F874A1100C555C5 /* sound.h */, DF8420F50E7BA6A700F5680E /* stack.cpp */, DF8420F60E7BA6A700F5680E /* stack.h */, + DF2FFC720F4867910006E566 /* staticres.cpp */, + DF2FFC730F4867910006E566 /* staticres.h */, DF8420F90E7BA6A700F5680E /* various.cpp */, DF8420FA0E7BA6A700F5680E /* various.h */, DF8420FC0E7BA6A700F5680E /* vars.cpp */, @@ -5395,11 +5868,10 @@ DF8421040E7BA6A700F5680E /* drascula */ = { isa = PBXGroup; children = ( - DF7F28A311FF24C400159131 /* console.cpp */, - DF7F28A411FF24C400159131 /* console.h */, - DFCDC6F611662AAB00A7D2A0 /* resource.cpp */, DF8421050E7BA6A700F5680E /* actors.cpp */, DF8421060E7BA6A700F5680E /* animation.cpp */, + DF7F28A311FF24C400159131 /* console.cpp */, + DF7F28A411FF24C400159131 /* console.h */, DF8421070E7BA6A700F5680E /* converse.cpp */, DF8421080E7BA6A700F5680E /* detection.cpp */, DF8421090E7BA6A700F5680E /* drascula.cpp */, @@ -5408,6 +5880,7 @@ DF84210C0E7BA6A700F5680E /* interface.cpp */, DF84210E0E7BA6A700F5680E /* objects.cpp */, DF84210F0E7BA6A700F5680E /* palette.cpp */, + DFCDC6F611662AAB00A7D2A0 /* resource.cpp */, DF8421100E7BA6A700F5680E /* rooms.cpp */, DF8421110E7BA6A700F5680E /* saveload.cpp */, DF8421120E7BA6A700F5680E /* sound.cpp */, @@ -5419,35 +5892,20 @@ DF8421170E7BA6A700F5680E /* gob */ = { isa = PBXGroup; children = ( - DF90EAA310B0234300C8F93F /* draw_playtoons.cpp */, - DF6BF4E810529E6E0069811F /* init_v4.cpp */, - DF6BF4E910529E6E0069811F /* inter_playtoons.cpp */, - DF7585C3100CB66E00CC3324 /* expression.cpp */, - DF7585C4100CB66E00CC3324 /* expression.h */, - DF7585C5100CB66E00CC3324 /* hotspots.cpp */, - DF7585C6100CB66E00CC3324 /* hotspots.h */, - DF7585C7100CB66E00CC3324 /* init_v6.cpp */, - DF7585C8100CB66E00CC3324 /* resources.cpp */, - DF7585C9100CB66E00CC3324 /* resources.h */, - DF7585CA100CB66E00CC3324 /* script.cpp */, - DF7585CB100CB66E00CC3324 /* script.h */, - DF7585CC100CB66E00CC3324 /* totfile.cpp */, - DF7585CD100CB66E00CC3324 /* totfile.h */, - DF6118780FE3A9AA0042AD3F /* save */, - DF6118590FE3A9020042AD3F /* helper.h */, - DF09CC060FAC4E1900A5AFD7 /* demos */, - DF09CC0D0FAC4E1900A5AFD7 /* draw_fascin.cpp */, - DF09CC0F0FAC4E1900A5AFD7 /* inter_fascin.cpp */, DF84211B0E7BA6A700F5680E /* dataio.cpp */, DF84211C0E7BA6A700F5680E /* dataio.h */, + DF09CC060FAC4E1900A5AFD7 /* demos */, DF84211D0E7BA6A700F5680E /* detection.cpp */, + DF895C23124C25150077F6E8 /* detection_tables.h */, DF84211E0E7BA6A700F5680E /* draw.cpp */, DF84211F0E7BA6A700F5680E /* draw.h */, DF8421200E7BA6A700F5680E /* draw_bargon.cpp */, + DF09CC0D0FAC4E1900A5AFD7 /* draw_fascin.cpp */, + DF90EAA310B0234300C8F93F /* draw_playtoons.cpp */, DF8421210E7BA6A700F5680E /* draw_v1.cpp */, DF8421220E7BA6A700F5680E /* draw_v2.cpp */, - DF8421230E7BA6A700F5680E /* driver_vga.cpp */, - DF8421240E7BA6A700F5680E /* driver_vga.h */, + DF7585C3100CB66E00CC3324 /* expression.cpp */, + DF7585C4100CB66E00CC3324 /* expression.h */, DF8421250E7BA6A700F5680E /* game.cpp */, DF8421260E7BA6A700F5680E /* game.h */, DF8421290E7BA6A700F5680E /* global.cpp */, @@ -5460,14 +5918,22 @@ DF8421300E7BA6A700F5680E /* goblin_v2.cpp */, DF8421310E7BA6A700F5680E /* goblin_v3.cpp */, DF8421320E7BA6A700F5680E /* goblin_v4.cpp */, + DF6118590FE3A9020042AD3F /* helper.h */, + DF7585C5100CB66E00CC3324 /* hotspots.cpp */, + DF7585C6100CB66E00CC3324 /* hotspots.h */, DF8421330E7BA6A700F5680E /* init.cpp */, DF8421340E7BA6A700F5680E /* init.h */, + DF895C24124C25150077F6E8 /* init_fascin.cpp */, DF8421350E7BA6A700F5680E /* init_v1.cpp */, DF8421360E7BA6A700F5680E /* init_v2.cpp */, DF8421370E7BA6A700F5680E /* init_v3.cpp */, + DF6BF4E810529E6E0069811F /* init_v4.cpp */, + DF7585C7100CB66E00CC3324 /* init_v6.cpp */, DF8421380E7BA6A700F5680E /* inter.cpp */, DF8421390E7BA6A700F5680E /* inter.h */, DF84213A0E7BA6A700F5680E /* inter_bargon.cpp */, + DF09CC0F0FAC4E1900A5AFD7 /* inter_fascin.cpp */, + DF6BF4E910529E6E0069811F /* inter_playtoons.cpp */, DF84213B0E7BA6A700F5680E /* inter_v1.cpp */, DF84213C0E7BA6A700F5680E /* inter_v2.cpp */, DF84213D0E7BA6A700F5680E /* inter_v3.cpp */, @@ -5484,11 +5950,20 @@ DF84214A0E7BA6A700F5680E /* mult_v2.cpp */, DF84214C0E7BA6A700F5680E /* palanim.cpp */, DF84214D0E7BA6A700F5680E /* palanim.h */, + DF7585C8100CB66E00CC3324 /* resources.cpp */, + DF7585C9100CB66E00CC3324 /* resources.h */, + DF6118780FE3A9AA0042AD3F /* save */, DF8421570E7BA6A700F5680E /* scenery.cpp */, DF8421580E7BA6A700F5680E /* scenery.h */, DF8421590E7BA6A700F5680E /* scenery_v1.cpp */, DF84215A0E7BA6A700F5680E /* scenery_v2.cpp */, + DF7585CA100CB66E00CC3324 /* script.cpp */, + DF7585CB100CB66E00CC3324 /* script.h */, DF84215B0E7BA6A700F5680E /* sound */, + 8CD80C89126271A9001C6C87 /* surface.cpp */, + 8CD80C8A126271A9001C6C87 /* surface.h */, + DF7585CC100CB66E00CC3324 /* totfile.cpp */, + DF7585CD100CB66E00CC3324 /* totfile.h */, DF84216F0E7BA6A700F5680E /* util.cpp */, DF8421700E7BA6A700F5680E /* util.h */, DF8421710E7BA6A700F5680E /* variables.cpp */, @@ -5534,29 +6009,11 @@ DF8421A30E7BA6A800F5680E /* kyra */ = { isa = PBXGroup; children = ( - DF2EC3FD10E64C4300765801 /* animator_tim.cpp */, - DF6BF4E210529E260069811F /* sound_adlib.h */, - DF6BF4E310529E260069811F /* sound_amiga.cpp */, - DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */, - DF6118B40FE3AA280042AD3F /* sound_lol.cpp */, - DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */, - DF6118B60FE3AA280042AD3F /* text_lol.cpp */, - DF6118B70FE3AA280042AD3F /* text_lol.h */, - DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */, - DF573CBD0F5A85E100961A72 /* timer_lol.cpp */, - DF2FFC490F4863100006E566 /* scene_lol.cpp */, - DF2FFC2E0F48628A0006E566 /* gui_lol.cpp */, - DF2FFC2F0F48628A0006E566 /* gui_lol.h */, - DF2FFC300F48628A0006E566 /* items_lol.cpp */, - DF2FFC310F48628A0006E566 /* script_lol.cpp */, - DF2FFC320F48628A0006E566 /* sequences_lol.cpp */, - DF2FFC330F48628A0006E566 /* sound_midi.cpp */, - DF2FFC360F48628A0006E566 /* util.cpp */, - DF2FFC370F48628A0006E566 /* util.h */, DF8421A40E7BA6A800F5680E /* animator_hof.cpp */, DF8421A50E7BA6A800F5680E /* animator_lok.cpp */, DF8421A60E7BA6A800F5680E /* animator_lok.h */, DF8421A70E7BA6A800F5680E /* animator_mr.cpp */, + DF2EC3FD10E64C4300765801 /* animator_tim.cpp */, DF8421A90E7BA6A800F5680E /* animator_v2.cpp */, DF8421AB0E7BA6A800F5680E /* debugger.cpp */, DF8421AC0E7BA6A800F5680E /* debugger.h */, @@ -5567,12 +6024,15 @@ DF8421B10E7BA6A800F5680E /* gui_hof.h */, DF8421B20E7BA6A800F5680E /* gui_lok.cpp */, DF8421B30E7BA6A800F5680E /* gui_lok.h */, + DF2FFC2E0F48628A0006E566 /* gui_lol.cpp */, + DF2FFC2F0F48628A0006E566 /* gui_lol.h */, DF8421B40E7BA6A800F5680E /* gui_mr.cpp */, DF8421B50E7BA6A800F5680E /* gui_mr.h */, DF8421B70E7BA6A800F5680E /* gui_v2.cpp */, DF8421B80E7BA6A800F5680E /* gui_v2.h */, DF8421BA0E7BA6A800F5680E /* items_hof.cpp */, DF8421BB0E7BA6A800F5680E /* items_lok.cpp */, + DF2FFC300F48628A0006E566 /* items_lol.cpp */, DF8421BC0E7BA6A800F5680E /* items_mr.cpp */, DF8421BE0E7BA6A800F5680E /* items_v2.cpp */, DF8421C10E7BA6A800F5680E /* kyra_hof.cpp */, @@ -5594,9 +6054,11 @@ DF8421D30E7BA6A800F5680E /* saveload.cpp */, DF8421D40E7BA6A800F5680E /* saveload_hof.cpp */, DF8421D50E7BA6A800F5680E /* saveload_lok.cpp */, + DF6118B30FE3AA280042AD3F /* saveload_lol.cpp */, DF8421D60E7BA6A800F5680E /* saveload_mr.cpp */, DF8421DA0E7BA6A800F5680E /* scene_hof.cpp */, DF8421DB0E7BA6A800F5680E /* scene_lok.cpp */, + DF2FFC490F4863100006E566 /* scene_lol.cpp */, DF8421DC0E7BA6A800F5680E /* scene_mr.cpp */, DF8421DD0E7BA6A800F5680E /* scene_v1.cpp */, DF8421DE0E7BA6A800F5680E /* scene_v2.cpp */, @@ -5616,6 +6078,7 @@ DF8421EF0E7BA6A800F5680E /* script.h */, DF8421F00E7BA6A800F5680E /* script_hof.cpp */, DF8421F10E7BA6A800F5680E /* script_lok.cpp */, + DF2FFC310F48628A0006E566 /* script_lol.cpp */, DF8421F20E7BA6A800F5680E /* script_mr.cpp */, DF8421F30E7BA6A800F5680E /* script_tim.cpp */, DF8421F40E7BA6A800F5680E /* script_tim.h */, @@ -5625,29 +6088,41 @@ DF8421F90E7BA6A800F5680E /* seqplayer.h */, DF8421FA0E7BA6A800F5680E /* sequences_hof.cpp */, DF8421FB0E7BA6A800F5680E /* sequences_lok.cpp */, + DF2FFC320F48628A0006E566 /* sequences_lol.cpp */, DF8421FC0E7BA6A800F5680E /* sequences_mr.cpp */, DF8421FE0E7BA6A800F5680E /* sequences_v2.cpp */, DF8422000E7BA6A800F5680E /* sound.cpp */, DF8422010E7BA6A800F5680E /* sound.h */, DF8422020E7BA6A800F5680E /* sound_adlib.cpp */, + DF6BF4E210529E260069811F /* sound_adlib.h */, + DF6BF4E310529E260069811F /* sound_amiga.cpp */, DF8422030E7BA6A800F5680E /* sound_digital.cpp */, DF8422040E7BA6A800F5680E /* sound_lok.cpp */, + DF6118B40FE3AA280042AD3F /* sound_lol.cpp */, + DF2FFC330F48628A0006E566 /* sound_midi.cpp */, + DF6118B50FE3AA280042AD3F /* sound_pcspk.cpp */, DF8422050E7BA6A800F5680E /* sound_towns.cpp */, DF8422070E7BA6A800F5680E /* sprites.cpp */, DF8422080E7BA6A800F5680E /* sprites.h */, + DF89C2870F62D55C00D756B6 /* sprites_lol.cpp */, DF8422090E7BA6A800F5680E /* staticres.cpp */, DF84220A0E7BA6A800F5680E /* text.cpp */, DF84220B0E7BA6A800F5680E /* text.h */, DF84220C0E7BA6A800F5680E /* text_hof.cpp */, DF84220D0E7BA6A800F5680E /* text_hof.h */, DF84220E0E7BA6A800F5680E /* text_lok.cpp */, + DF6118B60FE3AA280042AD3F /* text_lol.cpp */, + DF6118B70FE3AA280042AD3F /* text_lol.h */, DF84220F0E7BA6A800F5680E /* text_mr.cpp */, DF8422100E7BA6A800F5680E /* text_mr.h */, DF8422140E7BA6A800F5680E /* timer.cpp */, DF8422150E7BA6A800F5680E /* timer.h */, DF8422160E7BA6A800F5680E /* timer_hof.cpp */, DF8422170E7BA6A800F5680E /* timer_lok.cpp */, + DF573CBD0F5A85E100961A72 /* timer_lol.cpp */, DF8422180E7BA6A800F5680E /* timer_mr.cpp */, + DF2FFC360F48628A0006E566 /* util.cpp */, + DF2FFC370F48628A0006E566 /* util.h */, DF84221C0E7BA6A800F5680E /* vqa.cpp */, DF84221D0E7BA6A800F5680E /* vqa.h */, DF84221E0E7BA6A800F5680E /* wsamovie.cpp */, @@ -5710,10 +6185,6 @@ DF84224E0E7BA6A800F5680E /* m4 */ = { isa = PBXGroup; children = ( - DF2EC3F610E64C0C00765801 /* dialogs.cpp */, - DF2EC3F710E64C0C00765801 /* dialogs.h */, - DF90EAAB10B0236F00C8F93F /* staticres.cpp */, - DF90EAAC10B0236F00C8F93F /* staticres.h */, DF84226E0E7BA6A800F5680E /* actor.cpp */, DF84226F0E7BA6A800F5680E /* actor.h */, DF8422710E7BA6A800F5680E /* animation.cpp */, @@ -5728,6 +6199,8 @@ DF84227E0E7BA6A900F5680E /* converse.cpp */, DF84227F0E7BA6A900F5680E /* converse.h */, DF8422810E7BA6A900F5680E /* detection.cpp */, + DF2EC3F610E64C0C00765801 /* dialogs.cpp */, + DF2EC3F710E64C0C00765801 /* dialogs.h */, DF8422830E7BA6A900F5680E /* events.cpp */, DF8422840E7BA6A900F5680E /* events.h */, DF8422860E7BA6A900F5680E /* font.cpp */, @@ -5744,12 +6217,22 @@ DF8422970E7BA6A900F5680E /* m4.h */, DF8422990E7BA6A900F5680E /* m4_menus.cpp */, DF84229A0E7BA6A900F5680E /* m4_menus.h */, + 8CB5A9B71253FD6800CB6BC7 /* m4_scene.cpp */, + 8CB5A9B81253FD6800CB6BC7 /* m4_scene.h */, DF84229C0E7BA6A900F5680E /* m4_views.cpp */, DF84229D0E7BA6A900F5680E /* m4_views.h */, DF84229F0E7BA6A900F5680E /* mads_anim.cpp */, DF8422A00E7BA6A900F5680E /* mads_anim.h */, + 8CB5A9B91253FD6800CB6BC7 /* mads_logic.cpp */, + 8CB5A9BA1253FD6800CB6BC7 /* mads_logic.h */, DF8422A20E7BA6A900F5680E /* mads_menus.cpp */, DF8422A30E7BA6A900F5680E /* mads_menus.h */, + 8CB5A9BB1253FD6800CB6BC7 /* mads_player.cpp */, + 8CB5A9BC1253FD6800CB6BC7 /* mads_player.h */, + 8CB5A9BD1253FD6800CB6BC7 /* mads_scene.cpp */, + 8CB5A9BE1253FD6800CB6BC7 /* mads_scene.h */, + 8CB5A9BF1253FD6900CB6BC7 /* mads_views.cpp */, + 8CB5A9C01253FD6900CB6BC7 /* mads_views.h */, DF8422A50E7BA6A900F5680E /* midi.cpp */, DF8422A60E7BA6A900F5680E /* midi.h */, DF8422A90E7BA6A900F5680E /* rails.cpp */, @@ -5767,6 +6250,8 @@ DF8422BA0E7BA6A900F5680E /* sound.h */, DF8422BC0E7BA6A900F5680E /* sprite.cpp */, DF8422BD0E7BA6A900F5680E /* sprite.h */, + DF90EAAB10B0236F00C8F93F /* staticres.cpp */, + DF90EAAC10B0236F00C8F93F /* staticres.h */, DF8422BF0E7BA6A900F5680E /* viewmgr.cpp */, DF8422C00E7BA6A900F5680E /* viewmgr.h */, DF8422C20E7BA6A900F5680E /* woodscript.cpp */, @@ -5812,10 +6297,6 @@ DF8422E60E7BA6A900F5680E /* parallaction */ = { isa = PBXGroup; children = ( - DF6118540FE3A8990042AD3F /* disk.cpp */, - DF5CEB260F75535000DEA624 /* sound_br.cpp */, - DF5CEB270F75535000DEA624 /* sound_ns.cpp */, - DF573CBA0F5A85B300961A72 /* exec.cpp */, DF8422E70E7BA6A900F5680E /* balloons.cpp */, DF8422E80E7BA6A900F5680E /* callables_br.cpp */, DF8422E90E7BA6A900F5680E /* callables_ns.cpp */, @@ -5823,9 +6304,11 @@ DF8422EB0E7BA6A900F5680E /* debug.h */, DF8422EC0E7BA6A900F5680E /* detection.cpp */, DF8422ED0E7BA6A900F5680E /* dialogue.cpp */, + DF6118540FE3A8990042AD3F /* disk.cpp */, DF8422EE0E7BA6A900F5680E /* disk.h */, DF8422EF0E7BA6A900F5680E /* disk_br.cpp */, DF8422F00E7BA6A900F5680E /* disk_ns.cpp */, + DF573CBA0F5A85B300961A72 /* exec.cpp */, DF8422F10E7BA6A900F5680E /* exec.h */, DF8422F20E7BA6A900F5680E /* exec_br.cpp */, DF8422F30E7BA6A900F5680E /* exec_ns.cpp */, @@ -5854,6 +6337,8 @@ DF84230B0E7BA6A900F5680E /* saveload.cpp */, DF84230C0E7BA6A900F5680E /* saveload.h */, DF84230E0E7BA6A900F5680E /* sound.h */, + DF5CEB260F75535000DEA624 /* sound_br.cpp */, + DF5CEB270F75535000DEA624 /* sound_ns.cpp */, DF84230F0E7BA6A900F5680E /* staticres.cpp */, DF8423100E7BA6A900F5680E /* walk.cpp */, DF8423110E7BA6A900F5680E /* walk.h */, @@ -5912,12 +6397,6 @@ DF84233E0E7BA6AA00F5680E /* saga */ = { isa = PBXGroup; children = ( - DF2FFC600F48672D0006E566 /* resource.cpp */, - DF2FFC610F48672D0006E566 /* resource.h */, - DF2FFC620F48672D0006E566 /* resource_hrs.cpp */, - DF2FFC630F48672D0006E566 /* resource_res.cpp */, - DF2FFC640F48672D0006E566 /* resource_rsc.cpp */, - DF2FFC650F48672D0006E566 /* sfuncs_ihnm.cpp */, DF84233F0E7BA6AA00F5680E /* actor.cpp */, DF8423400E7BA6AA00F5680E /* actor.h */, DF8423410E7BA6AA00F5680E /* actor_path.cpp */, @@ -5956,6 +6435,11 @@ DF8423660E7BA6AA00F5680E /* puzzle.h */, DF8423670E7BA6AA00F5680E /* render.cpp */, DF8423680E7BA6AA00F5680E /* render.h */, + DF2FFC600F48672D0006E566 /* resource.cpp */, + DF2FFC610F48672D0006E566 /* resource.h */, + DF2FFC620F48672D0006E566 /* resource_hrs.cpp */, + DF2FFC630F48672D0006E566 /* resource_res.cpp */, + DF2FFC640F48672D0006E566 /* resource_rsc.cpp */, DF84236B0E7BA6AA00F5680E /* saga.cpp */, DF84236C0E7BA6AA00F5680E /* saga.h */, DF84236D0E7BA6AA00F5680E /* saveload.cpp */, @@ -5964,6 +6448,7 @@ DF8423700E7BA6AA00F5680E /* script.cpp */, DF8423710E7BA6AA00F5680E /* script.h */, DF8423720E7BA6AA00F5680E /* sfuncs.cpp */, + DF2FFC650F48672D0006E566 /* sfuncs_ihnm.cpp */, DF8423730E7BA6AA00F5680E /* sndres.cpp */, DF8423740E7BA6AA00F5680E /* sndres.h */, DF8423750E7BA6AA00F5680E /* sound.cpp */, @@ -5978,23 +6463,6 @@ DF84237B0E7BA6AA00F5680E /* scumm */ = { isa = PBXGroup; children = ( - DF2EC4FD10E64D7C00765801 /* player_pce.cpp */, - DF2EC4FE10E64D7C00765801 /* player_pce.h */, - DF2EC4FF10E64D7C00765801 /* player_sid.cpp */, - DF2EC50010E64D7C00765801 /* player_sid.h */, - DF6BF4F110529EE40069811F /* player_v4a.cpp */, - DF6BF4F210529EE40069811F /* player_v4a.h */, - DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */, - DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */, - DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */, - DF09CC1D0FAC4E6200A5AFD7 /* scumm_v0.h */, - DF09CC1E0FAC4E6200A5AFD7 /* scumm_v2.h */, - DF09CC1F0FAC4E6200A5AFD7 /* scumm_v3.h */, - DF09CC200FAC4E6200A5AFD7 /* scumm_v4.h */, - DF09CC210FAC4E6200A5AFD7 /* scumm_v5.h */, - DF09CC220FAC4E6200A5AFD7 /* scumm_v6.h */, - DF09CC230FAC4E6200A5AFD7 /* scumm_v7.h */, - DF09CC240FAC4E6200A5AFD7 /* scumm_v8.h */, DF84237C0E7BA6AA00F5680E /* actor.cpp */, DF84237D0E7BA6AA00F5680E /* actor.h */, DF84237E0E7BA6AA00F5680E /* akos.cpp */, @@ -6025,6 +6493,7 @@ DF8423970E7BA6AA00F5680E /* file_nes.h */, DF8423980E7BA6AA00F5680E /* gfx.cpp */, DF8423990E7BA6AA00F5680E /* gfx.h */, + 8CD80C90126271BD001C6C87 /* gfx_towns.cpp */, DF84239B0E7BA6AA00F5680E /* he */, DF8423B50E7BA6AA00F5680E /* help.cpp */, DF8423B60E7BA6AA00F5680E /* help.h */, @@ -6032,7 +6501,6 @@ DF8423C20E7BA6AA00F5680E /* imuse_digi */, DF8423D00E7BA6AA00F5680E /* input.cpp */, DF8423D10E7BA6AA00F5680E /* insane */, - DF8423D90E7BA6AA00F5680E /* midiparser_eup.cpp */, DF8423DA0E7BA6AA00F5680E /* midiparser_ro.cpp */, DF8423DC0E7BA6AA00F5680E /* music.h */, DF8423DD0E7BA6AA00F5680E /* nut_renderer.cpp */, @@ -6044,14 +6512,23 @@ DF8423E30E7BA6AA00F5680E /* player_mod.h */, DF8423E40E7BA6AA00F5680E /* player_nes.cpp */, DF8423E50E7BA6AA00F5680E /* player_nes.h */, + DF2EC4FD10E64D7C00765801 /* player_pce.cpp */, + DF2EC4FE10E64D7C00765801 /* player_pce.h */, + DF2EC4FF10E64D7C00765801 /* player_sid.cpp */, + DF2EC50010E64D7C00765801 /* player_sid.h */, + DF895C01124C24680077F6E8 /* player_towns.cpp */, + DF895C02124C24680077F6E8 /* player_towns.h */, DF8423E60E7BA6AA00F5680E /* player_v1.cpp */, DF8423E70E7BA6AA00F5680E /* player_v1.h */, DF8423E80E7BA6AA00F5680E /* player_v2.cpp */, DF8423E90E7BA6AA00F5680E /* player_v2.h */, DF8423EA0E7BA6AA00F5680E /* player_v2a.cpp */, DF8423EB0E7BA6AA00F5680E /* player_v2a.h */, + DF6118C60FE3AABD0042AD3F /* player_v2cms.cpp */, DF8423EC0E7BA6AA00F5680E /* player_v3a.cpp */, DF8423ED0E7BA6AA00F5680E /* player_v3a.h */, + DF6BF4F110529EE40069811F /* player_v4a.cpp */, + DF6BF4F210529EE40069811F /* player_v4a.h */, DF8423EF0E7BA6AA00F5680E /* resource.cpp */, DF8423F00E7BA6AA00F5680E /* resource.h */, DF8423F10E7BA6AA00F5680E /* resource_v2.cpp */, @@ -6064,12 +6541,22 @@ DF8423F80E7BA6AA00F5680E /* script.h */, DF8423F90E7BA6AA00F5680E /* script_v0.cpp */, DF8423FA0E7BA6AA00F5680E /* script_v2.cpp */, + DF09CC260FAC4EAB00A5AFD7 /* script_v3.cpp */, + DF09CC270FAC4EAB00A5AFD7 /* script_v4.cpp */, DF8423FB0E7BA6AA00F5680E /* script_v5.cpp */, DF8423FC0E7BA6AA00F5680E /* script_v6.cpp */, DF8423FD0E7BA6AA00F5680E /* script_v8.cpp */, DF8423FE0E7BA6AA00F5680E /* scumm-md5.h */, DF8423FF0E7BA6AA00F5680E /* scumm.cpp */, DF8424000E7BA6AA00F5680E /* scumm.h */, + DF09CC1D0FAC4E6200A5AFD7 /* scumm_v0.h */, + DF09CC1E0FAC4E6200A5AFD7 /* scumm_v2.h */, + DF09CC1F0FAC4E6200A5AFD7 /* scumm_v3.h */, + DF09CC200FAC4E6200A5AFD7 /* scumm_v4.h */, + DF09CC210FAC4E6200A5AFD7 /* scumm_v5.h */, + DF09CC220FAC4E6200A5AFD7 /* scumm_v6.h */, + DF09CC230FAC4E6200A5AFD7 /* scumm_v7.h */, + DF09CC240FAC4E6200A5AFD7 /* scumm_v8.h */, DF8424010E7BA6AA00F5680E /* smush */, DF8424150E7BA6AB00F5680E /* sound.cpp */, DF8424160E7BA6AB00F5680E /* sound.h */, @@ -6192,7 +6679,6 @@ DF8424200E7BA6AB00F5680E /* sky */ = { isa = PBXGroup; children = ( - DFAAAFF80F0112C1003E9390 /* detection.cpp */, DF8424210E7BA6AB00F5680E /* autoroute.cpp */, DF8424220E7BA6AB00F5680E /* autoroute.h */, DF8424230E7BA6AB00F5680E /* compact.cpp */, @@ -6201,6 +6687,7 @@ DF8424260E7BA6AB00F5680E /* control.h */, DF8424270E7BA6AB00F5680E /* debug.cpp */, DF8424280E7BA6AB00F5680E /* debug.h */, + DFAAAFF80F0112C1003E9390 /* detection.cpp */, DF8424290E7BA6AB00F5680E /* disk.cpp */, DF84242A0E7BA6AB00F5680E /* disk.h */, DF84242B0E7BA6AB00F5680E /* grid.cpp */, @@ -6251,7 +6738,6 @@ DF84244E0E7BA6AB00F5680E /* sword1 */ = { isa = PBXGroup; children = ( - DFAAAFFB0F0112DF003E9390 /* detection.cpp */, DF84244F0E7BA6AB00F5680E /* animation.cpp */, DF8424500E7BA6AB00F5680E /* animation.h */, DF8424510E7BA6AB00F5680E /* collision.h */, @@ -6259,6 +6745,7 @@ DF8424530E7BA6AB00F5680E /* control.h */, DF8424560E7BA6AB00F5680E /* debug.cpp */, DF8424570E7BA6AB00F5680E /* debug.h */, + DFAAAFFB0F0112DF003E9390 /* detection.cpp */, DF8424580E7BA6AB00F5680E /* eventman.cpp */, DF8424590E7BA6AB00F5680E /* eventman.h */, DF84245A0E7BA6AB00F5680E /* logic.cpp */, @@ -6352,16 +6839,6 @@ DF8424AA0E7BA6AB00F5680E /* tinsel */ = { isa = PBXGroup; children = ( - DF2FFC1F0F4862520006E566 /* bmv.cpp */, - DF2FFC200F4862520006E566 /* dialogs.cpp */, - DF2FFC210F4862520006E566 /* dialogs.h */, - DF2FFC220F4862520006E566 /* drives.cpp */, - DF2FFC230F4862520006E566 /* drives.h */, - DF2FFC240F4862520006E566 /* mareels.h */, - DF2FFC250F4862520006E566 /* pdisplay.h */, - DF2FFC260F4862520006E566 /* play.h */, - DF2FFC270F4862520006E566 /* sysvar.cpp */, - DF2FFC280F4862520006E566 /* sysvar.h */, DF8424AB0E7BA6AB00F5680E /* actors.cpp */, DF8424AC0E7BA6AB00F5680E /* actors.h */, DF8424AD0E7BA6AB00F5680E /* anim.cpp */, @@ -6369,6 +6846,7 @@ DF8424AF0E7BA6AB00F5680E /* background.cpp */, DF8424B00E7BA6AB00F5680E /* background.h */, DF8424B10E7BA6AB00F5680E /* bg.cpp */, + DF2FFC1F0F4862520006E566 /* bmv.cpp */, DF8424B20E7BA6AB00F5680E /* cliprect.cpp */, DF8424B30E7BA6AB00F5680E /* cliprect.h */, DF8424B40E7BA6AB00F5680E /* config.cpp */, @@ -6379,6 +6857,10 @@ DF8424B90E7BA6AB00F5680E /* debugger.cpp */, DF8424BA0E7BA6AB00F5680E /* debugger.h */, DF8424BB0E7BA6AB00F5680E /* detection.cpp */, + DF2FFC200F4862520006E566 /* dialogs.cpp */, + DF2FFC210F4862520006E566 /* dialogs.h */, + DF2FFC220F4862520006E566 /* drives.cpp */, + DF2FFC230F4862520006E566 /* drives.h */, DF8424BC0E7BA6AB00F5680E /* dw.h */, DF8424BD0E7BA6AB00F5680E /* effect.cpp */, DF8424BE0E7BA6AB00F5680E /* events.cpp */, @@ -6395,6 +6877,7 @@ DF8424C90E7BA6AB00F5680E /* heapmem.cpp */, DF8424CA0E7BA6AB00F5680E /* heapmem.h */, DF8424CD0E7BA6AB00F5680E /* mareels.cpp */, + DF2FFC240F4862520006E566 /* mareels.h */, DF8424CF0E7BA6AB00F5680E /* move.cpp */, DF8424D00E7BA6AB00F5680E /* move.h */, DF8424D10E7BA6AB00F5680E /* multiobj.cpp */, @@ -6408,8 +6891,10 @@ DF8424D90E7BA6AB00F5680E /* pcode.cpp */, DF8424DA0E7BA6AB00F5680E /* pcode.h */, DF8424DB0E7BA6AB00F5680E /* pdisplay.cpp */, + DF2FFC250F4862520006E566 /* pdisplay.h */, DF8424DC0E7BA6AB00F5680E /* pid.h */, DF8424DD0E7BA6AB00F5680E /* play.cpp */, + DF2FFC260F4862520006E566 /* play.h */, DF8424DE0E7BA6AB00F5680E /* polygons.cpp */, DF8424DF0E7BA6AB00F5680E /* polygons.h */, DF8424E00E7BA6AB00F5680E /* rince.cpp */, @@ -6429,6 +6914,8 @@ DF8424EF0E7BA6AB00F5680E /* sound.h */, DF8424F00E7BA6AB00F5680E /* strres.cpp */, DF8424F10E7BA6AB00F5680E /* strres.h */, + DF2FFC270F4862520006E566 /* sysvar.cpp */, + DF2FFC280F4862520006E566 /* sysvar.h */, DF8424F20E7BA6AB00F5680E /* text.cpp */, DF8424F30E7BA6AB00F5680E /* text.h */, DF8424F40E7BA6AB00F5680E /* timers.cpp */, @@ -6462,16 +6949,44 @@ path = touche; sourceTree = ""; }; + DF895C0C124C24C00077F6E8 /* fmtowns_pc98 */ = { + isa = PBXGroup; + children = ( + DF895C0D124C24C00077F6E8 /* towns_audio.cpp */, + DF895C0E124C24C00077F6E8 /* towns_audio.h */, + DF895C0F124C24C00077F6E8 /* towns_euphony.cpp */, + DF895C10124C24C00077F6E8 /* towns_euphony.h */, + DF895C11124C24C00077F6E8 /* towns_pc98_driver.cpp */, + DF895C12124C24C00077F6E8 /* towns_pc98_driver.h */, + DF895C13124C24C00077F6E8 /* towns_pc98_fmsynth.cpp */, + DF895C14124C24C00077F6E8 /* towns_pc98_fmsynth.h */, + ); + path = fmtowns_pc98; + sourceTree = ""; + }; DF90EABF10B023F300C8F93F /* codecs */ = { isa = PBXGroup; children = ( DFB0579611B7549C0015AE65 /* cinepak.cpp */, DFB0579711B7549C0015AE65 /* cinepak.h */, + DF90EAC010B023F400C8F93F /* codec.h */, + DF895CAB124E58980077F6E8 /* indeo3.cpp */, + DF895CAC124E58980077F6E8 /* indeo3.h */, + DF895CAD124E58980077F6E8 /* mjpeg.cpp */, + DF895CAE124E58980077F6E8 /* mjpeg.h */, DFCDC6FC11662AD700A7D2A0 /* msrle.cpp */, DFCDC6FD11662AD700A7D2A0 /* msrle.h */, - DF90EAC010B023F400C8F93F /* codec.h */, DF90EAC110B023F400C8F93F /* msvideo1.cpp */, DF90EAC210B023F400C8F93F /* msvideo1.h */, + DF895CAF124E58980077F6E8 /* qdm2.cpp */, + DF895CB0124E58980077F6E8 /* qdm2.h */, + DF895CB1124E58980077F6E8 /* qdm2data.h */, + DF895CB2124E58980077F6E8 /* qtrle.cpp */, + DF895CB3124E58980077F6E8 /* qtrle.h */, + DF895CB4124E58980077F6E8 /* rpza.cpp */, + DF895CB5124E58980077F6E8 /* rpza.h */, + DF895CB6124E58980077F6E8 /* smc.cpp */, + DF895CB7124E58980077F6E8 /* smc.h */, ); path = codecs; sourceTree = ""; @@ -6493,27 +7008,27 @@ DFC830190F48AF18005EF03C /* sci */ = { isa = PBXGroup; children = ( - DFB0577D11B7541F0015AE65 /* resource_audio.cpp */, - DFB0577E11B7541F0015AE65 /* util.cpp */, - DFB0577F11B7541F0015AE65 /* util.h */, - DF45B175116628A5009B85CC /* graphics */, - DF45B1A5116628A5009B85CC /* parser */, - DF45B1AB116628A5009B85CC /* sound */, - DF45B1C5116628A5009B85CC /* video */, - DF2EC40310E64C8000765801 /* event.cpp */, - DF2EC40410E64C8000765801 /* event.h */, - DF90E9B410AEDA5300C8F93F /* detection_tables.h */, + DFAAD2390F50120E00C3A4E2 /* console.cpp */, + DFAAD23A0F50120E00C3A4E2 /* console.h */, DF6118420FE3A8250042AD3F /* debug.h */, DF6118430FE3A8250042AD3F /* decompressor.cpp */, DF6118440FE3A8250042AD3F /* decompressor.h */, + DFC8301A0F48AF18005EF03C /* detection.cpp */, + DF90E9B410AEDA5300C8F93F /* detection_tables.h */, + DFC8301B0F48AF18005EF03C /* engine */, + DF2EC40310E64C8000765801 /* event.cpp */, + DF2EC40410E64C8000765801 /* event.h */, + DF45B175116628A5009B85CC /* graphics */, + DF45B1A5116628A5009B85CC /* parser */, DF6118450FE3A8250042AD3F /* resource.cpp */, DF6118460FE3A8250042AD3F /* resource.h */, - DFAAD2390F50120E00C3A4E2 /* console.cpp */, - DFAAD23A0F50120E00C3A4E2 /* console.h */, - DFC8301A0F48AF18005EF03C /* detection.cpp */, - DFC8301B0F48AF18005EF03C /* engine */, + DFB0577D11B7541F0015AE65 /* resource_audio.cpp */, DFC830960F48AF18005EF03C /* sci.cpp */, DFC830970F48AF18005EF03C /* sci.h */, + DF45B1AB116628A5009B85CC /* sound */, + DFB0577E11B7541F0015AE65 /* util.cpp */, + DFB0577F11B7541F0015AE65 /* util.h */, + DF45B1C5116628A5009B85CC /* video */, ); path = sci; sourceTree = ""; @@ -6521,47 +7036,49 @@ DFC8301B0F48AF18005EF03C /* engine */ = { isa = PBXGroup; children = ( - DF7F286411FF23EF00159131 /* kvideo.cpp */, - DF7F286511FF23EF00159131 /* workarounds.cpp */, - DF7F286611FF23EF00159131 /* workarounds.h */, DFCDC6D5116629CE00A7D2A0 /* features.cpp */, DFCDC6D6116629CE00A7D2A0 /* features.h */, - DFCDC6D7116629CE00A7D2A0 /* kparse.cpp */, - DFCDC6D8116629CE00A7D2A0 /* selector.h */, - DF90E9BD10AEDA9B00C8F93F /* selector.cpp */, - DF7585F6100CB75800CC3324 /* static_selectors.cpp */, - DF6118380FE3A8080042AD3F /* kmisc.cpp */, - DF6118390FE3A8080042AD3F /* segment.cpp */, - DF61183A0FE3A8080042AD3F /* segment.h */, - DF61183B0FE3A8080042AD3F /* savegame.h */, - DF89C2A30F62D79E00D756B6 /* script.cpp */, - DF573BFE0F5A81EA00961A72 /* kernel.h */, - DF573BFF0F5A81EA00961A72 /* script.h */, - DF573C000F5A81EA00961A72 /* seg_manager.h */, - DF573C010F5A81EA00961A72 /* state.cpp */, - DF573C020F5A81EA00961A72 /* state.h */, - DF573C030F5A81EA00961A72 /* vm.h */, - DF573C040F5A81EA00961A72 /* vm_types.h */, DFC8301E0F48AF18005EF03C /* gc.cpp */, DFC8301F0F48AF18005EF03C /* gc.h */, DFC830230F48AF18005EF03C /* kernel.cpp */, + DF573BFE0F5A81EA00961A72 /* kernel.h */, + DF895C28124C25350077F6E8 /* kernel_tables.h */, DFC830260F48AF18005EF03C /* kevent.cpp */, DFC830270F48AF18005EF03C /* kfile.cpp */, DFC830280F48AF18005EF03C /* kgraphics.cpp */, DFC830290F48AF18005EF03C /* klists.cpp */, DFC8302A0F48AF18005EF03C /* kmath.cpp */, DFC8302B0F48AF18005EF03C /* kmenu.cpp */, + DF6118380FE3A8080042AD3F /* kmisc.cpp */, DFC8302C0F48AF18005EF03C /* kmovement.cpp */, + DFCDC6D7116629CE00A7D2A0 /* kparse.cpp */, DFC8302D0F48AF18005EF03C /* kpathing.cpp */, DFC8302E0F48AF18005EF03C /* kscripts.cpp */, DFC8302F0F48AF18005EF03C /* ksound.cpp */, DFC830300F48AF18005EF03C /* kstring.cpp */, + DF7F286411FF23EF00159131 /* kvideo.cpp */, DFC830310F48AF18005EF03C /* message.cpp */, DFC830320F48AF18005EF03C /* message.h */, DFC830360F48AF18005EF03C /* savegame.cpp */, + DF61183B0FE3A8080042AD3F /* savegame.h */, + DF89C2A30F62D79E00D756B6 /* script.cpp */, + DF573BFF0F5A81EA00961A72 /* script.h */, + DF895C29124C25350077F6E8 /* script_patches.cpp */, DFC830390F48AF18005EF03C /* scriptdebug.cpp */, DFC8303A0F48AF18005EF03C /* seg_manager.cpp */, + DF573C000F5A81EA00961A72 /* seg_manager.h */, + DF6118390FE3A8080042AD3F /* segment.cpp */, + DF61183A0FE3A8080042AD3F /* segment.h */, + DF90E9BD10AEDA9B00C8F93F /* selector.cpp */, + DFCDC6D8116629CE00A7D2A0 /* selector.h */, + DF573C010F5A81EA00961A72 /* state.cpp */, + DF573C020F5A81EA00961A72 /* state.h */, + DF7585F6100CB75800CC3324 /* static_selectors.cpp */, DFC8303C0F48AF18005EF03C /* vm.cpp */, + DF573C030F5A81EA00961A72 /* vm.h */, + DF573C040F5A81EA00961A72 /* vm_types.h */, + DF7F286511FF23EF00159131 /* workarounds.cpp */, + DF7F286611FF23EF00159131 /* workarounds.h */, ); path = engine; sourceTree = ""; @@ -6569,18 +7086,18 @@ DFD5184C0DF3420D00854012 /* scaler */ = { isa = PBXGroup; children = ( - DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */, DFD518AA0DF34BA600854012 /* 2xsai.cpp */, DFD518AB0DF34BA600854012 /* aspect.cpp */, DFD518AD0DF34BA600854012 /* hq2x.cpp */, DFD518B10DF34BA600854012 /* hq3x.cpp */, + DFD5189E0DF34AD700854012 /* intern.h */, DFD518B50DF34BA600854012 /* scale2x.cpp */, DFD518B60DF34BA600854012 /* scale2x.h */, DFD518B80DF34BA600854012 /* scale3x.cpp */, DFD518B90DF34BA600854012 /* scale3x.h */, DFD518A00DF34B2500854012 /* scalebit.cpp */, DFD518A10DF34B2500854012 /* scalebit.h */, - DFD5189E0DF34AD700854012 /* intern.h */, + DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */, ); path = scaler; sourceTree = ""; @@ -6765,46 +7282,23 @@ DFE473950D81F4E800B6D1FB /* common */ = { isa = PBXGroup; children = ( - DF7F289111FF247300159131 /* translation.cpp */, - DFB0577311B753DA0015AE65 /* debug-channels.h */, - DFB0577411B753DA0015AE65 /* rational.cpp */, - DFB0577511B753DA0015AE65 /* rational.h */, - DF9B9261118E46FE0069C19D /* error.cpp */, - DFEC5D0A1166C5CF00C90552 /* random.cpp */, - DFEC5D0B1166C5CF00C90552 /* random.h */, - DFEC5D0C1166C5CF00C90552 /* str-array.h */, - DFEC5D0D1166C5CF00C90552 /* tokenizer.cpp */, - DFEC5D0E1166C5CF00C90552 /* tokenizer.h */, - DFEC5D0F1166C5CF00C90552 /* types.h */, - DFCDC70911662B6B00A7D2A0 /* macresman.cpp */, - DFCDC70A11662B6B00A7D2A0 /* macresman.h */, - DF2EC50910E64DB300765801 /* textconsole.cpp */, - DF2EC50A10E64DB300765801 /* textconsole.h */, - DF6BF4F710529F140069811F /* EventDispatcher.cpp */, - DF6BF4F810529F140069811F /* EventRecorder.cpp */, - DF6BF4F910529F140069811F /* EventRecorder.h */, - DF6BF4FA10529F140069811F /* list_intern.h */, - DF6BF4FB10529F140069811F /* serializer.h */, - DF2FFBD10F485DFB0006E566 /* debug.cpp */, - DF2FFBD20F485DFB0006E566 /* debug.h */, - DF7E8C0F0ED5FCC2001CB19F /* xmlparser.cpp */, - DF7E8C100ED5FCC2001CB19F /* xmlparser.h */, + DFE473980D81F4E800B6D1FB /* algorithm.h */, DF842A400E7BBBB400F5680E /* archive.cpp */, DF842A410E7BBBB400F5680E /* archive.h */, - DF842A430E7BBBB400F5680E /* ptr.h */, - DF842A440E7BBBB400F5680E /* queue.h */, - DF842A450E7BBBB400F5680E /* unarj.cpp */, - DF842A460E7BBBB400F5680E /* unarj.h */, - DFD511460DF3383500854012 /* memorypool.cpp */, - DFD511470DF3383500854012 /* memorypool.h */, - DFE473980D81F4E800B6D1FB /* algorithm.h */, DFE473990D81F4E800B6D1FB /* array.h */, DFE4739A0D81F4E800B6D1FB /* config-file.cpp */, DFE4739B0D81F4E800B6D1FB /* config-file.h */, DFE4739C0D81F4E800B6D1FB /* config-manager.cpp */, DFE4739D0D81F4E800B6D1FB /* config-manager.h */, + DFB0577311B753DA0015AE65 /* debug-channels.h */, + DF2FFBD10F485DFB0006E566 /* debug.cpp */, + DF2FFBD20F485DFB0006E566 /* debug.h */, DFE4739E0D81F4E800B6D1FB /* endian.h */, + DF9B9261118E46FE0069C19D /* error.cpp */, DFE4739F0D81F4E800B6D1FB /* error.h */, + DF6BF4F710529F140069811F /* EventDispatcher.cpp */, + DF6BF4F810529F140069811F /* EventRecorder.cpp */, + DF6BF4F910529F140069811F /* EventRecorder.h */, DFE473A00D81F4E800B6D1FB /* events.h */, DFE473A10D81F4E800B6D1FB /* file.cpp */, DFE473A20D81F4E800B6D1FB /* file.h */, @@ -6818,29 +7312,52 @@ DFE473AA0D81F4E800B6D1FB /* iff_container.h */, DFE473AB0D81F4E800B6D1FB /* keyboard.h */, DFE473AC0D81F4E800B6D1FB /* list.h */, + DF6BF4FA10529F140069811F /* list_intern.h */, + DFCDC70911662B6B00A7D2A0 /* macresman.cpp */, + DFCDC70A11662B6B00A7D2A0 /* macresman.h */, DFE473AD0D81F4E800B6D1FB /* md5.cpp */, DFE473AE0D81F4E800B6D1FB /* md5.h */, + DFD511460DF3383500854012 /* memorypool.cpp */, + DFD511470DF3383500854012 /* memorypool.h */, DFE473B00D81F4E800B6D1FB /* mutex.cpp */, DFE473B10D81F4E800B6D1FB /* mutex.h */, DFE473B20D81F4E800B6D1FB /* noncopyable.h */, DFE473B30D81F4E800B6D1FB /* pack-end.h */, DFE473B40D81F4E800B6D1FB /* pack-start.h */, + DF842A430E7BBBB400F5680E /* ptr.h */, + DF842A440E7BBBB400F5680E /* queue.h */, + DFEC5D0A1166C5CF00C90552 /* random.cpp */, + DFEC5D0B1166C5CF00C90552 /* random.h */, + DFB0577411B753DA0015AE65 /* rational.cpp */, + DFB0577511B753DA0015AE65 /* rational.h */, DFE473B50D81F4E800B6D1FB /* rect.h */, DFE473B60D81F4E800B6D1FB /* savefile.h */, DFE473B70D81F4E800B6D1FB /* scummsys.h */, + DF6BF4FB10529F140069811F /* serializer.h */, DFE473B80D81F4E800B6D1FB /* singleton.h */, DFE473B90D81F4E800B6D1FB /* stack.h */, + DFEC5D0C1166C5CF00C90552 /* str-array.h */, DFE473BA0D81F4E800B6D1FB /* str.cpp */, DFE473BB0D81F4E800B6D1FB /* str.h */, DFE473BC0D81F4E800B6D1FB /* stream.cpp */, DFE473BD0D81F4E800B6D1FB /* stream.h */, DFE473BE0D81F4E800B6D1FB /* system.cpp */, DFE473BF0D81F4E800B6D1FB /* system.h */, + DF2EC50910E64DB300765801 /* textconsole.cpp */, + DF2EC50A10E64DB300765801 /* textconsole.h */, DFE473C00D81F4E800B6D1FB /* timer.h */, + DFEC5D0D1166C5CF00C90552 /* tokenizer.cpp */, + DFEC5D0E1166C5CF00C90552 /* tokenizer.h */, + DF7F289111FF247300159131 /* translation.cpp */, + DFEC5D0F1166C5CF00C90552 /* types.h */, + DF842A450E7BBBB400F5680E /* unarj.cpp */, + DF842A460E7BBBB400F5680E /* unarj.h */, DFE473C10D81F4E800B6D1FB /* unzip.cpp */, DFE473C20D81F4E800B6D1FB /* unzip.h */, DFE473C30D81F4E800B6D1FB /* util.cpp */, DFE473C40D81F4E800B6D1FB /* util.h */, + DF7E8C0F0ED5FCC2001CB19F /* xmlparser.cpp */, + DF7E8C100ED5FCC2001CB19F /* xmlparser.h */, DFE473C50D81F4E800B6D1FB /* zlib.cpp */, DFE473C60D81F4E800B6D1FB /* zlib.h */, ); @@ -6851,30 +7368,13 @@ DFE477520D81F4E900B6D1FB /* graphics */ = { isa = PBXGroup; children = ( - DFB0578F11B7547D0015AE65 /* pict.cpp */, - DFB0579011B7547D0015AE65 /* pict.h */, + DFE477530D81F4E900B6D1FB /* colormasks.h */, DF6BF4C010529DA50069811F /* conversion.cpp */, DF6BF4C110529DA50069811F /* conversion.h */, - DF6BF4C210529DA50069811F /* jpeg.cpp */, - DF6BF4C310529DA50069811F /* jpeg.h */, - DF7585EA100CB6EA00CC3324 /* sjis.cpp */, - DF7585EB100CB6EA00CC3324 /* sjis.h */, - DF2FFB940F485D950006E566 /* video */, - DF2FFB900F485D890006E566 /* dither.cpp */, - DF2FFB910F485D890006E566 /* dither.h */, - DF2FFB920F485D890006E566 /* pixelformat.h */, - DF7E8C050ED5FCAF001CB19F /* thumbnail.cpp */, - DF7E8C060ED5FCAF001CB19F /* thumbnail.h */, - DF7E8C070ED5FCAF001CB19F /* VectorRenderer.cpp */, - DF7E8C080ED5FCAF001CB19F /* VectorRenderer.h */, - DF7E8C090ED5FCAF001CB19F /* VectorRendererSpec.cpp */, - DF7E8C0A0ED5FCAF001CB19F /* VectorRendererSpec.h */, - DFD5184C0DF3420D00854012 /* scaler */, - DFD5183B0DF3411800854012 /* scaler.cpp */, - DFD5183C0DF3411800854012 /* scaler.h */, - DFE477530D81F4E900B6D1FB /* colormasks.h */, DFE477540D81F4E900B6D1FB /* cursorman.cpp */, DFE477550D81F4E900B6D1FB /* cursorman.h */, + DF2FFB900F485D890006E566 /* dither.cpp */, + DF2FFB910F485D890006E566 /* dither.h */, DFE477580D81F4E900B6D1FB /* font.cpp */, DFE477590D81F4E900B6D1FB /* font.h */, DFE4775A0D81F4E900B6D1FB /* fontman.cpp */, @@ -6884,10 +7384,27 @@ DFE477620D81F4E900B6D1FB /* iff.h */, DFE477630D81F4E900B6D1FB /* imagedec.cpp */, DFE477640D81F4E900B6D1FB /* imagedec.h */, + DF6BF4C210529DA50069811F /* jpeg.cpp */, + DF6BF4C310529DA50069811F /* jpeg.h */, + DFB0578F11B7547D0015AE65 /* pict.cpp */, + DFB0579011B7547D0015AE65 /* pict.h */, + DF2FFB920F485D890006E566 /* pixelformat.h */, DFE4776A0D81F4E900B6D1FB /* primitives.cpp */, DFE4776B0D81F4E900B6D1FB /* primitives.h */, + DFD5184C0DF3420D00854012 /* scaler */, + DFD5183B0DF3411800854012 /* scaler.cpp */, + DFD5183C0DF3411800854012 /* scaler.h */, + DF7585EA100CB6EA00CC3324 /* sjis.cpp */, + DF7585EB100CB6EA00CC3324 /* sjis.h */, DFE477860D81F4E900B6D1FB /* surface.cpp */, DFE477870D81F4E900B6D1FB /* surface.h */, + DF7E8C050ED5FCAF001CB19F /* thumbnail.cpp */, + DF7E8C060ED5FCAF001CB19F /* thumbnail.h */, + DF7E8C070ED5FCAF001CB19F /* VectorRenderer.cpp */, + DF7E8C080ED5FCAF001CB19F /* VectorRenderer.h */, + DF7E8C090ED5FCAF001CB19F /* VectorRendererSpec.cpp */, + DF7E8C0A0ED5FCAF001CB19F /* VectorRendererSpec.h */, + DF2FFB940F485D950006E566 /* video */, ); name = graphics; path = ../../graphics; @@ -6907,29 +7424,13 @@ DFE477880D81F4E900B6D1FB /* gui */ = { isa = PBXGroup; children = ( - DF7F288911FF244F00159131 /* Tooltip.cpp */, - DF7F288A11FF244F00159131 /* Tooltip.h */, - DF9B9246118E46730069C19D /* error.cpp */, - DF9B9247118E46730069C19D /* error.h */, - DF2EC3E410E6490800765801 /* browser_osx.mm */, - DF2FFBD50F485E360006E566 /* GuiManager.cpp */, - DF2FFBD60F485E360006E566 /* GuiManager.h */, - DF7E8BF00ED5FC77001CB19F /* saveload.cpp */, - DF7E8BF10ED5FC77001CB19F /* saveload.h */, - DF7E8BF40ED5FC77001CB19F /* ThemeEngine.cpp */, - DF7E8BF50ED5FC77001CB19F /* ThemeEngine.h */, - DF7E8BF60ED5FC77001CB19F /* ThemeEval.cpp */, - DF7E8BF70ED5FC77001CB19F /* ThemeEval.h */, - DF7E8BF80ED5FC77001CB19F /* ThemeLayout.cpp */, - DF7E8BF90ED5FC77001CB19F /* ThemeLayout.h */, - DF7E8BFA0ED5FC77001CB19F /* ThemeParser.cpp */, - DF7E8BFB0ED5FC77001CB19F /* ThemeParser.h */, DFE477890D81F4E900B6D1FB /* about.cpp */, DFE4778A0D81F4E900B6D1FB /* about.h */, DFE4778B0D81F4E900B6D1FB /* Actions.cpp */, DFE4778C0D81F4E900B6D1FB /* Actions.h */, DFE4778D0D81F4E900B6D1FB /* browser.cpp */, DFE4778E0D81F4E900B6D1FB /* browser.h */, + DF2EC3E410E6490800765801 /* browser_osx.mm */, DFE4778F0D81F4E900B6D1FB /* chooser.cpp */, DFE477900D81F4E900B6D1FB /* chooser.h */, DFE477910D81F4E900B6D1FB /* console.cpp */, @@ -6943,6 +7444,10 @@ DFE477990D81F4E900B6D1FB /* editable.h */, DFE4779A0D81F4E900B6D1FB /* EditTextWidget.cpp */, DFE4779B0D81F4E900B6D1FB /* EditTextWidget.h */, + DF9B9246118E46730069C19D /* error.cpp */, + DF9B9247118E46730069C19D /* error.h */, + DF2FFBD50F485E360006E566 /* GuiManager.cpp */, + DF2FFBD60F485E360006E566 /* GuiManager.h */, DFE4779E0D81F4E900B6D1FB /* Key.cpp */, DFE4779F0D81F4E900B6D1FB /* Key.h */, DFE477A20D81F4E900B6D1FB /* launcher.cpp */, @@ -6959,13 +7464,25 @@ DFE477B00D81F4E900B6D1FB /* options.h */, DFE477B10D81F4E900B6D1FB /* PopUpWidget.cpp */, DFE477B20D81F4E900B6D1FB /* PopUpWidget.h */, + DF7E8BF00ED5FC77001CB19F /* saveload.cpp */, + DF7E8BF10ED5FC77001CB19F /* saveload.h */, DFE477B30D81F4E900B6D1FB /* ScrollBarWidget.cpp */, DFE477B40D81F4E900B6D1FB /* ScrollBarWidget.h */, DFE477B50D81F4E900B6D1FB /* TabWidget.cpp */, DFE477B60D81F4E900B6D1FB /* TabWidget.h */, DFE477BA0D81F4E900B6D1FB /* themebrowser.cpp */, DFE477BB0D81F4E900B6D1FB /* themebrowser.h */, + DF7E8BF40ED5FC77001CB19F /* ThemeEngine.cpp */, + DF7E8BF50ED5FC77001CB19F /* ThemeEngine.h */, + DF7E8BF60ED5FC77001CB19F /* ThemeEval.cpp */, + DF7E8BF70ED5FC77001CB19F /* ThemeEval.h */, + DF7E8BF80ED5FC77001CB19F /* ThemeLayout.cpp */, + DF7E8BF90ED5FC77001CB19F /* ThemeLayout.h */, + DF7E8BFA0ED5FC77001CB19F /* ThemeParser.cpp */, + DF7E8BFB0ED5FC77001CB19F /* ThemeParser.h */, DFE477C00D81F4E900B6D1FB /* themes */, + DF7F288911FF244F00159131 /* Tooltip.cpp */, + DF7F288A11FF244F00159131 /* Tooltip.h */, DFE477C40D81F4E900B6D1FB /* widget.cpp */, DFE477C50D81F4E900B6D1FB /* widget.h */, ); @@ -6985,15 +7502,11 @@ DFE477C60D81F4E900B6D1FB /* sound */ = { isa = PBXGroup; children = ( - DF45B0EB116627D9009B85CC /* decoders */, - DF89C2B80F62D91000D756B6 /* timestamp.cpp */, - DF89C2B90F62D91000D756B6 /* timestamp.h */, - DF842A6F0E7BBDB200F5680E /* musicplugin.cpp */, - DF842A700E7BBDB200F5680E /* musicplugin.h */, DFE477CB0D81F4E900B6D1FB /* audiocd.cpp */, DFE477CC0D81F4E900B6D1FB /* audiocd.h */, DFE477CD0D81F4E900B6D1FB /* audiostream.cpp */, DFE477CE0D81F4E900B6D1FB /* audiostream.h */, + DF45B0EB116627D9009B85CC /* decoders */, DFE477D10D81F4E900B6D1FB /* fmopl.cpp */, DFE477D20D81F4E900B6D1FB /* fmopl.h */, DFE477D50D81F4E900B6D1FB /* mididrv.cpp */, @@ -7007,10 +7520,14 @@ DFE477DD0D81F4E900B6D1FB /* mods */, DFE477ED0D81F4E900B6D1FB /* mpu401.cpp */, DFE477EE0D81F4E900B6D1FB /* mpu401.h */, + DF842A6F0E7BBDB200F5680E /* musicplugin.cpp */, + DF842A700E7BBDB200F5680E /* musicplugin.h */, DFE477EF0D81F4E900B6D1FB /* null.cpp */, DFE477F00D81F4E900B6D1FB /* rate.cpp */, DFE477F10D81F4E900B6D1FB /* rate.h */, DFE477F60D81F4E900B6D1FB /* softsynth */, + DF89C2B80F62D91000D756B6 /* timestamp.cpp */, + DF89C2B90F62D91000D756B6 /* timestamp.h */, ); name = sound; path = ../../sound; @@ -7019,12 +7536,10 @@ DFE477DD0D81F4E900B6D1FB /* mods */ = { isa = PBXGroup; children = ( - DF6BF50210529F540069811F /* maxtrax.cpp */, - DF6BF50310529F540069811F /* maxtrax.h */, - DF6BF50410529F540069811F /* tfmx.cpp */, - DF6BF50510529F540069811F /* tfmx.h */, DFE477DE0D81F4E900B6D1FB /* infogrames.cpp */, DFE477DF0D81F4E900B6D1FB /* infogrames.h */, + DF6BF50210529F540069811F /* maxtrax.cpp */, + DF6BF50310529F540069811F /* maxtrax.h */, DFE477E00D81F4E900B6D1FB /* module.cpp */, DFE477E10D81F4E900B6D1FB /* module.h */, DFE477E20D81F4E900B6D1FB /* paula.cpp */, @@ -7035,6 +7550,8 @@ DFE477E70D81F4E900B6D1FB /* rjp1.h */, DFE477E80D81F4E900B6D1FB /* soundfx.cpp */, DFE477E90D81F4E900B6D1FB /* soundfx.h */, + DF6BF50410529F540069811F /* tfmx.cpp */, + DF6BF50510529F540069811F /* tfmx.h */, ); path = mods; sourceTree = ""; @@ -7042,15 +7559,19 @@ DFE477F60D81F4E900B6D1FB /* softsynth */ = { isa = PBXGroup; children = ( - DF2EC51710E64EE600765801 /* wave6581.cpp */, - DF2EC51010E64E3100765801 /* sid.cpp */, - DF2EC51110E64E3100765801 /* sid.h */, - DFF958A80FB222F300A3EC78 /* opl */, DFE477F70D81F4E900B6D1FB /* adlib.cpp */, + DF895C08124C24B50077F6E8 /* appleiigs.cpp */, + DF0E303F1252C6090082D593 /* cms.cpp */, + DF0E30401252C6090082D593 /* cms.h */, DFE477F80D81F4E900B6D1FB /* emumidi.h */, DFE477F90D81F4E900B6D1FB /* fluidsynth.cpp */, + DF895C0C124C24C00077F6E8 /* fmtowns_pc98 */, + DFF958A80FB222F300A3EC78 /* opl */, DFE478210D81F4E900B6D1FB /* pcspk.cpp */, DFE478220D81F4E900B6D1FB /* pcspk.h */, + DF2EC51010E64E3100765801 /* sid.cpp */, + DF2EC51110E64E3100765801 /* sid.h */, + DF2EC51710E64EE600765801 /* wave6581.cpp */, DFE478230D81F4E900B6D1FB /* ym2612.cpp */, DFE478240D81F4E900B6D1FB /* ym2612.h */, ); @@ -7062,10 +7583,10 @@ children = ( DFEC5D3D1166C6B400C90552 /* dbopl.cpp */, DFEC5D3E1166C6B400C90552 /* dbopl.h */, - DF6118CF0FE3AB560042AD3F /* mame.cpp */, - DF6118D00FE3AB560042AD3F /* mame.h */, DFF958A90FB222F300A3EC78 /* dosbox.cpp */, DFF958AA0FB222F300A3EC78 /* dosbox.h */, + DF6118CF0FE3AB560042AD3F /* mame.cpp */, + DF6118D00FE3AB560042AD3F /* mame.h */, ); path = opl; sourceTree = ""; @@ -7134,7 +7655,14 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "scummvm" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; @@ -7159,6 +7687,13 @@ DFE47C8B0D81F86900B6D1FB /* sky.cpt in Resources */, DF2FFD2B0F48717F0006E566 /* Default.png in Resources */, DF2FFD2C0F48717F0006E566 /* icon.png in Resources */, + DF895C34124C26660077F6E8 /* icon-72.png in Resources */, + DF895C41124C271F0077F6E8 /* icon4.png in Resources */, + 8CB5A9E11253FDF500CB6BC7 /* drascula.dat in Resources */, + 8CB5A9E21253FDF500CB6BC7 /* hugo.dat in Resources */, + 8CB5A9E31253FDF500CB6BC7 /* m4.dat in Resources */, + 8CB5A9E41253FDF500CB6BC7 /* teenagent.dat in Resources */, + 8CD1ED8A1262030100FA198C /* toon.dat in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7173,6 +7708,13 @@ DF093E7C0F63CB26002D821E /* queen.tbl in Resources */, DF093E7D0F63CB26002D821E /* sky.cpt in Resources */, DF0944B10F6430ED002D821E /* scummvm.icns in Resources */, + DF895C35124C26660077F6E8 /* icon-72.png in Resources */, + DF895C42124C271F0077F6E8 /* icon4.png in Resources */, + 8CB5A9DD1253FDF500CB6BC7 /* drascula.dat in Resources */, + 8CB5A9DE1253FDF500CB6BC7 /* hugo.dat in Resources */, + 8CB5A9DF1253FDF500CB6BC7 /* m4.dat in Resources */, + 8CB5A9E01253FDF500CB6BC7 /* teenagent.dat in Resources */, + 8CD1ED891262030100FA198C /* toon.dat in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7188,6 +7730,13 @@ DFF959130FB22D5700A3EC78 /* sky.cpt in Resources */, DFF959140FB22D5700A3EC78 /* Default.png in Resources */, DFF959150FB22D5700A3EC78 /* icon.png in Resources */, + DF895C36124C26660077F6E8 /* icon-72.png in Resources */, + DF895C43124C271F0077F6E8 /* icon4.png in Resources */, + 8CB5A9D91253FDF500CB6BC7 /* drascula.dat in Resources */, + 8CB5A9DA1253FDF500CB6BC7 /* hugo.dat in Resources */, + 8CB5A9DB1253FDF500CB6BC7 /* m4.dat in Resources */, + 8CB5A9DC1253FDF500CB6BC7 /* teenagent.dat in Resources */, + 8CD1ED881262030100FA198C /* toon.dat in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -7432,7 +7981,6 @@ DF8425E00E7BA6AC00F5680E /* draw_bargon.cpp in Sources */, DF8425E10E7BA6AC00F5680E /* draw_v1.cpp in Sources */, DF8425E20E7BA6AC00F5680E /* draw_v2.cpp in Sources */, - DF8425E30E7BA6AC00F5680E /* driver_vga.cpp in Sources */, DF8425E40E7BA6AC00F5680E /* game.cpp in Sources */, DF8425E70E7BA6AC00F5680E /* global.cpp in Sources */, DF8425E80E7BA6AC00F5680E /* gob.cpp in Sources */, @@ -7744,7 +8292,6 @@ DF8427AD0E7BA6AC00F5680E /* insane_enemy.cpp in Sources */, DF8427AE0E7BA6AC00F5680E /* insane_iact.cpp in Sources */, DF8427AF0E7BA6AC00F5680E /* insane_scenes.cpp in Sources */, - DF8427B00E7BA6AC00F5680E /* midiparser_eup.cpp in Sources */, DF8427B10E7BA6AC00F5680E /* midiparser_ro.cpp in Sources */, DF8427B30E7BA6AC00F5680E /* nut_renderer.cpp in Sources */, DF8427B40E7BA6AC00F5680E /* object.cpp in Sources */, @@ -8016,8 +8563,6 @@ DF61184C0FE3A8250042AD3F /* decompressor.cpp in Sources */, DF61184D0FE3A8250042AD3F /* resource.cpp in Sources */, DF6118560FE3A8990042AD3F /* disk.cpp in Sources */, - DF61186B0FE3A9410042AD3F /* coktelvideo.cpp in Sources */, - DF61186C0FE3A9410042AD3F /* indeo3.cpp in Sources */, DF61186D0FE3A9410042AD3F /* dxa_decoder.cpp in Sources */, DF61186E0FE3A9410042AD3F /* flic_decoder.cpp in Sources */, DF61186F0FE3A9410042AD3F /* smk_decoder.cpp in Sources */, @@ -8099,12 +8644,10 @@ DF45B1D4116628A5009B85CC /* menu.cpp in Sources */, DF45B1D5116628A5009B85CC /* paint.cpp in Sources */, DF45B1D6116628A5009B85CC /* paint16.cpp in Sources */, - DF45B1D7116628A5009B85CC /* paint32.cpp in Sources */, DF45B1D8116628A5009B85CC /* palette.cpp in Sources */, DF45B1D9116628A5009B85CC /* picture.cpp in Sources */, DF45B1DA116628A5009B85CC /* portrait.cpp in Sources */, DF45B1DB116628A5009B85CC /* ports.cpp in Sources */, - DF45B1DC116628A5009B85CC /* robot.cpp in Sources */, DF45B1DD116628A5009B85CC /* screen.cpp in Sources */, DF45B1DE116628A5009B85CC /* text16.cpp in Sources */, DF45B1DF116628A5009B85CC /* transitions.cpp in Sources */, @@ -8121,7 +8664,6 @@ DF45B1F0116628A5009B85CC /* music.cpp in Sources */, DF45B1F1116628A5009B85CC /* soundcmd.cpp in Sources */, DF45B1F2116628A5009B85CC /* seq_decoder.cpp in Sources */, - DF45B1F3116628A5009B85CC /* vmd_decoder.cpp in Sources */, DFCDC6D9116629CE00A7D2A0 /* features.cpp in Sources */, DFCDC6DA116629CE00A7D2A0 /* kparse.cpp in Sources */, DFCDC6F711662AAB00A7D2A0 /* resource.cpp in Sources */, @@ -8144,7 +8686,6 @@ DFB0578B11B754570015AE65 /* maciconbar.cpp in Sources */, DFB0579211B7547D0015AE65 /* pict.cpp in Sources */, DFB0579911B7549C0015AE65 /* cinepak.cpp in Sources */, - DF7F285E11FF23B700159131 /* frameout.cpp in Sources */, DF7F286211FF23D500159131 /* amigamac.cpp in Sources */, DF7F286911FF23EF00159131 /* kvideo.cpp in Sources */, DF7F286A11FF23EF00159131 /* workarounds.cpp in Sources */, @@ -8157,6 +8698,79 @@ DF7F289511FF247300159131 /* translation.cpp in Sources */, DF7F28A111FF24B000159131 /* mac_snd.cpp in Sources */, DF7F28A611FF24C400159131 /* console.cpp in Sources */, + DF895BFE124C24350077F6E8 /* coktel_decoder.cpp in Sources */, + DF895C03124C24680077F6E8 /* player_towns.cpp in Sources */, + DF895C09124C24B60077F6E8 /* appleiigs.cpp in Sources */, + DF895C15124C24C10077F6E8 /* towns_audio.cpp in Sources */, + DF895C16124C24C10077F6E8 /* towns_euphony.cpp in Sources */, + DF895C17124C24C10077F6E8 /* towns_pc98_driver.cpp in Sources */, + DF895C18124C24C10077F6E8 /* towns_pc98_fmsynth.cpp in Sources */, + DF895C25124C25150077F6E8 /* init_fascin.cpp in Sources */, + DF895C2A124C25350077F6E8 /* script_patches.cpp in Sources */, + DF895CB8124E58980077F6E8 /* indeo3.cpp in Sources */, + DF895CB9124E58980077F6E8 /* mjpeg.cpp in Sources */, + DF895CBA124E58980077F6E8 /* qdm2.cpp in Sources */, + DF895CBB124E58980077F6E8 /* qtrle.cpp in Sources */, + DF895CBC124E58980077F6E8 /* rpza.cpp in Sources */, + DF895CBD124E58990077F6E8 /* smc.cpp in Sources */, + DF0E303B1252C5BD0082D593 /* cms.cpp in Sources */, + DF0E30421252C6090082D593 /* cms.cpp in Sources */, + 8CB5A9CB1253FD6900CB6BC7 /* m4_scene.cpp in Sources */, + 8CB5A9CC1253FD6900CB6BC7 /* mads_logic.cpp in Sources */, + 8CB5A9CD1253FD6900CB6BC7 /* mads_player.cpp in Sources */, + 8CB5A9CE1253FD6900CB6BC7 /* mads_scene.cpp in Sources */, + 8CB5A9CF1253FD6900CB6BC7 /* mads_views.cpp in Sources */, + 8CD1ED53126202AB00FA198C /* detection.cpp in Sources */, + 8CD1ED54126202AB00FA198C /* display.cpp in Sources */, + 8CD1ED55126202AB00FA198C /* engine.cpp in Sources */, + 8CD1ED56126202AB00FA198C /* file.cpp in Sources */, + 8CD1ED57126202AB00FA198C /* hugo.cpp in Sources */, + 8CD1ED58126202AB00FA198C /* intro.cpp in Sources */, + 8CD1ED59126202AB00FA198C /* inventory.cpp in Sources */, + 8CD1ED5C126202AB00FA198C /* mouse.cpp in Sources */, + 8CD1ED5D126202AB00FA198C /* parser.cpp in Sources */, + 8CD1ED5E126202AB00FA198C /* route.cpp in Sources */, + 8CD1ED5F126202AB00FA198C /* schedule.cpp in Sources */, + 8CD1ED60126202AB00FA198C /* sound.cpp in Sources */, + 8CD1ED61126202AB00FA198C /* util.cpp in Sources */, + 8CD1ED62126202AB00FA198C /* anim.cpp in Sources */, + 8CD1ED63126202AB00FA198C /* audio.cpp in Sources */, + 8CD1ED64126202AB00FA198C /* character.cpp in Sources */, + 8CD1ED65126202AB00FA198C /* conversation.cpp in Sources */, + 8CD1ED66126202AB00FA198C /* detection.cpp in Sources */, + 8CD1ED67126202AB00FA198C /* drew.cpp in Sources */, + 8CD1ED68126202AB00FA198C /* flux.cpp in Sources */, + 8CD1ED69126202AB00FA198C /* font.cpp in Sources */, + 8CD1ED6A126202AB00FA198C /* hotspot.cpp in Sources */, + 8CD1ED6D126202AB00FA198C /* movie.cpp in Sources */, + 8CD1ED6E126202AB00FA198C /* path.cpp in Sources */, + 8CD1ED6F126202AB00FA198C /* picture.cpp in Sources */, + 8CD1ED70126202AB00FA198C /* resource.cpp in Sources */, + 8CD1ED71126202AB00FA198C /* script.cpp in Sources */, + 8CD1ED72126202AB00FA198C /* script_func.cpp in Sources */, + 8CD1ED73126202AB00FA198C /* state.cpp in Sources */, + 8CD1ED74126202AB00FA198C /* text.cpp in Sources */, + 8CD1ED75126202AB00FA198C /* tools.cpp in Sources */, + 8CD1ED76126202AB00FA198C /* toon.cpp in Sources */, + 8CD80C8D126271A9001C6C87 /* surface.cpp in Sources */, + 8CD80C93126271BD001C6C87 /* gfx_towns.cpp in Sources */, + 8CD80D04126272A0001C6C87 /* actor.cpp in Sources */, + 8CD80D05126272A0001C6C87 /* animation.cpp in Sources */, + 8CD80D06126272A0001C6C87 /* callbacks.cpp in Sources */, + 8CD80D07126272A0001C6C87 /* console.cpp in Sources */, + 8CD80D08126272A0001C6C87 /* detection.cpp in Sources */, + 8CD80D09126272A0001C6C87 /* dialog.cpp in Sources */, + 8CD80D0A126272A0001C6C87 /* font.cpp in Sources */, + 8CD80D0B126272A0001C6C87 /* inventory.cpp in Sources */, + 8CD80D0D126272A0001C6C87 /* music.cpp in Sources */, + 8CD80D0E126272A0001C6C87 /* objects.cpp in Sources */, + 8CD80D0F126272A0001C6C87 /* pack.cpp in Sources */, + 8CD80D10126272A0001C6C87 /* resources.cpp in Sources */, + 8CD80D11126272A0001C6C87 /* scene.cpp in Sources */, + 8CD80D12126272A0001C6C87 /* segment.cpp in Sources */, + 8CD80D13126272A0001C6C87 /* surface.cpp in Sources */, + 8CD80D14126272A0001C6C87 /* surface_list.cpp in Sources */, + 8CD80D15126272A0001C6C87 /* teenagent.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -8394,7 +9008,6 @@ DF093F720F63CB26002D821E /* draw_bargon.cpp in Sources */, DF093F730F63CB26002D821E /* draw_v1.cpp in Sources */, DF093F740F63CB26002D821E /* draw_v2.cpp in Sources */, - DF093F750F63CB26002D821E /* driver_vga.cpp in Sources */, DF093F760F63CB26002D821E /* game.cpp in Sources */, DF093F790F63CB26002D821E /* global.cpp in Sources */, DF093F7A0F63CB26002D821E /* gob.cpp in Sources */, @@ -8706,7 +9319,6 @@ DF0940D80F63CB26002D821E /* insane_enemy.cpp in Sources */, DF0940D90F63CB26002D821E /* insane_iact.cpp in Sources */, DF0940DA0F63CB26002D821E /* insane_scenes.cpp in Sources */, - DF0940DB0F63CB26002D821E /* midiparser_eup.cpp in Sources */, DF0940DC0F63CB26002D821E /* midiparser_ro.cpp in Sources */, DF0940DD0F63CB26002D821E /* nut_renderer.cpp in Sources */, DF0940DE0F63CB26002D821E /* object.cpp in Sources */, @@ -8983,8 +9595,6 @@ DF6118490FE3A8250042AD3F /* decompressor.cpp in Sources */, DF61184A0FE3A8250042AD3F /* resource.cpp in Sources */, DF6118550FE3A8990042AD3F /* disk.cpp in Sources */, - DF6118660FE3A9410042AD3F /* coktelvideo.cpp in Sources */, - DF6118670FE3A9410042AD3F /* indeo3.cpp in Sources */, DF6118680FE3A9410042AD3F /* dxa_decoder.cpp in Sources */, DF6118690FE3A9410042AD3F /* flic_decoder.cpp in Sources */, DF61186A0FE3A9410042AD3F /* smk_decoder.cpp in Sources */, @@ -9064,12 +9674,10 @@ DF45B1FE116628A5009B85CC /* menu.cpp in Sources */, DF45B1FF116628A5009B85CC /* paint.cpp in Sources */, DF45B200116628A5009B85CC /* paint16.cpp in Sources */, - DF45B201116628A5009B85CC /* paint32.cpp in Sources */, DF45B202116628A5009B85CC /* palette.cpp in Sources */, DF45B203116628A5009B85CC /* picture.cpp in Sources */, DF45B204116628A5009B85CC /* portrait.cpp in Sources */, DF45B205116628A5009B85CC /* ports.cpp in Sources */, - DF45B206116628A5009B85CC /* robot.cpp in Sources */, DF45B207116628A5009B85CC /* screen.cpp in Sources */, DF45B208116628A5009B85CC /* text16.cpp in Sources */, DF45B209116628A5009B85CC /* transitions.cpp in Sources */, @@ -9086,7 +9694,6 @@ DF45B21A116628A5009B85CC /* music.cpp in Sources */, DF45B21B116628A5009B85CC /* soundcmd.cpp in Sources */, DF45B21C116628A5009B85CC /* seq_decoder.cpp in Sources */, - DF45B21D116628A5009B85CC /* vmd_decoder.cpp in Sources */, DFCDC6DB116629CE00A7D2A0 /* features.cpp in Sources */, DFCDC6DC116629CE00A7D2A0 /* kparse.cpp in Sources */, DFCDC6F811662AAB00A7D2A0 /* resource.cpp in Sources */, @@ -9109,7 +9716,6 @@ DFB0578C11B754570015AE65 /* maciconbar.cpp in Sources */, DFB0579311B7547D0015AE65 /* pict.cpp in Sources */, DFB0579A11B7549C0015AE65 /* cinepak.cpp in Sources */, - DF7F285F11FF23B700159131 /* frameout.cpp in Sources */, DF7F286311FF23D500159131 /* amigamac.cpp in Sources */, DF7F286B11FF23EF00159131 /* kvideo.cpp in Sources */, DF7F286C11FF23EF00159131 /* workarounds.cpp in Sources */, @@ -9122,6 +9728,79 @@ DF7F289711FF247300159131 /* translation.cpp in Sources */, DF7F28A211FF24B000159131 /* mac_snd.cpp in Sources */, DF7F28A711FF24C400159131 /* console.cpp in Sources */, + DF895BFF124C24350077F6E8 /* coktel_decoder.cpp in Sources */, + DF895C04124C24680077F6E8 /* player_towns.cpp in Sources */, + DF895C0A124C24B60077F6E8 /* appleiigs.cpp in Sources */, + DF895C19124C24C10077F6E8 /* towns_audio.cpp in Sources */, + DF895C1A124C24C10077F6E8 /* towns_euphony.cpp in Sources */, + DF895C1B124C24C10077F6E8 /* towns_pc98_driver.cpp in Sources */, + DF895C1C124C24C10077F6E8 /* towns_pc98_fmsynth.cpp in Sources */, + DF895C26124C25150077F6E8 /* init_fascin.cpp in Sources */, + DF895C2B124C25350077F6E8 /* script_patches.cpp in Sources */, + DF895CBE124E58990077F6E8 /* indeo3.cpp in Sources */, + DF895CBF124E58990077F6E8 /* mjpeg.cpp in Sources */, + DF895CC0124E58990077F6E8 /* qdm2.cpp in Sources */, + DF895CC1124E58990077F6E8 /* qtrle.cpp in Sources */, + DF895CC2124E58990077F6E8 /* rpza.cpp in Sources */, + DF895CC3124E58990077F6E8 /* smc.cpp in Sources */, + DF0E303C1252C5BD0082D593 /* cms.cpp in Sources */, + DF0E30431252C6090082D593 /* cms.cpp in Sources */, + 8CB5A9C61253FD6900CB6BC7 /* m4_scene.cpp in Sources */, + 8CB5A9C71253FD6900CB6BC7 /* mads_logic.cpp in Sources */, + 8CB5A9C81253FD6900CB6BC7 /* mads_player.cpp in Sources */, + 8CB5A9C91253FD6900CB6BC7 /* mads_scene.cpp in Sources */, + 8CB5A9CA1253FD6900CB6BC7 /* mads_views.cpp in Sources */, + 8CD1ED2F126202AB00FA198C /* detection.cpp in Sources */, + 8CD1ED30126202AB00FA198C /* display.cpp in Sources */, + 8CD1ED31126202AB00FA198C /* engine.cpp in Sources */, + 8CD1ED32126202AB00FA198C /* file.cpp in Sources */, + 8CD1ED33126202AB00FA198C /* hugo.cpp in Sources */, + 8CD1ED34126202AB00FA198C /* intro.cpp in Sources */, + 8CD1ED35126202AB00FA198C /* inventory.cpp in Sources */, + 8CD1ED38126202AB00FA198C /* mouse.cpp in Sources */, + 8CD1ED39126202AB00FA198C /* parser.cpp in Sources */, + 8CD1ED3A126202AB00FA198C /* route.cpp in Sources */, + 8CD1ED3B126202AB00FA198C /* schedule.cpp in Sources */, + 8CD1ED3C126202AB00FA198C /* sound.cpp in Sources */, + 8CD1ED3D126202AB00FA198C /* util.cpp in Sources */, + 8CD1ED3E126202AB00FA198C /* anim.cpp in Sources */, + 8CD1ED3F126202AB00FA198C /* audio.cpp in Sources */, + 8CD1ED40126202AB00FA198C /* character.cpp in Sources */, + 8CD1ED41126202AB00FA198C /* conversation.cpp in Sources */, + 8CD1ED42126202AB00FA198C /* detection.cpp in Sources */, + 8CD1ED43126202AB00FA198C /* drew.cpp in Sources */, + 8CD1ED44126202AB00FA198C /* flux.cpp in Sources */, + 8CD1ED45126202AB00FA198C /* font.cpp in Sources */, + 8CD1ED46126202AB00FA198C /* hotspot.cpp in Sources */, + 8CD1ED49126202AB00FA198C /* movie.cpp in Sources */, + 8CD1ED4A126202AB00FA198C /* path.cpp in Sources */, + 8CD1ED4B126202AB00FA198C /* picture.cpp in Sources */, + 8CD1ED4C126202AB00FA198C /* resource.cpp in Sources */, + 8CD1ED4D126202AB00FA198C /* script.cpp in Sources */, + 8CD1ED4E126202AB00FA198C /* script_func.cpp in Sources */, + 8CD1ED4F126202AB00FA198C /* state.cpp in Sources */, + 8CD1ED50126202AB00FA198C /* text.cpp in Sources */, + 8CD1ED51126202AB00FA198C /* tools.cpp in Sources */, + 8CD1ED52126202AB00FA198C /* toon.cpp in Sources */, + 8CD80C8C126271A9001C6C87 /* surface.cpp in Sources */, + 8CD80C92126271BD001C6C87 /* gfx_towns.cpp in Sources */, + 8CD80CF2126272A0001C6C87 /* actor.cpp in Sources */, + 8CD80CF3126272A0001C6C87 /* animation.cpp in Sources */, + 8CD80CF4126272A0001C6C87 /* callbacks.cpp in Sources */, + 8CD80CF5126272A0001C6C87 /* console.cpp in Sources */, + 8CD80CF6126272A0001C6C87 /* detection.cpp in Sources */, + 8CD80CF7126272A0001C6C87 /* dialog.cpp in Sources */, + 8CD80CF8126272A0001C6C87 /* font.cpp in Sources */, + 8CD80CF9126272A0001C6C87 /* inventory.cpp in Sources */, + 8CD80CFB126272A0001C6C87 /* music.cpp in Sources */, + 8CD80CFC126272A0001C6C87 /* objects.cpp in Sources */, + 8CD80CFD126272A0001C6C87 /* pack.cpp in Sources */, + 8CD80CFE126272A0001C6C87 /* resources.cpp in Sources */, + 8CD80CFF126272A0001C6C87 /* scene.cpp in Sources */, + 8CD80D00126272A0001C6C87 /* segment.cpp in Sources */, + 8CD80D01126272A0001C6C87 /* surface.cpp in Sources */, + 8CD80D02126272A0001C6C87 /* surface_list.cpp in Sources */, + 8CD80D03126272A0001C6C87 /* teenagent.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -9363,7 +10042,6 @@ DFF95A080FB22D5700A3EC78 /* draw_bargon.cpp in Sources */, DFF95A090FB22D5700A3EC78 /* draw_v1.cpp in Sources */, DFF95A0A0FB22D5700A3EC78 /* draw_v2.cpp in Sources */, - DFF95A0B0FB22D5700A3EC78 /* driver_vga.cpp in Sources */, DFF95A0C0FB22D5700A3EC78 /* game.cpp in Sources */, DFF95A0F0FB22D5700A3EC78 /* global.cpp in Sources */, DFF95A100FB22D5700A3EC78 /* gob.cpp in Sources */, @@ -9675,7 +10353,6 @@ DFF95B6D0FB22D5700A3EC78 /* insane_enemy.cpp in Sources */, DFF95B6E0FB22D5700A3EC78 /* insane_iact.cpp in Sources */, DFF95B6F0FB22D5700A3EC78 /* insane_scenes.cpp in Sources */, - DFF95B700FB22D5700A3EC78 /* midiparser_eup.cpp in Sources */, DFF95B710FB22D5700A3EC78 /* midiparser_ro.cpp in Sources */, DFF95B720FB22D5700A3EC78 /* nut_renderer.cpp in Sources */, DFF95B730FB22D5700A3EC78 /* object.cpp in Sources */, @@ -9947,8 +10624,6 @@ DF61184F0FE3A8250042AD3F /* decompressor.cpp in Sources */, DF6118500FE3A8250042AD3F /* resource.cpp in Sources */, DF6118570FE3A8990042AD3F /* disk.cpp in Sources */, - DF6118700FE3A9410042AD3F /* coktelvideo.cpp in Sources */, - DF6118710FE3A9410042AD3F /* indeo3.cpp in Sources */, DF6118720FE3A9410042AD3F /* dxa_decoder.cpp in Sources */, DF6118730FE3A9410042AD3F /* flic_decoder.cpp in Sources */, DF6118740FE3A9410042AD3F /* smk_decoder.cpp in Sources */, @@ -10030,12 +10705,10 @@ DF45B228116628A5009B85CC /* menu.cpp in Sources */, DF45B229116628A5009B85CC /* paint.cpp in Sources */, DF45B22A116628A5009B85CC /* paint16.cpp in Sources */, - DF45B22B116628A5009B85CC /* paint32.cpp in Sources */, DF45B22C116628A5009B85CC /* palette.cpp in Sources */, DF45B22D116628A5009B85CC /* picture.cpp in Sources */, DF45B22E116628A5009B85CC /* portrait.cpp in Sources */, DF45B22F116628A5009B85CC /* ports.cpp in Sources */, - DF45B230116628A5009B85CC /* robot.cpp in Sources */, DF45B231116628A5009B85CC /* screen.cpp in Sources */, DF45B232116628A5009B85CC /* text16.cpp in Sources */, DF45B233116628A5009B85CC /* transitions.cpp in Sources */, @@ -10052,7 +10725,6 @@ DF45B244116628A5009B85CC /* music.cpp in Sources */, DF45B245116628A5009B85CC /* soundcmd.cpp in Sources */, DF45B246116628A5009B85CC /* seq_decoder.cpp in Sources */, - DF45B247116628A5009B85CC /* vmd_decoder.cpp in Sources */, DFCDC6DD116629CE00A7D2A0 /* features.cpp in Sources */, DFCDC6DE116629CE00A7D2A0 /* kparse.cpp in Sources */, DFCDC6F911662AAB00A7D2A0 /* resource.cpp in Sources */, @@ -10075,7 +10747,6 @@ DFB0578A11B754570015AE65 /* maciconbar.cpp in Sources */, DFB0579111B7547D0015AE65 /* pict.cpp in Sources */, DFB0579811B7549C0015AE65 /* cinepak.cpp in Sources */, - DF7F285D11FF23B700159131 /* frameout.cpp in Sources */, DF7F286111FF23D500159131 /* amigamac.cpp in Sources */, DF7F286711FF23EF00159131 /* kvideo.cpp in Sources */, DF7F286811FF23EF00159131 /* workarounds.cpp in Sources */, @@ -10088,6 +10759,79 @@ DF7F289311FF247300159131 /* translation.cpp in Sources */, DF7F28A011FF24B000159131 /* mac_snd.cpp in Sources */, DF7F28A511FF24C400159131 /* console.cpp in Sources */, + DF895C00124C24350077F6E8 /* coktel_decoder.cpp in Sources */, + DF895C05124C24680077F6E8 /* player_towns.cpp in Sources */, + DF895C0B124C24B60077F6E8 /* appleiigs.cpp in Sources */, + DF895C1D124C24C10077F6E8 /* towns_audio.cpp in Sources */, + DF895C1E124C24C10077F6E8 /* towns_euphony.cpp in Sources */, + DF895C1F124C24C10077F6E8 /* towns_pc98_driver.cpp in Sources */, + DF895C20124C24C10077F6E8 /* towns_pc98_fmsynth.cpp in Sources */, + DF895C27124C25150077F6E8 /* init_fascin.cpp in Sources */, + DF895C2C124C25350077F6E8 /* script_patches.cpp in Sources */, + DF895CC4124E58990077F6E8 /* indeo3.cpp in Sources */, + DF895CC5124E58990077F6E8 /* mjpeg.cpp in Sources */, + DF895CC6124E58990077F6E8 /* qdm2.cpp in Sources */, + DF895CC7124E58990077F6E8 /* qtrle.cpp in Sources */, + DF895CC8124E58990077F6E8 /* rpza.cpp in Sources */, + DF895CC9124E58990077F6E8 /* smc.cpp in Sources */, + DF0E303A1252C5BD0082D593 /* cms.cpp in Sources */, + DF0E30411252C6090082D593 /* cms.cpp in Sources */, + 8CB5A9C11253FD6900CB6BC7 /* m4_scene.cpp in Sources */, + 8CB5A9C21253FD6900CB6BC7 /* mads_logic.cpp in Sources */, + 8CB5A9C31253FD6900CB6BC7 /* mads_player.cpp in Sources */, + 8CB5A9C41253FD6900CB6BC7 /* mads_scene.cpp in Sources */, + 8CB5A9C51253FD6900CB6BC7 /* mads_views.cpp in Sources */, + 8CD1ED0B126202AB00FA198C /* detection.cpp in Sources */, + 8CD1ED0C126202AB00FA198C /* display.cpp in Sources */, + 8CD1ED0D126202AB00FA198C /* engine.cpp in Sources */, + 8CD1ED0E126202AB00FA198C /* file.cpp in Sources */, + 8CD1ED0F126202AB00FA198C /* hugo.cpp in Sources */, + 8CD1ED10126202AB00FA198C /* intro.cpp in Sources */, + 8CD1ED11126202AB00FA198C /* inventory.cpp in Sources */, + 8CD1ED14126202AB00FA198C /* mouse.cpp in Sources */, + 8CD1ED15126202AB00FA198C /* parser.cpp in Sources */, + 8CD1ED16126202AB00FA198C /* route.cpp in Sources */, + 8CD1ED17126202AB00FA198C /* schedule.cpp in Sources */, + 8CD1ED18126202AB00FA198C /* sound.cpp in Sources */, + 8CD1ED19126202AB00FA198C /* util.cpp in Sources */, + 8CD1ED1A126202AB00FA198C /* anim.cpp in Sources */, + 8CD1ED1B126202AB00FA198C /* audio.cpp in Sources */, + 8CD1ED1C126202AB00FA198C /* character.cpp in Sources */, + 8CD1ED1D126202AB00FA198C /* conversation.cpp in Sources */, + 8CD1ED1E126202AB00FA198C /* detection.cpp in Sources */, + 8CD1ED1F126202AB00FA198C /* drew.cpp in Sources */, + 8CD1ED20126202AB00FA198C /* flux.cpp in Sources */, + 8CD1ED21126202AB00FA198C /* font.cpp in Sources */, + 8CD1ED22126202AB00FA198C /* hotspot.cpp in Sources */, + 8CD1ED25126202AB00FA198C /* movie.cpp in Sources */, + 8CD1ED26126202AB00FA198C /* path.cpp in Sources */, + 8CD1ED27126202AB00FA198C /* picture.cpp in Sources */, + 8CD1ED28126202AB00FA198C /* resource.cpp in Sources */, + 8CD1ED29126202AB00FA198C /* script.cpp in Sources */, + 8CD1ED2A126202AB00FA198C /* script_func.cpp in Sources */, + 8CD1ED2B126202AB00FA198C /* state.cpp in Sources */, + 8CD1ED2C126202AB00FA198C /* text.cpp in Sources */, + 8CD1ED2D126202AB00FA198C /* tools.cpp in Sources */, + 8CD1ED2E126202AB00FA198C /* toon.cpp in Sources */, + 8CD80C8B126271A9001C6C87 /* surface.cpp in Sources */, + 8CD80C91126271BD001C6C87 /* gfx_towns.cpp in Sources */, + 8CD80CE0126272A0001C6C87 /* actor.cpp in Sources */, + 8CD80CE1126272A0001C6C87 /* animation.cpp in Sources */, + 8CD80CE2126272A0001C6C87 /* callbacks.cpp in Sources */, + 8CD80CE3126272A0001C6C87 /* console.cpp in Sources */, + 8CD80CE4126272A0001C6C87 /* detection.cpp in Sources */, + 8CD80CE5126272A0001C6C87 /* dialog.cpp in Sources */, + 8CD80CE6126272A0001C6C87 /* font.cpp in Sources */, + 8CD80CE7126272A0001C6C87 /* inventory.cpp in Sources */, + 8CD80CE9126272A0001C6C87 /* music.cpp in Sources */, + 8CD80CEA126272A0001C6C87 /* objects.cpp in Sources */, + 8CD80CEB126272A0001C6C87 /* pack.cpp in Sources */, + 8CD80CEC126272A0001C6C87 /* resources.cpp in Sources */, + 8CD80CED126272A0001C6C87 /* scene.cpp in Sources */, + 8CD80CEE126272A0001C6C87 /* segment.cpp in Sources */, + 8CD80CEF126272A0001C6C87 /* surface.cpp in Sources */, + 8CD80CF0126272A0001C6C87 /* surface_list.cpp in Sources */, + 8CD80CF1126272A0001C6C87 /* teenagent.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -10110,7 +10854,7 @@ GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_FIX_AND_CONTINUE = NO; - GCC_OPTIMIZATION_LEVEL = 3; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = ""; GCC_THUMB_SUPPORT = NO; @@ -10123,9 +10867,6 @@ INFOPLIST_FILE = Info.plist; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/../../sound/softsynth/mt32\"", - "\"$(SRCROOT)/../../engines/cruise\"", - "\"$(SRCROOT)/../../engines/m4\"", "\"$(SRCROOT)/lib\"", ); ONLY_ACTIVE_ARCH = YES; @@ -10133,7 +10874,7 @@ PRODUCT_NAME = ScummVM; PROVISIONING_PROFILE = "EF590570-5FAC-4346-9071-D609DE2B28D8"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphoneos3.2; + SDKROOT = iphoneos4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -10166,9 +10907,6 @@ INFOPLIST_FILE = Info.plist; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/../../sound/softsynth/mt32\"", - "\"$(SRCROOT)/../../engines/cruise\"", - "\"$(SRCROOT)/../../engines/m4\"", "\"$(SRCROOT)/lib\"", ); ONLY_ACTIVE_ARCH = YES; @@ -10194,45 +10932,45 @@ GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_INPUT_FILETYPE = automatic; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - XCODE, + CONFIG_H, IPHONE_OFFICIAL, - USE_VORBIS, - USE_FLAC, - USE_TREMOR, - USE_MAD, - USE_ZLIB, - SCUMMVM, - ENABLE_SCI, - ENABLE_TUCKER, - ENABLE_TOUCHE, - ENABLE_TINSEL, - ENABLE_SWORD2, - ENABLE_SWORD1, - ENABLE_SKY, - ENABLE_IHNM, - ENABLE_SAGA, - ENABLE_QUEEN, - ENABLE_PARALLACTION, - ENABLE_MADE, - ENABLE_LURE, - ENABLE_KYRA, - ENABLE_IGOR, - ENABLE_GROOVIE, - ENABLE_GOB, - ENABLE_DRASCULA, - ENABLE_CINE, - ENABLE_AGOS, - ENABLE_AGI, + IPHONE, + UNIX, + SCUMM_LITTLE_ENDIAN, + SCUMM_NEED_ALIGNMENT, ENABLE_SCUMM, ENABLE_SCUMM_7_8, - CONFIG_H, - SCUMM_NEED_ALIGNMENT, - SCUMM_LITTLE_ENDIAN, - UNIX, - IPHONE, - ENABLE_SCI32, ENABLE_HE, + ENABLE_AGI, + ENABLE_AGOS, + ENABLE_CINE, + ENABLE_CRUISE, + ENABLE_DRASCULA, + ENABLE_GOB, + ENABLE_GROOVIE, + ENABLE_IGOR, + ENABLE_KYRA, + ENABLE_LURE, + ENABLE_MADE, + ENABLE_PARALLACTION, + ENABLE_QUEEN, + ENABLE_SAGA, + ENABLE_IHNM, + ENABLE_SCI, + ENABLE_SKY, + ENABLE_SWORD1, + ENABLE_SWORD2, + ENABLE_TEENAGENT, + ENABLE_TINSEL, + ENABLE_TOUCHE, + ENABLE_TUCKER, + USE_FLAC, + USE_MAD, + USE_TREMOR, + USE_VORBIS, + USE_ZLIB, ); GCC_THUMB_SUPPORT = NO; GCC_USE_GCC3_PFE_SUPPORT = NO; @@ -10249,8 +10987,9 @@ PREBINDING = NO; PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; - SDKROOT = iphonesimulator3.2; + SDKROOT = iphoneos4.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64 armv6 armv7"; }; name = Debug; }; @@ -10265,62 +11004,77 @@ GCC_C_LANGUAGE_STANDARD = c99; GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; + GCC_ENABLE_EXCEPTIONS = NO; GCC_INPUT_FILETYPE = automatic; GCC_PREPROCESSOR_DEFINITIONS = ( - XCODE, + CONFIG_H, IPHONE_OFFICIAL, - USE_VORBIS, - USE_FLAC, - USE_TREMOR, - USE_MAD, - USE_ZLIB, - SCUMMVM, - ENABLE_SCI, - ENABLE_TUCKER, - ENABLE_TOUCHE, - ENABLE_TINSEL, - ENABLE_SWORD2, - ENABLE_SWORD1, - ENABLE_SKY, - ENABLE_IHNM, - ENABLE_SAGA, - ENABLE_QUEEN, - ENABLE_PARALLACTION, - ENABLE_MADE, - ENABLE_LURE, - ENABLE_KYRA, - ENABLE_IGOR, - ENABLE_GROOVIE, - ENABLE_GOB, - ENABLE_DRASCULA, - ENABLE_CINE, - ENABLE_AGOS, - ENABLE_AGI, + IPHONE, + UNIX, + SCUMM_LITTLE_ENDIAN, + SCUMM_NEED_ALIGNMENT, ENABLE_SCUMM, ENABLE_SCUMM_7_8, - CONFIG_H, - SCUMM_NEED_ALIGNMENT, - SCUMM_LITTLE_ENDIAN, - UNIX, - IPHONE, - ENABLE_SCI32, ENABLE_HE, + ENABLE_AGI, + ENABLE_AGOS, + ENABLE_CINE, + ENABLE_CRUISE, + ENABLE_DRASCULA, + ENABLE_GOB, + ENABLE_GROOVIE, + ENABLE_IGOR, + ENABLE_KYRA, + ENABLE_LURE, + ENABLE_MADE, + ENABLE_PARALLACTION, + ENABLE_QUEEN, + ENABLE_SAGA, + ENABLE_IHNM, + ENABLE_SCI, + ENABLE_SKY, + ENABLE_SWORD1, + ENABLE_SWORD2, + ENABLE_TEENAGENT, + ENABLE_TINSEL, + ENABLE_TOUCHE, + ENABLE_TUCKER, + USE_FLAC, + USE_MAD, + USE_TREMOR, + USE_VORBIS, + USE_ZLIB, ); GCC_THUMB_SUPPORT = NO; GCC_USE_GCC3_PFE_SUPPORT = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; HEADER_SEARCH_PATHS = ( + /opt/local/include/SDL, + /opt/local/include, + /sw/include/SDL, + /sw/include, ../../engines/, ../../, ); LIBRARY_SEARCH_PATHS = ""; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; - OTHER_LDFLAGS = "-lz"; + OTHER_LDFLAGS = ( + "-lSDLmain", + "-logg", + "-lvorbisfile", + "-lvorbis", + "-lmad", + "-lFLAC", + "-lSDL", + "-lz", + ); PREBINDING = NO; PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; SDKROOT = iphonesimulator3.2; TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64 armv6 armv7"; }; name = Release; }; @@ -10338,48 +11092,51 @@ GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( - USE_VORBIS, - USE_FLAC, - USE_TREMOR, - USE_MPEG2, - USE_MAD, - USE_ZLIB, - SCUMMVM, - ENABLE_SCI, - ENABLE_TUCKER, - ENABLE_TOUCHE, - ENABLE_TINSEL, - ENABLE_SWORD2, - ENABLE_SWORD1, - ENABLE_SKY, - ENABLE_IHNM, - ENABLE_SAGA, - ENABLE_QUEEN, - ENABLE_PARALLACTION, - ENABLE_MADE, - ENABLE_LURE, - ENABLE_KYRA, - ENABLE_IGOR, - ENABLE_GROOVIE, - ENABLE_GOB, - ENABLE_DRASCULA, - ENABLE_CINE, - ENABLE_AGOS, - ENABLE_AGI, + CONFIG_H, + MACOSX, + SDL_BACKEND, + UNIX, + SCUMM_LITTLE_ENDIAN, + SCUMM_NEED_ALIGNMENT, ENABLE_SCUMM, ENABLE_SCUMM_7_8, - CONFIG_H, - SCUMM_NEED_ALIGNMENT, - SCUMM_LITTLE_ENDIAN, - UNIX, - SDL_BACKEND, - MACOSX, ENABLE_HE, + ENABLE_AGI, + ENABLE_AGOS, + ENABLE_CINE, + ENABLE_CRUISE, + ENABLE_DRASCULA, + ENABLE_GOB, + ENABLE_GROOVIE, + ENABLE_IGOR, + ENABLE_KYRA, + ENABLE_LURE, + ENABLE_MADE, + ENABLE_PARALLACTION, + ENABLE_QUEEN, + ENABLE_SAGA, + ENABLE_IHNM, + ENABLE_SCI, + ENABLE_SKY, + ENABLE_SWORD1, + ENABLE_SWORD2, + ENABLE_TEENAGENT, + ENABLE_TINSEL, + ENABLE_TOUCHE, + ENABLE_TUCKER, + USE_FLAC, + USE_MAD, + USE_MPEG2, + USE_TREMOR, + USE_VORBIS, + USE_ZLIB, ); GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( /opt/local/include/SDL, /opt/local/include, + /sw/include/SDL, + /sw/include, include/, ../../engines/, ../../, @@ -10389,10 +11146,6 @@ /sw/lib, /opt/local/lib, "$(inherited)", - "\\\"$(SRCROOT)/../../sound/softsynth/mt32\\\"", - "\\\"$(SRCROOT)/../../engines/cruise\\\"", - "\\\"$(SRCROOT)/../../engines/m4\\\"", - "\\\"$(SRCROOT)/lib\\\"", ); ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ""; @@ -10409,7 +11162,7 @@ PREBINDING = NO; PRODUCT_NAME = ScummVM; SDKROOT = macosx10.6; - VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64 arm7 arm6"; + VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64"; }; name = Debug; }; @@ -10425,49 +11178,51 @@ GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( - USE_VORBIS, - USE_FLAC, - USE_TREMOR, - USE_MPEG2, - USE_MAD, - USE_ZLIB, - SCUMMVM, - ENABLE_SCI, - ENABLE_TUCKER, - ENABLE_TOUCHE, - ENABLE_TINSEL, - ENABLE_SWORD2, - ENABLE_SWORD1, - ENABLE_SKY, - ENABLE_IHNM, - ENABLE_SAGA, - ENABLE_QUEEN, - ENABLE_PARALLACTION, - ENABLE_MADE, - ENABLE_LURE, - ENABLE_KYRA, - ENABLE_IGOR, - ENABLE_GROOVIE, - ENABLE_GOB, - ENABLE_DRASCULA, - ENABLE_CINE, - ENABLE_AGOS, - ENABLE_AGI, + CONFIG_H, + MACOSX, + SDL_BACKEND, + UNIX, + SCUMM_LITTLE_ENDIAN, + SCUMM_NEED_ALIGNMENT, ENABLE_SCUMM, ENABLE_SCUMM_7_8, - CONFIG_H, - SCUMM_NEED_ALIGNMENT, - SCUMM_LITTLE_ENDIAN, - UNIX, - SDL_BACKEND, - MACOSX, ENABLE_HE, + ENABLE_AGI, + ENABLE_AGOS, + ENABLE_CINE, + ENABLE_CRUISE, + ENABLE_DRASCULA, + ENABLE_GOB, + ENABLE_GROOVIE, + ENABLE_IGOR, + ENABLE_KYRA, + ENABLE_LURE, + ENABLE_MADE, + ENABLE_PARALLACTION, + ENABLE_QUEEN, + ENABLE_SAGA, + ENABLE_IHNM, + ENABLE_SCI, + ENABLE_SKY, + ENABLE_SWORD1, + ENABLE_SWORD2, + ENABLE_TEENAGENT, + ENABLE_TINSEL, + ENABLE_TOUCHE, + ENABLE_TUCKER, + USE_FLAC, + USE_MAD, + USE_MPEG2, + USE_TREMOR, + USE_VORBIS, + USE_ZLIB, ); GCC_VERSION = ""; HEADER_SEARCH_PATHS = ( /opt/local/include/SDL, /opt/local/include, - include/, + /sw/include/SDL, + /sw/include, ../../engines/, ../../, ); @@ -10476,10 +11231,6 @@ /sw/lib, /opt/local/lib, "$(inherited)", - "\\\"$(SRCROOT)/../../sound/softsynth/mt32\\\"", - "\\\"$(SRCROOT)/../../engines/cruise\\\"", - "\\\"$(SRCROOT)/../../engines/m4\\\"", - "\\\"$(SRCROOT)/lib\\\"", ); ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ""; @@ -10496,7 +11247,7 @@ PREBINDING = NO; PRODUCT_NAME = ScummVM; SDKROOT = macosx10.6; - VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64 arm7 arm6"; + VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64"; WRAPPER_EXTENSION = app; }; name = Release; @@ -10519,17 +11270,28 @@ GCC_THUMB_SUPPORT = NO; GCC_UNROLL_LOOPS = YES; HEADER_SEARCH_PATHS = ( + /opt/local/include/SDL, + /opt/local/include, + /sw/include/SDL, + /sw/include, ../../engines/, ../../, - /opt/local/include, ); - INFOPLIST_FILE = "/Users/oystein/iphone/scummvm/dists/iphone/Info copy 2.plist"; + INFOPLIST_FILE = Info.plist; LIBRARY_SEARCH_PATHS = ( + /sw/lib, + /opt/local/lib, "$(inherited)", - "\\\"$(SRCROOT)/../../sound/softsynth/mt32\\\"", - "\\\"$(SRCROOT)/../../engines/cruise\\\"", - "\\\"$(SRCROOT)/../../engines/m4\\\"", - "\\\"$(SRCROOT)/lib\\\"", + ); + OTHER_LDFLAGS = ( + "-lSDLmain", + "-logg", + "-lvorbisfile", + "-lvorbis", + "-lmad", + "-lFLAC", + "-lSDL", + "-lz", ); PREBINDING = NO; PRODUCT_NAME = ScummVM; @@ -10556,17 +11318,28 @@ GCC_THUMB_SUPPORT = NO; GCC_UNROLL_LOOPS = YES; HEADER_SEARCH_PATHS = ( + /opt/local/include/SDL, + /opt/local/include, + /sw/include/SDL, + /sw/include, ../../engines/, ../../, - /opt/local/include, ); - INFOPLIST_FILE = "/Users/oystein/iphone/scummvm/dists/iphone/Info copy 2.plist"; + INFOPLIST_FILE = Info.plist; LIBRARY_SEARCH_PATHS = ( + /sw/lib, + /opt/local/lib, "$(inherited)", - "\\\"$(SRCROOT)/../../sound/softsynth/mt32\\\"", - "\\\"$(SRCROOT)/../../engines/cruise\\\"", - "\\\"$(SRCROOT)/../../engines/m4\\\"", - "\\\"$(SRCROOT)/lib\\\"", + ); + OTHER_LDFLAGS = ( + "-lSDLmain", + "-logg", + "-lvorbisfile", + "-lvorbis", + "-lmad", + "-lFLAC", + "-lSDL", + "-lz", ); PREBINDING = NO; PRODUCT_NAME = ScummVM; diff --git a/dists/irix/scummvm.spec b/dists/irix/scummvm.spec index 08dbf20826d..f19a4716b77 100644 --- a/dists/irix/scummvm.spec +++ b/dists/irix/scummvm.spec @@ -1,5 +1,5 @@ product scummvm - id "ScummVM 1.2.0svn" + id "ScummVM 1.3.0svn" image sw id "software" version 18 diff --git a/dists/macosx/Info.plist b/dists/macosx/Info.plist index 633c6b7e967..1a649254838 100644 --- a/dists/macosx/Info.plist +++ b/dists/macosx/Info.plist @@ -1,5 +1,5 @@ - + CFBundleDevelopmentRegion @@ -9,7 +9,7 @@ CFBundleExecutable scummvm CFBundleGetInfoString - 1.2.0svn, Copyright 2001-2010 The ScummVM team + 1.3.0svn, Copyright 2001-2010 The ScummVM team CFBundleIconFile scummvm.icns CFBundleIdentifier @@ -21,9 +21,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.0svn + 1.3.0svn CFBundleVersion - 1.2.0svn + 1.3.0svn NSPrincipalClass NSApplication NSHumanReadableCopyright diff --git a/dists/macosx/Info.plist.in b/dists/macosx/Info.plist.in index 26a044e5dfa..0eedf19919e 100644 --- a/dists/macosx/Info.plist.in +++ b/dists/macosx/Info.plist.in @@ -1,5 +1,5 @@ - + CFBundleDevelopmentRegion diff --git a/dists/redhat/scummvm-tools.spec b/dists/redhat/scummvm-tools.spec index 5721233ff6d..2370468e287 100644 --- a/dists/redhat/scummvm-tools.spec +++ b/dists/redhat/scummvm-tools.spec @@ -7,7 +7,7 @@ # Prologue information #------------------------------------------------------------------------------ Name : scummvm-tools -Version : 1.2.0svn +Version : 1.3.0svn Release : 1 Summary : ScummVM-related tools Group : Interpreters @@ -37,14 +37,13 @@ Tools for compressing ScummVM datafiles and other related tools. (cd libmad-0.15.1b; grep -v 'force-\(mem\|addr\)' configure > configure.new; mv -f configure.new configure; chmod 700 configure; ./configure --enable-static --disable-shared --prefix=%{_builddir}/scummvm-%{version}/tmp; make; make install) ./configure --with-mad-prefix=%{_builddir}/scummvm-%{version}/tmp make -echo -e " This script is installed as\n "%{_datadir}/scummvm-tools/convert_dxa.sh.sample >> README %install install -m755 -d %{buildroot}%{_bindir} +install -m755 -D create_sjisfnt %{buildroot}%{_bindir} install -m755 -D scummvm-tools{,-cli} %{buildroot}%{_bindir} install -m755 -D de{cine,gob,kyra,riven,scumm,sword2} %{buildroot}%{_bindir} install -m755 -D {construct,extract}_mohawk %{buildroot}%{_bindir} -install -m644 -D convert_dxa.sh %{buildroot}%{_datadir}/scummvm-tools/convert_dxa.sh.sample %clean rm -Rf ${RPM_BUILD_ROOT} @@ -55,10 +54,10 @@ rm -Rf ${RPM_BUILD_ROOT} %files %doc README COPYING %attr(0755,root,root)%{_bindir}/scummvm* +%attr(0755,root,root)%{_bindir}/create_sjisfnt %attr(0755,root,root)%{_bindir}/de* %attr(0755,root,root)%{_bindir}/extract_* %attr(0755,root,root)%{_bindir}/construct_* -%attr(0644,root,root)%{_datadir}/scummvm-tools/convert_dxa.sh.sample #------------------------------------------------------------------------------ # Change Log diff --git a/dists/redhat/scummvm-tools.spec.in b/dists/redhat/scummvm-tools.spec.in index 56a40007551..f64871486d5 100644 --- a/dists/redhat/scummvm-tools.spec.in +++ b/dists/redhat/scummvm-tools.spec.in @@ -37,14 +37,13 @@ Tools for compressing ScummVM datafiles and other related tools. (cd libmad-0.15.1b; grep -v 'force-\(mem\|addr\)' configure > configure.new; mv -f configure.new configure; chmod 700 configure; ./configure --enable-static --disable-shared --prefix=%{_builddir}/scummvm-%{version}/tmp; make; make install) ./configure --with-mad-prefix=%{_builddir}/scummvm-%{version}/tmp make -echo -e " This script is installed as\n "%{_datadir}/scummvm-tools/convert_dxa.sh.sample >> README %install install -m755 -d %{buildroot}%{_bindir} +install -m755 -D create_sjisfnt %{buildroot}%{_bindir} install -m755 -D scummvm-tools{,-cli} %{buildroot}%{_bindir} install -m755 -D de{cine,gob,kyra,riven,scumm,sword2} %{buildroot}%{_bindir} install -m755 -D {construct,extract}_mohawk %{buildroot}%{_bindir} -install -m644 -D convert_dxa.sh %{buildroot}%{_datadir}/scummvm-tools/convert_dxa.sh.sample %clean rm -Rf ${RPM_BUILD_ROOT} @@ -55,10 +54,10 @@ rm -Rf ${RPM_BUILD_ROOT} %files %doc README COPYING %attr(0755,root,root)%{_bindir}/scummvm* +%attr(0755,root,root)%{_bindir}/create_sjisfnt %attr(0755,root,root)%{_bindir}/de* %attr(0755,root,root)%{_bindir}/extract_* %attr(0755,root,root)%{_bindir}/construct_* -%attr(0644,root,root)%{_datadir}/scummvm-tools/convert_dxa.sh.sample #------------------------------------------------------------------------------ # Change Log diff --git a/dists/redhat/scummvm.spec b/dists/redhat/scummvm.spec index 1212e8b61be..950acf2a74a 100644 --- a/dists/redhat/scummvm.spec +++ b/dists/redhat/scummvm.spec @@ -7,7 +7,7 @@ # Prologue information #------------------------------------------------------------------------------ Name : scummvm -Version : 1.2.0svn +Version : 1.3.0svn Release : 1 Summary : Graphic adventure game interpreter Group : Interpreters @@ -17,7 +17,6 @@ Url : http://www.scummvm.org Source : %{name}-%{version}.tar.bz2 Source1 : libmad-0.15.1b.tar.bz2 -Source2 : mpeg2dec-0.4.1.tar.bz2 BuildRoot : %{_tmppath}/%{name}-%{version}-root BuildRequires: desktop-file-utils @@ -32,34 +31,36 @@ BuildRequires: SDL-devel >= 1.2.2 # Description #------------------------------------------------------------------------------ %description -ScummVM is an interpreter that will play graphic adventure games written for -LucasArts' SCUMM virtual machine (such as Day of the Tentacle and -Monkey Island), Sierra's AGI adventures (such as early King's Quest and -Space Quest games), Adventure Soft's Simon the Sorcerer 1, 2 and Feeble Files, -Revolution Software's Beneath a Steel Sky and Broken Sword I and II, -Interactive Binary Illusions' Flight of the Amazon Queen, -Coktel Vision's Gobliiins, Wyrmkeep's Inherit the Earth, Westwood's -Legend of Kyrandia, and various others. +ScummVM is an interpreter that will play many graphic adventure games, +including LucasArts SCUMM games (such as Monkey Island 1-3, Day of the +Tentacle, Sam & Max, ...), many of Sierra's AGI and SCI games (such as King's +Quest 1-6, Space Quest 1-5, ...), Discworld 1 and 2, Simon the Sorcerer 1 and +2, Beneath A Steel Sky, Lure of the Temptress, Broken Sword 1 and 2, Flight of +the Amazon Queen, Gobliiins 1-3, The Legend of Kyrandia 1-3, many of Humongous +Entertainment's children's SCUMM games (including Freddi Fish and Putt Putt +games) and many more. See http://www.scummvm.org for a full compatibility list. #------------------------------------------------------------------------------ # install scripts #------------------------------------------------------------------------------ %prep -%setup -q -a 1 -a 2 -n scummvm-%{version} +%setup -q -a 1 -n scummvm-%{version} mkdir tmp %build (cd libmad-0.15.1b; ./configure --enable-static --disable-shared --prefix=%{_builddir}/scummvm-%{version}/tmp; make; make install) -(cd mpeg2dec-0.4.1; ./configure --enable-static --disable-shared --prefix=%{_builddir}/scummvm-%{version}/tmp; make; make install) -./configure --with-mad-prefix=%{_builddir}/scummvm-%{version}/tmp --with-mpeg2-prefix=%{_builddir}/scummvm-%{version}/tmp --prefix=%{_prefix} --enable-release +./configure --with-mad-prefix=%{_builddir}/scummvm-%{version}/tmp --prefix=%{_prefix} --enable-release make %install install -m755 -D scummvm %{buildroot}%{_bindir}/scummvm install -m644 -D dists/scummvm.6 %{buildroot}%{_mandir}/man6/scummvm.6 install -m644 -D icons/scummvm.xpm %{buildroot}%{_datadir}/pixmaps/scummvm.xpm +install -m644 -D icons/scummvm.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/scummvm.svg +install -m644 -D dists/redhat/scummvm48.png %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/scummvm.png install -m644 -D gui/themes/scummclassic.zip %{buildroot}%{_datadir}/scummvm/scummclassic.zip install -m644 -D gui/themes/scummmodern.zip %{buildroot}%{_datadir}/scummvm/scummmodern.zip +install -m644 -D gui/themes/translations.dat %{buildroot}%{_datadir}/scummvm/translations.dat install -m644 -D dists/pred.dic %{buildroot}%{_datadir}/scummvm/pred.dic install -m644 -D dists/engine-data/kyra.dat %{buildroot}%{_datadir}/scummvm/kyra.dat install -m644 -D dists/engine-data/lure.dat %{buildroot}%{_datadir}/scummvm/lure.dat @@ -72,16 +73,31 @@ desktop-file-install --vendor scummvm --dir=%{buildroot}/%{_datadir}/application %clean rm -Rf ${RPM_BUILD_ROOT} +%post +touch --no-create %{_datadir}/icons/hicolor || : +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : +fi + +%postun +touch --no-create %{_datadir}/icons/hicolor || : +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : +fi + #------------------------------------------------------------------------------ # Files listing. #------------------------------------------------------------------------------ %files %defattr(0644,root,root,0755) -%doc AUTHORS README NEWS COPYING COPYING.LGPL COPYRIGHT +%doc AUTHORS README NEWS COPYING COPYING.LGPL COPYING.BSD COPYRIGHT %attr(0755,root,root)%{_bindir}/scummvm %{_datadir}/applications/* %{_datadir}/pixmaps/scummvm.xpm +%{_datadir}/icons/hicolor/48x48/apps/scummvm.png +%{_datadir}/icons/hicolor/scalable/apps/scummvm.svg %{_datadir}/scummvm/scumm*.zip +%{_datadir}/scummvm/translations.dat %{_datadir}/scummvm/pred.dic %{_datadir}/scummvm/kyra.dat %{_datadir}/scummvm/queen.tbl @@ -95,6 +111,9 @@ rm -Rf ${RPM_BUILD_ROOT} # Change Log #------------------------------------------------------------------------------ %changelog +* Fri Sep 17 2010 (1.2.0) + - include png/svg icons + - remove libmpeg2 * Thu Sep 21 2006 (0.9.1) - include modern theme * Mon Dec 20 2004 (0.7.0) diff --git a/dists/redhat/scummvm.spec.in b/dists/redhat/scummvm.spec.in index 89bb7692fb0..13ce600d026 100644 --- a/dists/redhat/scummvm.spec.in +++ b/dists/redhat/scummvm.spec.in @@ -17,7 +17,6 @@ Url : http://www.scummvm.org Source : %{name}-%{version}.tar.bz2 Source1 : libmad-0.15.1b.tar.bz2 -Source2 : mpeg2dec-0.4.1.tar.bz2 BuildRoot : %{_tmppath}/%{name}-%{version}-root BuildRequires: desktop-file-utils @@ -32,34 +31,36 @@ BuildRequires: SDL-devel >= 1.2.2 # Description #------------------------------------------------------------------------------ %description -ScummVM is an interpreter that will play graphic adventure games written for -LucasArts' SCUMM virtual machine (such as Day of the Tentacle and -Monkey Island), Sierra's AGI adventures (such as early King's Quest and -Space Quest games), Adventure Soft's Simon the Sorcerer 1, 2 and Feeble Files, -Revolution Software's Beneath a Steel Sky and Broken Sword I and II, -Interactive Binary Illusions' Flight of the Amazon Queen, -Coktel Vision's Gobliiins, Wyrmkeep's Inherit the Earth, Westwood's -Legend of Kyrandia, and various others. +ScummVM is an interpreter that will play many graphic adventure games, +including LucasArts SCUMM games (such as Monkey Island 1-3, Day of the +Tentacle, Sam & Max, ...), many of Sierra's AGI and SCI games (such as King's +Quest 1-6, Space Quest 1-5, ...), Discworld 1 and 2, Simon the Sorcerer 1 and +2, Beneath A Steel Sky, Lure of the Temptress, Broken Sword 1 and 2, Flight of +the Amazon Queen, Gobliiins 1-3, The Legend of Kyrandia 1-3, many of Humongous +Entertainment's children's SCUMM games (including Freddi Fish and Putt Putt +games) and many more. See http://www.scummvm.org for a full compatibility list. #------------------------------------------------------------------------------ # install scripts #------------------------------------------------------------------------------ %prep -%setup -q -a 1 -a 2 -n scummvm-%{version} +%setup -q -a 1 -n scummvm-%{version} mkdir tmp %build (cd libmad-0.15.1b; ./configure --enable-static --disable-shared --prefix=%{_builddir}/scummvm-%{version}/tmp; make; make install) -(cd mpeg2dec-0.4.1; ./configure --enable-static --disable-shared --prefix=%{_builddir}/scummvm-%{version}/tmp; make; make install) -./configure --with-mad-prefix=%{_builddir}/scummvm-%{version}/tmp --with-mpeg2-prefix=%{_builddir}/scummvm-%{version}/tmp --prefix=%{_prefix} --enable-release +./configure --with-mad-prefix=%{_builddir}/scummvm-%{version}/tmp --prefix=%{_prefix} --enable-release make %install install -m755 -D scummvm %{buildroot}%{_bindir}/scummvm install -m644 -D dists/scummvm.6 %{buildroot}%{_mandir}/man6/scummvm.6 install -m644 -D icons/scummvm.xpm %{buildroot}%{_datadir}/pixmaps/scummvm.xpm +install -m644 -D icons/scummvm.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/scummvm.svg +install -m644 -D dists/redhat/scummvm48.png %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/scummvm.png install -m644 -D gui/themes/scummclassic.zip %{buildroot}%{_datadir}/scummvm/scummclassic.zip install -m644 -D gui/themes/scummmodern.zip %{buildroot}%{_datadir}/scummvm/scummmodern.zip +install -m644 -D gui/themes/translations.dat %{buildroot}%{_datadir}/scummvm/translations.dat install -m644 -D dists/pred.dic %{buildroot}%{_datadir}/scummvm/pred.dic install -m644 -D dists/engine-data/kyra.dat %{buildroot}%{_datadir}/scummvm/kyra.dat install -m644 -D dists/engine-data/lure.dat %{buildroot}%{_datadir}/scummvm/lure.dat @@ -72,16 +73,31 @@ desktop-file-install --vendor scummvm --dir=%{buildroot}/%{_datadir}/application %clean rm -Rf ${RPM_BUILD_ROOT} +%post +touch --no-create %{_datadir}/icons/hicolor || : +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : +fi + +%postun +touch --no-create %{_datadir}/icons/hicolor || : +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache --quiet %{_datadir}/icons/hicolor || : +fi + #------------------------------------------------------------------------------ # Files listing. #------------------------------------------------------------------------------ %files %defattr(0644,root,root,0755) -%doc AUTHORS README NEWS COPYING COPYING.LGPL COPYRIGHT +%doc AUTHORS README NEWS COPYING COPYING.LGPL COPYING.BSD COPYRIGHT %attr(0755,root,root)%{_bindir}/scummvm %{_datadir}/applications/* %{_datadir}/pixmaps/scummvm.xpm +%{_datadir}/icons/hicolor/48x48/apps/scummvm.png +%{_datadir}/icons/hicolor/scalable/apps/scummvm.svg %{_datadir}/scummvm/scumm*.zip +%{_datadir}/scummvm/translations.dat %{_datadir}/scummvm/pred.dic %{_datadir}/scummvm/kyra.dat %{_datadir}/scummvm/queen.tbl @@ -95,6 +111,9 @@ rm -Rf ${RPM_BUILD_ROOT} # Change Log #------------------------------------------------------------------------------ %changelog +* Fri Sep 17 2010 (1.2.0) + - include png/svg icons + - remove libmpeg2 * Thu Sep 21 2006 (0.9.1) - include modern theme * Mon Dec 20 2004 (0.7.0) diff --git a/dists/redhat/scummvm48.png b/dists/redhat/scummvm48.png new file mode 100644 index 00000000000..3f7fca230cd Binary files /dev/null and b/dists/redhat/scummvm48.png differ diff --git a/dists/scummvm.rc b/dists/scummvm.rc index f7bae3ca930..e123bebd6fe 100644 --- a/dists/scummvm.rc +++ b/dists/scummvm.rc @@ -7,8 +7,8 @@ IDI_ICON ICON DISCARDABLE "../../icons/scummvm.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 - PRODUCTVERSION 1,2,0,0 + FILEVERSION 1,3,0,0 + PRODUCTVERSION 1,3,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -25,13 +25,13 @@ BEGIN BEGIN VALUE "Comments", "Look! A three headed monkey (TM)! .. Nice use of the TM!\0" VALUE "FileDescription", "http://www.scummvm.org/\0" - VALUE "FileVersion", "1.2.0svn\0" + VALUE "FileVersion", "1.3.0svn\0" VALUE "InternalName", "scummvm\0" VALUE "LegalCopyright", "Copyright © 2001-2010 The ScummVM Team\0" VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0" VALUE "OriginalFilename", "scummvm.exe\0" VALUE "ProductName", "ScummVM\0" - VALUE "ProductVersion", "1.2.0svn\0" + VALUE "ProductVersion", "1.3.0svn\0" END END BLOCK "VarFileInfo" diff --git a/dists/slackware/scummvm.SlackBuild b/dists/slackware/scummvm.SlackBuild index 220aa4ad083..a53c1b2a574 100755 --- a/dists/slackware/scummvm.SlackBuild +++ b/dists/slackware/scummvm.SlackBuild @@ -9,7 +9,7 @@ if [ "$TMP" = "" ]; then fi PKG=$TMP/package-scummvm -VERSION=1.2.0svn +VERSION=1.3.0svn ARCH=i486 BUILD=1 diff --git a/dists/wii/meta.xml b/dists/wii/meta.xml index 8659263076a..b881b4ce39e 100644 --- a/dists/wii/meta.xml +++ b/dists/wii/meta.xml @@ -2,7 +2,7 @@ ScummVM The ScummVM Team - 1.2.0svn@REVISION@ + 1.3.0svn@REVISION@ @TIMESTAMP@ Point & Click Adventures ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files. The clever part about this: ScummVM just replaces the executables shipped with the games, allowing you to play them on systems for which they were never designed! diff --git a/dists/wii/meta.xml.in b/dists/wii/meta.xml.in index 7f05bbf3507..970ae7d54b1 100644 --- a/dists/wii/meta.xml.in +++ b/dists/wii/meta.xml.in @@ -8,5 +8,6 @@ ScummVM is a program which allows you to run certain classic graphical point-and-click adventure games, provided you already have their data files. The clever part about this: ScummVM just replaces the executables shipped with the games, allowing you to play them on systems for which they were never designed! Some of the adventures ScummVM supports include Adventure Soft's Simon the Sorcerer 1 and 2; Revolution's Beneath A Steel Sky and Broken Sword I & II; Flight of the Amazon Queen; Wyrmkeep's Inherit the Earth; Coktel Vision's Gobliiins; Westwood Studios' The Legend of Kyrandia and games based on LucasArts' SCUMM (Script Creation Utility for Maniac Mansion) system such as Monkey Island, Day of the Tentacle, Sam and Max and more. + diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 46ecc037678..d31330b69e7 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -226,7 +226,7 @@ bool cleanupPirated(ADGameDescList &matched) { // We ruled out all variants and now have nothing if (matched.empty()) { - + warning("Illegitimate copy of the game detected. We give no support in such cases %d", matched.size()); return true; @@ -400,7 +400,7 @@ static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, matched = true; break; } - + if (!matched) continue; @@ -448,7 +448,7 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p if (g->flags & ADGF_MACRESFORK) { Common::MacResManager *macResMan = new Common::MacResManager(); - + if (macResMan->open(parent, fname)) { if (!macResMan->getResForkMD5(tmp.md5, params.md5Bytes)) tmp.md5[0] = 0; @@ -472,7 +472,7 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p tmp.size = -1; tmp.md5[0] = 0; } - + debug(3, "> '%s': '%s'", fname.c_str(), tmp.md5); filesSizeMD5[fname] = tmp; } @@ -622,7 +622,7 @@ static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParam matchedDesc = agdesc; maxNumMatchedFiles = numMatchedFiles; - debug(4, "and overriden"); + debug(4, "and overridden"); } } } diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index b15a4c3bace..4dcf5fee5e1 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -360,12 +360,12 @@ int AgiEngine::agiInit() { switch (getVersion() >> 12) { case 2: - report("Emulating Sierra AGI v%x.%03x\n", + debug("Emulating Sierra AGI v%x.%03x\n", (int)(getVersion() >> 12) & 0xF, (int)(getVersion()) & 0xFFF); break; case 3: - report("Emulating Sierra AGI v%x.002.%03x\n", + debug("Emulating Sierra AGI v%x.002.%03x\n", (int)(getVersion() >> 12) & 0xF, (int)(getVersion()) & 0xFFF); break; @@ -382,10 +382,10 @@ int AgiEngine::agiInit() { _game.sbuf = _game.sbuf256c; if (_game.gameFlags & ID_AMIGA) - report("Amiga padded game detected.\n"); + debug(1, "Amiga padded game detected."); if (_game.gameFlags & ID_AGDS) - report("AGDS mode enabled.\n"); + debug(1, "AGDS mode enabled."); ec = _loader->init(); // load vol files, etc @@ -577,18 +577,25 @@ void AgiEngine::initialize() { _soundemu = SOUND_EMU_APPLE2GS; } else if (getPlatform() == Common::kPlatformCoCo3) { _soundemu = SOUND_EMU_COCO3; + } else if (ConfMan.get("music_driver") == "auto") { + // Default sound is the proper PCJr emulation + _soundemu = SOUND_EMU_PCJR; } else { - switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK|MDT_ADLIB|MDT_PCJR|MDT_MIDI))) { + switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK|MDT_AMIGA|MDT_ADLIB|MDT_PCJR|MDT_MIDI))) { case MT_PCSPK: _soundemu = SOUND_EMU_PC; break; - case MT_PCJR: - _soundemu = SOUND_EMU_PCJR; - break; case MT_ADLIB: _soundemu = SOUND_EMU_NONE; break; + case MT_PCJR: + _soundemu = SOUND_EMU_PCJR; + break; + case MT_AMIGA: + _soundemu = SOUND_EMU_AMIGA; + break; default: + debug(0, "DEF"); _soundemu = SOUND_EMU_MIDI; break; } @@ -648,7 +655,7 @@ void AgiEngine::initialize() { _game.state = STATE_LOADED; debugC(2, kDebugLevelMain, "game loaded"); } else { - report("Could not open AGI game"); + warning("Could not open AGI game"); } debugC(2, kDebugLevelMain, "Init sound"); @@ -696,7 +703,6 @@ Common::Error AgiBase::init() { Common::Error AgiEngine::go() { CursorMan.showMouse(true); - report(" \nAGI engine %s is ready.\n", gScummVMVersion); if (_game.state < STATE_LOADED) { do { mainCycle(); @@ -709,6 +715,33 @@ Common::Error AgiEngine::go() { } void AgiEngine::parseFeatures() { + + /* FIXME: Seems this method doesn't really do anything. It might + be a leftover that could be removed, except that some of its + intended purpose may still need to be reimplemented. + + [0:29] can you tell me what the point behind AgiEngine::parseFeatures() is? + [0:30] <_sev> when games are created with WAGI studio + [0:31] <_sev> it creates .wag site with game-specific features such as full game title, whether to use AGIMOUSE etc + [0:32] ... and the "features" config key is created by our detector based on the wag file, I guess? + [0:33] <_sev> yes + [0:33] it's just that I cant seem to find a place we do that + [0:33] <_sev> it is used for fallback + [0:34] <_sev> ah, perhaps it was not updated + [0:34] I only see us check the value, but never set it + [0:34] maybe I am grepping wrong, who knows :) + [0:44] _sev: so, unless I miss something, it seem that function does nothing right now + [0:45] <_sev> Fingolfin: it could be unfinished. It was part of GSoC 3 years ago + [0:45] well + [0:45] <_sev> I just don't remember + [0:45] but don't we just re-parse the wag when the game is loaded anyway? + [0:45] <_sev> but it documents the format + [0:45] the advanced meta engine would re-run the detector, wouldn't it? + [0:45] <_sev> yep + [0:47] so... shouldn't we at least add a comment to the function explaining what it does and that it's unfinished etc.? maybe add a TODO to the wiki? + [0:47] otherwise it might stay as it is for another 3 years :) + */ + if (!ConfMan.hasKey("features")) return; @@ -740,13 +773,15 @@ void AgiEngine::parseFeatures() { for (int i = 0; i < numFeatures; i++) { for (const Flags *flag = flags; flag->name; flag++) { if (!scumm_stricmp(feature[i], flag->name)) { - debug(0, "Added feature: %s", flag->name); + debug(2, "Added feature: %s", flag->name); setFeature(flag->flag); break; } } } + + free(features); } } // End of namespace Agi diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 4df8824b0e8..8ff7f6c35eb 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -52,8 +52,12 @@ namespace Common { class RandomSource; } * * Status of this engine: ??? * - * Supported games: - * - ??? + * Games using this engine: + * - Early Sierra adventure games + * - many fan made games + * - Mickey's Space Adventure (Pre-AGI) + * - Winnie the Pooh in the Hundred Acre Wood (Pre-AGI) + * - Troll's Tale (Pre-AGI) */ namespace Agi { @@ -232,8 +236,6 @@ enum AgiMouseButton { kAgiMouseButtonMiddle // Middle mouse button }; -#define report printf - enum GameId { GID_AGI = 1 }; @@ -556,8 +558,8 @@ struct AgiGame { int lineUserInput; /**< line to put user input on */ int lineMinPrint; /**< num lines to print on */ int cursorPos; /**< column where the input cursor is */ - uint8 inputBuffer[40]; /**< buffer for user input */ - uint8 echoBuffer[40]; /**< buffer for echo.line */ + byte inputBuffer[40]; /**< buffer for user input */ + byte echoBuffer[40]; /**< buffer for echo.line */ int keypress; InputMode inputMode; /**< keyboard input mode */ diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index e5942455e2b..370f48e018e 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -152,7 +152,7 @@ bool Console::Cmd_Flags(int argc, const char **argv) { for (j = 0; j < 10; j++, i++) { DebugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F'); } - report("\n"); + DebugPrintf("\n"); } return true; diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 57bcabb1889..86c1b519a9c 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -319,12 +319,12 @@ int AgiEngine::playGame() { // We run AGIMOUSE always as a side effect if (getFeatures() & GF_AGIMOUSE || true) - report("Using AGI Mouse 1.0 protocol\n"); + debug(1, "Using AGI Mouse 1.0 protocol"); if (getFeatures() & GF_AGIPAL) debug(1, "Running AGIPAL game"); - report("Running AGI script.\n"); + debug(0, "Running AGI script.\n"); setflag(fEnteredCli, false); setflag(fSaidAcceptedInput, false); diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index d1bed5d716e..14ef169c48c 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -435,7 +435,8 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const Common::FSList &fsl // If there's game last edit date in the *.wag file, add it to extra if (wagGameLastEdit != NULL) { - if (!_extra.empty() ) _extra += " "; + if (!_extra.empty()) + _extra += " "; _extra += wagGameLastEdit->getData(); debug(3, "Agi::fallbackDetector: Game's last edit date (%s) from WAG file", wagGameLastEdit->getData()); } diff --git a/engines/agi/id.cpp b/engines/agi/id.cpp index 77c527444bd..2e12e45458b 100644 --- a/engines/agi/id.cpp +++ b/engines/agi/id.cpp @@ -47,7 +47,7 @@ int AgiEngine::setupV2Game(int ver) { if (getFeatures() & GF_AGDS) setVersion(ver = 0x2440); // ALL AGDS games built for 2.440 - report("Setting up for version 0x%04X\n", ver); + debug(0, "Setting up for version 0x%04X", ver); // 'quit' takes 0 args for 2.089 if (ver == 0x2089) @@ -70,7 +70,7 @@ int AgiEngine::setupV2Game(int ver) { int AgiEngine::setupV3Game(int ver) { int ec = errOK; - report("Setting up for version 0x%04X\n", ver); + debug(0, "Setting up for version 0x%04X", ver); // 'unknown176' takes 1 arg for 3.002.086, not 0 args. // 'unknown173' also takes 1 arg for 3.002.068, not 0 args. diff --git a/engines/agi/inv.cpp b/engines/agi/inv.cpp index da56449fda7..46dfcb2b43c 100644 --- a/engines/agi/inv.cpp +++ b/engines/agi/inv.cpp @@ -114,7 +114,7 @@ void AgiEngine::selectItems(int n) { int fsel = 0; bool exit_select = false; - while (!exit_select) { + while (!exit_select && !(shouldQuit() || _restartGame)) { if (n > 0) printItem(fsel, STATUS_BG, STATUS_FG); diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index 62bcd5d8d8b..344654128d3 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -121,7 +121,6 @@ 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 occurred\n", _game.controllers[i].controller); return true; } } diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp index de6f8d0653c..54b40d66b22 100644 --- a/engines/agi/loader_v2.cpp +++ b/engines/agi/loader_v2.cpp @@ -43,7 +43,7 @@ int AgiLoader_v2::loadDir(AgiDir *agid, const char *fname) { uint32 flen; uint i; - report("Loading directory: %s\n", fname); + debug(0, "Loading directory: %s", fname); if (!fp.open(fname)) { return errBadFileOpen; @@ -157,7 +157,7 @@ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { exit(1); } } else { - report("Error: bad signature %04x\n", sig); + warning("AgiLoader_v2::loadVolRes: bad signature %04x", sig); // fprintf (stderr, "ACK! BAD RESOURCE!!!\n"); return 0; } diff --git a/engines/agi/lzw.cpp b/engines/agi/lzw.cpp index 60bd8f4fca7..f645cb16d3c 100644 --- a/engines/agi/lzw.cpp +++ b/engines/agi/lzw.cpp @@ -107,7 +107,7 @@ uint8 *LZWDecoder::decodeString(uint8 *buffer, uint32 code) { *buffer++ = appendCharacter[code]; code = prefixCode[code]; if (i++ >= 4000) { - error("lzw: error in code expansion."); + error("lzw: error in code expansion"); } } *buffer = code; diff --git a/engines/agi/objects.cpp b/engines/agi/objects.cpp index 5d1866bea4a..8de36f24e19 100644 --- a/engines/agi/objects.cpp +++ b/engines/agi/objects.cpp @@ -46,9 +46,9 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) { // if so, its encrypted, else it is not if (READ_LE_UINT16(mem) > flen) { - report("Decrypting objects... "); + debugN(0, "Decrypting objects... "); decrypt(mem, flen); - report("done.\n"); + debug(0, "done."); } // alloc memory for object list @@ -79,7 +79,7 @@ int AgiEngine::decodeObjects(uint8 *mem, uint32 flen) { (_objects + i)->name = strdup(""); } } - report("Reading objects: %d objects read.\n", _game.numObjects); + debug(0, "Reading objects: %d objects read.", _game.numObjects); return errOK; } @@ -92,8 +92,7 @@ int AgiEngine::loadObjects(const char *fname) { _objects = NULL; _game.numObjects = 0; - debugC(5, kDebugLevelResources, "(fname = %s)", fname); - report("Loading objects: %s\n", fname); + debugC(5, kDebugLevelResources, "(Loading objects '%s')", fname); if (!fp.open(fname)) return errBadFileOpen; @@ -130,7 +129,7 @@ void AgiEngine::unloadObjects() { void AgiEngine::objectSetLocation(unsigned int n, int i) { if (n >= _game.numObjects) { - report("Error: Can't access object %d.\n", n); + warning("AgiEngine::objectSetLocation: Can't access object %d.\n", n); return; } _objects[n].location = i; @@ -138,7 +137,7 @@ void AgiEngine::objectSetLocation(unsigned int n, int i) { int AgiEngine::objectGetLocation(unsigned int n) { if (n >= _game.numObjects) { - report("Error: Can't access object %d.\n", n); + warning("AgiEngine::objectGetLocation: Can't access object %d.\n", n); return 0; } return _objects[n].location; @@ -146,7 +145,7 @@ int AgiEngine::objectGetLocation(unsigned int n) { const char *AgiEngine::objectName(unsigned int n) { if (n >= _game.numObjects) { - report("Error: Can't access object %d.\n", n); + warning("AgiEngine::objectName: Can't access object %d.\n", n); return ""; } return _objects[n].name; diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index a60080186c5..2ea53e57ad0 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -492,11 +492,12 @@ void AgiEngine::cmd_init_joy(uint8 *p) { // do nothing } void AgiEngine::cmd_script_size(uint8 *p) { - report("script.size(%d)\n", p0); + debug(0, "script.size(%d)", p0); } void AgiEngine::cmd_cancel_line(uint8 *p) { _game.inputBuffer[0] = 0; + _game.cursorPos = 0; writePrompt(); } @@ -608,7 +609,7 @@ void AgiEngine::cmd_set_simple(uint8 *p) { void AgiEngine::cmd_pop_script(uint8 *p) { if (getVersion() >= 0x2915) { - report("pop.script\n"); + debug(0, "pop.script"); } } @@ -620,7 +621,7 @@ void AgiEngine::cmd_hold_key(uint8 *p) { void AgiEngine::cmd_discard_sound(uint8 *p) { if (getVersion() >= 0x2936) { - report("discard.sound\n"); + debug(0, "discard.sound"); } } @@ -1100,7 +1101,7 @@ void AgiEngine::cmd_set_game_id(uint8 *p) { else _game.id[0] = 0; - report("Game ID: \"%s\"\n", _game.id); + debug(0, "Game ID: \"%s\"", _game.id); } void AgiEngine::cmd_pause(uint8 *p) { @@ -1452,7 +1453,7 @@ void AgiEngine::cmd_clear_text_rect(uint8 *p) { } void AgiEngine::cmd_toggle_monitor(uint8 *p) { - report("toggle.monitor\n"); + debug(0, "toggle.monitor"); } void AgiEngine::cmd_echo_line(uint8 *p) { @@ -1509,7 +1510,7 @@ void AgiEngine::cmd_push_script(uint8 *p) { _game.vars[29] = _mouse.y; } else { if (getVersion() >= 0x2915) { - report("push.script\n"); + debug(0, "push.script"); } } } @@ -1517,7 +1518,7 @@ void AgiEngine::cmd_push_script(uint8 *p) { void AgiEngine::cmd_set_pri_base(uint8 *p) { int i, x, pri; - report("Priority base set to %d\n", p0); + debug(0, "Priority base set to %d", p0); // _game.alt_pri = true; x = (_HEIGHT - p0) * _HEIGHT / 10; diff --git a/engines/agi/op_dbg.cpp b/engines/agi/op_dbg.cpp index be10f6ee753..f3b4815790c 100644 --- a/engines/agi/op_dbg.cpp +++ b/engines/agi/op_dbg.cpp @@ -275,11 +275,11 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) { uint8 a, c, z; if (str) { - report(" %s\n", str); + debug(0, " %s", str); return; } - report("%03d:%04x ", lognum, ip); + debugN(0, "%03d:%04x ", lognum, ip); switch (*(code + ip)) { case 0xFC: @@ -289,7 +289,7 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) { x = logicNamesIf; if (_debug.opcodes) { - report("%02X %02X %02X %02X %02X %02X %02X %02X %02X\n" + debugN(0, "%02X %02X %02X %02X %02X %02X %02X %02X %02X\n" " ", (uint8)*(code + (0 + ip)) & 0xFF, (uint8)*(code + (1 + ip)) & 0xFF, @@ -301,7 +301,7 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) { (uint8)*(code + (7 + ip)) & 0xFF, (uint8)*(code + (8 + ip)) & 0xFF); } - report("%s ", (x + *(code + ip) - 0xFC)->name); + debugN(0, "%s ", (x + *(code + ip) - 0xFC)->name); break; default: x = mode == lCOMMAND_MODE ? logicNamesCmd : logicNamesTest; @@ -309,7 +309,7 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) { c = (unsigned char)(x + *(code + ip))->argMask; if (_debug.opcodes) { - report("%02X %02X %02X %02X %02X %02X %02X %02X %02X\n" + debugN(0, "%02X %02X %02X %02X %02X %02X %02X %02X %02X\n" " ", (uint8)*(code + (0 + ip)) & 0xFF, (uint8)*(code + (1 + ip)) & 0xFF, @@ -321,23 +321,23 @@ void AgiEngine::debugConsole(int lognum, int mode, const char *str) { (uint8)*(code + (7 + ip)) & 0xFF, (uint8)*(code + (8 + ip)) & 0xFF); } - report("%s ", (x + *(code + ip))->name); + debugN(0, "%s ", (x + *(code + ip))->name); for (z = 1; a > 0;) { if (~c & 0x80) { - report("%d", *(code + (ip + z))); + debugN(0, "%d", *(code + (ip + z))); } else { - report("v%d[%d]", *(code + (ip + z)), getvar(*(code + (ip + z)))); + debugN(0, "v%d[%d]", *(code + (ip + z)), getvar(*(code + (ip + z)))); } c <<= 1; z++; if (--a > 0) - report(","); + debugN(0, ","); } break; } - report("\n"); + debugN(0, "\n"); } } // End of namespace Agi diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index dc77433cb23..47b72cc8c67 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -562,7 +562,7 @@ void PictureMgr::drawPicture() { _patCode = 0; _patNum = 0; _priOn = _scrOn = false; - _scrColor = 0xf; + _scrColor = (_pictureVersion == AGIPIC_C64) ? 0x0 : 0xf; _priColor = 0x4; drawing = 1; diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index ec8a1f48781..ea041a93c7b 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -302,6 +302,8 @@ void Mickey::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, i if (y != IDI_MSA_ROW_MENU_1) return; sel = sel1; break; + default: + return; } for (iWord = 0; iWord < menu.row[iRow].count; iWord++) { @@ -1234,7 +1236,7 @@ int Mickey::getPlanet() { if (!_game.nButtons) return -1; - for (int iPlanet = 0; iPlanet < IDI_MSA_MAX_DAT; iPlanet++) { + for (int iPlanet = 0; iPlanet < IDI_MSA_MAX_DAT - 1; iPlanet++) { if (!strcmp(IDS_MSA_ADDR_PLANET[iPlanet], _game.szAddr)) { return iPlanet; } @@ -1313,7 +1315,7 @@ void Mickey::flipSwitch() { _game.iPlanetXtal[0] = IDI_MSA_PLANET_EARTH; _game.iPlanetXtal[8] = IDI_MSA_PLANET_URANUS; - for (int i = 1; i < 9; i++) { + for (int i = 1; i < IDI_MSA_MAX_PLANET; i++) { if (i < 8) { do { // Earth (planet 0) and Uranus (planet 8) are excluded diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp index 153fec641a1..414477a3816 100644 --- a/engines/agi/predictive.cpp +++ b/engines/agi/predictive.cpp @@ -210,13 +210,12 @@ bool AgiEngine::predictiveDialog() { } } - temp[MAXWORDLEN] = 0; - - strncpy(temp, prefix.c_str(), MAXWORDLEN); - strncat(temp, _currentWord.c_str(), MAXWORDLEN); + Common::strlcpy(temp, prefix.c_str(), sizeof(temp)); + Common::strlcat(temp, _currentWord.c_str(), sizeof(temp)); for (int i = prefix.size() + _currentCode.size(); i < MAXWORDLEN; i++) temp[i] = ' '; + temp[MAXWORDLEN] = 0; printText(temp, 0, 8, 7, MAXWORDLEN, 15, 0); _gfx->flushBlock(62, 54, 249, 66); @@ -461,9 +460,8 @@ bool AgiEngine::predictiveDialog() { } press: - strncpy(_predictiveResult, prefix.c_str(), 40); - strncat(_predictiveResult, _currentWord.c_str(), 40); - _predictiveResult[prefix.size() + _currentCode.size() + 1] = 0; + Common::strlcpy(_predictiveResult, prefix.c_str(), sizeof(_predictiveResult)); + Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult)); getout: // if another window was shown, bring it up again @@ -518,7 +516,7 @@ void AgiEngine::loadDict() { _predictiveDictLine = (char **)calloc(1, sizeof(char *) * lines); if (_predictiveDictLine == NULL) { - warning("Cannot allocate memory for line index buffer."); + warning("Cannot allocate memory for line index buffer"); return; } _predictiveDictLine[0] = _predictiveDictText; diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 88b14dcfe2c..1a968816d43 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -333,7 +333,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { debug(0, "Saved game MD5: \"%s\"", md5); if (!getGameMD5()) { - warning("Since your game was only detected via the fallback detector, there is no possibility to assure the save is compatible with your game version."); + warning("Since your game was only detected via the fallback detector, there is no possibility to assure the save is compatible with your game version"); debug(0, "The game used for saving is \"%s\".", md5); } else if (strcmp(md5, getGameMD5())) { @@ -809,12 +809,11 @@ int AgiEngine::saveGameDialog() { printText("Select a slot in which you wish to\nsave the game:", 0, hm + 1, vm + 1, w, MSG_BOX_TEXT, MSG_BOX_COLOUR); slot = selectSlot(); - if (slot == 0) + if (slot + _firstSlot == 0) messageBox("That slot is for Autosave only."); else if (slot < 0) return errOK; - } - while (slot == 0); + } while (slot + _firstSlot == 0); drawWindow(hp, vp + 5 * CHAR_LINES, GFX_WIDTH - hp, GFX_HEIGHT - vp - 9 * CHAR_LINES); diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index cb4e307ea6e..b215822917a 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -176,9 +176,9 @@ SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) { case SOUND_EMU_NONE: case SOUND_EMU_AMIGA: case SOUND_EMU_MAC: + case SOUND_EMU_PC: _soundGen = new SoundGenSarien(_vm, pMixer); break; - case SOUND_EMU_PC: case SOUND_EMU_PCJR: _soundGen = new SoundGenPCJr(_vm, pMixer); break; diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp index f054be0682e..858c1c8515d 100644 --- a/engines/agi/sound_coco3.cpp +++ b/engines/agi/sound_coco3.cpp @@ -61,9 +61,9 @@ void SoundGenCoCo3::play(int resnum) { uint32 start_time = _vm->_system->getMillis(); while (_vm->_system->getMillis() < start_time + note.duration) { - _vm->_system->updateScreen(); + _vm->_system->updateScreen(); - _vm->_system->delayMillis(10); + _vm->_system->delayMillis(10); } } } while (note.freq != 0xff); diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp index 840538b92ba..f7f38a8d55c 100644 --- a/engines/agi/sound_midi.cpp +++ b/engines/agi/sound_midi.cpp @@ -74,8 +74,15 @@ SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB); _driver = MidiDriver::createMidi(dev); + if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) { + _nativeMT32 = true; + _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + } else { + _nativeMT32 = false; + } + memset(_channel, 0, sizeof(_channel)); - memset(_channelVolume, 255, sizeof(_channelVolume)); + memset(_channelVolume, 127, sizeof(_channelVolume)); _masterVolume = 0; this->open(); _smfParser = MidiParser::createParser_SMF(); @@ -122,10 +129,10 @@ int SoundGenMIDI::open() { _driver->setTimerCallback(this, &onTimer); - // General MIDI System On message - // Resets all GM devices to default settings - _driver->sysEx((const byte *)"\x7E\x7F\x09\x01", 4); - g_system->delayMillis(20); + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); return 0; } @@ -287,7 +294,7 @@ static uint32 convertSND2MIDI(byte *snddata, byte **data) { for (n = 0; n < 3; n++) { uint16 start, end, pos; - + st.write("MTrk", 4); lp = st.pos(); st.writeUint32BE(0); /* chunklength */ diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp index b9d701d7f71..35c960d2606 100644 --- a/engines/agi/sound_pcjr.cpp +++ b/engines/agi/sound_pcjr.cpp @@ -125,6 +125,9 @@ SoundGenPCJr::SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p _dissolveMethod = 3; + memset(_channel, 0, sizeof(_channel)); + memset(_tchannel, 0, sizeof(_tchannel)); + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); } @@ -158,7 +161,7 @@ void SoundGenPCJr::play(int resnum) { void SoundGenPCJr::stop(void) { int i; - for (i = 0; i < CHAN_MAX ; i++) { + for (i = 0; i < CHAN_MAX; i++) { _channel[i].avail = 0; _tchannel[i].avail = 0; } diff --git a/engines/agi/sound_sarien.cpp b/engines/agi/sound_sarien.cpp index 08bdd474974..4ede50a7490 100644 --- a/engines/agi/sound_sarien.cpp +++ b/engines/agi/sound_sarien.cpp @@ -95,13 +95,10 @@ SoundGenSarien::SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(v break; } - report("Initializing sound:\n"); - - report("sound: envelopes "); if (_env) { - report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN); + debug(0, "Initializing sound: envelopes enabled (decay=%d, sustain=%d)", ENV_DECAY, ENV_SUSTAIN); } else { - report("disabled\n"); + debug(0, "Initializing sound: envelopes disabled"); } _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp index 464c218ae87..c48ed90ad8d 100644 --- a/engines/agi/words.cpp +++ b/engines/agi/words.cpp @@ -52,10 +52,10 @@ int AgiEngine::loadWords(const char *fname) { words = NULL; if (!fp.open(fname)) { - report("Warning: can't open %s\n", fname); + warning("loadWords: can't open %s", fname); return errOK; // err_BadFileOpen } - report("Loading dictionary: %s\n", fname); + debug(0, "Loading dictionary: %s", fname); fp.seek(0, SEEK_END); flen = fp.pos(); diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 670c7011981..10b6416c61d 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -562,11 +562,11 @@ Common::Error AGOSEngine::init() { _driver = MidiDriver::createMidi(dev); - if (_nativeMT32) { + if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - } - _midi.mapMT32toGM (getGameType() != GType_SIMON2 && !_nativeMT32); + _midi.setNativeMT32(_nativeMT32); + _midi.mapMT32toGM(getGameType() != GType_SIMON2 && !_nativeMT32); _midi.setDriver(_driver); @@ -926,10 +926,10 @@ AGOSEngine::~AGOSEngine() { free(_textMem); free(_xtblList); - free(_backGroundBuf); - free(_backBuf); + delete _backGroundBuf; + delete _backBuf; free(_planarBuf); - free(_scaleBuf); + delete _scaleBuf; free(_zoneBuffers); free(_window4BackScn); diff --git a/engines/agos/agos.h b/engines/agos/agos.h index b12bf09d620..5ebfc7b87f4 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -47,8 +47,13 @@ * * Status of this engine: ??? * - * Supported games: - * - ??? + * Games using this engine: + * - Elvira: Mistress of the Dark + * - Elvira 2: The Jaws of Cerberus + * - The Feeble Files + * - Simon the Sorcerer + * - Simon the Sorcerer 2 + * - Simon the Sorcerer Puzzle Pack */ namespace AGOS { diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 1b3ac9fd65f..af85c501144 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -372,10 +372,10 @@ bool MoviePlayerDXA::processFrame() { _vm->_system->unlockScreen(); Common::Rational soundTime(_mixer->getSoundElapsedTime(_bgSound), 1000); - if ((_bgSoundStream == NULL) || ((int)(soundTime * getFrameRate()) / 1000 < getCurFrame() + 1)) { + if ((_bgSoundStream == NULL) || ((soundTime * getFrameRate()).toInt() / 1000 < getCurFrame() + 1)) { if (_bgSoundStream && _mixer->isSoundHandleActive(_bgSound)) { - while (_mixer->isSoundHandleActive(_bgSound) && ((int) (soundTime * getFrameRate())) < getCurFrame()) { + while (_mixer->isSoundHandleActive(_bgSound) && (soundTime * getFrameRate()).toInt() < getCurFrame()) { _vm->_system->delayMillis(10); soundTime = Common::Rational(_mixer->getSoundElapsedTime(_bgSound), 1000); } diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp index 874bf1a8025..6c6b127a51d 100644 --- a/engines/agos/items.cpp +++ b/engines/agos/items.cpp @@ -429,6 +429,9 @@ Item *AGOSEngine::findMaster(int16 a, int16 n) { for (j = 1; j < _itemArraySize; j++) { Item *item = derefItem(j); + if (item == NULL) + continue; + if (wordMatch(item, a, n)) return item; } @@ -442,6 +445,9 @@ Item *AGOSEngine::nextMaster(Item *i, int16 a, int16 n) { for (j = first; j < _itemArraySize; j++) { Item *item = derefItem(j); + if (item == NULL) + continue; + if (wordMatch(item, a, n)) return item; } diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp index ab5bfc4c94e..858307685c6 100644 --- a/engines/agos/midi.cpp +++ b/engines/agos/midi.cpp @@ -77,10 +77,10 @@ int MidiPlayer::open() { return ret; _driver->setTimerCallback(this, &onTimer); - // General MIDI System On message - // Resets all GM devices to default settings - _driver->sysEx((const byte *)"\x7E\x7F\x09\x01", 4); - g_system->delayMillis(20); + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); return 0; } diff --git a/engines/agos/midi.h b/engines/agos/midi.h index d4c09118f64..d76997737a6 100644 --- a/engines/agos/midi.h +++ b/engines/agos/midi.h @@ -61,6 +61,7 @@ protected: MidiDriver *_driver; bool _map_mt32_to_gm; bool _passThrough; + bool _nativeMT32; MusicInfo _music; MusicInfo _sfx; @@ -97,6 +98,7 @@ public: void loadS1D(Common::File *in, bool sfx = false); void mapMT32toGM(bool map); + void setNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; } void setLoop(bool loop); void startTrack(int track); void queueTrack(int track, bool loop); diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp index e9fbaf35259..ffa95506c59 100644 --- a/engines/agos/saveload.cpp +++ b/engines/agos/saveload.cpp @@ -26,6 +26,7 @@ #include "common/file.h" #include "common/savefile.h" #include "common/system.h" +#include "common/translation.h" #include "gui/about.h" #include "gui/message.h" @@ -146,14 +147,14 @@ void AGOSEngine::quickLoadOrSave() { } bool success; - char buf[60]; + Common::String buf; char *filename = genSaveName(_saveLoadSlot); if (_saveLoadType == 2) { Subroutine *sub; success = loadGame(genSaveName(_saveLoadSlot)); if (!success) { - sprintf(buf, "Failed to load game state to file:\n\n%s", filename); + buf = Common::String::printf(_("Failed to load game state from file:\n\n%s"), filename); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { drawIconArray(2, me(), 0, 0); setBitFlag(97, true); @@ -188,7 +189,7 @@ void AGOSEngine::quickLoadOrSave() { } else { success = saveGame(_saveLoadSlot, _saveLoadName); if (!success) - sprintf(buf, "Failed to save game state to file:\n\n%s", filename); + buf = Common::String::printf(_("Failed to save game state to file:\n\n%s"), filename); } if (!success) { @@ -196,7 +197,7 @@ void AGOSEngine::quickLoadOrSave() { dialog.runModal(); } else if (_saveLoadType == 1) { - sprintf(buf, "Successfully saved game state in file:\n\n%s", filename); + buf = Common::String::printf(_("Successfully saved game state in file:\n\n%s"), filename); GUI::TimedMessageDialog dialog(buf, 1500); dialog.runModal(); diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp index 0391d67b31a..909c051362f 100644 --- a/engines/agos/script_pn.cpp +++ b/engines/agos/script_pn.cpp @@ -890,7 +890,7 @@ int AGOSEngine_PN::doline(int needsave) { int myTag = ++_tagOfActiveDoline; // Obtain a unique tag for this doline invocation _dolineReturnVal = 0; - if (needsave) + if (_stackbase && needsave) _stackbase->tagOfParentDoline = myTag; do { diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp index bd4c89a4042..6ec72814fa2 100644 --- a/engines/agos/sound.cpp +++ b/engines/agos/sound.cpp @@ -776,7 +776,7 @@ void Sound::playVoiceData(byte *soundData, uint sound) { } void Sound::playSoundData(Audio::SoundHandle *handle, byte *soundData, uint sound, int pan, int vol, bool loop) { - int size = READ_LE_UINT32(soundData + 4); + int size = READ_LE_UINT32(soundData + 4) + 8; Common::MemoryReadStream *stream = new Common::MemoryReadStream(soundData, size); Audio::RewindableAudioStream *sndStream = Audio::makeWAVStream(stream, DisposeAfterUse::YES); diff --git a/engines/agos/verb_pn.cpp b/engines/agos/verb_pn.cpp index 129e1dec0e0..b36f634ec02 100644 --- a/engines/agos/verb_pn.cpp +++ b/engines/agos/verb_pn.cpp @@ -185,7 +185,7 @@ void AGOSEngine_PN::hitBox5(HitArea *ha) { _mousePrintFG++; _mouseString = (const char *)"take \0"; - _mouseString1 = getMessage(_objectName1, _dragStore->msg1); + _mouseString1 = _dragStore ? getMessage(_objectName1, _dragStore->msg1) : ""; if (_dragStore->flags & kOBFRoomBox) _mouseString1 = (const char *)"all\r"; diff --git a/engines/cine/cine.h b/engines/cine/cine.h index 114d98d442b..cab6b92a5d4 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -71,7 +71,7 @@ * yet been finished. The game is not completable. * * - * Supported games: + * Games using this engine: * * Cinematique evo.1 * - Future Wars diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp index 27d0e593da4..34b196d5c7d 100644 --- a/engines/cine/pal.cpp +++ b/engines/cine/pal.cpp @@ -186,8 +186,7 @@ const Graphics::PixelFormat &Palette::colorFormat() const { void Palette::setGlobalOSystemPalette() const { byte buf[256 * 4]; // Allocate space for the largest possible palette // The color format used by OSystem's setPalette-function: - static const Graphics::PixelFormat kSystemPalFormat(4, 8, 8, 8, 0, 0, 8, 16, 0); - save(buf, sizeof(buf), kSystemPalFormat, CINE_LITTLE_ENDIAN); + save(buf, sizeof(buf), Graphics::PixelFormat(4, 8, 8, 8, 0, 0, 8, 16, 0), CINE_LITTLE_ENDIAN); if (g_cine->getPlatform() == Common::kPlatformAmiga && colorCount() == 16) { // The Amiga version of Future Wars does use the upper 16 colors for a darkened diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp index 95f3789abd4..f5c94023882 100644 --- a/engines/cine/part.cpp +++ b/engines/cine/part.cpp @@ -164,7 +164,7 @@ void CineEngine::readVolCnf() { // All file name blocks' sizes were divisible by either 11 or 13, but not with both. fileNameLength = (fileNameLenMod11 ? 11 : 13); } else { - warning("Couldn't deduce file name length from data in 'vol.cnf', using a backup deduction scheme."); + warning("Couldn't deduce file name length from data in 'vol.cnf', using a backup deduction scheme"); // Here we use the former file name length detection method // if we couldn't deduce the file name length from the data. fileNameLength = (compressed ? 11 : 13); diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index 430a32ac69b..5db9a83928a 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -3098,7 +3098,7 @@ void decompileScript(const byte *scriptPtr, uint16 scriptSize, uint16 scriptIdx) } void dumpScript(char *dumpName) { - Common::DumpFile fHandle; + Common::DumpFile fHandle; uint16 i; fHandle.open(dumpName); diff --git a/engines/cruise/background.cpp b/engines/cruise/background.cpp index 3ac57cc3762..edd52d3b4a6 100644 --- a/engines/cruise/background.cpp +++ b/engines/cruise/background.cpp @@ -216,8 +216,7 @@ int loadBackground(const char *name, int idx) { if (strlen(name) >= sizeof(backgroundTable[idx].name)) warning("background name length exceeded allowable maximum"); - strncpy(backgroundTable[idx].name, name, sizeof(backgroundTable[idx].name)); - backgroundTable[idx].name[sizeof(backgroundTable[idx].name) - 1] = 0; + Common::strlcpy(backgroundTable[idx].name, name, sizeof(backgroundTable[idx].name)); } return (0); diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h index 94f5c68ca0a..ad3bb20ca11 100644 --- a/engines/cruise/cruise.h +++ b/engines/cruise/cruise.h @@ -42,7 +42,7 @@ * * Status of this engine: Game is completable, engine needs objectifying * - * Supported games: + * Games using this engine: * - Cruise for a Corpse */ namespace Cruise { diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp index b2ac7a2fd68..b48240b30e6 100644 --- a/engines/cruise/dataLoader.cpp +++ b/engines/cruise/dataLoader.cpp @@ -55,7 +55,7 @@ void decodeGfxUnified(dataFileEntry *pCurrentFileEntry, int16 format) { break; default: - error("Unkown gfx format %d", format); + error("Unknown gfx format %d", format); } uint8 *buffer = (uint8 *)MemAlloc(spriteSize); diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index 3d07abf4415..c3d435bde60 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -58,9 +58,9 @@ int16 Op_LoadOverlay() { updateAllScriptsImports(); - strcpy(nextOverlay, overlayName); + Common::strlcpy(nextOverlay, overlayName, sizeof(nextOverlay)); - return(overlayLoadResult); + return overlayLoadResult; } int16 Op_Strcpy() { diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp index 2ffaa29e4af..e5a1136c23a 100644 --- a/engines/cruise/menu.cpp +++ b/engines/cruise/menu.cpp @@ -29,6 +29,7 @@ #include "engines/metaengine.h" #include "gui/saveload.h" +#include "common/translation.h" namespace Cruise { @@ -212,9 +213,9 @@ static void handleSaveLoad(bool saveFlag) { EngineMan.findGame(_vm->getGameId(), &plugin); GUI::SaveLoadChooser *dialog; if (saveFlag) - dialog = new GUI::SaveLoadChooser("Save game:", "Save"); + dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save")); else - dialog = new GUI::SaveLoadChooser("Load game:", "Load"); + dialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load")); dialog->setSaveMode(saveFlag); int slot = dialog->runModal(plugin, ConfMan.getActiveDomainName()); diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp index d6c1aa47f34..3d07575c165 100644 --- a/engines/cruise/script.cpp +++ b/engines/cruise/script.cpp @@ -185,8 +185,9 @@ int32 opcodeType1() { return 0; } case 2: { + assert (ptr); *(ptr + var_A + offset) = var; - return (0); + return 0; } default: error("Unsupported code in opcodeType1 case 1"); diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp index c61cedc5039..07bd646caef 100644 --- a/engines/cruise/vars.cpp +++ b/engines/cruise/vars.cpp @@ -51,8 +51,8 @@ int32 volumeDataLoaded = 0; int16 numOfDisks; -char lastOverlay[15]; -char nextOverlay[15]; +char lastOverlay[38]; +char nextOverlay[38]; int16 currentActiveMenu; int16 autoMsg; diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h index af39993f2ff..54920a14366 100644 --- a/engines/cruise/vars.h +++ b/engines/cruise/vars.h @@ -154,8 +154,8 @@ extern int32 volumeDataLoaded; extern int16 numOfDisks; -extern char lastOverlay[15]; -extern char nextOverlay[15]; +extern char lastOverlay[38]; +extern char nextOverlay[38]; extern int16 currentActiveMenu; extern int16 autoMsg; diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index cb081e46838..6b0f4d3b398 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -36,6 +36,7 @@ #include "gui/GuiManager.h" #include "gui/launcher.h" #include "gui/ListWidget.h" +#include "gui/message.h" #include "gui/options.h" #include "gui/saveload.h" #include "gui/ThemeEval.h" @@ -102,7 +103,6 @@ MainMenuDialog::MainMenuDialog(Engine *engine) // 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", _("~H~elp"), 0, kHelpCmd); - _helpButton->setEnabled(false); new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), 0, kAboutCmd); @@ -147,8 +147,13 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat case kAboutCmd: _aboutDialog->runModal(); break; - case kHelpCmd: - // Not handled here -- needs to be handled by a subclass (for now) + case kHelpCmd: { + GUI::MessageDialog dialog( + "Sorry, this engine does not currently provide in-game help. " + "Please consult the README for basic information, and for " + "instructions on how to obtain further assistance."); + dialog.runModal(); + } break; case kRTLCmd: { Common::Event eventRTL; diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp index 07a9928cfa2..ce426740fa6 100644 --- a/engines/draci/detection.cpp +++ b/engines/draci/detection.cpp @@ -202,10 +202,7 @@ SaveStateDescriptor DraciMetaEngine::querySaveMetaInfos(const char *target, int int minutes = header.time & 0xFF; desc.setSaveTime(hour, minutes); - minutes = header.playtime / 60; - hour = minutes / 60; - minutes %= 60; - desc.setPlayTime(hour, minutes); + desc.setPlayTime(header.playtime * 1000); return desc; } diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index cd3920b30d0..7a7d7b83724 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -170,6 +170,7 @@ int DraciEngine::init() { _music = new MusicPlayer(_midiDriver, musicPathMask); _music->setNativeMT32(native_mt32); + _music->open(); //_music->setAdLib(adlib); // Load the game's fonts @@ -402,7 +403,7 @@ DraciEngine::~DraciEngine() { Common::Error DraciEngine::run() { init(); - _engineStartTime = _system->getMillis() / 1000; + setTotalPlayTime(0); _game->init(); // Load game from specified slot, if any @@ -417,8 +418,6 @@ Common::Error DraciEngine::run() { void DraciEngine::pauseEngineIntern(bool pause) { Engine::pauseEngineIntern(pause); if (pause) { - // Record start of the pause, so that we can later - // adjust _engineStartTime accordingly. _pauseStartTime = _system->getMillis(); _anims->pauseAnimations(); @@ -433,7 +432,6 @@ void DraciEngine::pauseEngineIntern(bool pause) { // Adjust engine start time const int delta = _system->getMillis() - _pauseStartTime; - _engineStartTime += delta / 1000; _game->shiftSpeechAndFadeTick(delta); _pauseStartTime = 0; } diff --git a/engines/draci/draci.h b/engines/draci/draci.h index 605e8cc2380..f2cc2ce2e79 100644 --- a/engines/draci/draci.h +++ b/engines/draci/draci.h @@ -37,10 +37,10 @@ class OSystem; /** * This is the namespace of the Draci engine. * - * Status of this engine: ??? + * Status of this engine: Complete * - * Supported games: - * - ??? + * Games using this engine: + * - Dragon History */ namespace Draci { @@ -107,7 +107,6 @@ public: Common::RandomSource _rnd; - int32 _engineStartTime; int32 _pauseStartTime; }; diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 8f3ad12cfdb..cb2832552a4 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -207,7 +207,7 @@ void Game::init() { _currentItem = _itemUnderCursor = NULL; _previousItemPosition = -1; - + _vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor _objUnderCursor = NULL; @@ -1618,15 +1618,15 @@ int GameObject::addAnim(Animation *anim) { } void GameObject::playAnim(int i) { - _anim[i]->play(); - _playingAnim = i; + _anim[i]->play(); + _playingAnim = i; } void GameObject::stopAnim() { - if (_playingAnim >= 0) { - _anim[_playingAnim]->stop(); - _playingAnim = -1; - } + if (_playingAnim >= 0) { + _anim[_playingAnim]->stop(); + _playingAnim = -1; + } } void GameObject::deleteAnims() { diff --git a/engines/draci/mouse.cpp b/engines/draci/mouse.cpp index 1d251d24c3f..14d1162fed6 100644 --- a/engines/draci/mouse.cpp +++ b/engines/draci/mouse.cpp @@ -54,10 +54,10 @@ void Mouse::handleEvent(Common::Event event) { case Common::EVENT_LBUTTONUP: debugC(6, kDraciGeneralDebugLevel, "Left button up (x: %u y: %u)", _x, _y); - // Don't set _lButton to false, because some touchpads generate - // down and up at such a quick succession, that they will - // cancel each other in the same call of handleEvents(). Let - // the game clear this flag by calling lButtonSet() instead. + // Don't set _lButton to false, because some touchpads generate + // down and up at such a quick succession, that they will + // cancel each other in the same call of handleEvents(). Let + // the game clear this flag by calling lButtonSet() instead. break; case Common::EVENT_RBUTTONDOWN: diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp index 8186d36068f..95b7ae08da2 100644 --- a/engines/draci/music.cpp +++ b/engines/draci/music.cpp @@ -38,15 +38,10 @@ namespace Draci { MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0), _driver(driver), _pathMask(pathMask), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false), _track(-1) { memset(_channel, 0, sizeof(_channel)); - memset(_channelVolume, 255, sizeof(_channelVolume)); + memset(_channelVolume, 127, sizeof(_channelVolume)); _masterVolume = 0; - this->open(); _smfParser = MidiParser::createParser_SMF(); _midiMusicData = NULL; - - // TODO: Load cmf.ins with the instrument table. It seems that an - // interface for such an operation is supported for AdLib. Maybe for - // this card, setting instruments is necessary. } MusicPlayer::~MusicPlayer() { @@ -89,6 +84,15 @@ int MusicPlayer::open() { if (ret) return ret; + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); + + // TODO: Load cmf.ins with the instrument table. It seems that an + // interface for such an operation is supported for AdLib. Maybe for + // this card, setting instruments is necessary. + _driver->setTimerCallback(this, &onTimer); return 0; } diff --git a/engines/draci/saveload.cpp b/engines/draci/saveload.cpp index 856e6da8326..32e852d9a6d 100644 --- a/engines/draci/saveload.cpp +++ b/engines/draci/saveload.cpp @@ -103,7 +103,7 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, header.saveName = saveName; header.date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); header.time = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); - header.playtime = vm._system->getMillis() / 1000 - vm._engineStartTime; + header.playtime = vm.getTotalPlayTime() / 1000; writeSavegameHeader(f, header); if (f->err()) { @@ -157,7 +157,7 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) { vm->_game->inventoryReload(); - vm->_engineStartTime = vm->_system->getMillis() / 1000 - header.playtime; + vm->setTotalPlayTime(header.playtime * 1000); return Common::kNoError; } diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index c9244d7eac3..6828066c3a2 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -407,14 +407,14 @@ void Sound::stopVoice() { } void Sound::setVolume() { - if (_mixer->isReady()) { - _muteSound = ConfMan.getBool("sfx_mute"); - _muteVoice = ConfMan.getBool("speech_mute"); - } else { - _muteSound = _muteVoice = true; - } + if (_mixer->isReady()) { + _muteSound = ConfMan.getBool("sfx_mute"); + _muteVoice = ConfMan.getBool("speech_mute"); + } else { + _muteSound = _muteVoice = true; + } if (ConfMan.getBool("mute")) { - _muteSound = _muteVoice = true; + _muteSound = _muteVoice = true; } _showSubtitles = ConfMan.getBool("subtitles"); _talkSpeed = ConfMan.getInt("talkspeed"); diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index d6a3bafd9f4..10f1bf4651e 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -761,17 +761,10 @@ void DrasculaEngine::animation_16_2() { clearRoom(); - // FIXME: Track 31 is missing from the soundtrack available - // from ScummVM's downloads page, so for now we're using the - // Spanish track 29 -#if 1 - playMusic(30); -#else if (_lang == kSpanish) playMusic(30); else playMusic(32); -#endif if (getScan() != 0) goto asco; diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index 0e703481482..d0906fdf55e 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -211,6 +211,7 @@ void DrasculaEngine::converse(int index) { } updateEvents(); + flushKeyBuffer(); phrase1_bottom = 8 * print_abc_opc(phrase1, 2, game1); phrase2_bottom = phrase1_bottom + 8 * print_abc_opc(phrase2, phrase1_bottom + 2, game2); @@ -287,8 +288,12 @@ void DrasculaEngine::response(int function) { playTalkSequence(function); if (currentChapter == 2) { - if (function == 16 || function == 20 || function == 23 || function == 29 || function == 31) + bool reloadConversationCharset = false; + + if (function == 16 || function == 20 || function == 23 || function == 29 || function == 31) { + reloadConversationCharset = true; loadPic(menuBackground, backSurface); + } if (function == 16) animation_16_2(); @@ -300,6 +305,9 @@ void DrasculaEngine::response(int function) { animation_29_2(); else if (function == 31) animation_31_2(); + + if (reloadConversationCharset) + loadPic("car.alg", backSurface); } else if (currentChapter == 3) { grr(); } diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index c10222cadd9..0dafcdc3cdf 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -240,6 +240,23 @@ static const DrasculaGameDescription gameDescriptions[] = { GUIO_NONE }, }, + + { + // Drascula French version (ScummVM repacked files) + { + "drascula", + 0, + { + {"packet.001", 0, "c6a8697396e213a18472542d5f547cb4", 32847563}, + {"packet.002", 1, "7b83cedb9bb326ed5143e5c459508d43", 722383}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + GF_PACKED, + GUIO_NONE + }, + }, { AD_TABLE_END_MARKER } }; diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index 0a8b7c8c9b3..535a9005d23 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -47,8 +47,8 @@ * * Status of this engine: ??? * - * Supported games: - * - ??? + * Games using this engine: + * - Drascula: The Vampire Strikes Back */ namespace Drascula { diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index 1495694a1b9..1d17c77f83b 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -120,7 +120,7 @@ void DrasculaEngine::showMenu() { x = whichObject(); strcpy(textIcon, iconName[x]); - for (n = 1; n < 43; n++) { + for (n = 1; n < ARRAYSIZE(inventoryObjects); n++) { h = inventoryObjects[n]; if (h != 0) { @@ -194,11 +194,10 @@ void DrasculaEngine::enterName() { } bool DrasculaEngine::checkMenuFlags() { - for (int n = 0; n < 43; n++) { - if (whichObject() == n) { - if (inventoryObjects[n] != 0 && checkAction(inventoryObjects[n])) - return true; - } + int n = whichObject(); + if (n != 0) { + if (inventoryObjects[n] != 0 && checkAction(inventoryObjects[n])) + return true; } return false; diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp index 73aea7b7f2d..2bd10140838 100644 --- a/engines/drascula/objects.cpp +++ b/engines/drascula/objects.cpp @@ -221,16 +221,17 @@ void DrasculaEngine::addObject(int obj) { * If no inventory slot is under the mouse cursor, return 0. */ int DrasculaEngine::whichObject() { - int n = 0; + int n; for (n = 1; n < ARRAYSIZE(inventoryObjects); n++) { if (mouseX > _itemLocations[n].x && mouseY > _itemLocations[n].y && mouseX < _itemLocations[n].x + OBJWIDTH && - mouseY < _itemLocations[n].y + OBJHEIGHT) - break; + mouseY < _itemLocations[n].y + OBJHEIGHT) { + return n; + } } - return n; + return 0; } void DrasculaEngine::updateVisible() { diff --git a/engines/drascula/resource.cpp b/engines/drascula/resource.cpp index 1226bc2e10e..57be51da430 100644 --- a/engines/drascula/resource.cpp +++ b/engines/drascula/resource.cpp @@ -92,13 +92,19 @@ void TextResourceParser::getLine(char *buf) { void TextResourceParser::parseInt(int &result) { char buf[256]; getLine(buf); - sscanf(buf, "%d", &result); + + if (!sscanf(buf, "%d", &result)) { + result = 0; + } } void TextResourceParser::parseString(char* result) { char buf[256]; getLine(buf); - sscanf(buf, "%s", result); + + if (!sscanf(buf, "%s", result)) { + *result = 0; + } } diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index 57bfad26afe..c6dd9f29dbe 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -1945,7 +1945,9 @@ bool DrasculaEngine::exitRoom(int doorNumber) { hare_se_ve = 1; clearRoom(); - sscanf(_targetSurface[doorNumber], "%d", &roomNum); + if (!sscanf(_targetSurface[doorNumber], "%d", &roomNum)) { + error("Malformed roomNum in targetSurface (%s)", _targetSurface[doorNumber]); + } curX = -1; enterRoom(roomNum); diff --git a/engines/drascula/saveload.cpp b/engines/drascula/saveload.cpp index abf17d0e8e0..4c288553a27 100644 --- a/engines/drascula/saveload.cpp +++ b/engines/drascula/saveload.cpp @@ -210,7 +210,7 @@ bool DrasculaEngine::loadGame(const char *gameName) { curY = sav->readSint32LE(); trackProtagonist = sav->readSint32LE(); - for (l = 1; l < 43; l++) { + for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) { inventoryObjects[l] = sav->readSint32LE(); } @@ -221,7 +221,9 @@ bool DrasculaEngine::loadGame(const char *gameName) { takeObject = sav->readSint32LE(); pickedObject = sav->readSint32LE(); loadedDifferentChapter = 0; - sscanf(currentData, "%d.ald", &roomNum); + if (!sscanf(currentData, "%d.ald", &roomNum)) { + error("Bad save format"); + } enterRoom(roomNum); selectVerb(kVerbNone); @@ -241,7 +243,7 @@ void DrasculaEngine::saveGame(char gameName[]) { out->writeSint32LE(curY); out->writeSint32LE(trackProtagonist); - for (l = 1; l < 43; l++) { + for (l = 1; l < ARRAYSIZE(inventoryObjects); l++) { out->writeSint32LE(inventoryObjects[l]); } diff --git a/engines/engine.cpp b/engines/engine.cpp index e2c0bb79f3f..0af01f72c9c 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -94,6 +94,8 @@ Engine::Engine(OSystem *syst) _saveFileMan(_system->getSavefileManager()), _targetName(ConfMan.getActiveDomainName()), _pauseLevel(0), + _pauseStartTime(0), + _engineStartTime(_system->getMillis()), _mainMenuDialog(NULL) { g_engine = this; @@ -110,7 +112,7 @@ Engine::Engine(OSystem *syst) // heaps of (sound) memory get allocated but never freed. Of course, // there still would be problems with many games... if (!_mixer->isReady()) - warning("Sound initialization failed. This may cause severe problems in some games."); + warning("Sound initialization failed. This may cause severe problems in some games"); // Setup a dummy cursor and palette, so that all engines can use // CursorMan.replace without having any headaches about memory leaks. @@ -380,9 +382,12 @@ void Engine::pauseEngine(bool pause) { _pauseLevel--; if (_pauseLevel == 1 && pause) { + _pauseStartTime = _system->getMillis(); pauseEngineIntern(true); } else if (_pauseLevel == 0) { pauseEngineIntern(false); + _engineStartTime += _system->getMillis() - _pauseStartTime; + _pauseStartTime = 0; } } @@ -398,6 +403,24 @@ void Engine::openMainMenuDialog() { syncSoundSettings(); } +uint32 Engine::getTotalPlayTime() const { + if (!_pauseLevel) + return _system->getMillis() - _engineStartTime; + else + return _pauseStartTime - _engineStartTime; +} + +void Engine::setTotalPlayTime(uint32 time) { + const uint32 currentTime = _system->getMillis(); + + // We need to reset the pause start time here in case the engine is already + // paused to avoid any incorrect play time counting. + if (_pauseLevel > 0) + _pauseStartTime = currentTime; + + _engineStartTime = currentTime - time; +} + int Engine::runDialog(GUI::Dialog &dialog) { pauseEngine(true); int result = dialog.runModal(); diff --git a/engines/engine.h b/engines/engine.h index ead1526d721..b4764319b86 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -74,6 +74,17 @@ private: */ int _pauseLevel; + /** + * The time when the pause was started. + */ + uint32 _pauseStartTime; + + /** + * The time when the engine was started. This value is used to calculate + * the current play time of the game running. + */ + int32 _engineStartTime; + public: @@ -234,6 +245,24 @@ public: */ void openMainMenuDialog(); + /** + * Get the total play time. + * + * @return How long the player has been playing in ms. + */ + uint32 getTotalPlayTime() const; + + /** + * Set the game time counter to the specified time. + * + * This can be used to set the play time counter after loading a savegame + * for example. Another use case is in case the engine wants to exclude + * time from the counter the user spent in original engine dialogs. + * + * @param time Play time to set up in ms. + */ + void setTotalPlayTime(uint32 time = 0); + inline Common::TimerManager *getTimerManager() { return _timer; } inline Common::EventManager *getEventManager() { return _eventMan; } inline Common::SaveFileManager *getSaveFileManager() { return _saveFileMan; } diff --git a/engines/engines.mk b/engines/engines.mk index e542ffd933f..eea4ffc0b94 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -74,6 +74,11 @@ DEFINES += -DENABLE_LOL endif endif +ifdef ENABLE_LASTEXPRESS +DEFINES += -DENABLE_LASTEXPRESS=$(ENABLE_LASTEXPRESS) +MODULES += engines/lastexpress +endif + ifdef ENABLE_LURE DEFINES += -DENABLE_LURE=$(ENABLE_LURE) MODULES += engines/lure @@ -141,6 +146,16 @@ DEFINES += -DENABLE_SWORD2=$(ENABLE_SWORD2) MODULES += engines/sword2 endif +ifdef ENABLE_SWORD25 +DEFINES += -DENABLE_SWORD25=$(ENABLE_SWORD25) +MODULES += engines/sword25 +endif + +ifdef ENABLE_TESTBED +DEFINES += -DENABLE_TESTBED=$(ENABLE_TESTBED) +MODULES += engines/testbed +endif + ifdef ENABLE_TEENAGENT DEFINES += -DENABLE_TEENAGENT=$(ENABLE_TEENAGENT) MODULES += engines/teenagent @@ -151,6 +166,11 @@ DEFINES += -DENABLE_TINSEL=$(ENABLE_TINSEL) MODULES += engines/tinsel endif +ifdef ENABLE_TOON +DEFINES += -DENABLE_TOON=$(ENABLE_TOON) +MODULES += engines/toon +endif + ifdef ENABLE_TOUCHE DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE) MODULES += engines/touche diff --git a/engines/gob/console.cpp b/engines/gob/console.cpp new file mode 100644 index 00000000000..247911402f6 --- /dev/null +++ b/engines/gob/console.cpp @@ -0,0 +1,147 @@ +/* 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 "gob/console.h" +#include "gob/gob.h" +#include "gob/inter.h" + +namespace Gob { + +GobConsole::GobConsole(GobEngine *vm) : GUI::Debugger(), _vm(vm) { + DCmd_Register("varSize", WRAP_METHOD(GobConsole, cmd_varSize)); + DCmd_Register("var8", WRAP_METHOD(GobConsole, cmd_var8)); + DCmd_Register("var16", WRAP_METHOD(GobConsole, cmd_var16)); + DCmd_Register("var32", WRAP_METHOD(GobConsole, cmd_var32)); + DCmd_Register("varString", WRAP_METHOD(GobConsole, cmd_varString)); +} + +GobConsole::~GobConsole() { +} + +void GobConsole::preEnter() { +} + +void GobConsole::postEnter() { +} + +bool GobConsole::cmd_varSize(int argc, const char **argv) { + DebugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize()); + return true; +} + +bool GobConsole::cmd_var8(int argc, const char **argv) { + if (argc == 1) { + DebugPrintf("Usage: var8 ()\n"); + return true; + } + + uint32 varNum = atoi(argv[1]); + + if (varNum >= _vm->_inter->_variables->getSize()) { + DebugPrintf("Variable offset out of range\n"); + return true; + } + + if (argc > 2) { + uint32 varVal = atoi(argv[2]); + _vm->_inter->_variables->writeOff8(varNum, varVal); + } + + DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum)); + + return true; +} + +bool GobConsole::cmd_var16(int argc, const char **argv) { + if (argc == 1) { + DebugPrintf("Usage: var16 ()\n"); + return true; + } + + uint32 varNum = atoi(argv[1]); + + if ((varNum + 1) >= _vm->_inter->_variables->getSize()) { + DebugPrintf("Variable offset out of range\n"); + return true; + } + + if (argc > 2) { + uint32 varVal = atoi(argv[2]); + _vm->_inter->_variables->writeOff16(varNum, varVal); + } + + DebugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum)); + + return true; +} + +bool GobConsole::cmd_var32(int argc, const char **argv) { + if (argc == 1) { + DebugPrintf("Usage: var32 ()\n"); + return true; + } + + uint32 varNum = atoi(argv[1]); + + if ((varNum + 3) >= _vm->_inter->_variables->getSize()) { + DebugPrintf("Variable offset out of range\n"); + return true; + } + + if (argc > 2) { + uint32 varVal = atoi(argv[2]); + _vm->_inter->_variables->writeOff32(varNum, varVal); + } + + DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum)); + + return true; +} + +bool GobConsole::cmd_varString(int argc, const char **argv) { + if (argc == 1) { + DebugPrintf("Usage: varString ()\n"); + return true; + } + + uint32 varNum = atoi(argv[1]); + + if (varNum >= _vm->_inter->_variables->getSize()) { + DebugPrintf("Variable offset out of range\n"); + return true; + } + + if (argc > 2) { + uint32 maxLength = _vm->_inter->_variables->getSize() - varNum; + + Common::strlcpy(_vm->_inter->_variables->getAddressOffString(varNum), argv[2], maxLength); + } + + DebugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum)); + + return true; +} + +} // End of namespace Gob diff --git a/engines/gob/console.h b/engines/gob/console.h new file mode 100644 index 00000000000..5dc60960621 --- /dev/null +++ b/engines/gob/console.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 GOB_CONSOLE_H +#define GOB_CONSOLE_H + +#include "gui/debugger.h" + +namespace Gob { + +class GobEngine; + +class GobConsole : public GUI::Debugger { +public: + GobConsole(GobEngine *vm); + virtual ~GobConsole(void); + +protected: + virtual void preEnter(); + virtual void postEnter(); + +private: + GobEngine *_vm; + + bool cmd_varSize(int argc, const char **argv); + bool cmd_var8(int argc, const char **argv); + bool cmd_var16(int argc, const char **argv); + bool cmd_var32(int argc, const char **argv); + bool cmd_varString(int argc, const char **argv); +}; + +} // End of namespace Mohawk + +#endif diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index 694cec6a6f3..55ca3350af2 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -24,10 +24,10 @@ */ #include "common/endian.h" +#include "common/str.h" #include "gob/gob.h" #include "gob/dataio.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" @@ -393,7 +393,7 @@ int32 DataIO::getChunkSize(const char *chunkName, int32 &packSize) { void DataIO::openDataFile(const char *src, bool itk) { char path[128]; - strncpy0(path, src, 127); + Common::strlcpy(path, src, 128); if (!strchr(path, '.')) { path[123] = 0; strcat(path, ".stk"); @@ -556,7 +556,7 @@ int32 DataIO::getDataSize(const char *name) { int32 chunkSize; int32 packSize = -1; - strncpy0(buf, name, 127); + Common::strlcpy(buf, name, 128); chunkSize = getChunkSize(buf, packSize); if (chunkSize >= 0) diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp index 25cd470f04f..011c524798a 100644 --- a/engines/gob/demos/demoplayer.cpp +++ b/engines/gob/demos/demoplayer.cpp @@ -28,7 +28,6 @@ #include "gob/gob.h" #include "gob/demos/demoplayer.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/draw.h" @@ -123,7 +122,7 @@ void DemoPlayer::init() { void DemoPlayer::clearScreen() { debugC(1, kDebugDemo, "Clearing the screen"); - _vm->_video->clearSurf(*_vm->_draw->_backSurface); + _vm->_draw->_backSurface->clear(); _vm->_draw->forceBlit(); _vm->_video->retrace(); } @@ -244,10 +243,11 @@ void DemoPlayer::playVideoDoubled(int slot) { int16 wD = (rect->left * 2) + (w * 2); int16 hD = (rect->top * 2) + (h * 2); - _vm->_video->drawSpriteDouble(*_vm->_draw->_spritesArray[0], *_vm->_draw->_frontSurface, - rect->left, rect->top, rect->right - 1, rect->bottom - 1, rect->left, rect->top, 0); - _vm->_draw->dirtiedRect(_vm->_draw->_frontSurface, - rect->left * 2, rect->top * 2, wD, hD); + _vm->_draw->_frontSurface->blitScaled(*_vm->_draw->_spritesArray[0], + rect->left, rect->top, rect->right - 1, rect->bottom - 1, rect->left * 2, rect->top * 2, 2); + + _vm->_draw->dirtiedRect(_vm->_draw->_frontSurface, + rect->left * 2, rect->top * 2, wD, hD); } } @@ -297,10 +297,10 @@ void DemoPlayer::evaluateVideoMode(const char *mode) { _doubleMode = false; // Only applicable when we actually can double - if (_vm->is640()) { - if (!scumm_strnicmp(mode, "AUTO", 4)) + if (_vm->is640x480() || _vm->is800x600()) { + if (!scumm_strnicmp(mode, "AUTO", 4)) _autoDouble = true; - else if (!scumm_strnicmp(mode, "VGA", 3) && _vm->is640()) + else if (!scumm_strnicmp(mode, "VGA", 3)) _doubleMode = true; } } diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h index 907dc64295d..43f15b8845f 100644 --- a/engines/gob/detection_tables.h +++ b/engines/gob/detection_tables.h @@ -420,6 +420,20 @@ static const GOBGameDescription gameDescriptions[] = { kFeaturesAdLib, 0, 0, 0 }, + { // Provided by pykman in the forums. + { + "gob1cd", + "Polish", + AD_ENTRY1s("intro.stk", "97d2443948b2e367cf567fe7e101f5f2", 4049267), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, { // CD 1.000 version. { "gob1cd", @@ -1054,6 +1068,20 @@ static const GOBGameDescription gameDescriptions[] = { kFeaturesCD, 0, 0, 0 }, + { // Supplied by pykman in bug report #3067489 + { + "gob2cd", + "v2.01 Polish", + AD_ENTRY1s("intro.stk", "3025f05482b646c18c2c79c615a3a1df", 5011726), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, { { "gob2cd", @@ -2236,16 +2264,14 @@ static const GOBGameDescription gameDescriptions[] = { kFeaturesAdLib, "demo.stk", "demo.tot", 0 }, -// This version is not detected on purpose: it's a pirated version, using a corrupted crack. -// Tagged ADGF_PIRATED! Do not re-add nor un-tag! - { + { // Supplied by scoriae { "fascination", - "", + "VGA", AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955), - UNK_LANG, + EN_ANY, kPlatformPC, - ADGF_PIRATED, + ADGF_NO_FLAGS, GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeFascination, @@ -2798,6 +2824,20 @@ static const GOBGameDescription gameDescriptions[] = { kFeaturesCD, 0, 0, 0 }, + { // Supplied by pykman in bug report #3067489 + { + "gob3cd", + "v1.02 Polish", + AD_ENTRY1s("intro.stk", "978afddcac81bb95a04757b61f78471c", 619825), + UNK_LANG, + 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", @@ -3200,7 +3240,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3214,7 +3254,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3228,7 +3268,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3242,7 +3282,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3256,7 +3296,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3270,7 +3310,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3284,7 +3324,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3298,7 +3338,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3312,7 +3352,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3326,7 +3366,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3340,7 +3380,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by jvprat on #scummvm @@ -3354,7 +3394,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by jvprat on #scummvm @@ -3368,7 +3408,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by jvprat on #scummvm @@ -3382,7 +3422,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by jvprat on #scummvm @@ -3396,7 +3436,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by jvprat on #scummvm @@ -3410,7 +3450,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by Hkz on #scummvm @@ -3424,7 +3464,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by Hkz on #scummvm @@ -3438,7 +3478,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by Hkz on #scummvm @@ -3452,7 +3492,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by DjDiabolik in bug report #1971294 @@ -3466,7 +3506,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by DjDiabolik in bug report #1971294 @@ -3480,7 +3520,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by DjDiabolik in bug report #1971294 @@ -3494,7 +3534,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by DjDiabolik in bug report #1971294 @@ -3508,7 +3548,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by DjDiabolik in bug report #1971294 @@ -3522,7 +3562,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { // Supplied by goodoldgeorg in bug report #2098838 @@ -3536,7 +3576,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3554,7 +3594,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesSCNDemo, 0, 0, 1 }, { @@ -3568,7 +3608,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3582,7 +3622,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3596,7 +3636,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3610,7 +3650,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3624,7 +3664,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3638,7 +3678,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -3652,7 +3692,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, "lda1.stk", 0, 0 }, { @@ -3666,7 +3706,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeDynasty, - kFeatures640, + kFeatures640x480, "lda1.stk", 0, 0 }, { @@ -3680,7 +3720,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, - kFeatures640, + kFeatures640x480 | kFeaturesTrueColor, 0, 0, 0 }, { // Supplied by gamin in the forums @@ -3694,7 +3734,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, - kFeatures640, + kFeatures640x480 | kFeaturesTrueColor, 0, 0, 0 }, { // Supplied by jvprat on #scummvm @@ -3708,7 +3748,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, - kFeatures640, + kFeatures640x480 | kFeaturesTrueColor, 0, 0, 0 }, { // Supplied by goodoldgeorg in bug report #2770340 @@ -3722,7 +3762,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, - kFeatures640, + kFeatures640x480 | kFeaturesTrueColor, 0, 0, 0 }, { @@ -3741,7 +3781,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeUrban, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesTrueColor | kFeaturesSCNDemo, 0, 0, 2 }, { @@ -3759,7 +3799,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -3777,7 +3817,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -3795,7 +3835,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { // Supplied by scoriae in the forums @@ -3813,7 +3853,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -3836,7 +3876,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesSCNDemo, 0, 0, 3 }, { @@ -3854,7 +3894,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesSCNDemo, 0, 0, 4 }, { @@ -3876,7 +3916,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesSCNDemo, 0, 0, 5 }, { @@ -3897,7 +3937,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesSCNDemo, 0, 0, 6 }, { @@ -3915,7 +3955,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -3933,7 +3973,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -3951,7 +3991,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { // Supplied by scoriae in the forums @@ -3969,7 +4009,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -3987,7 +4027,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4005,7 +4045,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4023,7 +4063,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4041,7 +4081,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { // Supplied by Hkz on #scummvm @@ -4059,7 +4099,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4077,7 +4117,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { //Supplied by goodoldgeorg in bug report #2820006 @@ -4095,7 +4135,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4113,7 +4153,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4131,7 +4171,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, - kFeatures640, + kFeatures640x480, "intro.stk", "intro.tot", 0 }, { @@ -4149,7 +4189,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4167,7 +4207,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4185,7 +4225,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, "intro2.stk", 0, 0 }, { @@ -4213,7 +4253,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified. @@ -4227,7 +4267,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4255,7 +4295,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4269,7 +4309,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4283,7 +4323,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4297,7 +4337,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4311,7 +4351,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4325,7 +4365,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", "ediintro.tot", 0 }, { @@ -4345,7 +4385,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeAdi2, - kFeatures640 | kFeaturesSCNDemo, + kFeatures640x480 | kFeaturesSCNDemo, 0, 0, 1 }, { @@ -4359,7 +4399,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4373,7 +4413,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4387,7 +4427,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4401,7 +4441,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4415,7 +4455,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4429,7 +4469,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4485,7 +4525,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4513,7 +4553,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4527,7 +4567,7 @@ static const GOBGameDescription gameDescriptions[] = { GUIO_NONE }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { @@ -4825,7 +4865,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeWoodruff, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //9 @@ -4881,7 +4921,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, - kFeaturesCD, + kFeaturesCD | kFeaturesTrueColor, 0, 0, 0 }, { //13 @@ -4895,7 +4935,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //14 @@ -4909,7 +4949,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //15 @@ -4923,7 +4963,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //16 @@ -4937,7 +4977,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //17 @@ -4951,7 +4991,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //18 @@ -4965,7 +5005,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypePlaytoons, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //19 @@ -4979,7 +5019,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeBambou, - kFeatures640, + kFeatures640x480, 0, 0, 0 }, { //20 @@ -5021,7 +5061,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeAdi2, - kFeatures640, + kFeatures640x480, "adi2.stk", 0, 0 }, { //23 @@ -5035,7 +5075,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeAdi4, - kFeatures640, + kFeatures640x480, "adif41.stk", 0, 0 }, { //24 @@ -5049,7 +5089,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NONE }, kGameTypeUrban, - kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo, + kFeaturesAdLib | kFeatures640x480 | kFeaturesSCNDemo, "", "", 8 } }; diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index 62b9a5e630c..bb357168b7a 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -24,6 +24,7 @@ */ #include "common/endian.h" +#include "common/str.h" #include "gob/gob.h" #include "gob/draw.h" @@ -263,10 +264,10 @@ void Draw::blitInvalidated() { _vm->_video->_doRangeClamp = false; for (int i = 0; i < _invalidatedCount; i++) { - _vm->_video->drawSprite(*_backSurface, *_frontSurface, + _frontSurface->blit(*_backSurface, _invalidatedLefts[i], _invalidatedTops[i], _invalidatedRights[i], _invalidatedBottoms[i], - _invalidatedLefts[i], _invalidatedTops[i], 0); + _invalidatedLefts[i], _invalidatedTops[i]); _vm->_video->dirtyRectsAdd(_invalidatedLefts[i], _invalidatedTops[i], _invalidatedRights[i], _invalidatedBottoms[i]); } @@ -300,7 +301,7 @@ void Draw::dirtiedRect(int16 surface, dirtiedRect(_spritesArray[surface], left, top, right, bottom); } -void Draw::dirtiedRect(SurfaceDescPtr surface, +void Draw::dirtiedRect(SurfacePtr surface, int16 left, int16 top, int16 right, int16 bottom) { if (surface == _backSurface) @@ -316,7 +317,7 @@ void Draw::initSpriteSurf(int16 index, int16 width, int16 height, _spritesArray[index] = _vm->_video->initSurfDesc(_vm->_global->_videoMode, width, height, flags); - _vm->_video->clearSurf(*_spritesArray[index]); + _spritesArray[index]->clear(); } void Draw::adjustCoords(char adjust, int16 *coord1, int16 *coord2) { @@ -328,7 +329,7 @@ void Draw::adjustCoords(char adjust, int16 *coord1, int16 *coord2) { if (coord2) *coord2 *= 2; if (coord1) - *coord2 *= 2; + *coord1 *= 2; break; case 1: @@ -381,14 +382,14 @@ int Draw::stringLength(const char *str, int16 fontIndex) { } void Draw::drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2, - int16 transp, SurfaceDesc &dest, const Font &font) { + int16 transp, Surface &dest, const Font &font) { while (*str != '\0') { const int16 charRight = x + font.getCharWidth(*str); const int16 charBottom = y + font.getCharHeight(); if ((charRight <= dest.getWidth()) && (charBottom <= dest.getHeight())) - _vm->_video->drawLetter(*str, x, y, font, transp, color1, color2, dest); + font.drawLetter(dest, *str, x, y, color1, color2, transp); x += font.getCharWidth(*str); str++; @@ -470,10 +471,8 @@ void Draw::oPlaytoons_sub_F_1B(uint16 id, int16 left, int16 top, int16 right, in else WRITE_VAR(24, (uint32) 0); WRITE_VAR(25, (uint32) shortId); - if (_hotspotText) { - strncpy(_hotspotText, paramStr, 40); - _hotspotText[39] = 0; - } + if (_hotspotText) + Common::strlcpy(_hotspotText, paramStr, 40); } _vm->_inter->funcBlock(0); _vm->_game->_script->pop(); @@ -548,14 +547,10 @@ void Draw::forceBlit(bool backwards) { return; if (!backwards) { - _vm->_video->drawSprite(*_backSurface, *_frontSurface, 0, 0, - _backSurface->getWidth() - 1, _backSurface->getHeight() - 1, - 0, 0, 0); + _frontSurface->blit(*_backSurface); _vm->_video->dirtyRectsAll(); } else - _vm->_video->drawSprite(*_frontSurface, *_backSurface, 0, 0, - _frontSurface->getWidth() - 1, _frontSurface->getHeight() - 1, - 0, 0, 0); + _backSurface->blit(*_frontSurface); } @@ -602,7 +597,7 @@ const int16 Draw::_wobbleTable[360] = { -0x0A03, -0x08E8, -0x07CC, -0x06B0, -0x0593, -0x0476, -0x0359, -0x023B, -0x011D }; -void Draw::wobble(SurfaceDesc &surfDesc) { +void Draw::wobble(Surface &surfDesc) { int16 amplitude = 32; uint16 curFrame = 0; uint16 frameWobble = 0; @@ -626,16 +621,14 @@ void Draw::wobble(SurfaceDesc &surfDesc) { amplitude--; for (uint16 y = 0; y < _vm->_height; y++) - _vm->_video->drawSprite(surfDesc, *_frontSurface, - 0, y, _vm->_width - 1, y, offsets[y], y, 0); + _frontSurface->blit(surfDesc, 0, y, _vm->_width - 1, y, offsets[y], y); _vm->_palAnim->fadeStep(0); _vm->_video->dirtyRectsAll(); _vm->_video->waitRetrace(); } - _vm->_video->drawSprite(surfDesc, *_frontSurface, - 0, 0, _vm->_width - 1, _vm->_height - 1, 0, 0, 0); + _frontSurface->blit(surfDesc); _applyPal = false; _invalidatedCount = 0; diff --git a/engines/gob/draw.h b/engines/gob/draw.h index cbadde8e271..fe373826662 100644 --- a/engines/gob/draw.h +++ b/engines/gob/draw.h @@ -66,7 +66,7 @@ public: int16 top; int16 width; int16 height; - SurfaceDescPtr savedSurface; + SurfacePtr savedSurface; }; int16 _renderFlags; @@ -98,7 +98,7 @@ public: FontToSprite _fontToSprite[4]; Font *_fonts[kFontCount]; - Common::Array _spritesArray; + Common::Array _spritesArray; int16 _invalidatedCount; int16 _invalidatedLefts[30]; @@ -112,8 +112,8 @@ public: bool _paletteCleared; bool _applyPal; - SurfaceDescPtr _backSurface; - SurfaceDescPtr _frontSurface; + SurfacePtr _backSurface; + SurfacePtr _frontSurface; int16 _unusedPalette1[18]; int16 _unusedPalette2[16]; @@ -137,9 +137,9 @@ public: int32 _cursorHotspotXVar; int32 _cursorHotspotYVar; - SurfaceDescPtr _cursorSprites; - SurfaceDescPtr _cursorSpritesBack; - SurfaceDescPtr _scummvmCursor; + SurfacePtr _cursorSprites; + SurfacePtr _cursorSpritesBack; + SurfacePtr _scummvmCursor; int16 _cursorAnim; int8 _cursorAnimLow[40]; @@ -174,7 +174,7 @@ public: void clearPalette(); void dirtiedRect(int16 surface, int16 left, int16 top, int16 right, int16 bottom); - void dirtiedRect(SurfaceDescPtr surface, int16 left, int16 top, int16 right, int16 bottom); + void dirtiedRect(SurfacePtr surface, int16 left, int16 top, int16 right, int16 bottom); void initSpriteSurf(int16 index, int16 width, int16 height, int16 flags); void freeSprite(int16 index) { @@ -187,7 +187,7 @@ public: } int stringLength(const char *str, int16 fontIndex); void drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2, - int16 transp, SurfaceDesc &dest, const Font &font); + int16 transp, Surface &dest, const Font &font); void printTextCentered(int16 id, int16 left, int16 top, int16 right, int16 bottom, const char *str, int16 fontIndex, int16 color); void oPlaytoons_sub_F_1B( uint16 id, int16 left, int16 top, int16 right, int16 bottom, char *paramStr, int16 var3, int16 var4, int16 shortId); @@ -196,7 +196,7 @@ public: void forceBlit(bool backwards = false); static const int16 _wobbleTable[360]; - void wobble(SurfaceDesc &surfDesc); + void wobble(Surface &surfDesc); Font *loadFont(const char *path) const; bool loadFont(int fontIndex, const char *path); @@ -267,7 +267,7 @@ public: virtual ~Draw_Fascination() {} virtual void spriteOperation(int16 operation); - void decompWin(int16 x, int16 y, SurfaceDescPtr destPtr); + void decompWin(int16 x, int16 y, SurfacePtr destPtr); void drawWin(int16 fct); void saveWin(int16 id); void restoreWin(int16 id); diff --git a/engines/gob/draw_fascin.cpp b/engines/gob/draw_fascin.cpp index dcb76d722c1..86e5cb8314b 100644 --- a/engines/gob/draw_fascin.cpp +++ b/engines/gob/draw_fascin.cpp @@ -40,7 +40,7 @@ Draw_Fascination::Draw_Fascination(GobEngine *vm) : Draw_v2(vm) { void Draw_Fascination::spriteOperation(int16 operation) { int16 len; int16 x, y; - SurfaceDescPtr sourceSurf, destSurf; + SurfacePtr sourceSurf, destSurf; bool deltaVeto; int16 left; int16 ratio; @@ -149,26 +149,24 @@ void Draw_Fascination::spriteOperation(int16 operation) { if (!sourceSurf || !destSurf) break; - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], - *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_spritesArray[_sourceSurface], _spriteLeft, spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); break; case DRAW_PUTPIXEL: - _vm->_video->putPixel(_destSpriteX, _destSpriteY, _frontColor, - *_spritesArray[_destSurface]); + _spritesArray[_destSurface]->putPixel(_destSpriteX, _destSpriteY, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX, _destSpriteY); break; case DRAW_FILLRECT: - _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX, + _spritesArray[_destSurface]->fillRect(destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); @@ -177,15 +175,14 @@ void Draw_Fascination::spriteOperation(int16 operation) { break; case DRAW_DRAWLINE: - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); break; case DRAW_INVALIDATE: - _vm->_video->drawCircle(*_spritesArray[_destSurface], _destSpriteX, + _spritesArray[_destSurface]->drawCircle(_destSpriteX, _destSpriteY, _spriteRight, _frontColor); dirtiedRect(_destSurface, _destSpriteX - _spriteRight, _destSpriteY - _spriteBottom, @@ -227,9 +224,8 @@ void Draw_Fascination::spriteOperation(int16 operation) { byte *dataBuf = _vm->_game->_resources->getTexts() + _textToPrint[1] + 1; len = *dataBuf++; for (int i = 0; i < len; i++, dataBuf += 2) { - _vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX, - _destSpriteY, *font, _transparency, _frontColor, - _backColor, *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], READ_LE_UINT16(dataBuf), + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); } } else { drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor, @@ -238,9 +234,8 @@ void Draw_Fascination::spriteOperation(int16 operation) { } } else { for (int i = 0; i < len; i++) { - _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, - _destSpriteY, *font, _transparency, - _frontColor, _backColor, *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], _textToPrint[i], + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); _destSpriteX += font->getCharWidth(_textToPrint[i]); } } @@ -255,11 +250,10 @@ void Draw_Fascination::spriteOperation(int16 operation) { * _fontToSprite[_fontIndex].height; x = ((_textToPrint[i] - _fontToSprite[_fontIndex].base) % ratio) * _fontToSprite[_fontIndex].width; - _vm->_video->drawSprite(*_spritesArray[_fontToSprite[_fontIndex].sprite], - *_spritesArray[_destSurface], x, y, + _spritesArray[_destSurface]->blit(*_spritesArray[_fontToSprite[_fontIndex].sprite], x, y, x + _fontToSprite[_fontIndex].width - 1, y + _fontToSprite[_fontIndex].height - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); _destSpriteX += _fontToSprite[_fontIndex].width; } } @@ -270,36 +264,28 @@ void Draw_Fascination::spriteOperation(int16 operation) { case DRAW_DRAWBAR: if (_needAdjust != 2) { - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom - 1, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _spriteBottom - 1, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect( _destSpriteX, _destSpriteY, _destSpriteX + 1, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _spriteRight - 1, _destSpriteY, + _spritesArray[_destSurface]->fillRect( _spriteRight - 1, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect( _destSpriteX, _destSpriteY, _spriteRight, _destSpriteY + 1, _frontColor); } else { - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _spriteRight, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); } @@ -308,19 +294,14 @@ void Draw_Fascination::spriteOperation(int16 operation) { case DRAW_CLEARRECT: if ((_backColor != 16) && (_backColor != 144)) { - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, - _spriteRight, _spriteBottom, - _backColor); + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); } dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); break; case DRAW_FILLRECTABS: - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, - _spriteRight, _spriteBottom, _backColor); + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); break; @@ -364,7 +345,7 @@ void Draw_Fascination::drawWin(int16 fct) { int len; Resource *resource; int table[10]; - SurfaceDescPtr tempSrf; + SurfacePtr tempSrf; if (_destSurface == kBackSurface) { @@ -486,9 +467,9 @@ void Draw_Fascination::drawWin(int16 fct) { } if ((_sourceSurface == kBackSurface) && (fct == 0)) { - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_spritesArray[_sourceSurface], _spriteLeft, _spriteTop, _spriteLeft + _spriteRight - 1, - _spriteTop + _spriteBottom - 1, _destSpriteX, _destSpriteY, _transparency); + _spriteTop + _spriteBottom - 1, _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); if (!found) return; @@ -498,18 +479,18 @@ void Draw_Fascination::drawWin(int16 fct) { for (int i = 9; i >= j; i--) { if (table[i]) - _vm->_video->drawSprite(*_fascinWin[table[i]].savedSurface, *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_fascinWin[table[i]].savedSurface, _fascinWin[table[i]].left & 7, 0, (_fascinWin[table[i]].left & 7) + _fascinWin[table[i]].width - 1, _fascinWin[table[i]].height - 1, _fascinWin[table[i]].left - _spriteLeft + _destSpriteX, - _fascinWin[table[i]].top - _spriteTop + _destSpriteY, 0); + _fascinWin[table[i]].top - _spriteTop + _destSpriteY); } return; } if (found) { tempSrf = _vm->_video->initSurfDesc(_vm->_global->_videoMode, width - left + 1, height - top + 1, 0); - _vm->_video->drawSprite(*_backSurface, *tempSrf, left, top, width, height, 0, 0, 0); + tempSrf->blit(*_backSurface, left, top, width, height, 0, 0); int max = 0; if (_vm->_global->_curWinId != 0) @@ -517,37 +498,37 @@ void Draw_Fascination::drawWin(int16 fct) { for (int i = 9; i >= max; i--) { if (table[i]) - _vm->_video->drawSprite(*_fascinWin[table[i]].savedSurface, *tempSrf, + tempSrf->blit(*_fascinWin[table[i]].savedSurface, _fascinWin[table[i]].left & 7, 0, (_fascinWin[table[i]].left & 7) + _fascinWin[table[i]].width - 1, _fascinWin[table[i]].height - 1, _fascinWin[table[i]].left - left, - _fascinWin[table[i]].top - top , 0); + _fascinWin[table[i]].top - top); } invalidateRect(left, top, width, height); switch (fct) { case DRAW_BLITSURF: // 0 - move - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], *tempSrf, + tempSrf->blit(*_spritesArray[_sourceSurface], _spriteLeft, _spriteTop, _spriteLeft + _spriteRight - 1, - _spriteTop + _spriteBottom - 1, 0, 0, _transparency); + _spriteTop + _spriteBottom - 1, 0, 0, (_transparency == 0) ? -1 : 0); break; case DRAW_PUTPIXEL: // 1 - put a pixel - _vm->_video->putPixel(0, 0, _frontColor, *tempSrf); + tempSrf->putPixel(0, 0, _frontColor); break; case DRAW_FILLRECT: // 2 - fill rectangle - _vm->_video->fillRect(*tempSrf, 0, 0, _spriteRight - 1, _spriteBottom - 1, _backColor); + tempSrf->fillRect(0, 0, _spriteRight - 1, _spriteBottom - 1, _backColor); break; case DRAW_DRAWLINE: // 3 - draw line - _vm->_video->drawLine(*tempSrf, 0, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _frontColor); + tempSrf->drawLine(0, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _frontColor); break; case DRAW_INVALIDATE: // 4 - Draw a circle - _vm->_video->drawCircle(*tempSrf, _spriteRight, _spriteRight, _spriteRight, _frontColor); + tempSrf->drawCircle(_spriteRight, _spriteRight, _spriteRight, _frontColor); break; case DRAW_LOADSPRITE: // 5 - Uncompress and load a sprite @@ -557,40 +538,40 @@ void Draw_Fascination::drawWin(int16 fct) { case DRAW_PRINTTEXT: // 6 - Display string len = strlen(_textToPrint); for (int j = 0; j < len; j++) - _vm->_video->drawLetter(_textToPrint[j], j * _fonts[_fontIndex]->getCharWidth(), 0, - *_fonts[_fontIndex], _transparency, _frontColor, _backColor, *tempSrf); + _fonts[_fontIndex]->drawLetter(*tempSrf, _textToPrint[j], + j * _fonts[_fontIndex]->getCharWidth(), 0, _frontColor, _backColor, _transparency); _destSpriteX += len * _fonts[_fontIndex]->getCharWidth(); break; case DRAW_DRAWBAR: // 7 - draw border - _vm->_video->drawLine(*tempSrf, 0, _spriteBottom - _destSpriteY, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _frontColor); - _vm->_video->drawLine(*tempSrf, 0, 0, 0, _spriteBottom - _destSpriteY, _frontColor); - _vm->_video->drawLine(*tempSrf, _spriteRight - _destSpriteX, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _frontColor); - _vm->_video->drawLine(*tempSrf, 0, 0, _spriteRight - _destSpriteX, 0, _frontColor); + tempSrf->drawLine(0, _spriteBottom - _destSpriteY, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _frontColor); + tempSrf->drawLine(0, 0, 0, _spriteBottom - _destSpriteY, _frontColor); + tempSrf->drawLine(_spriteRight - _destSpriteX, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _frontColor); + tempSrf->drawLine(0, 0, _spriteRight - _destSpriteX, 0, _frontColor); break; case DRAW_CLEARRECT: // 8 - clear rectangle if (_backColor < 16) - _vm->_video->fillRect(*tempSrf, 0, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _backColor); + tempSrf->fillRect(0, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _backColor); break; case DRAW_FILLRECTABS: // 9 - fill rectangle, with other coordinates - _vm->_video->fillRect(*tempSrf, 0, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _backColor); + tempSrf->fillRect(0, 0, _spriteRight - _destSpriteX, _spriteBottom - _destSpriteY, _backColor); break; case DRAW_DRAWLETTER: // 10 - Display a character if (_fontToSprite[_fontIndex].sprite == -1) { if (_letterToPrint) - _vm->_video->drawLetter(_letterToPrint, 0, 0, *_fonts[_fontIndex], _transparency, _frontColor, _backColor, *tempSrf); + _fonts[_fontIndex]->drawLetter(*tempSrf, _letterToPrint, 0, 0, _frontColor, _backColor, _transparency); } else { int xx, yy, nn; nn = _spritesArray[_fontToSprite[_fontIndex].sprite]->getWidth() / _fontToSprite[_fontIndex].width; yy = ((_letterToPrint - _fontToSprite[_fontIndex].base) / nn) * _fontToSprite[_fontIndex].height; xx = ((_letterToPrint - _fontToSprite[_fontIndex].base) % nn) * _fontToSprite[_fontIndex].width; - _vm->_video->drawSprite(*_spritesArray[_fontToSprite[_fontIndex].sprite], *tempSrf, + tempSrf->blit(*_spritesArray[_fontToSprite[_fontIndex].sprite], xx, yy, xx + _fontToSprite[_fontIndex].width - 1, - yy + _fontToSprite[_fontIndex].height - 1, 0, 0, _transparency); + yy + _fontToSprite[_fontIndex].height - 1, 0, 0, (_transparency == 0) ? -1 : 0); } break; @@ -606,26 +587,26 @@ void Draw_Fascination::drawWin(int16 fct) { for (; i < 10; i++) { if (table[i]) { int k = table[i]; - _vm->_video->drawSprite(*tempSrf, *_fascinWin[k].savedSurface, + _fascinWin[k].savedSurface->blit(*tempSrf, 0, 0, width - left, height - top, left - _fascinWin[k].left + (_fascinWin[k].left & 7), - top - _fascinWin[k].top, 0); + top - _fascinWin[k].top); // Shift skipped as always set to zero (?) - _vm->_video->drawSprite(*_frontSurface, *tempSrf, + tempSrf->blit(*_frontSurface, MAX(left , _fascinWin[k].left), MAX(top , _fascinWin[k].top), MIN(width , (int16) (_fascinWin[k].left + _fascinWin[k].width - 1)), MIN(height, (int16) (_fascinWin[k].top + _fascinWin[k].height - 1)), MAX(left , _fascinWin[k].left) - left, - MAX(top , _fascinWin[k].top) - top, 0); + MAX(top , _fascinWin[k].top) - top); if (_cursorIndex != -1) - _vm->_video->drawSprite(*_cursorSpritesBack, *tempSrf, + tempSrf->blit(*_cursorSpritesBack, 0, 0, _cursorWidth - 1, _cursorHeight - 1, - _cursorX - left, _cursorY - top, 0); + _cursorX - left, _cursorY - top); for (int j = 9; j > i; j--) { if (table[j] && overlapWin(k, table[j])) { int l = table[j]; - _vm->_video->drawSprite(*_fascinWin[l].savedSurface, *tempSrf, + tempSrf->blit(*_fascinWin[l].savedSurface, MAX(_fascinWin[l].left, _fascinWin[k].left) - _fascinWin[l].left + (_fascinWin[l].left & 7), MAX(_fascinWin[l].top , _fascinWin[k].top ) - _fascinWin[l].top, @@ -634,37 +615,37 @@ void Draw_Fascination::drawWin(int16 fct) { MIN(_fascinWin[l].top + _fascinWin[l].height - 1, _fascinWin[k].top + _fascinWin[k].height - 1) - _fascinWin[l].top, MAX(_fascinWin[l].left, _fascinWin[k].left) - left, - MAX(_fascinWin[l].top , _fascinWin[k].top ) - top, 0); + MAX(_fascinWin[l].top , _fascinWin[k].top ) - top); } } } } - _vm->_video->drawSprite(*tempSrf, *_backSurface, 0, 0, width - left, height - top, left, top, 0); + _backSurface->blit(*tempSrf, 0, 0, width - left, height - top, left, top); tempSrf.reset(); } else { invalidateRect(left, top, width, height); switch (fct) { case DRAW_BLITSURF: // 0 - move - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], *_backSurface, + _backSurface->blit(*_spritesArray[_sourceSurface], _spriteLeft, _spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); break; case DRAW_PUTPIXEL: // 1 - put a pixel - _vm->_video->putPixel(_destSpriteX, _destSpriteY, _frontColor, *_backSurface); + _backSurface->putPixel(_destSpriteX, _destSpriteY, _frontColor); break; case DRAW_FILLRECT: // 2 - fill rectangle - _vm->_video->fillRect(*_backSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); + _backSurface->fillRect(_destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); break; case DRAW_DRAWLINE: // 3 - draw line - _vm->_video->drawLine(*_backSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); + _backSurface->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); break; case DRAW_INVALIDATE: // 4 - Draw a circle - _vm->_video->drawCircle(*_backSurface, _spriteRight, _spriteRight, _spriteRight, _frontColor); + _backSurface->drawCircle(_spriteRight, _spriteRight, _spriteRight, _frontColor); break; case DRAW_LOADSPRITE: // 5 - Uncompress and load a sprite @@ -674,42 +655,43 @@ void Draw_Fascination::drawWin(int16 fct) { case DRAW_PRINTTEXT: // 6 - Display string len = strlen(_textToPrint); for (int j = 0; j < len; j++) - _vm->_video->drawLetter(_textToPrint[j], _destSpriteX + j * _fonts[_fontIndex]->getCharWidth(), - _destSpriteY, *_fonts[_fontIndex], _transparency, _frontColor, _backColor, *_backSurface); + _fonts[_fontIndex]->drawLetter(*_backSurface, _textToPrint[j], + _destSpriteX + j * _fonts[_fontIndex]->getCharWidth(), _destSpriteY, + _frontColor, _backColor, _transparency); _destSpriteX += len * _fonts[_fontIndex]->getCharWidth(); break; case DRAW_DRAWBAR: // 7 - draw border - _vm->_video->drawLine(*_backSurface, _destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_backSurface, _destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_backSurface, _spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_backSurface, _destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); + _backSurface->drawLine(_destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); + _backSurface->drawLine(_destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); + _backSurface->drawLine(_spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); + _backSurface->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); break; case DRAW_CLEARRECT: // 8 - clear rectangle if (_backColor < 16) - _vm->_video->fillRect(*_backSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); + _backSurface->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); break; case DRAW_FILLRECTABS: // 9 - fill rectangle, with other coordinates - _vm->_video->fillRect(*_backSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); + _backSurface->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); break; case DRAW_DRAWLETTER: // 10 - Display a character if (_fontToSprite[_fontIndex].sprite == -1) { if (_letterToPrint) - _vm->_video->drawLetter(_letterToPrint, _destSpriteX, _destSpriteY, *_fonts[_fontIndex], _transparency, - _frontColor, _backColor, *_spritesArray[_destSurface]); + _fonts[_fontIndex]->drawLetter(*_spritesArray[_destSurface], _letterToPrint, + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); } else { int xx, yy, nn; nn = _spritesArray[_fontToSprite[_fontIndex].sprite]->getWidth() / _fontToSprite[_fontIndex].width; yy = ((_letterToPrint - _fontToSprite[_fontIndex].base) / nn) * _fontToSprite[_fontIndex].height; xx = ((_letterToPrint - _fontToSprite[_fontIndex].base) % nn) * _fontToSprite[_fontIndex].width; - _vm->_video->drawSprite(*_spritesArray[_fontToSprite[_fontIndex].sprite], *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_spritesArray[_fontToSprite[_fontIndex].sprite], xx, yy, xx + _fontToSprite[_fontIndex].width - 1, yy + _fontToSprite[_fontIndex].height - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); } break; @@ -736,7 +718,7 @@ void Draw_Fascination::drawWin(int16 fct) { } } -void Draw_Fascination::decompWin(int16 x, int16 y, SurfaceDescPtr destPtr) { +void Draw_Fascination::decompWin(int16 x, int16 y, SurfacePtr destPtr) { Resource *resource; resource = _vm->_game->_resources->getResource((uint16) _spriteLeft, &_spriteRight, &_spriteBottom); @@ -884,11 +866,11 @@ void Draw_Fascination::moveWin(int16 id) { saveWin(id); // Shift skipped as always set to zero (?) - _vm->_video->drawSprite(*_frontSurface, *_backSurface, + _backSurface->blit(*_frontSurface, oldLeft, oldTop, oldLeft + _fascinWin[id].width - 1, oldTop + _fascinWin[id].height - 1, - _fascinWin[id].left, _fascinWin[id].top, 0); + _fascinWin[id].left, _fascinWin[id].top); invalidateRect(_fascinWin[id].left, _fascinWin[id].top, _fascinWin[id].left + _fascinWin[id].width - 1, _fascinWin[id].top + _fascinWin[id].height - 1); @@ -909,8 +891,8 @@ void Draw_Fascination::activeWin(int16 id) { int16 t[10], t2[10]; int nextId = -1; int oldId = -1; - SurfaceDescPtr tempSrf; - SurfaceDescPtr oldSrf[10]; + SurfacePtr tempSrf; + SurfacePtr oldSrf[10]; if (_fascinWin[id].id == -1) return; @@ -934,11 +916,11 @@ void Draw_Fascination::activeWin(int16 id) { for (int i = 9; i >= 0; i--) { if (t[i] != -1) { if (nextId != -1) - _vm->_video->drawSprite(*_backSurface, *_fascinWin[nextId].savedSurface, + _fascinWin[nextId].savedSurface->blit(*_backSurface, _fascinWin[t[i]].left, _fascinWin[t[i]].top, _fascinWin[t[i]].left + _fascinWin[t[i]].width - 1, _fascinWin[t[i]].top + _fascinWin[t[i]].height - 1, - _fascinWin[t[i]].left & 7, 0, 0); + _fascinWin[t[i]].left & 7, 0); t2[i] = nextId; restoreWin(t[i]); nextId = t[i]; @@ -946,35 +928,35 @@ void Draw_Fascination::activeWin(int16 id) { } oldId = nextId; - _vm->_video->drawSprite(*_backSurface, *_fascinWin[nextId].savedSurface, + _fascinWin[nextId].savedSurface->blit(*_backSurface, _fascinWin[id].left, _fascinWin[id].top, _fascinWin[id].left + _fascinWin[id].width - 1, _fascinWin[id].top + _fascinWin[id].height - 1, - _fascinWin[id].left & 7, 0, 0); + _fascinWin[id].left & 7, 0); restoreWin(id); nextId = id; for (int i = 0; i < 10; i++) { if (t[i] != -1) { - _vm->_video->drawSprite(*_backSurface, *_fascinWin[nextId].savedSurface, + _fascinWin[nextId].savedSurface->blit(*_backSurface, _fascinWin[t[i]].left, _fascinWin[t[i]].top, _fascinWin[t[i]].left + _fascinWin[t[i]].width - 1, _fascinWin[t[i]].top + _fascinWin[t[i]].height - 1, - _fascinWin[t[i]].left & 7, 0, 0); + _fascinWin[t[i]].left & 7, 0); oldSrf[t[i]] = _fascinWin[nextId].savedSurface; if (t2[i] != -1) - _vm->_video->drawSprite(*_fascinWin[t2[i]].savedSurface, *_backSurface, + _backSurface->blit(*_fascinWin[t2[i]].savedSurface, _fascinWin[t[i]].left & 7, 0, (_fascinWin[t[i]].left & 7) + _fascinWin[t[i]].width - 1, _fascinWin[t[i]].height - 1, _fascinWin[t[i]].left, - _fascinWin[t[i]].top, 0); + _fascinWin[t[i]].top); else { // Shift skipped as always set to zero (?) - _vm->_video->drawSprite(*_frontSurface, *_backSurface, + _backSurface->blit(*_frontSurface, _fascinWin[t[i]].left, _fascinWin[t[i]].top, _fascinWin[t[i]].left + _fascinWin[t[i]].width - 1, _fascinWin[t[i]].top + _fascinWin[t[i]].height - 1, - _fascinWin[t[i]].left, _fascinWin[t[i]].top, 0); + _fascinWin[t[i]].left, _fascinWin[t[i]].top); } invalidateRect(_fascinWin[t[i]].left, _fascinWin[t[i]].top, _fascinWin[t[i]].left + _fascinWin[t[i]].width - 1, @@ -984,16 +966,16 @@ void Draw_Fascination::activeWin(int16 id) { } tempSrf = _vm->_video->initSurfDesc(_vm->_global->_videoMode, _winMaxWidth + 7, _winMaxHeight, 0); - _vm->_video->drawSprite(*_backSurface, *tempSrf, + tempSrf->blit(*_backSurface, _fascinWin[id].left, _fascinWin[id].top, _fascinWin[id].left + _fascinWin[id].width - 1, _fascinWin[id].top + _fascinWin[id].height - 1, - _fascinWin[id].left & 7, 0, 0); - _vm->_video->drawSprite(*_fascinWin[oldId].savedSurface, *_backSurface, + _fascinWin[id].left & 7, 0); + _backSurface->blit(*_fascinWin[oldId].savedSurface, _fascinWin[id].left & 7, 0, (_fascinWin[id].left & 7) + _fascinWin[id].width - 1, _fascinWin[id].height - 1, - _fascinWin[id].left, _fascinWin[id].top, 0); + _fascinWin[id].left, _fascinWin[id].top); _fascinWin[oldId].savedSurface.reset(); _fascinWin[oldId].savedSurface = tempSrf; @@ -1026,18 +1008,18 @@ void Draw_Fascination::closeAllWin() { } void Draw_Fascination::saveWin(int16 id) { - _vm->_video->drawSprite(*_backSurface, *_fascinWin[id].savedSurface, + _fascinWin[id].savedSurface->blit(*_backSurface, _fascinWin[id].left, _fascinWin[id].top, _fascinWin[id].left + _fascinWin[id].width - 1, _fascinWin[id].top + _fascinWin[id].height - 1, - _fascinWin[id].left & 7, 0, 0); + _fascinWin[id].left & 7, 0); } void Draw_Fascination::restoreWin(int16 id) { - _vm->_video->drawSprite(*_fascinWin[id].savedSurface, *_backSurface, + _backSurface->blit(*_fascinWin[id].savedSurface, _fascinWin[id].left & 7, 0, (_fascinWin[id].left & 7) + _fascinWin[id].width - 1, _fascinWin[id].height - 1, - _fascinWin[id].left, _fascinWin[id].top, 0); + _fascinWin[id].left, _fascinWin[id].top); invalidateRect(_fascinWin[id].left, _fascinWin[id].top, _fascinWin[id].left + _fascinWin[id].width - 1, _fascinWin[id].top + _fascinWin[id].height - 1); @@ -1049,14 +1031,19 @@ void Draw_Fascination::drawWinTrace(int16 left, int16 top, int16 width, int16 he right = left + width - 1; bottom = top + height - 1; - for (int32 x = left; x < right; x++) { - _frontSurface->getVidMem()[_frontSurface->getWidth() * top + x] = (128 + _frontSurface->getVidMem()[_frontSurface->getWidth() * top + x]) & 0xff; - _frontSurface->getVidMem()[_frontSurface->getWidth() * bottom + x] = (128 + _frontSurface->getVidMem()[_frontSurface->getWidth() * bottom + x]) & 0xff; + Pixel pixelTop = _frontSurface->get(left, top); + Pixel pixelBottom = _frontSurface->get(left, bottom); + for (int16 i = 0; i < width; i++, pixelTop++, pixelBottom++) { + pixelTop.set((pixelTop.get() + 128) & 0xFF); + pixelBottom.set((pixelBottom.get() + 128) & 0xFF); } - for (int32 y = top; y < bottom; y++) { - _frontSurface->getVidMem()[_frontSurface->getWidth() * y + left] = (128 + _frontSurface->getVidMem()[_frontSurface->getWidth() * y + left]) & 0xff; - _frontSurface->getVidMem()[_frontSurface->getWidth() * y + right] = (128 + _frontSurface->getVidMem()[_frontSurface->getWidth() * y + right]) & 0xff; + Pixel pixelLeft = _frontSurface->get(left, top); + Pixel pixelRight = _frontSurface->get(right, top); + + for (int16 i = 0; i < height; i++, pixelLeft += _frontSurface->getWidth(), pixelRight += _frontSurface->getWidth()) { + pixelLeft.set((pixelLeft.get() + 128) & 0xFF); + pixelRight.set((pixelRight.get() + 128) & 0xFF); } _vm->_video->dirtyRectsAll(); diff --git a/engines/gob/draw_playtoons.cpp b/engines/gob/draw_playtoons.cpp index 583d13986e6..fc5521a9593 100644 --- a/engines/gob/draw_playtoons.cpp +++ b/engines/gob/draw_playtoons.cpp @@ -38,7 +38,7 @@ Draw_Playtoons::Draw_Playtoons(GobEngine *vm) : Draw_v2(vm) { void Draw_Playtoons::spriteOperation(int16 operation) { int16 len; int16 x, y; - SurfaceDescPtr sourceSurf, destSurf; + SurfacePtr sourceSurf, destSurf; bool deltaVeto; int16 left; int16 ratio; @@ -139,12 +139,11 @@ void Draw_Playtoons::spriteOperation(int16 operation) { if (!sourceSurf || !destSurf) break; - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], - *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_spritesArray[_sourceSurface], _spriteLeft, spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); @@ -152,26 +151,26 @@ void Draw_Playtoons::spriteOperation(int16 operation) { case DRAW_PUTPIXEL: switch (_pattern & 0xFF) { - case -1: + case 0xFF: warning("oPlaytoons_spriteOperation: operation DRAW_PUTPIXEL, pattern -1"); break; case 1: - _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX, + _spritesArray[_destSurface]->fillRect(destSpriteX, _destSpriteY, _destSpriteX + 1, _destSpriteY + 1, _frontColor); break; case 2: - _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX - 1, + _spritesArray[_destSurface]->fillRect(destSpriteX - 1, _destSpriteY - 1, _destSpriteX + 1, _destSpriteY + 1, _frontColor); break; case 3: - _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX - 1, + _spritesArray[_destSurface]->fillRect(destSpriteX - 1, _destSpriteY - 1, _destSpriteX + 2, _destSpriteY + 2, _frontColor); break; default: - _vm->_video->putPixel(_destSpriteX, _destSpriteY, _frontColor, *_spritesArray[_destSurface]); + _spritesArray[_destSurface]->putPixel(_destSpriteX, _destSpriteY, _frontColor); break; } dirtiedRect(_destSurface, _destSpriteX - (_pattern / 2), @@ -188,7 +187,7 @@ void Draw_Playtoons::spriteOperation(int16 operation) { warning("oPlaytoons_spriteOperation: operation DRAW_FILLRECT, pattern %d", _pattern & 0xFF); break; case 0: - _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX, + _spritesArray[_destSurface]->fillRect(destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); @@ -204,23 +203,18 @@ void Draw_Playtoons::spriteOperation(int16 operation) { case DRAW_DRAWLINE: if ((_needAdjust != 2) && (_needAdjust < 10)) { warning ("oPlaytoons_spriteOperation: operation DRAW_DRAWLINE, draw multiple lines"); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX + 1, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX + 1, _destSpriteY, _spriteRight + 1, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY + 1, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY + 1, _spriteRight, _spriteBottom + 1, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX + 1, _destSpriteY + 1, + _spritesArray[_destSurface]->drawLine(_destSpriteX + 1, _destSpriteY + 1, _spriteRight + 1, _spriteBottom + 1, _frontColor); } else { switch (_pattern & 0xFF) { case 0: - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); break; @@ -228,7 +222,7 @@ void Draw_Playtoons::spriteOperation(int16 operation) { warning("oPlaytoons_spriteOperation: operation DRAW_DRAWLINE, draw %d lines", (_pattern & 0xFF) * (_pattern & 0xFF)); for (int16 i = 0; i <= _pattern ; i++) for (int16 j = 0; j <= _pattern ; j++) - _vm->_video->drawLine(*_spritesArray[_destSurface], + _spritesArray[_destSurface]->drawLine( _destSpriteX - (_pattern / 2) + i, _destSpriteY - (_pattern / 2) + j, _spriteRight - (_pattern / 2) + i, @@ -247,7 +241,7 @@ void Draw_Playtoons::spriteOperation(int16 operation) { if ((_pattern & 0xFF) != 0) warning("oPlaytoons_spriteOperation: operation DRAW_INVALIDATE, pattern %d", _pattern & 0xFF); - _vm->_video->drawCircle(*_spritesArray[_destSurface], _destSpriteX, + _spritesArray[_destSurface]->drawCircle(_destSpriteX, _destSpriteY, _spriteRight, _frontColor); dirtiedRect(_destSurface, _destSpriteX - _spriteRight, _destSpriteY - _spriteBottom, @@ -289,9 +283,8 @@ void Draw_Playtoons::spriteOperation(int16 operation) { byte *dataBuf = _vm->_game->_resources->getTexts() + _textToPrint[1] + 1; len = *dataBuf++; for (int i = 0; i < len; i++, dataBuf += 2) { - _vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX, - _destSpriteY, *font, _transparency, _frontColor, - _backColor, *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], READ_LE_UINT16(dataBuf), + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); } } else { drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor, @@ -300,9 +293,8 @@ void Draw_Playtoons::spriteOperation(int16 operation) { } } else { for (int i = 0; i < len; i++) { - _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, - _destSpriteY, *font, _transparency, - _frontColor, _backColor, *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], _textToPrint[i], + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); _destSpriteX += font->getCharWidth(_textToPrint[i]); } } @@ -317,11 +309,10 @@ void Draw_Playtoons::spriteOperation(int16 operation) { * _fontToSprite[_fontIndex].height; x = ((_textToPrint[i] - _fontToSprite[_fontIndex].base) % ratio) * _fontToSprite[_fontIndex].width; - _vm->_video->drawSprite(*_spritesArray[_fontToSprite[_fontIndex].sprite], - *_spritesArray[_destSurface], x, y, + _spritesArray[_destSurface]->blit(*_spritesArray[_fontToSprite[_fontIndex].sprite], x, y, x + _fontToSprite[_fontIndex].width - 1, y + _fontToSprite[_fontIndex].height - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); _destSpriteX += _fontToSprite[_fontIndex].width; } } @@ -332,36 +323,28 @@ void Draw_Playtoons::spriteOperation(int16 operation) { case DRAW_DRAWBAR: if ((_needAdjust != 2) && (_needAdjust < 10)){ - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom - 1, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _spriteBottom - 1, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _destSpriteX + 1, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _spriteRight - 1, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_spriteRight - 1, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY + 1, _frontColor); } else { - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _spriteRight, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); } @@ -371,8 +354,7 @@ void Draw_Playtoons::spriteOperation(int16 operation) { case DRAW_CLEARRECT: warning ("oPlaytoons_spriteOperation: DRAW_CLEARRECT uses _backColor %d", _backColor); if (_backColor != -1) { - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); } @@ -381,8 +363,7 @@ void Draw_Playtoons::spriteOperation(int16 operation) { break; case DRAW_FILLRECTABS: - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 1cec15ce04c..d130f424c26 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -24,11 +24,11 @@ */ #include "common/endian.h" +#include "common/str.h" #include "graphics/cursorman.h" #include "gob/gob.h" #include "gob/draw.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" @@ -119,13 +119,13 @@ void Draw_v1::animateCursor(int16 cursor) { newY -= hotspotY = (uint16) VAR(_cursorIndex + _cursorHotspotYVar); } - _vm->_video->clearSurf(*_scummvmCursor); - _vm->_video->drawSprite(*_cursorSprites, *_scummvmCursor, + _scummvmCursor->clear(); + _scummvmCursor->blit(*_cursorSprites, cursorIndex * _cursorWidth, 0, (cursorIndex + 1) * _cursorWidth - 1, - _cursorHeight - 1, 0, 0, 0); - CursorMan.replaceCursor(_scummvmCursor->getVidMem(), - _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0); + _cursorHeight - 1, 0, 0); + CursorMan.replaceCursor(_scummvmCursor->getData(), + _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0, 1, &_vm->getPixelFormat()); if (_frontSurface != _backSurface) { _showCursor = 3; @@ -258,7 +258,7 @@ void Draw_v1::printTotText(int16 id) { } else if (cmd == 1) { val = READ_LE_UINT16(ptrEnd + 18) * 4; - strncpy0(buf, GET_VARO_STR(val), 19); + Common::strlcpy(buf, GET_VARO_STR(val), 20); } else { val = READ_LE_UINT16(ptrEnd + 18) * 4; @@ -346,27 +346,24 @@ void Draw_v1::spriteOperation(int16 operation) { Font *font = 0; switch (operation) { case DRAW_BLITSURF: - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], - *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_spritesArray[_sourceSurface], _spriteLeft, _spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); break; case DRAW_PUTPIXEL: - _vm->_video->putPixel(_destSpriteX, _destSpriteY, - _frontColor, *_spritesArray[_destSurface]); + _spritesArray[_destSurface]->putPixel(_destSpriteX, _destSpriteY, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX, _destSpriteY); break; case DRAW_FILLRECT: - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); @@ -375,8 +372,7 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_DRAWLINE: - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); @@ -417,31 +413,24 @@ void Draw_v1::spriteOperation(int16 operation) { _destSpriteY + font->getCharHeight() - 1); for (int i = 0; i < len; i++) { - _vm->_video->drawLetter(_textToPrint[i], - _destSpriteX, _destSpriteY, - *font, _transparency, - _frontColor, _backColor, - *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], _textToPrint[i], + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); _destSpriteX += font->getCharWidth(); } break; case DRAW_DRAWBAR: - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _spriteRight, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); @@ -449,8 +438,7 @@ void Draw_v1::spriteOperation(int16 operation) { case DRAW_CLEARRECT: if (_backColor < 16) { - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); } @@ -458,8 +446,7 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_FILLRECTABS: - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); @@ -476,11 +463,8 @@ void Draw_v1::spriteOperation(int16 operation) { dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + font->getCharWidth() - 1, _destSpriteY + font->getCharHeight() - 1); - _vm->_video->drawLetter(_letterToPrint, - _destSpriteX, _destSpriteY, - *font, _transparency, - _frontColor, _backColor, - *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], _letterToPrint, + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); break; } @@ -498,11 +482,10 @@ void Draw_v1::spriteOperation(int16 operation) { _destSpriteX + _fontToSprite[_fontIndex].width, _destSpriteY + _fontToSprite[_fontIndex].height); - _vm->_video->drawSprite(*_spritesArray[(int16)_fontToSprite[_fontIndex].sprite], - *_spritesArray[_destSurface], x, y, + _spritesArray[_destSurface]->blit(*_spritesArray[(int16)_fontToSprite[_fontIndex].sprite], x, y, x + _fontToSprite[_fontIndex].width, y + _fontToSprite[_fontIndex].height, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); break; } diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 4ecb759e9dd..ec678644d51 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -24,11 +24,11 @@ */ #include "common/endian.h" +#include "common/str.h" #include "graphics/cursorman.h" #include "gob/gob.h" #include "gob/draw.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/game.h" @@ -53,7 +53,7 @@ void Draw_v2::initScreen() { initSpriteSurf(kBackSurface, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0); _backSurface = _spritesArray[kBackSurface]; - _vm->_video->clearSurf(*_backSurface); + _backSurface->clear(); if (!_spritesArray[kCursorSurface]) { initSpriteSurf(kCursorSurface, 32, 16, 2); @@ -144,13 +144,13 @@ void Draw_v2::animateCursor(int16 cursor) { newY -= hotspotY = (uint16) VAR(_cursorIndex + _cursorHotspotYVar); } - _vm->_video->clearSurf(*_scummvmCursor); - _vm->_video->drawSprite(*_cursorSprites, *_scummvmCursor, + _scummvmCursor->clear(); + _scummvmCursor->blit(*_cursorSprites, cursorIndex * _cursorWidth, 0, (cursorIndex + 1) * _cursorWidth - 1, - _cursorHeight - 1, 0, 0, 0); - CursorMan.replaceCursor(_scummvmCursor->getVidMem(), - _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0); + _cursorHeight - 1, 0, 0); + CursorMan.replaceCursor(_scummvmCursor->getData(), + _cursorWidth, _cursorHeight, hotspotX, hotspotY, 0, 1, &_vm->getPixelFormat()); if (_frontSurface != _backSurface) { if (!_noInvalidated) { @@ -550,7 +550,7 @@ void Draw_v2::printTotText(int16 id) { sprintf(buf, "%d", VAR_OFFSET(val)); } else if (cmd == 1) { val = READ_LE_UINT16(ptrEnd + 18) * 4; - strncpy0(buf, GET_VARO_STR(val), 19); + Common::strlcpy(buf, GET_VARO_STR(val), 20); } else { val = READ_LE_UINT16(ptrEnd + 18) * 4; sprintf(buf, "%d", VAR_OFFSET(val)); @@ -617,7 +617,7 @@ void Draw_v2::printTotText(int16 id) { void Draw_v2::spriteOperation(int16 operation) { int16 len; int16 x, y; - SurfaceDescPtr sourceSurf, destSurf; + SurfacePtr sourceSurf, destSurf; bool deltaVeto; int16 left; int16 ratio; @@ -718,26 +718,24 @@ void Draw_v2::spriteOperation(int16 operation) { if (!sourceSurf || !destSurf) break; - _vm->_video->drawSprite(*_spritesArray[_sourceSurface], - *_spritesArray[_destSurface], + _spritesArray[_destSurface]->blit(*_spritesArray[_sourceSurface], _spriteLeft, spriteTop, _spriteLeft + _spriteRight - 1, _spriteTop + _spriteBottom - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1); break; case DRAW_PUTPIXEL: - _vm->_video->putPixel(_destSpriteX, _destSpriteY, _frontColor, - *_spritesArray[_destSurface]); + _spritesArray[_destSurface]->putPixel(_destSpriteX, _destSpriteY, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _destSpriteX, _destSpriteY); break; case DRAW_FILLRECT: - _vm->_video->fillRect(*_spritesArray[_destSurface], destSpriteX, + _spritesArray[_destSurface]->fillRect(destSpriteX, _destSpriteY, _destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1, _backColor); @@ -746,15 +744,14 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_DRAWLINE: - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); break; case DRAW_INVALIDATE: - _vm->_video->drawCircle(*_spritesArray[_destSurface], _destSpriteX, + _spritesArray[_destSurface]->drawCircle(_destSpriteX, _destSpriteY, _spriteRight, _frontColor); dirtiedRect(_destSurface, _destSpriteX - _spriteRight, _destSpriteY - _spriteBottom, @@ -796,9 +793,8 @@ void Draw_v2::spriteOperation(int16 operation) { byte *dataBuf = _vm->_game->_resources->getTexts() + _textToPrint[1] + 1; len = *dataBuf++; for (int i = 0; i < len; i++, dataBuf += 2) { - _vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX, - _destSpriteY, *font, _transparency, _frontColor, - _backColor, *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], READ_LE_UINT16(dataBuf), + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); } } else { drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor, @@ -807,9 +803,8 @@ void Draw_v2::spriteOperation(int16 operation) { } } else { for (int i = 0; i < len; i++) { - _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, - _destSpriteY, *font, _transparency, - _frontColor, _backColor, *_spritesArray[_destSurface]); + font->drawLetter(*_spritesArray[_destSurface], _textToPrint[i], + _destSpriteX, _destSpriteY, _frontColor, _backColor, _transparency); _destSpriteX += font->getCharWidth(_textToPrint[i]); } } @@ -824,11 +819,10 @@ void Draw_v2::spriteOperation(int16 operation) { * _fontToSprite[_fontIndex].height; x = ((_textToPrint[i] - _fontToSprite[_fontIndex].base) % ratio) * _fontToSprite[_fontIndex].width; - _vm->_video->drawSprite(*_spritesArray[_fontToSprite[_fontIndex].sprite], - *_spritesArray[_destSurface], x, y, + _spritesArray[_destSurface]->blit(*_spritesArray[_fontToSprite[_fontIndex].sprite], x, y, x + _fontToSprite[_fontIndex].width - 1, y + _fontToSprite[_fontIndex].height - 1, - _destSpriteX, _destSpriteY, _transparency); + _destSpriteX, _destSpriteY, (_transparency == 0) ? -1 : 0); _destSpriteX += _fontToSprite[_fontIndex].width; } } @@ -839,36 +833,28 @@ void Draw_v2::spriteOperation(int16 operation) { case DRAW_DRAWBAR: if (_needAdjust != 2) { - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom - 1, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _spriteBottom - 1, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _destSpriteX + 1, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _spriteRight - 1, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_spriteRight - 1, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY + 1, _frontColor); } else { - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _spriteBottom, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _spriteBottom, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _destSpriteX, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _spriteRight, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_spriteRight, _destSpriteY, _spriteRight, _spriteBottom, _frontColor); - _vm->_video->drawLine(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->drawLine(_destSpriteX, _destSpriteY, _spriteRight, _destSpriteY, _frontColor); } @@ -877,8 +863,7 @@ void Draw_v2::spriteOperation(int16 operation) { case DRAW_CLEARRECT: if ((_backColor != 16) && (_backColor != 144)) { - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); } @@ -887,8 +872,7 @@ void Draw_v2::spriteOperation(int16 operation) { break; case DRAW_FILLRECTABS: - _vm->_video->fillRect(*_spritesArray[_destSurface], - _destSpriteX, _destSpriteY, + _spritesArray[_destSurface]->fillRect(_destSpriteX, _destSpriteY, _spriteRight, _spriteBottom, _backColor); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, _spriteRight, _spriteBottom); diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp deleted file mode 100644 index c93962c206e..00000000000 --- a/engines/gob/driver_vga.cpp +++ /dev/null @@ -1,244 +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/endian.h" -#include "graphics/primitives.h" - -#include "gob/driver_vga.h" - -namespace Gob { - -static void plotPixel(int x, int y, int color, void *data) { - SurfaceDesc *dest = (SurfaceDesc *)data; - - if ((x >= 0) && (x < dest->getWidth()) && - (y >= 0) && (y < dest->getHeight())) - dest->getVidMem()[(y * dest->getWidth()) + x] = color; -} - -void VGAVideoDriver::putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest) { - if ((x >= 0) && (x < dest.getWidth()) && - (y >= 0) && (y < dest.getHeight())) - dest.getVidMem()[(y * dest.getWidth()) + x] = color; -} - -void VGAVideoDriver::drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, - int16 y1, byte color) { - - Graphics::drawLine(x0, y0, x1, y1, color, &plotPixel, &dest); -} - -void VGAVideoDriver::fillRect(SurfaceDesc &dest, int16 left, int16 top, - int16 right, int16 bottom, byte color) { - - if ((left >= dest.getWidth()) || (right >= dest.getWidth()) || - (top >= dest.getHeight()) || (bottom >= dest.getHeight())) - return; - - byte *pos = dest.getVidMem() + (top * dest.getWidth()) + left; - int16 width = (right - left) + 1; - int16 height = (bottom - top) + 1; - - while (height--) { - for (int16 i = 0; i < width; ++i) - pos[i] = color; - - pos += dest.getWidth(); - } -} - -void VGAVideoDriver::drawLetter(unsigned char item, int16 x, int16 y, - const Font &font, byte color1, byte color2, - byte transp, SurfaceDesc &dest) { - uint16 data; - - const byte *src = font.getCharData(item); - byte *dst = dest.getVidMem() + x + dest.getWidth() * y; - - int nWidth = font.getCharWidth(); - - if (nWidth & 7) - nWidth = (nWidth & 0xF8) + 8; - - nWidth >>= 3; - - for (int i = 0; i < font.getCharHeight(); i++) { - int width = font.getCharWidth(); - - for (int k = 0; k < nWidth; k++) { - - data = *src++; - for (int j = 0; j < MIN(8, width); j++) { - if (data & 0x80) - *dst = color2; - else if (color1 == 0) - *dst = transp; - - dst++; - data <<= 1; - } - - width -= 8; - - } - - dst += dest.getWidth() - font.getCharWidth(); - } -} - -void VGAVideoDriver::drawSprite(SurfaceDesc &source, SurfaceDesc &dest, - int16 left, int16 top, int16 right, int16 bottom, - int16 x, int16 y, int16 transp) { - - if ((x >= dest.getWidth()) || (x < 0) || - (y >= dest.getHeight()) || (y < 0)) - return; - - int16 width = MIN((right - left) + 1, (int) dest.getWidth()); - int16 height = MIN((bottom - top) + 1, (int) dest.getHeight()); - - if ((width < 1) || (height < 1)) - return; - - const byte *srcPos = source.getVidMem() + (top * source.getWidth()) + left; - byte *destPos = dest.getVidMem() + (y * dest.getWidth()) + x; - - uint32 size = width * height; - - if (transp) { - - while (height--) { - for (int16 i = 0; i < width; ++i) { - if (srcPos[i]) - destPos[i] = srcPos[i]; - } - - srcPos += source.getWidth(); - destPos += dest.getWidth(); - } - - } else if (((srcPos >= destPos) && (srcPos <= (destPos + size))) || - ((destPos >= srcPos) && (destPos <= (srcPos + size)))) { - - while (height--) { - memmove(destPos, srcPos, width); - - srcPos += source.getWidth(); - destPos += dest.getWidth(); - } - - } else { - - while (height--) { - memcpy(destPos, srcPos, width); - - srcPos += source.getWidth(); - destPos += dest.getWidth(); - } - - } -} - -void VGAVideoDriver::drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, - int16 left, int16 top, int16 right, int16 bottom, - int16 x, int16 y, int16 transp) { - - if ((x >= dest.getWidth()) || (x < 0) || - (y >= dest.getHeight()) || (y < 0)) - return; - - int16 width = MIN((right - left) + 1, dest.getWidth() / 2); - int16 height = MIN((bottom - top) + 1, dest.getHeight() / 2); - - if ((width < 1) || (height < 1)) - return; - - const byte *srcPos = source.getVidMem() + (top * source.getWidth()) + left; - byte *destPos = dest.getVidMem() + ((y * 2) * dest.getWidth()) + (x * 2); - - while (height--) { - const byte *srcBak = srcPos; - - for (int i = 0; i < 2; i++) { - srcPos = srcBak; - - for (int16 j = 0; j < width; j++) { - if (!transp || srcPos[i]) { - destPos[2 * j + 0] = srcPos[j]; - destPos[2 * j + 1] = srcPos[j]; - } - } - - destPos += dest.getWidth(); - } - - srcPos = srcBak + source.getWidth(); - } -} - -void VGAVideoDriver::drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, byte transp, SurfaceDesc &dest) { - int destRight = x + width; - int destBottom = y + height; - - byte *dst = dest.getVidMem() + x + dest.getWidth() * y; - - int curx = x; - int cury = y; - - while (1) { - uint8 val = *sprBuf++; - unsigned int repeat = val & 7; - val &= 0xF8; - - if (!(val & 8)) { - repeat <<= 8; - repeat |= *sprBuf++; - } - repeat++; - val >>= 4; - - for (unsigned int i = 0; i < repeat; ++i) { - if (curx < dest.getWidth() && cury < dest.getHeight()) - if (!transp || val) - *dst = val; - - dst++; - curx++; - if (curx == destRight) { - dst += dest.getWidth() + x - curx; - curx = x; - cury++; - if (cury == destBottom) - return; - } - } - - } - -} - -} - diff --git a/engines/gob/driver_vga.h b/engines/gob/driver_vga.h deleted file mode 100644 index 3102016cb54..00000000000 --- a/engines/gob/driver_vga.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef GOB_DRIVER_VGA_H -#define GOB_DRIVER_VGA_H - -#include "gob/video.h" - -namespace Gob { - -class VGAVideoDriver : public VideoDriver { -public: - VGAVideoDriver() {} - virtual ~VGAVideoDriver() {} - - void putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest); - void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, - int16 x1, int16 y1, byte color); - void fillRect(SurfaceDesc &dest, int16 left, int16 top, - int16 right, int16 bottom, byte color); - void drawLetter(unsigned char item, int16 x, int16 y, - const Font &font, byte color1, byte color2, - byte transp, SurfaceDesc &dest); - void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, - int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); - void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, - int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); - void drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, byte transp, SurfaceDesc &dest); -}; - -} - -#endif // GOB_DRIVER_VGA_H diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index b5025ba76f8..98c1066cb0b 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -24,10 +24,10 @@ */ #include "common/endian.h" +#include "common/str.h" #include "gob/gob.h" #include "gob/game.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/dataio.h" #include "gob/variables.h" @@ -214,7 +214,7 @@ void Game::prepareStart() { _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); _vm->_draw->initScreen(); - _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, + _vm->_draw->_frontSurface->fillRect(0, 0, _vm->_video->_surfWidth - 1, _vm->_video->_surfHeight - 1, 1); _vm->_util->setMousePos(152, 92); @@ -247,7 +247,7 @@ void Game::playTot(int16 skipPlay) { int16 *oldCaptureCounter; int16 *oldBreakFrom; int16 *oldNestLevel; - int16 _captureCounter; + int16 captureCounter = 0; int16 breakFrom; int16 nestLevel; @@ -259,7 +259,7 @@ void Game::playTot(int16 skipPlay) { _vm->_inter->_nestLevel = &nestLevel; _vm->_inter->_breakFromLevel = &breakFrom; - _vm->_scenery->_pCaptureCounter = &_captureCounter; + _vm->_scenery->_pCaptureCounter = &captureCounter; strcpy(savedTotName, _curTotFile); if (skipPlay <= 0) { @@ -319,10 +319,12 @@ void Game::playTot(int16 skipPlay) { _vm->_inter->renewTimeInVars(); - WRITE_VAR(13, _vm->_global->_useMouse); - WRITE_VAR(14, _vm->_global->_soundFlags); - WRITE_VAR(15, _vm->_global->_fakeVideoMode); - WRITE_VAR(16, _vm->_global->_language); + if (_vm->_inter->_variables) { + WRITE_VAR(13, _vm->_global->_useMouse); + WRITE_VAR(14, _vm->_global->_soundFlags); + WRITE_VAR(15, _vm->_global->_fakeVideoMode); + WRITE_VAR(16, _vm->_global->_language); + } _vm->_inter->callSub(2); @@ -357,7 +359,8 @@ void Game::playTot(int16 skipPlay) { if (_totToLoad[0] == 0) break; - strcpy(_curTotFile, _totToLoad); + Common::strlcpy(_curTotFile, _totToLoad, 14); + } } else { _vm->_inter->initControlVars(0); @@ -370,7 +373,7 @@ void Game::playTot(int16 skipPlay) { _vm->_inter->_terminate = 2; } - strcpy(_curTotFile, savedTotName); + Common::strlcpy(_curTotFile, savedTotName, 14); _vm->_inter->_nestLevel = oldNestLevel; _vm->_inter->_breakFromLevel = oldBreakFrom; @@ -575,7 +578,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { if (flags & 1) _vm->_inter->_variables = 0; - strncpy0(_curTotFile, newTotFile, 9); + Common::strlcpy(_curTotFile, newTotFile, 10); strcat(_curTotFile, ".TOT"); if (_vm->_inter->_terminate != 0) { diff --git a/engines/gob/global.h b/engines/gob/global.h index 4fce5952eb2..713b501f35b 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -127,7 +127,7 @@ public: bool _setAllPalette; bool _dontSetPalette; - SurfaceDescPtr _primarySurfDesc; + SurfacePtr _primarySurfDesc; int16 _debugFlag; int16 _inVM; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 02a8af92bc9..a1d3b1a61d7 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -136,6 +136,8 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { _copyProtection = ConfMan.getBool("copy_protection"); + _console = new GobConsole(this); + DebugMan.addDebugChannel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level"); DebugMan.addDebugChannel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level"); DebugMan.addDebugChannel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level"); @@ -153,6 +155,8 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { } GobEngine::~GobEngine() { + delete _console; + deinitGameParts(); } @@ -209,10 +213,6 @@ bool GobEngine::isEGA() const { return (_features & kFeaturesEGA) != 0; } -bool GobEngine::is640() const { - return (_features & kFeatures640) != 0; -} - bool GobEngine::hasAdLib() const { return (_features & kFeaturesAdLib) != 0; } @@ -225,22 +225,36 @@ bool GobEngine::isBATDemo() const { return (_features & kFeaturesBATDemo) != 0; } +bool GobEngine::is640x480() const { + return (_features & kFeatures640x480) != 0; +} + bool GobEngine::is800x600() const { return (_features & kFeatures800x600) != 0; } +bool GobEngine::isTrueColor() const { + return (_features & kFeaturesTrueColor) != 0; +} + bool GobEngine::isDemo() const { return (isSCNDemo() || isBATDemo()); } +const Graphics::PixelFormat &GobEngine::getPixelFormat() const { + return _pixelFormat; +} + Common::Error GobEngine::run() { if (!initGameParts()) { GUIErrorMessage("GobEngine::init(): Unknown version of game engine"); return Common::kUnknownError; } - _video->setSize(is640()); - _video->init(); + if (!initGraphics()) { + GUIErrorMessage("GobEngine::init(): Failed to set up graphics"); + return Common::kUnknownError; + } // On some systems it's not safe to run CD audio games from the CD. if (isCD()) @@ -518,22 +532,6 @@ bool GobEngine::initGameParts() { _inter->setupOpcodes(); - if (is640()) { - _video->_surfWidth = _width = 640; - _video->_surfHeight = _video->_splitHeight1 = _height = 480; - _global->_mouseMaxX = 640; - _global->_mouseMaxY = 480; - _mode = 0x18; - _global->_primarySurfDesc = SurfaceDescPtr(new SurfaceDesc(0x18, 640, 480)); - } else { - _video->_surfWidth = _width = 320; - _video->_surfHeight = _video->_splitHeight1 = _height = 200; - _global->_mouseMaxX = 320; - _global->_mouseMaxY = 200; - _mode = 0x14; - _global->_primarySurfDesc = SurfaceDescPtr(new SurfaceDesc(0x14, 320, 200)); - } - return true; } @@ -556,4 +554,34 @@ void GobEngine::deinitGameParts() { delete _dataIO; _dataIO = 0; } +bool GobEngine::initGraphics() { + if (is800x600()) { + warning("GobEngine::initGraphics(): 800x600 games currently unsupported"); + return false; + } else if (is640x480()) { + _width = 640; + _height = 480; + _mode = 0x18; + } else { + _width = 320; + _height = 200; + _mode = 0x14; + } + + _video->setSize(is640x480()); + + _pixelFormat = g_system->getScreenFormat(); + + _video->_surfWidth = _width; + _video->_surfHeight = _height; + _video->_splitHeight1 = _height; + + _global->_mouseMaxX = _width; + _global->_mouseMaxY = _height; + + _global->_primarySurfDesc = SurfacePtr(new Surface(_width, _height, _pixelFormat.bytesPerPixel)); + + return true; +} + } // End of namespace Gob diff --git a/engines/gob/gob.h b/engines/gob/gob.h index dcca236ee35..fe69e27c019 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -32,6 +32,8 @@ #include "engines/engine.h" +#include "gob/console.h" + namespace GUI { class StaticTextWidget; } @@ -41,8 +43,14 @@ namespace GUI { * * Status of this engine: ??? * - * Supported games: - * - ??? + * Games using this engine: + * - Gobliiins + * - Gobliins 2 + * - Goblins 3 + * - Ween: The Prophecy + * - Bargon Attack + * - Lost in Time + * - The Bizarre Adventures of Woodruff and the Schnibble */ namespace Gob { @@ -62,6 +70,7 @@ class PalAnim; class Scenery; class Util; class SaveLoad; +class GobConsole; #define WRITE_VAR_UINT32(var, val) _vm->_inter->_variables->writeVar32(var, val) #define WRITE_VAR_UINT16(var, val) _vm->_inter->_variables->writeVar16(var, val) @@ -119,14 +128,15 @@ enum GameType { }; enum Features { - kFeaturesNone = 0, - kFeaturesCD = 1 << 0, - kFeaturesEGA = 1 << 1, - kFeaturesAdLib = 1 << 2, - kFeatures640 = 1 << 3, - kFeaturesSCNDemo = 1 << 4, - kFeaturesBATDemo = 1 << 5, - kFeatures800x600 = 1 << 6 + kFeaturesNone = 0, + kFeaturesCD = 1 << 0, + kFeaturesEGA = 1 << 1, + kFeaturesAdLib = 1 << 2, + kFeaturesSCNDemo = 1 << 3, + kFeaturesBATDemo = 1 << 4, + kFeatures640x480 = 1 << 5, + kFeatures800x600 = 1 << 6, + kFeaturesTrueColor = 1 << 7 }; enum { @@ -151,6 +161,7 @@ private: GameType _gameType; int32 _features; Common::Platform _platform; + GobConsole *_console; uint32 _pauseStart; @@ -163,6 +174,8 @@ private: bool initGameParts(); void deinitGameParts(); + bool initGraphics(); + public: static const Common::Language _gobToScummVMLang[]; @@ -173,6 +186,8 @@ public: uint16 _height; uint8 _mode; + Graphics::PixelFormat _pixelFormat; + Common::String _startStk; Common::String _startTot; uint32 _demoIndex; @@ -208,13 +223,18 @@ public: GameType getGameType() const; bool isCD() const; bool isEGA() const; - bool is640() const; bool hasAdLib() const; bool isSCNDemo() const; bool isBATDemo() const; + bool is640x480() const; bool is800x600() const; + bool isTrueColor() const; bool isDemo() const; + GUI::Debugger *getDebugger() { return _console; } + + const Graphics::PixelFormat &getPixelFormat() const; + GobEngine(OSystem *syst); virtual ~GobEngine(); diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index 11043df7824..88827e7fcf9 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -23,9 +23,10 @@ * */ +#include "common/str.h" + #include "gob/gob.h" #include "gob/goblin.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/draw.h" @@ -233,9 +234,9 @@ void Goblin::drawObjects() { if (objDesc->toRedraw == 0) continue; - _vm->_video->drawSprite(*_vm->_mult->_animSurf, *_vm->_draw->_backSurface, + _vm->_draw->_backSurface->blit(*_vm->_mult->_animSurf, objDesc->left, objDesc->top, objDesc->right, - objDesc->bottom, objDesc->left, objDesc->top, 0); + objDesc->bottom, objDesc->left, objDesc->top); _vm->_draw->invalidateRect(objDesc->left, objDesc->top, objDesc->right, objDesc->bottom); @@ -668,11 +669,11 @@ void Goblin::adjustDest(int16 posX, int16 posY) { resDelta = i; } - for (i = 1; ((i + _pressedMapX) < _vm->_map->_mapWidth) && + for (i = 1; ((i + _pressedMapX) < _vm->_map->getMapWidth()) && (_vm->_map->getPass(_pressedMapX + i, _pressedMapY) == 0); i++) ; - if ((_pressedMapX + i) < _vm->_map->_mapWidth) { + if ((_pressedMapX + i) < _vm->_map->getMapWidth()) { deltaPix = (i * 12) - (posX % 12); if ((resDelta == -1) || (deltaPix < resDeltaPix)) { resDeltaPix = deltaPix; @@ -681,11 +682,11 @@ void Goblin::adjustDest(int16 posX, int16 posY) { } } - for (i = 1; ((i + _pressedMapY) < _vm->_map->_mapHeight) && + for (i = 1; ((i + _pressedMapY) < _vm->_map->getMapHeight()) && (_vm->_map->getPass(_pressedMapX, _pressedMapY + i) == 0); i++) ; - if ((_pressedMapY + i) < _vm->_map->_mapHeight) { + if ((_pressedMapY + i) < _vm->_map->getMapHeight()) { deltaPix = (i * 6) - (posY % 6); if ((resDelta == -1) || (deltaPix < resDeltaPix)) { resDeltaPix = deltaPix; @@ -726,8 +727,8 @@ void Goblin::adjustDest(int16 posX, int16 posY) { } } - _pressedMapX = CLIP((int) _pressedMapX, 0, _vm->_map->_mapWidth - 1); - _pressedMapY = CLIP((int) _pressedMapY, 0, _vm->_map->_mapHeight - 1); + _pressedMapX = CLIP((int) _pressedMapX, 0, _vm->_map->getMapWidth() - 1); + _pressedMapY = CLIP((int) _pressedMapY, 0, _vm->_map->getMapHeight() - 1); } void Goblin::adjustTarget() { @@ -737,18 +738,18 @@ void Goblin::adjustTarget() { if ((_pressedMapY > 0) && (_vm->_map->getItem(_pressedMapX, _pressedMapY - 1) != 0)) { _pressedMapY--; - } else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) && + } else if ((_pressedMapX < (_vm->_map->getMapWidth() - 1)) && (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY) != 0)) { _pressedMapX++; - } else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) && + } else if ((_pressedMapX < (_vm->_map->getMapWidth() - 1)) && (_pressedMapY > 0) && (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY - 1) != 0)) { _pressedMapY--; _pressedMapX++; } } - _pressedMapX = CLIP((int) _pressedMapX, 0, _vm->_map->_mapWidth - 1); - _pressedMapY = CLIP((int) _pressedMapY, 0, _vm->_map->_mapHeight - 1); + _pressedMapX = CLIP((int) _pressedMapX, 0, _vm->_map->getMapWidth() - 1); + _pressedMapY = CLIP((int) _pressedMapY, 0, _vm->_map->getMapHeight() - 1); } void Goblin::targetDummyItem(Gob_Object *gobDesc) { @@ -847,7 +848,7 @@ void Goblin::targetItem() { } } - if (_pressedMapY < (_vm->_map->_mapHeight-1)) { + if (_pressedMapY < (_vm->_map->getMapHeight()-1)) { if ((_vm->_map->getItem(_pressedMapX, _pressedMapY + 1)) == (_vm->_map->getItem(_pressedMapX, _pressedMapY))) { _pressedMapY++; @@ -898,8 +899,8 @@ void Goblin::targetItem() { } } } - _pressedMapX = CLIP((int) _pressedMapX, 0, _vm->_map->_mapWidth - 1); - _pressedMapY = CLIP((int) _pressedMapY, 0, _vm->_map->_mapHeight - 1); + _pressedMapX = CLIP((int) _pressedMapX, 0, _vm->_map->getMapWidth() - 1); + _pressedMapY = CLIP((int) _pressedMapY, 0, _vm->_map->getMapHeight() - 1); } void Goblin::moveFindItem(int16 posX, int16 posY) { @@ -933,23 +934,23 @@ void Goblin::moveFindItem(int16 posX, int16 posY) { break; } - _pressedMapX = CLIP(posX / 12, 0, _vm->_map->_mapWidth - 1); - _pressedMapY = CLIP(posY / 6, 0, _vm->_map->_mapHeight - 1); + _pressedMapX = CLIP(posX / 12, 0, _vm->_map->getMapWidth() - 1); + _pressedMapY = CLIP(posY / 6, 0, _vm->_map->getMapHeight() - 1); if ((_vm->_map->getItem(_pressedMapX, _pressedMapY) == 0) && (i < 20)) { - if ((_pressedMapY < (_vm->_map->_mapHeight - 1)) && + if ((_pressedMapY < (_vm->_map->getMapHeight() - 1)) && (_vm->_map->getItem(_pressedMapX, _pressedMapY + 1) != 0)) { _pressedMapY++; - } else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) && - (_pressedMapY < (_vm->_map->_mapHeight - 1)) && + } else if ((_pressedMapX < (_vm->_map->getMapWidth() - 1)) && + (_pressedMapY < (_vm->_map->getMapHeight() - 1)) && (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY + 1) != 0)) { _pressedMapX++; _pressedMapY++; - } else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) && + } else if ((_pressedMapX < (_vm->_map->getMapWidth() - 1)) && (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY) != 0)) { _pressedMapX++; - } else if ((_pressedMapX < (_vm->_map->_mapWidth - 1)) && + } else if ((_pressedMapX < (_vm->_map->getMapWidth() - 1)) && (_pressedMapY > 0) && (_vm->_map->getItem(_pressedMapX + 1, _pressedMapY - 1) != 0)) { _pressedMapX++; @@ -965,15 +966,15 @@ void Goblin::moveFindItem(int16 posX, int16 posY) { (_vm->_map->getItem(_pressedMapX - 1, _pressedMapY) != 0)) { _pressedMapX--; } else if ((_pressedMapX > 0) && - (_pressedMapY < (_vm->_map->_mapHeight - 1)) && + (_pressedMapY < (_vm->_map->getMapHeight() - 1)) && (_vm->_map->getItem(_pressedMapX - 1, _pressedMapY + 1) != 0)) { _pressedMapX--; _pressedMapY++; } } } else { - _pressedMapX = CLIP(posX / 12, 0, _vm->_map->_mapWidth - 1); - _pressedMapY = CLIP(posY / 6, 0, _vm->_map->_mapHeight - 1); + _pressedMapX = CLIP(posX / 12, 0, _vm->_map->getMapWidth() - 1); + _pressedMapY = CLIP(posY / 6, 0, _vm->_map->getMapHeight() - 1); } } @@ -1186,7 +1187,7 @@ void Goblin::loadObjects(const char *source) { freeObjects(); initList(); - strncpy0(_vm->_map->_sourceFile, source, 14); + Common::strlcpy(_vm->_map->_sourceFile, source, 15); _vm->_map->_sourceFile[strlen(_vm->_map->_sourceFile) - 4] = 0; _vm->_map->loadMapObjects(source); @@ -1386,8 +1387,8 @@ void Goblin::pickItem(int16 indexToPocket, int16 idToPocket) { _itemIndInPocket = indexToPocket; _itemIdInPocket = idToPocket; - for (int y = 0; y < _vm->_map->_mapHeight; y++) { - for (int x = 0; x < _vm->_map->_mapWidth; x++) { + for (int y = 0; y < _vm->_map->getMapHeight(); y++) { + for (int x = 0; x < _vm->_map->getMapWidth(); x++) { if (_itemByteFlag == 1) { if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == idToPocket) _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF); @@ -1450,7 +1451,7 @@ void Goblin::placeItem(int16 indexInPocket, int16 idInPocket) { _vm->_map->placeItem(xPos, yPos - 1, idInPocket); if (lookDir == 4) { - if (xPos < _vm->_map->_mapWidth - 1) { + if (xPos < _vm->_map->getMapWidth() - 1) { _vm->_map->placeItem(xPos + 1, yPos, idInPocket); if (yPos > 0) @@ -1497,16 +1498,16 @@ void Goblin::swapItems(int16 indexToPick, int16 idToPick) { _itemIdInPocket = idToPick; if (_itemByteFlag == 0) { - for (y = 0; y < _vm->_map->_mapHeight; y++) { - for (x = 0; x < _vm->_map->_mapWidth; x++) { + for (y = 0; y < _vm->_map->getMapHeight(); y++) { + for (x = 0; x < _vm->_map->getMapWidth(); x++) { if ((_vm->_map->getItem(x, y) & 0xFF) == idToPick) _vm->_map->setItem(x, y, (_vm->_map->getItem(x, y) & 0xFF00) + idToPlace); } } } else { - for (y = 0; y < _vm->_map->_mapHeight; y++) { - for (x = 0; x < _vm->_map->_mapWidth; x++) { + for (y = 0; y < _vm->_map->getMapHeight(); y++) { + for (x = 0; x < _vm->_map->getMapWidth(); x++) { if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == idToPick) _vm->_map->setItem(x, y, (_vm->_map->getItem(x, y) & 0xFF) + (idToPlace << 8)); } @@ -1704,15 +1705,15 @@ void Goblin::setState(int16 index, int16 state) { animData->newCycle = _vm->_scenery->getAnimLayer(animation, layer)->framesCount; _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 1); - if (_vm->_map->_bigTiles) { - *obj->pPosY = ((obj->goblinY + 1) * _vm->_map->_tilesHeight) - + if (_vm->_map->hasBigTiles()) { + *obj->pPosY = ((obj->goblinY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (obj->goblinY + 1) / 2; } else { - *obj->pPosY = (obj->goblinY + 1) * _vm->_map->_tilesHeight - + *obj->pPosY = (obj->goblinY + 1) * _vm->_map->getTilesHeight() - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); } - *obj->pPosX = obj->goblinX * _vm->_map->_tilesWidth; + *obj->pPosX = obj->goblinX * _vm->_map->getTilesWidth(); } void Goblin::animate(Mult::Mult_Object *obj) { @@ -1780,40 +1781,69 @@ void Goblin::animate(Mult::Mult_Object *obj) { } void Goblin::move(int16 destX, int16 destY, int16 objIndex) { - Mult::Mult_Object *obj; - Mult::Mult_AnimData *animData; - int16 mouseX; - int16 mouseY; - int16 gobDestX; - int16 gobDestY; - obj = &_vm->_mult->_objects[objIndex]; - animData = obj->pAnimData; + Mult::Mult_Object *obj = &_vm->_mult->_objects[objIndex]; + Mult::Mult_AnimData *animData = obj->pAnimData; - obj->gobDestX = destX; - obj->gobDestY = destY; + obj->gobDestX = destX; + obj->gobDestY = destY; animData->destX = destX; animData->destY = destY; if (animData->isBusy != 0) { if ((destX == -1) && (destY == -1)) { - mouseX = _vm->_global->_inter_mouseX; - mouseY = _vm->_global->_inter_mouseY; - if (_vm->_map->_bigTiles) - mouseY += ((_vm->_global->_inter_mouseY / _vm->_map->_tilesHeight) + 1) / 2; + int16 mouseX = _vm->_global->_inter_mouseX; + int16 mouseY = _vm->_global->_inter_mouseY; - gobDestX = mouseX / _vm->_map->_tilesWidth; - gobDestY = mouseY / _vm->_map->_tilesHeight; + if (_vm->_map->hasBigTiles()) + mouseY += ((_vm->_global->_inter_mouseY / _vm->_map->getTilesHeight()) + 1) / 2; + + int16 gobDestX = mouseX / _vm->_map->getTilesWidth(); + int16 gobDestY = mouseY / _vm->_map->getTilesHeight(); if (_vm->_map->getPass(gobDestX, gobDestY) == 0) _vm->_map->findNearestWalkable(gobDestX, gobDestY, mouseX, mouseY); - animData->destX = obj->gobDestX = - (gobDestX == -1) ? obj->goblinX : gobDestX; - animData->destY = obj->gobDestY = - (gobDestY == -1) ? obj->goblinY : gobDestY; + obj->gobDestX = (gobDestX == -1) ? obj->goblinX : gobDestX; + obj->gobDestY = (gobDestY == -1) ? obj->goblinY : gobDestY; + + animData->destX = obj->gobDestX; + animData->destY = obj->gobDestY; } } + + WRITE_VAR(56, 0); + + byte passType = _vm->_map->getPass(obj->gobDestX, obj->gobDestY); + + // Prevent continous walking on wide stairs + if (passType == 11) { + if (_vm->_map->getScreenWidth() == 640) { + obj->gobDestY++; + animData->destY++; + } + } + + // Prevent stopping in the middle of big ladders + if ((passType == 19) || (passType == 20)) { + int ladderTop = 0; + while (_vm->_map->getPass(obj->gobDestX, obj->gobDestY + ladderTop) == passType) + ladderTop++; + + int ladderBottom = 0; + while (_vm->_map->getPass(obj->gobDestX, obj->gobDestY + ladderBottom) == passType) + ladderBottom--; + + int ladderDest; + if (ABS(ladderBottom) <= ladderTop) + ladderDest = obj->gobDestY + ladderBottom; + else + ladderDest = obj->gobDestY + ladderTop; + + obj->gobDestY = ladderDest; + animData->destY = ladderDest; + } + initiateMove(obj); } diff --git a/engines/gob/goblin_v1.cpp b/engines/gob/goblin_v1.cpp index f55fec433cb..3dc4c6611d7 100644 --- a/engines/gob/goblin_v1.cpp +++ b/engines/gob/goblin_v1.cpp @@ -154,8 +154,10 @@ void Goblin_v1::initiateMove(Mult::Mult_Object *obj) { _vm->_map->_nearestWayPoint, _vm->_map->_nearestDest) == 0) { _pathExistence = 0; } else { - _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; - _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; + const WayPoint &wayPoint = _vm->_map->getWayPoint(_vm->_map->_nearestWayPoint); + + _vm->_map->_destX = wayPoint.x; + _vm->_map->_destY = wayPoint.y; } } } @@ -173,10 +175,10 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, _pathExistence = 0; } - nextAct = _vm->_map->getDirection(_vm->_map->_curGoblinX, + nextAct = (int16) _vm->_map->getDirection(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY, _vm->_map->_destX, _vm->_map->_destY); - if (nextAct == 0) + if (nextAct == kDirNone) _pathExistence = 0; } else if (_pathExistence == 3) { _vm->_map->_curGoblinX = _gobPositions[_currentGoblin].x; @@ -199,20 +201,20 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest) { _vm->_map->optimizePoints(0, 0, 0); - _vm->_map->_destX = - _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; - _vm->_map->_destY = - _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; + const WayPoint &wayPoint = _vm->_map->getWayPoint(_vm->_map->_nearestWayPoint); + + _vm->_map->_destX = wayPoint.x; + _vm->_map->_destY = wayPoint.y; if (_vm->_map->_nearestWayPoint > _vm->_map->_nearestDest) _vm->_map->_nearestWayPoint--; } else if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest) { _vm->_map->optimizePoints(0, 0, 0); - _vm->_map->_destX = - _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; - _vm->_map->_destY = - _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; + const WayPoint &wayPoint = _vm->_map->getWayPoint(_vm->_map->_nearestWayPoint); + + _vm->_map->_destX = wayPoint.x; + _vm->_map->_destY = wayPoint.y; if (_vm->_map->_nearestWayPoint < _vm->_map->_nearestDest) _vm->_map->_nearestWayPoint++; @@ -220,8 +222,12 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, if ((_vm->_map->checkDirectPath(0, _vm->_map->_curGoblinX, _vm->_map->_curGoblinY, _gobDestX, _gobDestY) == 3) && (_vm->_map->getPass(_pressedMapX, _pressedMapY) != 0)) { - _vm->_map->_destX = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].x; - _vm->_map->_destY = _vm->_map->_wayPoints[_vm->_map->_nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(_vm->_map->_nearestWayPoint); + + _vm->_map->_destX = wayPoint.x; + _vm->_map->_destY = wayPoint.y; + } else { _pathExistence = 1; _vm->_map->_destX = _pressedMapX; @@ -229,7 +235,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, } } } - nextAct = _vm->_map->getDirection(_vm->_map->_curGoblinX, + nextAct = (int16) _vm->_map->getDirection(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY, _vm->_map->_destX, _vm->_map->_destY); } } @@ -238,11 +244,11 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, nextAct = 0x4DC8; switch (nextAct) { - case Map::kDirW: + case kDirW: gobDesc->nextState = rotateState(gobDesc->curLookDir, 0); break; - case Map::kDirE: + case kDirE: gobDesc->nextState = rotateState(gobDesc->curLookDir, 4); break; @@ -254,7 +260,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, gobDesc->nextState = 23; break; - case Map::kDirN: + case kDirN: if ((_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY - 1) == 6) && (_currentGoblin != 1)) { _pathExistence = 0; @@ -275,7 +281,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, gobDesc->nextState = rotateState(gobDesc->curLookDir, 2); break; - case Map::kDirS: + case kDirS: if ((_vm->_map->getPass(_vm->_map->_curGoblinX, _vm->_map->_curGoblinY + 1) == 6) && (_currentGoblin != 1)) { _pathExistence = 0; @@ -296,7 +302,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, gobDesc->nextState = rotateState(gobDesc->curLookDir, 6); break; - case Map::kDirSE: + case kDirSE: if ((_vm->_map->getPass(_vm->_map->_curGoblinX + 1, _vm->_map->_curGoblinY + 1) == 6) && (_currentGoblin != 1)) { _pathExistence = 0; @@ -310,7 +316,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, gobDesc->nextState = rotateState(gobDesc->curLookDir, 4); break; - case Map::kDirSW: + case kDirSW: if ((_vm->_map->getPass(_vm->_map->_curGoblinX - 1, _vm->_map->_curGoblinY + 1) == 6) && (_currentGoblin != 1)) { _pathExistence = 0; @@ -324,7 +330,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, gobDesc->nextState = rotateState(gobDesc->curLookDir, 0); break; - case Map::kDirNW: + case kDirNW: if ((_vm->_map->getPass(_vm->_map->_curGoblinX - 1, _vm->_map->_curGoblinY - 1) == 6) && (_currentGoblin != 1)) { _pathExistence = 0; @@ -338,7 +344,7 @@ void Goblin_v1::movePathFind(Mult::Mult_Object *obj, gobDesc->nextState = rotateState(gobDesc->curLookDir, 0); break; - case Map::kDirNE: + case kDirNE: if ((_vm->_map->getPass(_vm->_map->_curGoblinX + 1, _vm->_map->_curGoblinY - 1) == 6) && (_currentGoblin != 1)) { _pathExistence = 0; diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp index 2747750abb6..503377c19b6 100644 --- a/engines/gob/goblin_v2.cpp +++ b/engines/gob/goblin_v2.cpp @@ -39,10 +39,10 @@ namespace Gob { Goblin_v2::Goblin_v2(GobEngine *vm) : Goblin_v1(vm) { _gobsCount = -1; - _rotStates[0][0] = 0; _rotStates[0][1] = 18; _rotStates[0][2] = 19; _rotStates[0][3] = 20; - _rotStates[1][0] = 13; _rotStates[1][1] = 2; _rotStates[1][2] = 12; _rotStates[1][3] = 14; - _rotStates[2][0] = 16; _rotStates[2][1] = 15; _rotStates[2][2] = 4; _rotStates[2][3] = 17; - _rotStates[3][0] = 23; _rotStates[3][1] = 21; _rotStates[3][2] = 22; _rotStates[3][3] = 6; + _rotStates[0][0] = 0; _rotStates[0][1] = 18; _rotStates[0][2] = 19; _rotStates[0][3] = 20; + _rotStates[1][0] = 13; _rotStates[1][1] = 2; _rotStates[1][2] = 12; _rotStates[1][3] = 14; + _rotStates[2][0] = 16; _rotStates[2][1] = 15; _rotStates[2][2] = 4; _rotStates[2][3] = 17; + _rotStates[3][0] = 23; _rotStates[3][1] = 21; _rotStates[3][2] = 22; _rotStates[3][3] = 6; } void Goblin_v2::freeObjects() { @@ -80,13 +80,13 @@ void Goblin_v2::placeObject(Gob_Object *objDesc, char animated, objAnim->newCycle = 0; _vm->_scenery->updateAnim(objAnim->layer, 0, objAnim->animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (!_vm->_map->_bigTiles) - *obj->pPosY = (y + 1) * _vm->_map->_tilesHeight + if (!_vm->_map->hasBigTiles()) + *obj->pPosY = (y + 1) * _vm->_map->getTilesHeight() - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); else - *obj->pPosY = ((y + 1) * _vm->_map->_tilesHeight) - + *obj->pPosY = ((y + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (y + 1) / 2; - *obj->pPosX = x * _vm->_map->_tilesWidth; + *obj->pPosX = x * _vm->_map->getTilesWidth(); } else { if ((obj->goblinStates != 0) && (obj->goblinStates[state] != 0)) { layer = obj->goblinStates[state][0].layer; @@ -99,13 +99,13 @@ void Goblin_v2::placeObject(Gob_Object *objDesc, char animated, objAnim->isStatic = 0; objAnim->newCycle = _vm->_scenery->getAnimLayer(animation, layer)->framesCount; _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (!_vm->_map->_bigTiles) - *obj->pPosY = (y + 1) * _vm->_map->_tilesHeight + if (!_vm->_map->hasBigTiles()) + *obj->pPosY = (y + 1) * _vm->_map->getTilesHeight() - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); else - *obj->pPosY = ((y + 1) * _vm->_map->_tilesHeight) - + *obj->pPosY = ((y + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (y + 1) / 2; - *obj->pPosX = x * _vm->_map->_tilesWidth; + *obj->pPosX = x * _vm->_map->getTilesWidth(); initiateMove(obj); } else initiateMove(obj); @@ -121,54 +121,55 @@ void Goblin_v2::initiateMove(Mult::Mult_Object *obj) { obj->pAnimData->pathExistence = _vm->_map->checkDirectPath(obj, obj->goblinX, obj->goblinY, obj->gobDestX, obj->gobDestY); if (obj->pAnimData->pathExistence == 3) { - obj->destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - obj->destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + obj->destX = wayPoint.x; + obj->destY = wayPoint.y; } } void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 nextAct) { - Mult::Mult_AnimData *animData; - int16 framesCount; - int16 gobX; - int16 gobY; - int16 gobDestX; - int16 gobDestY; - int16 destX; - int16 destY; - int16 dir; + Mult::Mult_AnimData *animData = obj->pAnimData; + + animData->newCycle = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount; + + int16 gobX = obj->goblinX; + int16 gobY = obj->goblinY; + int16 destX = obj->destX; + int16 destY = obj->destY; + int16 gobDestX = obj->gobDestX; + int16 gobDestY = obj->gobDestY; - dir = 0; - animData = obj->pAnimData; - framesCount = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount; - animData->newCycle = framesCount; - gobX = obj->goblinX; - gobY = obj->goblinY; - animData->order = gobY; - gobDestX = obj->gobDestX; - gobDestY = obj->gobDestY; animData->destX = gobDestX; animData->destY = gobDestY; - destX = obj->destX; - destY = obj->destY; + animData->order = gobY; + + Direction dir = kDirNone; if (animData->pathExistence == 1) { + dir = _vm->_map->getDirection(gobX, gobY, destX, destY); - if (dir == 0) + if (dir == kDirNone) animData->pathExistence = 0; - if ((gobX == destX) && (gobY == destY)) + if ((gobX == gobDestX) && (gobY == gobDestY)) animData->pathExistence = 4; + } else if (animData->pathExistence == 3) { - if ((gobX == gobDestX) && (gobY == gobDestY)) { - animData->pathExistence = 4; - destX = gobDestX; - destY = gobDestY; - } else { + + if ((gobX != gobDestX) || (gobY != gobDestY)) { + if (_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) != 1) { + if ((gobX == destX) && (gobY == destY)) { + if (obj->nearestWayPoint > obj->nearestDest) { _vm->_map->optimizePoints(obj, gobX, gobY); - destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + destX = wayPoint.x; + destY = wayPoint.y; + if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) { WRITE_VAR(56, 1); animData->pathExistence = 0; @@ -177,8 +178,12 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 obj->nearestWayPoint--; } else if (obj->nearestWayPoint < obj->nearestDest) { _vm->_map->optimizePoints(obj, gobX, gobY); - destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + destX = wayPoint.x; + destY = wayPoint.y; + if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) { WRITE_VAR(56, 1); animData->pathExistence = 0; @@ -188,8 +193,12 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } else { if ((_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) == 3) && (_vm->_map->getPass(gobDestX, gobDestY) != 0)) { - destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + destX = wayPoint.x; + destY = wayPoint.y; + WRITE_VAR(56, 1); } else { animData->pathExistence = 1; @@ -197,26 +206,35 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 destY = gobDestY; } } + } + } else { destX = gobDestX; destY = gobDestY; } + dir = _vm->_map->getDirection(gobX, gobY, destX, destY); + + } else { + animData->pathExistence = 4; + destX = gobDestX; + destY = gobDestY; } + } - obj->goblinX = gobX; - obj->goblinY = gobY; - obj->gobDestX = gobDestX; - obj->gobDestY = gobDestY; - obj->destX = destX; - obj->destY = destY; + obj->goblinX = gobX; + obj->goblinY = gobY; + obj->destX = destX; + obj->destY = destY; + obj->gobDestX = gobDestX; + obj->gobDestY = gobDestY; switch (dir) { - case Map::kDirNW: + case kDirNW: animData->nextState = 1; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 40; if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) @@ -224,28 +242,29 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirN: + case kDirN: animData->nextState = (animData->curLookDir == 2) ? 2 : rotateState(animData->curLookDir, 2); - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { - if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) { - if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10) - animData->nextState = 42; - else - animData->nextState = 2; - } else + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) == 10) animData->nextState = 40; - } else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) + else if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10) + animData->nextState = 42; + else + animData->nextState = 2; + } + + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) animData->nextState = 38; - else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) animData->nextState = 26; } break; - case Map::kDirNE: - animData->nextState = 3; - if (_vm->_map->_screenWidth == 640) { + case kDirNE: + animData->nextState = 3; + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 42; if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10) @@ -253,17 +272,17 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirW: + case kDirW: animData->nextState = rotateState(animData->curLookDir, 0); break; - case Map::kDirE: + case kDirE: animData->nextState = rotateState(animData->curLookDir, 4); break; - case Map::kDirSW: + case kDirSW: animData->nextState = 7; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 41; if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) @@ -271,10 +290,10 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirS: + case kDirS: animData->nextState = (animData->curLookDir == 6) ? 6 : rotateState(animData->curLookDir, 6); - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) animData->nextState = 39; if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) @@ -282,9 +301,9 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirSE: + case kDirSE: animData->nextState = 5; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 43; if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) != 10) @@ -293,7 +312,7 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 break; default: - if (animData->curLookDir == 0) + if (animData->curLookDir == 0) animData->nextState = 8; else if (animData->curLookDir == 2) animData->nextState = 29; @@ -307,12 +326,6 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 void Goblin_v2::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 nextAct, int16 framesCount) { - Mult::Mult_AnimData *animData; - int16 gobX; - int16 gobY; - int16 animation; - int16 state; - int16 layer; if (!obj->goblinStates) return; @@ -320,7 +333,7 @@ void Goblin_v2::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, movePathFind(obj, 0, 0); playSounds(obj); - animData = obj->pAnimData; + Mult::Mult_AnimData *animData = obj->pAnimData; framesCount = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount; @@ -395,72 +408,87 @@ void Goblin_v2::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, } if ((animData->newState != -1) && (animData->frame == framesCount) && - (animData->newState != animData->state)) { + (animData->newState != animData->state)) { + animData->nextState = animData->newState; - animData->newState = -1; - animData->state = animData->nextState; + animData->newState = -1; + animData->state = animData->nextState; Scenery::AnimLayer *animLayer = _vm->_scenery->getAnimLayer(animData->animation, animData->layer); + *obj->pPosX += animLayer->animDeltaX; *obj->pPosY += animLayer->animDeltaY; - animation = obj->goblinStates[animData->nextState][0].animation; - layer = obj->goblinStates[animData->nextState][0].layer; - animData->layer = layer; + int16 animation = obj->goblinStates[animData->nextState][0].animation; + int16 layer = obj->goblinStates[animData->nextState][0].layer; + + animData->layer = layer; animData->animation = animation; - animData->frame = 0; - } else { - if (isMovement(animData->state)) { - state = animData->nextState; - if (animData->frame == ((framesCount + 1) / 2)) { - gobX = obj->goblinX; - gobY = obj->goblinY; + animData->frame = 0; - advMovement(obj, state); + return; + } - if (animData->state != state) { - animation = obj->goblinStates[state][0].animation; - layer = obj->goblinStates[state][0].layer; - animData->layer = layer; - animData->animation = animation; - animData->frame = 0; - animData->state = state; - _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_map->_bigTiles) - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2; - else - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); - *obj->pPosX = gobX * _vm->_map->_tilesWidth; - } - } - } + if (isMovement(animData->state)) { + int16 state = animData->nextState; - if (animData->frame >= framesCount) { - state = animData->nextState; - animation = obj->goblinStates[state][0].animation; - layer = obj->goblinStates[state][0].layer; - animData->layer = layer; - animData->animation = animation; - animData->frame = 0; - animData->state = state; - gobX = obj->goblinX; - gobY = obj->goblinY; + if (animData->frame == ((framesCount + 1) / 2)) { + int16 gobX = obj->goblinX; + int16 gobY = obj->goblinY + 1; advMovement(obj, state); - _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_map->_bigTiles) - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2; - else - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); - *obj->pPosX = gobX * _vm->_map->_tilesWidth; + if (animData->state != state) { + int16 animation = obj->goblinStates[state][0].animation; + int16 layer = obj->goblinStates[state][0].layer; + + animData->layer = layer; + animData->animation = animation; + animData->frame = 0; + animData->state = state; + + _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); + uint32 gobPosX = gobX * _vm->_map->getTilesWidth(); + uint32 gobPosY = (gobY * _vm->_map->getTilesHeight()) - + (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); + + if (_vm->_map->hasBigTiles()) + gobPosY -= gobY / 2; + + *obj->pPosX = gobPosX; + *obj->pPosY = gobPosY; + } } } + + if (animData->frame < framesCount) + return; + + int16 state = animData->nextState; + int16 animation = obj->goblinStates[state][0].animation; + int16 layer = obj->goblinStates[state][0].layer; + + animData->layer = layer; + animData->animation = animation; + animData->frame = 0; + animData->state = state; + + int16 gobX = obj->goblinX; + int16 gobY = obj->goblinY + 1; + + advMovement(obj, state); + + _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); + uint32 gobPosX = gobX * _vm->_map->getTilesWidth(); + uint32 gobPosY = (gobY * _vm->_map->getTilesHeight()) - + (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); + + if (_vm->_map->hasBigTiles()) + gobPosY -= gobY / 2; + + *obj->pPosX = gobPosX; + *obj->pPosY = gobPosY; } void Goblin_v2::handleGoblins() { diff --git a/engines/gob/goblin_v4.cpp b/engines/gob/goblin_v4.cpp index 25c52cef358..523357aab1c 100644 --- a/engines/gob/goblin_v4.cpp +++ b/engines/gob/goblin_v4.cpp @@ -77,8 +77,12 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 if ((gobX == destX) && (gobY == destY)) { if (obj->nearestWayPoint > obj->nearestDest) { _vm->_map->optimizePoints(obj, gobX, gobY); - destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + destX = wayPoint.x; + destY = wayPoint.y; + if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) { WRITE_VAR(56, 1); animData->pathExistence = 0; @@ -87,8 +91,12 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 obj->nearestWayPoint--; } else if (obj->nearestWayPoint < obj->nearestDest) { _vm->_map->optimizePoints(obj, gobX, gobY); - destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + destX = wayPoint.x; + destY = wayPoint.y; + if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) { WRITE_VAR(56, 1); animData->pathExistence = 0; @@ -98,8 +106,12 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } else { if ((_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) == 3) && (_vm->_map->getPass(gobDestX, gobDestY) != 0)) { - destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; - destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + + const WayPoint &wayPoint = _vm->_map->getWayPoint(obj->nearestWayPoint); + + destX = wayPoint.x; + destY = wayPoint.y; + WRITE_VAR(56, 1); } else { animData->pathExistence = 1; @@ -123,20 +135,20 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 obj->destX = destX; obj->destY = destY; - if (_vm->_map->_widthByte == 4) { + if (_vm->_map->getVersion() == 4) { switch (dir) { - case Map::kDirNW: - animData->nextState = turnState(animData->state, Map::kDirNW); + case kDirNW: + animData->nextState = turnState(animData->state, kDirNW); if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && (animData->nextState == 1)) animData->nextState = 40; if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) - animData->nextState = turnState(animData->state, Map::kDirNW); + animData->nextState = turnState(animData->state, kDirNW); break; - case Map::kDirN: + case kDirN: animData->nextState = - (animData->curLookDir == 2) ? 2 : turnState(animData->state, Map::kDirN); + (animData->curLookDir == 2) ? 2 : turnState(animData->state, kDirN); if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) { if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10) @@ -154,35 +166,35 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 animData->nextState = 26; break; - case Map::kDirNE: - animData->nextState = turnState(animData->state, Map::kDirNE); + case kDirNE: + animData->nextState = turnState(animData->state, kDirNE); if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && (animData->nextState == 3)) animData->nextState = 42; if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10) - animData->nextState = turnState(animData->state, Map::kDirNE); + animData->nextState = turnState(animData->state, kDirNE); break; - case Map::kDirW: - animData->nextState = turnState(animData->state, Map::kDirW); + case kDirW: + animData->nextState = turnState(animData->state, kDirW); break; - case Map::kDirE: - animData->nextState = turnState(animData->state, Map::kDirE); + case kDirE: + animData->nextState = turnState(animData->state, kDirE); break; - case Map::kDirSW: - animData->nextState = turnState(animData->state, Map::kDirSW); + case kDirSW: + animData->nextState = turnState(animData->state, kDirSW); if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && (animData->nextState == 7)) animData->nextState = 41; if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY) != 10) - animData->nextState = turnState(animData->state, Map::kDirSW); + animData->nextState = turnState(animData->state, kDirSW); break; - case Map::kDirS: + case kDirS: animData->nextState = - (animData->curLookDir == 6) ? 6 : turnState(animData->state, Map::kDirS); + (animData->curLookDir == 6) ? 6 : turnState(animData->state, kDirS); if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) { if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) == 10) @@ -201,13 +213,13 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 animData->nextState = 27; break; - case Map::kDirSE: - animData->nextState = turnState(animData->state, Map::kDirSE); + case kDirSE: + animData->nextState = turnState(animData->state, kDirSE); if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && (animData->nextState == 5)) animData->nextState = 43; if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY) != 10) - animData->nextState = turnState(animData->state, Map::kDirSE); + animData->nextState = turnState(animData->state, kDirSE); break; default: @@ -260,9 +272,9 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } } else { switch (dir) { - case Map::kDirNW: + case kDirNW: animData->nextState = 1; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 40; if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) @@ -270,10 +282,10 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirN: + case kDirN: animData->nextState = (animData->curLookDir == 2) ? 2 : rotateState(animData->curLookDir, 2); - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) { if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10) @@ -289,9 +301,9 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirNE: + case kDirNE: animData->nextState = 3; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 42; if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10) @@ -299,17 +311,17 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirW: + case kDirW: animData->nextState = rotateState(animData->curLookDir, 0); break; - case Map::kDirE: + case kDirE: animData->nextState = rotateState(animData->curLookDir, 4); break; - case Map::kDirSW: + case kDirSW: animData->nextState = 7; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 41; if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) @@ -317,10 +329,10 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirS: + case kDirS: animData->nextState = (animData->curLookDir == 6) ? 6 : rotateState(animData->curLookDir, 6); - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) animData->nextState = 39; else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) @@ -328,9 +340,9 @@ void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 } break; - case Map::kDirSE: + case kDirSE: animData->nextState = 5; - if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getScreenWidth() == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 43; if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) != 10) @@ -496,13 +508,13 @@ void Goblin_v4::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, animData->frame = 0; animData->state = state; _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_map->_bigTiles) - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + if (_vm->_map->hasBigTiles()) + *obj->pPosY = ((gobY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2; else - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + *obj->pPosY = ((gobY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); - *obj->pPosX = gobX * _vm->_map->_tilesWidth; + *obj->pPosX = gobX * _vm->_map->getTilesWidth(); } } } @@ -521,13 +533,13 @@ void Goblin_v4::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, advMovement(obj, state); _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); - if (_vm->_map->_bigTiles) - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + if (_vm->_map->hasBigTiles()) + *obj->pPosY = ((gobY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2; else - *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + *obj->pPosY = ((gobY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); - *obj->pPosX = gobX * _vm->_map->_tilesWidth; + *obj->pPosX = gobX * _vm->_map->getTilesWidth(); } } } @@ -589,35 +601,35 @@ int16 Goblin_v4::turnState(int16 state, uint16 dir) { } switch (dir) { - case Map::kDirNW: + case kDirNW: cx = 1; break; - case Map::kDirN: + case kDirN: cx = 2; break; - case Map::kDirNE: + case kDirNE: cx = 3; break; - case Map::kDirW: + case kDirW: cx = 0; break; - case Map::kDirE: + case kDirE: cx = 4; break; - case Map::kDirSW: + case kDirSW: cx = 7; break; - case Map::kDirS: + case kDirS: cx = 6; break; - case Map::kDirSE: + case kDirSE: cx = 5; break; } diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp index 78b3553aeba..94c3c6fb24c 100644 --- a/engines/gob/hotspots.cpp +++ b/engines/gob/hotspots.cpp @@ -23,9 +23,10 @@ * */ +#include "common/str.h" + #include "gob/hotspots.h" #include "gob/global.h" -#include "gob/helper.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/script.h" @@ -880,10 +881,10 @@ uint16 Hotspots::updateInput(uint16 xPos, uint16 yPos, uint16 width, uint16 heig while (1) { // If we the edit field has enough space, add a space for the new character - strncpy0(tempStr, str, 254); + Common::strlcpy(tempStr, str, 255); strcat(tempStr, " "); if ((editSize != 0) && strlen(tempStr) > editSize) - strncpy0(tempStr, str, 255); + Common::strlcpy(tempStr, str, 256); // Clear input area fillRect(xPos, yPos, @@ -1236,18 +1237,18 @@ void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, _vm->_draw->_invalidatedBottoms[0] = 199; _vm->_draw->_invalidatedCount = 1; if (windowNum == 0) { - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left + width - 1, top, left + width - 1, top + height - 1, 0); - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left, top, left, top + height - 1, 0); - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left, top, left + width - 1, top, 0); - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left, top + height - 1, left + width - 1, top + height - 1, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left + width - 1, top, left + width - 1, top + height - 1, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left, top + height - 1, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left + width - 1, top, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top + height - 1, left + width - 1, top + height - 1, 0); } else { if ((_vm->_draw->_fascinWin[windowNum].id != -1) && (_vm->_draw->_fascinWin[windowNum].id == _vm->_draw->_winCount - 1)) { left += _vm->_draw->_fascinWin[windowNum].left; top += _vm->_draw->_fascinWin[windowNum].top; - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left + width - 1, top, left + width - 1, top + height - 1, 0); - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left, top, left, top + height - 1, 0); - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left, top, left + width - 1, top, 0); - _vm->_video->drawLine(*_vm->_draw->_spritesArray[_vm->_draw->_destSurface], left, top + height - 1, left + width - 1, top + height - 1, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left + width - 1, top, left + width - 1, top + height - 1, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left, top + height - 1, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top, left + width - 1, top, 0); + _vm->_draw->_spritesArray[_vm->_draw->_destSurface]->drawLine(left, top + height - 1, left + width - 1, top + height - 1, 0); left -= _vm->_draw->_fascinWin[windowNum].left; top -= _vm->_draw->_fascinWin[windowNum].top; } @@ -1295,7 +1296,7 @@ void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, uint32 funcEnter = 0, funcLeave = 0; if ((windowNum != 0) && (type != 0) && (type != 2)) - warning("evaluateNew - type %d, win %d\n",type, windowNum); + warning("evaluateNew - type %d, win %d",type, windowNum); // Evaluate parameters for the new hotspot switch (type) { @@ -1392,7 +1393,7 @@ void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, flags = _vm->_game->_script->readInt16(); if (flags > 3) - warning("evaluateNew: Warning, use of type 2 or 20. flags = %d, should be %d\n", flags, flags&3); + warning("evaluateNew: Warning, use of type 2 or 20. flags = %d, should be %d", flags, flags&3); funcEnter = 0; @@ -1516,7 +1517,7 @@ void Hotspots::evaluate() { int16 duration = _vm->_game->_script->peekByte(1); byte leaveWindowIndex = 0; - if ( _vm->getGameType() == kGameTypeFascination ) + if (_vm->getGameType() == kGameTypeFascination) leaveWindowIndex = _vm->_game->_script->peekByte(2); byte hotspotIndex1 = _vm->_game->_script->peekByte(3); @@ -1642,7 +1643,7 @@ int16 Hotspots::findCursor(uint16 x, uint16 y) const { int16 deltax = 0; int16 deltay = 0; - if ( _vm->getGameType() == kGameTypeFascination ) + if (_vm->getGameType() == kGameTypeFascination) cursor = curWindow(deltax, deltay); if (cursor == 0) { @@ -2006,14 +2007,14 @@ void Hotspots::checkStringMatch(const Hotspot &spot, const InputDesc &input, char tempStr[256]; char spotStr[256]; - strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + Common::strlcpy(tempStr, GET_VARO_STR(spot.key), 256); if (spot.getType() < kTypeInput3NoLeave) _vm->_util->cleanupStr(tempStr); uint16 pos = 0; do { - strncpy0(spotStr, str, 255); + Common::strlcpy(spotStr, str, 256); pos += strlen(str) + 1; str += strlen(str) + 1; @@ -2106,7 +2107,7 @@ void Hotspots::fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 _vm->_draw->_spriteBottom = height; _vm->_draw->_backColor = color; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); } void Hotspots::printText(uint16 x, uint16 y, const char *str, uint16 fontIndex, uint16 color) const { @@ -2140,7 +2141,7 @@ void Hotspots::updateAllTexts(const InputDesc *inputs) const { // Get its text char tempStr[256]; - strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + Common::strlcpy(tempStr, GET_VARO_STR(spot.key), 256); // Coordinates uint16 x = spot.left; diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index 3da71a2ba66..5c59a5692f7 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -53,7 +53,6 @@ Init::~Init() { } void Init::cleanup() { - _vm->_video->freeDriver(); _vm->_global->_primarySurfDesc.reset(); _vm->_sound->speakerOff(); @@ -65,8 +64,6 @@ void Init::doDemo() { if (_vm->isSCNDemo()) { // This is a non-interactive demo with a SCN script and VMD videos - _vm->_video->setPrePalette(); - SCNPlayer scnPlayer(_vm); if (_vm->_demoIndex > 0) diff --git a/engines/gob/init_v3.cpp b/engines/gob/init_v3.cpp index cb4a0b713fb..b3816c10e9a 100644 --- a/engines/gob/init_v3.cpp +++ b/engines/gob/init_v3.cpp @@ -39,10 +39,11 @@ Init_v3::~Init_v3() { } void Init_v3::updateConfig() { -// In the CD version of Goblins3, some texts are flagged 'subtitles' -// incorrectly and therefore should be displayed in all cases. +// In the CD and Windows version of Goblins3, some texts are flagged +// 'subtitles' incorrectly and therefore should be displayed in all cases. // The first obvious example is just after Death level. - if ((_vm->getGameType() == kGameTypeGob3) && _vm->isCD()) + if ((_vm->getGameType() == kGameTypeGob3) && + (_vm->isCD() || (_vm->getPlatform() == Common::kPlatformWindows))) _vm->_global->_doSubtitles = true; } diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index f6e6d411004..8db42b217cf 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -268,23 +268,23 @@ void Inter::funcBlock(int16 retFlag) { int addr = _vm->_game->_script->pos(); if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie, EGA - !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt005.tot")) || (startaddr == 0x188D && addr == 0x1A58 && // Zombie, Mac - !strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt005.tot")) || (startaddr == 0x1299 && addr == 0x139A && // Dungeon - !strncmp(_vm->_game->_curTotFile, "avt006.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt006.tot")) || (startaddr == 0x11C0 && addr == 0x12C9 && // Cauldron, EGA - !strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt012.tot")) || (startaddr == 0x11C8 && addr == 0x1341 && // Cauldron, Mac - !strncmp(_vm->_game->_curTotFile, "avt012.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt012.tot")) || (startaddr == 0x09F2 && addr == 0x0AF3 && // Statue - !strncmp(_vm->_game->_curTotFile, "avt016.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt016.tot")) || (startaddr == 0x0B92 && addr == 0x0C93 && // Castle - !strncmp(_vm->_game->_curTotFile, "avt019.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt019.tot")) || (startaddr == 0x17D9 && addr == 0x18DA && // Finale, EGA - !strncmp(_vm->_game->_curTotFile, "avt022.tot", 10)) || + !scumm_stricmp(_vm->_game->_curTotFile, "avt022.tot")) || (startaddr == 0x17E9 && addr == 0x19A8 && // Finale, Mac - !strncmp(_vm->_game->_curTotFile, "avt022.tot", 10))) { + !scumm_stricmp(_vm->_game->_curTotFile, "avt022.tot"))) { _vm->_util->longDelay(5000); } @@ -295,7 +295,7 @@ void Inter::funcBlock(int16 retFlag) { // of Fascination have a too short delay between the storage room and the lab. // We manually add it here. if ((_vm->getGameType() == kGameTypeFascination) && - !strncmp(_vm->_game->_curTotFile, "PLANQUE.tot", 9)) { + !scumm_stricmp(_vm->_game->_curTotFile, "PLANQUE.tot")) { int addr = _vm->_game->_script->pos(); if ((startaddr == 0x0202 && addr == 0x0330) || // Before Lab, Amiga & Atari, English (startaddr == 0x023D && addr == 0x032D) || // Before Lab, PC floppy, German @@ -306,6 +306,21 @@ void Inter::funcBlock(int16 retFlag) { } // End of workaround cmd = _vm->_game->_script->readByte(); + + // WORKAROUND: + // A VGA version has some broken code in its scripts, this workaround skips the corrupted parts. + if (_vm->getGameType() == kGameTypeFascination) { + int addr = _vm->_game->_script->pos(); + if ((startaddr == 0x212D) && (addr == 0x290E) && (cmd == 0x90) && !scumm_stricmp(_vm->_game->_curTotFile, "INTRO1.tot")) { + _vm->_game->_script->skip(2); + cmd = _vm->_game->_script->readByte(); + } + if ((startaddr == 0x207D) && (addr == 0x22CE) && (cmd == 0x90) && !scumm_stricmp(_vm->_game->_curTotFile, "INTRO2.tot")) { + _vm->_game->_script->skip(2); + cmd = _vm->_game->_script->readByte(); + } + } + if ((cmd >> 4) >= 12) { cmd2 = 16 - (cmd >> 4); cmd &= 0xF; diff --git a/engines/gob/inter.h b/engines/gob/inter.h index ca97483054a..4554a0783bf 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -542,7 +542,6 @@ protected: bool o6_loadCursor(OpFuncParams ¶ms); bool o6_assign(OpFuncParams ¶ms); - bool o6_palLoad(OpFuncParams ¶ms); bool o6_removeHotspot(OpFuncParams ¶ms); bool o6_fillRect(OpFuncParams ¶ms); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 5c561966414..3afb70d6c09 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -120,16 +120,16 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { int16 mouseX; int16 mouseY; MouseButtons buttons; - SurfaceDescPtr surface; + SurfacePtr surface; SoundDesc samples[4]; int16 comp[5] = { 0, 1, 2, 3, -1 }; static const char *sndFiles[] = {"1INTROII.snd", "2INTROII.snd", "1INTRO3.snd", "2INTRO3.snd"}; surface = _vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, 0); _vm->_video->drawPackedSprite("2ille.ims", *surface); - _vm->_video->drawSprite(*surface, *_vm->_draw->_frontSurface, 0, 0, 319, 199, 0, 0, 0); + _vm->_draw->_frontSurface->blit(*surface, 0, 0, 319, 199, 0, 0); _vm->_video->drawPackedSprite("2ille4.ims", *surface); - _vm->_video->drawSprite(*surface, *_vm->_draw->_frontSurface, 0, 0, 319, 199, 320, 0, 0); + _vm->_draw->_frontSurface->blit(*surface, 0, 0, 319, 199, 320, 0); _vm->_util->setScrollOffset(320, 0); _vm->_video->dirtyRectsAll(); _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); @@ -140,7 +140,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == kKeyEscape) || _vm->shouldQuit()) { _vm->_palAnim->fade(0, -2, 0); - _vm->_video->clearSurf(*_vm->_draw->_frontSurface); + _vm->_draw->_frontSurface->clear(); memset((char *)_vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); WRITE_VAR(0, kKeyEscape); @@ -161,7 +161,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { _vm->_sound->blasterPlayComposition(comp, 0, samples, 4); _vm->_sound->blasterWaitEndPlay(true, false); _vm->_palAnim->fade(0, 0, 0); - _vm->_video->clearSurf(*_vm->_draw->_frontSurface); + _vm->_draw->_frontSurface->clear(); } void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { @@ -192,7 +192,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { _vm->shouldQuit()) { _vm->_sound->blasterStop(10); _vm->_palAnim->fade(0, -2, 0); - _vm->_video->clearSurf(*_vm->_draw->_frontSurface); + _vm->_draw->_frontSurface->clear(); memset(_vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); WRITE_VAR(0, kKeyEscape); diff --git a/engines/gob/inter_fascin.cpp b/engines/gob/inter_fascin.cpp index d2b97eea43a..895eb85440d 100644 --- a/engines/gob/inter_fascin.cpp +++ b/engines/gob/inter_fascin.cpp @@ -137,7 +137,8 @@ bool Inter_Fascination::oFascin_repeatUntil(OpFuncParams ¶ms) { // This results in a crash in Scummvm. This workaround avoids that crash. if (_vm->getPlatform() == Common::kPlatformPC) { if ((!scumm_stricmp(_vm->_game->_curTotFile, "INTRO1.TOT") && (blockPos == 3533)) || - (!scumm_stricmp(_vm->_game->_curTotFile, "INTRO2.TOT") && (blockPos == 3519))) + (!scumm_stricmp(_vm->_game->_curTotFile, "INTRO2.TOT") && (blockPos == 3519)) || + (!scumm_stricmp(_vm->_game->_curTotFile, "INTRO2.TOT") && (blockPos == 3265))) //PC Hebrew _terminate = 1; } } while (!flag && !_break && !_terminate && !_vm->shouldQuit()); diff --git a/engines/gob/inter_playtoons.cpp b/engines/gob/inter_playtoons.cpp index befed4b1c2c..050bbce1327 100644 --- a/engines/gob/inter_playtoons.cpp +++ b/engines/gob/inter_playtoons.cpp @@ -24,12 +24,12 @@ */ #include "common/endian.h" +#include "common/str.h" #include "gui/message.h" #include "gob/gob.h" #include "gob/inter.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" @@ -415,9 +415,9 @@ void Inter_Playtoons::oPlaytoons_copyFile() { char fileName2[128]; _vm->_game->_script->evalExpr(0); - strncpy0(fileName1, _vm->_game->_script->getResultStr(), 127); + Common::strlcpy(fileName1, _vm->_game->_script->getResultStr(), 128); _vm->_game->_script->evalExpr(0); - strncpy0(fileName2, _vm->_game->_script->getResultStr(), 127); + Common::strlcpy(fileName2, _vm->_game->_script->getResultStr(), 128); warning("Playtoons Stub: copy file from \"%s\" to \"%s\"", fileName1, fileName2); } @@ -427,7 +427,7 @@ void Inter_Playtoons::oPlaytoons_openItk() { char *backSlash; _vm->_game->_script->evalExpr(0); - strncpy0(fileName, _vm->_game->_script->getResultStr(), 124); + Common::strlcpy(fileName, _vm->_game->_script->getResultStr(), 124); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 11fe0c9c5e1..6dab8161d0d 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -24,11 +24,11 @@ */ #include "common/endian.h" +#include "common/str.h" #include "common/file.h" #include "gob/gob.h" #include "gob/inter.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" @@ -492,10 +492,10 @@ void Inter_v1::o1_initMult() { _vm->_mult->_animSurf = _vm->_draw->_spritesArray[Draw::kAnimSurface]; } - _vm->_video->drawSprite(*_vm->_draw->_backSurface, *_vm->_mult->_animSurf, + _vm->_mult->_animSurf->blit(*_vm->_draw->_backSurface, _vm->_mult->_animLeft, _vm->_mult->_animTop, _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1, - _vm->_mult->_animTop + _vm->_mult->_animHeight - 1, 0, 0, 0); + _vm->_mult->_animTop + _vm->_mult->_animHeight - 1, 0, 0); debugC(4, kDebugGraphics, "o1_initMult: x = %d, y = %d, w = %d, h = %d", _vm->_mult->_animLeft, _vm->_mult->_animTop, @@ -707,8 +707,7 @@ bool Inter_v1::o1_loadCursor(OpFuncParams ¶ms) { if (!resource) return false; - _vm->_video->fillRect(*_vm->_draw->_cursorSprites, - index * _vm->_draw->_cursorWidth, 0, + _vm->_draw->_cursorSprites->fillRect(index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); @@ -972,7 +971,7 @@ bool Inter_v1::o1_loadTot(OpFuncParams ¶ms) { if ((_vm->_game->_script->peekByte() & 0x80) != 0) { _vm->_game->_script->skip(1); _vm->_game->_script->evalExpr(0); - strncpy0(buf, _vm->_game->_script->getResultStr(), 15); + Common::strlcpy(buf, _vm->_game->_script->getResultStr(), 16); } else { size = _vm->_game->_script->readInt8(); memcpy(buf, _vm->_game->_script->readString(size), size); @@ -1075,7 +1074,7 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { } } if (!allZero) { - _vm->_video->clearSurf(*_vm->_draw->_frontSurface); + _vm->_draw->_frontSurface->clear(); _vm->_draw->_noInvalidated57 = true; _vm->_game->_script->skip(48); return false; @@ -1190,6 +1189,9 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { int16 key; uint32 now; + _vm->_draw->forceBlit(); + _vm->_video->retrace(); + cmd = _vm->_game->_script->readInt16(); animPalette(); _vm->_draw->blitInvalidated(); @@ -1510,7 +1512,7 @@ bool Inter_v1::o1_strToLong(OpFuncParams ¶ms) { int32 res; strVar = _vm->_game->_script->readVarIndex(); - strncpy0(str, GET_VARO_STR(strVar), 19); + Common::strlcpy(str, GET_VARO_STR(strVar), 20); res = atoi(str); destVar = _vm->_game->_script->readVarIndex(); @@ -2560,8 +2562,8 @@ void Inter_v1::animPalette() { } void Inter_v1::manipulateMap(int16 xPos, int16 yPos, int16 item) { - for (int y = 0; y < _vm->_map->_mapHeight; y++) { - for (int x = 0; x < _vm->_map->_mapWidth; x++) { + for (int y = 0; y < _vm->_map->getMapHeight(); y++) { + for (int x = 0; x < _vm->_map->getMapWidth(); x++) { if ((_vm->_map->getItem(x, y) & 0xFF) == item) _vm->_map->setItem(x, y, _vm->_map->getItem(x, y) & 0xFF00); else if (((_vm->_map->getItem(x, y) & 0xFF00) >> 8) == item) @@ -2569,7 +2571,7 @@ void Inter_v1::manipulateMap(int16 xPos, int16 yPos, int16 item) { } } - if (xPos < _vm->_map->_mapWidth - 1) { + if (xPos < _vm->_map->getMapWidth() - 1) { if (yPos > 0) { if (((_vm->_map->getItem(xPos, yPos) & 0xFF00) != 0) || ((_vm->_map->getItem(xPos, yPos - 1) & 0xFF00) != 0) || @@ -2658,7 +2660,7 @@ void Inter_v1::manipulateMap(int16 xPos, int16 yPos, int16 item) { return; } - if ((xPos < _vm->_map->_mapWidth - 2) && + if ((xPos < _vm->_map->getMapWidth() - 2) && (_vm->_map->getPass(xPos + 2, yPos) == 1)) { _vm->_map->_itemPoses[item].x = xPos + 2; _vm->_map->_itemPoses[item].y = yPos; @@ -2666,7 +2668,7 @@ void Inter_v1::manipulateMap(int16 xPos, int16 yPos, int16 item) { return; } - if ((xPos < _vm->_map->_mapWidth - 1) && + if ((xPos < _vm->_map->getMapWidth() - 1) && (_vm->_map->getPass(xPos + 1, yPos) == 1)) { _vm->_map->_itemPoses[item].x = xPos + 1; _vm->_map->_itemPoses[item].y = yPos; diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 0003332e476..2cb430ff9b1 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -24,6 +24,7 @@ */ #include "common/endian.h" +#include "common/str.h" #include "gui/message.h" @@ -32,7 +33,6 @@ #include "gob/gob.h" #include "gob/inter.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" @@ -432,7 +432,7 @@ void Inter_v2::o2_loadMultObject() { obj.gobDestY = val; obj.goblinY = val; - *(obj.pPosX) *= _vm->_map->_tilesWidth; + *(obj.pPosX) *= _vm->_map->getTilesWidth(); layer = objAnim.layer; animation = obj.goblinStates[layer][0].animation; @@ -447,14 +447,14 @@ void Inter_v2::o2_loadMultObject() { _vm->_scenery->updateAnim(layer, 0, animation, 0, *(obj.pPosX), *(obj.pPosY), 0); - if (!_vm->_map->_bigTiles) - *(obj.pPosY) = (obj.goblinY + 1) * _vm->_map->_tilesHeight + if (!_vm->_map->hasBigTiles()) + *(obj.pPosY) = (obj.goblinY + 1) * _vm->_map->getTilesHeight() - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); else - *(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->_tilesHeight) - + *(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - ((obj.goblinY + 1) / 2); - *(obj.pPosX) = obj.goblinX * _vm->_map->_tilesWidth; + *(obj.pPosX) = obj.goblinX * _vm->_map->getTilesWidth(); } else if ((objAnim.animType == 101) && (objIndex < _vm->_goblin->_gobsCount)) { @@ -530,7 +530,7 @@ void Inter_v2::o2_readLIC() { char path[40]; _vm->_game->_script->evalExpr(0); - strncpy0(path, _vm->_game->_script->getResultStr(), 35); + Common::strlcpy(path, _vm->_game->_script->getResultStr(), 36); strcat(path, ".LIC"); _vm->_sound->cdLoadLIC(path); @@ -778,14 +778,14 @@ void Inter_v2::o2_setGoblinState() { _vm->_scenery->updateAnim(layer, 0, animation, 0, *(obj.pPosX), *(obj.pPosY), 0); - if (_vm->_map->_bigTiles) - *(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->_tilesHeight) - + if (_vm->_map->hasBigTiles()) + *(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - ((obj.goblinY + 1) / 2); else - *(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->_tilesHeight) - + *(obj.pPosY) = ((obj.goblinY + 1) * _vm->_map->getTilesHeight()) - (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); - *(obj.pPosX) = obj.goblinX * _vm->_map->_tilesWidth; + *(obj.pPosX) = obj.goblinX * _vm->_map->getTilesWidth(); break; } } @@ -963,7 +963,7 @@ void Inter_v2::o2_playImd() { _vm->_game->_script->evalExpr(0); _vm->_game->_script->getResultStr()[8] = 0; - strncpy0(imd, _vm->_game->_script->getResultStr(), 127); + Common::strlcpy(imd, _vm->_game->_script->getResultStr(), 128); VideoPlayer::Properties props; @@ -1031,7 +1031,7 @@ void Inter_v2::o2_openItk() { char fileName[32]; _vm->_game->_script->evalExpr(0); - strncpy0(fileName, _vm->_game->_script->getResultStr(), 27); + Common::strlcpy(fileName, _vm->_game->_script->getResultStr(), 28); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); @@ -1462,7 +1462,7 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams ¶ms) { varName = _vm->_game->_script->readInt16(); - strncpy0(fileName, GET_VAR_STR(varName), 15); + Common::strlcpy(fileName, GET_VAR_STR(varName), 16); strcat(fileName, ".INS"); _vm->_sound->infogramesLoadInstruments(fileName); @@ -1474,7 +1474,7 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { varName = _vm->_game->_script->readInt16(); - strncpy0(fileName, GET_VAR_STR(varName), 15); + Common::strlcpy(fileName, GET_VAR_STR(varName), 16); strcat(fileName, ".DUM"); _vm->_sound->infogramesLoadSong(fileName); @@ -1560,7 +1560,7 @@ int16 Inter_v2::loadSound(int16 search) { if (id == -1) { char sndfile[14]; - strncpy0(sndfile, _vm->_game->_script->readString(9), 9); + Common::strlcpy(sndfile, _vm->_game->_script->readString(9), 10); if (type == SOUND_ADL) strcat(sndfile, ".ADL"); diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index ce1f19e9a72..698dddeae9e 100644 --- a/engines/gob/inter_v4.cpp +++ b/engines/gob/inter_v4.cpp @@ -24,11 +24,11 @@ */ #include "common/endian.h" +#include "common/str.h" #include "common/file.h" #include "gob/gob.h" #include "gob/inter.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/draw.h" #include "gob/game.h" @@ -134,8 +134,8 @@ void Inter_v4::o4_initScreen() { _vm->_util->setScrollOffset(); if (offY > 0) { - _vm->_draw->_spritesArray[24] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); - _vm->_draw->_spritesArray[25] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); + _vm->_draw->_spritesArray[24] = SurfacePtr(new Surface(_vm->_width, offY, _vm->getPixelFormat().bytesPerPixel)); + _vm->_draw->_spritesArray[25] = SurfacePtr(new Surface(_vm->_width, offY, _vm->getPixelFormat().bytesPerPixel)); _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25]; } } @@ -145,7 +145,7 @@ void Inter_v4::o4_playVmdOrMusic() { bool close; _vm->_game->_script->evalExpr(0); - strncpy0(fileName, _vm->_game->_script->getResultStr(), 127); + Common::strlcpy(fileName, _vm->_game->_script->getResultStr(), 128); // WORKAROUND: The nut rolling animation in the administration center // in Woodruff is called "noixroul", but the scripts think it's "noixroule". diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp index b6cfe0ea3cb..a684a94a7d0 100644 --- a/engines/gob/inter_v5.cpp +++ b/engines/gob/inter_v5.cpp @@ -194,8 +194,8 @@ void Inter_v5::o5_initScreen() { _vm->_util->setScrollOffset(); if (offY > 0) { - _vm->_draw->_spritesArray[24] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); - _vm->_draw->_spritesArray[25] = SurfaceDescPtr(new SurfaceDesc(videoMode, _vm->_width, offY)); + _vm->_draw->_spritesArray[24] = SurfacePtr(new Surface(_vm->_width, offY, _vm->getPixelFormat().bytesPerPixel)); + _vm->_draw->_spritesArray[25] = SurfacePtr(new Surface(_vm->_width, offY, _vm->getPixelFormat().bytesPerPixel)); _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25]; } } diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp index a5a4f7d666c..e1eff279b5b 100644 --- a/engines/gob/inter_v6.cpp +++ b/engines/gob/inter_v6.cpp @@ -24,12 +24,12 @@ */ #include "common/endian.h" +#include "common/str.h" #include "common/file.h" #include "graphics/dither.h" #include "gob/gob.h" #include "gob/inter.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/dataio.h" #include "gob/game.h" @@ -65,7 +65,6 @@ void Inter_v6::setupOpcodesFunc() { OPCODEFUNC(0x03, o6_loadCursor); OPCODEFUNC(0x09, o6_assign); - OPCODEFUNC(0x13, o6_palLoad); OPCODEFUNC(0x19, o6_removeHotspot); OPCODEFUNC(0x33, o6_fillRect); } @@ -105,7 +104,7 @@ void Inter_v6::o6_playVmdOrMusic() { bool close; _vm->_game->_script->evalExpr(0); - strncpy0(fileName, _vm->_game->_script->getResultStr(), 127); + Common::strlcpy(fileName, _vm->_game->_script->getResultStr(), 128); VideoPlayer::Properties props; @@ -188,7 +187,7 @@ void Inter_v6::o6_openItk() { char fileName[32]; _vm->_game->_script->evalExpr(0); - strncpy0(fileName, _vm->_game->_script->getResultStr(), 27); + Common::strlcpy(fileName, _vm->_game->_script->getResultStr(), 28); if (!strchr(fileName, '.')) strcat(fileName, ".ITK"); @@ -239,7 +238,7 @@ bool Inter_v6::o6_loadCursor(OpFuncParams ¶ms) { props.lastFrame = i; _vm->_vidPlayer->play(vmdSlot, props); - _vm->_vidPlayer->copyFrame(vmdSlot, _vm->_draw->_cursorSprites->getVidMem(), + _vm->_vidPlayer->copyFrame(vmdSlot, _vm->_draw->_cursorSprites->getData(), 0, 0, _vm->_draw->_cursorWidth, _vm->_draw->_cursorWidth, (start + i) * _vm->_draw->_cursorWidth, 0, _vm->_draw->_cursorSprites->getWidth()); @@ -263,8 +262,7 @@ bool Inter_v6::o6_loadCursor(OpFuncParams ¶ms) { if (!resource) return false; - _vm->_video->fillRect(*_vm->_draw->_cursorSprites, - index * _vm->_draw->_cursorWidth, 0, + _vm->_draw->_cursorSprites->fillRect(index * _vm->_draw->_cursorWidth, 0, index * _vm->_draw->_cursorWidth + _vm->_draw->_cursorWidth - 1, _vm->_draw->_cursorHeight - 1, 0); @@ -357,17 +355,6 @@ bool Inter_v6::o6_assign(OpFuncParams ¶ms) { return false; } -bool Inter_v6::o6_palLoad(OpFuncParams ¶ms) { - o1_palLoad(params); - - if (_gotFirstPalette) - _vm->_video->_palLUT->setPalette((const byte *)_vm->_global->_pPaletteDesc->vgaPal, - Graphics::PaletteLUT::kPaletteRGB, 6, 0); - - _gotFirstPalette = true; - return false; -} - bool Inter_v6::o6_removeHotspot(OpFuncParams ¶ms) { int16 id; uint8 stateType1 = Hotspots::kStateFilledDisabled | Hotspots::kStateType1; diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp index 9f1f5bdc59a..500f6515ec1 100644 --- a/engines/gob/map.cpp +++ b/engines/gob/map.cpp @@ -32,33 +32,40 @@ namespace Gob { Map::Map(GobEngine *vm) : _vm(vm) { - _widthByte = 0; - _mapWidth = -1; - _mapHeight = -1; - _screenWidth = 0; - _screenHeight = 0; - _tilesWidth = 0; - _tilesHeight = 0; - _passWidth = 0; + _mapVersion = 0; + + _passWidth = 0; + _mapWidth = -1; + _mapHeight = -1; + _passMap = 0; + + _screenWidth = 0; + _screenHeight = 0; + + _tilesWidth = 0; + _tilesHeight = 0; - _passMap = 0; - _itemsMap = 0; - _wayPointsCount = 0; - _wayPoints = 0; _bigTiles = false; + _wayPointCount = 0; + _wayPoints = 0; + + _nearestWayPoint = 0; + _nearestDest = 0; + + _itemsMap = 0; + for (int i = 0; i < 40; i++) { - _itemPoses[i].x = 0; - _itemPoses[i].y = 0; + _itemPoses[i].x = 0; + _itemPoses[i].y = 0; _itemPoses[i].orient = 0; } - _nearestWayPoint = 0; - _nearestDest = 0; _curGoblinX = 0; _curGoblinY = 0; _destX = 0; _destY = 0; + _sourceFile[0] = 0; _loadFromAvo = false; @@ -76,6 +83,87 @@ Map::~Map() { delete[] _wayPoints; } +uint8 Map::getVersion() const { + return _mapVersion; +} + +int16 Map::getMapWidth() const { + return _mapWidth; +} + +int16 Map::getMapHeight() const { + return _mapHeight; +} + +int16 Map::getScreenWidth() const { + return _screenWidth; +} + +int16 Map::getScreenHeight() const { + return _screenHeight; +} + +int16 Map::getTilesWidth() const { + return _tilesWidth; +} + +int16 Map::getTilesHeight() const { + return _tilesHeight; +} + +bool Map::hasBigTiles() const { + return _bigTiles; +} + +int8 Map::getPass(int x, int y, int width) const { + if (!_passMap) + return 0; + + if ((x < 0) || (y < 0) || (x >= _mapWidth) || (y >= _mapHeight)) + return 0; + + if (width == -1) + width = _passWidth; + return _passMap[y * width + x]; +} + +void Map::setPass(int x, int y, int8 pass, int width) { + if (!_passMap) + return; + + if ((x < 0) || (y < 0) || (x >= _mapWidth) || (y >= _mapHeight)) + return; + + if (width == -1) + width = _passWidth; + _passMap[y * width + x] = pass; +} + +const WayPoint &Map::getWayPoint(int n) const { + assert(_wayPoints); + assert(n < _wayPointCount); + + return _wayPoints[n]; +} + +int16 Map::getItem(int x, int y) const { + assert(_itemsMap); + + x = CLIP(x, 0, _mapWidth - 1); + y = CLIP(y, 0, _mapHeight - 1); + + return _itemsMap[y][x]; +} + +void Map::setItem(int x, int y, int16 item) { + assert(_itemsMap); + + x = CLIP(x, 0, _mapWidth - 1); + y = CLIP(y, 0, _mapHeight - 1); + + _itemsMap[y][x] = item; +} + void Map::placeItem(int16 x, int16 y, int16 id) { if ((getItem(x, y) & 0xFF00) != 0) setItem(x, y, (getItem(x, y) & 0xFF00) | id); @@ -83,150 +171,175 @@ void Map::placeItem(int16 x, int16 y, int16 id) { setItem(x, y, (getItem(x, y) & 0x00FF) | (id << 8)); } -enum { - kLeft = (1 << 0), - kUp = (1 << 1), - kRight = (1 << 2), - kDown = (1 << 3) -}; - -int16 Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { - int16 dir = 0; - +Direction Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { if ((x0 == x1) && (y0 == y1)) - return 0; + // Already at the destination + return kDirNone; if ((x1 < 0) || (x1 > _mapWidth) || (y1 < 0) || (y1 > _mapHeight)) - return 0; + // Destination out of range + return kDirNone; + RelativeDirection relDir = kRelDirNone; + + // Find the direct direction we want to move if (y1 > y0) - dir |= kDown; + relDir = kRelDirDown; else if (y1 < y0) - dir |= kUp; + relDir = kRelDirUp; if (x1 > x0) - dir |= kRight; + relDir = (RelativeDirection)(relDir | kRelDirRight); else if (x1 < x0) - dir |= kLeft; + relDir = (RelativeDirection)(relDir | kRelDirLeft); - if ((getPass(x0, y0) == 3) && (dir & kUp)) { - if ((getPass(x0, y0 - 1) != 0)) - return kDirN; - } - if ((getPass(x0, y0) == 3) && (dir & kDown)) { - if ((getPass(x0, y0 + 1) != 0)) - return kDirS; - } + // Are we on ladders and can continue the ladder in the wanted direction? + if ((getPass(x0, y0) == 3) && (relDir & kRelDirUp ) && (getPass(x0, y0 - 1) != 0)) + return kDirN; - if ((getPass(x0, y0) == 6) && (dir & kUp)) { - if ((getPass(x0, y0 - 1) != 0)) - return kDirN; - } + if ((getPass(x0, y0) == 3) && (relDir & kRelDirDown) && (getPass(x0, y0 + 1) != 0)) + return kDirS; - if ((getPass(x0, y0) == 6) && (dir & kDown)) { - if ((getPass(x0, y0 + 1) != 0)) - return kDirS; - } + if ((getPass(x0, y0) == 6) && (relDir & kRelDirUp ) && (getPass(x0, y0 - 1) != 0)) + return kDirN; - if (dir == kLeft) { - if (((x0 - 1) >= 0) && (getPass(x0 - 1, y0) != 0)) + if ((getPass(x0, y0) == 6) && (relDir & kRelDirDown) && (getPass(x0, y0 + 1) != 0)) + return kDirS; + + + // Want to go left + if (relDir == kRelDirLeft) { + if (getPass(x0 - 1, y0) != 0) + // Can go west return kDirW; - return 0; + + // Can't go + return kDirNone; } - if (dir == kRight) { - if (((x0 + 1) < _mapWidth) && (getPass(x0 + 1, y0) != 0)) + // Want to go left + if (relDir == kRelDirRight) { + if (getPass(x0 + 1, y0) != 0) + // Can go east return kDirE; - return 0; + + // Can't go + return kDirNone; } - if (dir == kUp) { - if (((y0 - 1) >= 0) && (getPass(x0, y0 - 1) != 0)) + + // Want to go up + if (relDir == kRelDirUp) { + if (getPass(x0 , y0 - 1) != 0) + // Can go north return kDirN; - if (((y0 - 1) >= 0) && ((x0 - 1) >= 0) && - (getPass(x0 - 1, y0 - 1) != 0)) + if (getPass(x0 - 1, y0 - 1) != 0) + // Can up north-west instead return kDirNW; - if (((y0 - 1) >= 0) && ((x0 + 1) < _mapWidth) && - (getPass(x0 + 1, y0 - 1) != 0)) + if (getPass(x0 + 1, y0 - 1) != 0) + // Can up north-east instead return kDirNE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == kDown) { - if (((y0 + 1) < _mapHeight) && (getPass(x0, y0 + 1) != 0)) + // Want to go down + if (relDir == kRelDirDown) { + if (getPass(x0 , y0 + 1) != 0) + // Can go south return kDirS; - if (((y0 + 1) < _mapHeight) && ((x0 - 1) >= 0) && - (getPass(x0 - 1, y0 + 1) != 0)) + if (getPass(x0 - 1, y0 + 1) != 0) + // Can up south-west instead return kDirSW; - if (((y0 + 1) < _mapHeight) && ((x0 + 1) < _mapWidth) && - (getPass(x0 + 1, y0 + 1) != 0)) + if (getPass(x0 + 1, y0 + 1) != 0) + // Can up south-east instead return kDirSE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kRight | kUp)) { - if (((y0 - 1) >= 0) && ((x0 + 1) < _mapWidth) && - (getPass(x0 + 1, y0 - 1) != 0)) + + // Want to go up and right + if (relDir == kRelDirRightUp) { + if (getPass(x0 + 1, y0 - 1) != 0) + // Can go north-east return kDirNE; - if (((y0 - 1) >= 0) && (getPass(x0, y0 - 1) != 0)) + if (getPass(x0 , y0 - 1) != 0) + // Can only go north return kDirN; - if (((x0 + 1) < _mapWidth) && (getPass(x0 + 1, y0) != 0)) + if (getPass(x0 + 1, y0 ) != 0) + // Can only go east return kDirE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kRight | kDown)) { - if (((x0 + 1) < _mapWidth) && ((y0 + 1) < _mapHeight) && - (getPass(x0 + 1, y0 + 1) != 0)) + // Want to go down and right + if (relDir == kRelDirRightDown) { + if (getPass(x0 + 1, y0 + 1) != 0) + // Can go south-east return kDirSE; - if (((y0 + 1) < _mapHeight) && (getPass(x0, y0 + 1) != 0)) + if (getPass(x0 , y0 + 1) != 0) + // Can only go south return kDirS; - if (((x0 + 1) < _mapWidth) && (getPass(x0 + 1, y0) != 0)) + if (getPass(x0 + 1, y0 ) != 0) + // Can only go east return kDirE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kLeft | kUp)) { - if (((x0 - 1) >= 0) && ((y0 - 1) >= 0) && - (getPass(x0 - 1, y0 - 1) != 0)) + // Want to go up and left + if (relDir == kRelDirLeftUp) { + if (getPass(x0 - 1, y0 - 1) != 0) + // Can go north-west return kDirNW; - if (((y0 - 1) >= 0) && (getPass(x0, y0 - 1) != 0)) + if (getPass(x0 , y0 - 1) != 0) + // Can only go north return kDirN; - if (((x0 - 1) >= 0) && (getPass(x0 - 1, y0) != 0)) + if (getPass(x0 - 1, y0 ) != 0) + // Can only go west return kDirW; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kLeft | kDown)) { - if (((x0 - 1) >= 0) && ((y0 + 1) < _mapHeight) && - (getPass(x0 - 1, y0 + 1) != 0)) + // Want to go left and down + if (relDir == kRelDirLeftDown) { + if (getPass(x0 - 1, y0 + 1) != 0) + // Can go south-west return kDirSW; - if (((y0 + 1) < _mapHeight) && (getPass(x0, y0 + 1) != 0)) + if (getPass(x0 , y0 + 1) != 0) + // Can only go south return kDirS; - if (((x0 - 1) >= 0) && (getPass(x0 - 1, y0) != 0)) + if (getPass(x0 - 1, y0 ) != 0) + // Can only go west return kDirW; - return 0; + // Can't go at all + return kDirNone; } - return -1; + + warning("Map::getDirection(): Invalid direction?!?"); + return kDirNone; } int16 Map::findNearestWayPoint(int16 x, int16 y) { @@ -236,7 +349,7 @@ int16 Map::findNearestWayPoint(int16 x, int16 y) { length = 30000; - for (int i = 0; i < _wayPointsCount; i++) { + for (int i = 0; i < _wayPointCount; i++) { if ((_wayPoints[i].x < 0) || (_wayPoints[i].x >= _mapWidth) || (_wayPoints[i].y < 0) || (_wayPoints[i].y >= _mapHeight)) break; @@ -318,73 +431,81 @@ void Map::findNearestWalkable(int16 &gobDestX, int16 &gobDestY, gobDestY -= distance; } -int16 Map::checkDirectPath(Mult::Mult_Object *obj, - int16 x0, int16 y0, int16 x1, int16 y1) { - uint16 dir; +void Map::moveDirection(Direction dir, int16 &x, int16 &y) { + switch (dir) { + case kDirNW: + x--; + y--; + break; - while (1) { - dir = getDirection(x0, y0, x1, y1); + case kDirN: + y--; + break; - if (obj) { - if (obj->nearestWayPoint < obj->nearestDest) { - if (_wayPoints[obj->nearestWayPoint + 1].notWalkable == 1) - return 3; - } else if (obj->nearestWayPoint > obj->nearestDest) { - if (obj->nearestDest > 0) - if (_wayPoints[obj->nearestDest - 1].notWalkable == 1) - return 3; - } - } + case kDirNE: + x++; + y--; + break; - if ((x0 == x1) && (y0 == y1)) - return 1; + case kDirW: + x--; + break; - if (dir == 0) - return 3; + case kDirE: + x++; + break; - switch (dir) { - case kDirNW: - x0--; - y0--; - break; + case kDirSW: + x--; + y++; + break; - case kDirN: - y0--; - break; + case kDirS: + y++; + break; - case kDirNE: - x0++; - y0--; - break; + case kDirSE: + x++; + y++; + break; - case kDirW: - x0--; - break; - - case kDirE: - x0++; - break; - - case kDirSW: - x0--; - y0++; - break; - - case kDirS: - y0++; - break; - - case kDirSE: - x0++; - y0++; - break; - } + default: + break; } } -int16 Map::checkLongPath(int16 x0, int16 y0, - int16 x1, int16 y1, int16 i0, int16 i1) { - uint16 dir = 0; +int16 Map::checkDirectPath(Mult::Mult_Object *obj, int16 x0, int16 y0, int16 x1, int16 y1) { + + while (1) { + Direction dir = getDirection(x0, y0, x1, y1); + + if (obj) { + // Check for a blocking waypoint + + if (obj->nearestWayPoint < obj->nearestDest) + if ((obj->nearestWayPoint + 1) < _wayPointCount) + if (_wayPoints[obj->nearestWayPoint + 1].notWalkable == 1) + return 3; + + if (obj->nearestWayPoint > obj->nearestDest) + if (obj->nearestWayPoint > 0) + if (_wayPoints[obj->nearestWayPoint - 1].notWalkable == 1) + return 3; + } + + if ((x0 == x1) && (y0 == y1)) + // Successfully reached the destination + return 1; + + if (dir == kDirNone) + // No way + return 3; + + moveDirection(dir, x0, y0); + } +} + +int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 i1) { int16 curX = x0; int16 curY = y0; int16 nextLink = 1; @@ -417,47 +538,13 @@ int16 Map::checkLongPath(int16 x0, int16 y0, return 1; return 0; } - dir = getDirection(x0, y0, curX, curY); - switch (dir) { - case 0: + + Direction dir = getDirection(x0, y0, curX, curY); + if (dir == kDirNone) + // No way return 0; - case kDirNW: - x0--; - y0--; - break; - - case kDirN: - y0--; - break; - - case kDirNE: - x0++; - y0--; - break; - - case kDirW: - x0--; - break; - - case kDirE: - x0++; - break; - - case kDirSW: - x0--; - y0++; - break; - - case kDirS: - y0++; - break; - - case kDirSE: - x0++; - y0++; - break; - } + moveDirection(dir, x0, y0); } } diff --git a/engines/gob/map.h b/engines/gob/map.h index 4a63e84a63e..4bf2dc62285 100644 --- a/engines/gob/map.h +++ b/engines/gob/map.h @@ -30,54 +30,48 @@ namespace Gob { +enum RelativeDirection { + kRelDirNone = 0 , + + kRelDirLeft = (1 << 0), + kRelDirUp = (1 << 1), + kRelDirRight = (1 << 2), + kRelDirDown = (1 << 3), + + kRelDirLeftUp = kRelDirLeft | kRelDirUp, + kRelDirLeftDown = kRelDirLeft | kRelDirDown, + kRelDirRightUp = kRelDirRight | kRelDirUp, + kRelDirRightDown = kRelDirRight | kRelDirDown +}; + // The same numeric values are also used for the arrow keys. +enum Direction { + kDirNone = 0x0000, + kDirNW = 0x4700, + kDirN = 0x4800, + kDirNE = 0x4900, + kDirW = 0x4B00, + kDirE = 0x4D00, + kDirSW = 0x4F00, + kDirS = 0x5000, + kDirSE = 0x5100 +}; + +struct WayPoint { + int16 x; + int16 y; + int16 notWalkable; +}; + +struct ItemPos { + int8 x; + int8 y; + int8 orient; +}; + class Map { public: - enum { - kDirNW = 0x4700, - kDirN = 0x4800, - kDirNE = 0x4900, - kDirW = 0x4B00, - kDirE = 0x4D00, - kDirSW = 0x4F00, - kDirS = 0x5000, - kDirSE = 0x5100 - }; - -#include "common/pack-start.h" // START STRUCT PACKING - - struct Point { - int16 x; - int16 y; - int16 notWalkable; - } PACKED_STRUCT; - -#define szMap_ItemPos 3 - - struct ItemPos { - int8 x; - int8 y; - int8 orient; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - - byte _widthByte; - int16 _mapWidth; - int16 _mapHeight; - int16 _screenWidth; - int16 _screenHeight; - int16 _tilesWidth; - int16 _tilesHeight; - int16 _passWidth; - bool _bigTiles; - bool _mapUnknownBool; - - int8 *_passMap; // [y * _mapWidth + x], getPass(x, y); - int16 **_itemsMap; // [y][x] - int16 _wayPointsCount; - Point *_wayPoints; int16 _nearestWayPoint; int16 _nearestDest; @@ -89,12 +83,36 @@ public: ItemPos _itemPoses[40]; char _sourceFile[15]; + Map(GobEngine *vm); + virtual ~Map(); + + uint8 getVersion() const; + + int16 getMapWidth() const; + int16 getMapHeight() const; + + int16 getScreenWidth() const; + int16 getScreenHeight() const; + + int16 getTilesWidth() const; + int16 getTilesHeight() const; + + bool hasBigTiles() const; + + int8 getPass(int x, int y, int width = -1) const; + void setPass(int x, int y, int8 pass, int width = -1); + + const WayPoint &getWayPoint(int n) const; + void findNearestWalkable(int16 &gobDestX, int16 &gobDestY, int16 mouseX, int16 mouseY); + int16 getItem(int x, int y) const; + void setItem(int x, int y, int16 item); void placeItem(int16 x, int16 y, int16 id); - int16 getDirection(int16 x0, int16 y0, int16 x1, int16 y1); + Direction getDirection(int16 x0, int16 y0, int16 x1, int16 y1); + int16 checkDirectPath(Mult::Mult_Object *obj, int16 x0, int16 y0, int16 x1, int16 y1); int16 checkLongPath(int16 x0, int16 y0, @@ -102,26 +120,44 @@ public: void loadMapsInitGobs(); - virtual int16 getItem(int x, int y) = 0; - virtual void setItem(int x, int y, int16 item) = 0; - - virtual int8 getPass(int x, int y, int heightOff = -1) = 0; - virtual void setPass(int x, int y, int8 pass, int heightOff = -1) = 0; - virtual void loadMapObjects(const char *avjFile) = 0; virtual void findNearestToGob(Mult::Mult_Object *obj) = 0; virtual void findNearestToDest(Mult::Mult_Object *obj) = 0; virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y) = 0; - Map(GobEngine *vm); - virtual ~Map(); - protected: - bool _loadFromAvo; - GobEngine *_vm; + bool _loadFromAvo; + + uint8 _mapVersion; + + int16 _mapWidth; + int16 _mapHeight; + + int16 _screenWidth; + int16 _screenHeight; + + int16 _tilesWidth; + int16 _tilesHeight; + + bool _bigTiles; + + bool _mapUnknownBool; + + int16 _passWidth; + int8 *_passMap; // [y * _mapWidth + x], getPass(x, y); + + int16 _wayPointCount; + WayPoint *_wayPoints; + + int16 **_itemsMap; // [y][x] + int16 findNearestWayPoint(int16 x, int16 y); + +private: + // Move the x and y values according to the direction + void moveDirection(Direction dir, int16 &x, int16 &y); }; class Map_v1 : public Map { @@ -131,37 +167,6 @@ public: virtual void findNearestToDest(Mult::Mult_Object *obj); virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y); - virtual int16 getItem(int x, int y) { - assert(_itemsMap); - - x = CLIP(x, 0, _mapWidth - 1); - y = CLIP(y, 0, _mapHeight - 1); - - return _itemsMap[y][x]; - } - virtual void setItem(int x, int y, int16 item) { - assert(_itemsMap); - - x = CLIP(x, 0, _mapWidth - 1); - y = CLIP(y, 0, _mapHeight - 1); - - _itemsMap[y][x] = item; - } - - virtual int8 getPass(int x, int y, int heightOff = -1) { - if (!_passMap) - return 0; - - return _passMap[y * _mapWidth + x]; - } - - virtual void setPass(int x, int y, int8 pass, int heightOff = -1) { - if (!_passMap) - return; - - _passMap[y * _mapWidth + x] = pass; - } - Map_v1(GobEngine *vm); virtual ~Map_v1(); @@ -180,24 +185,6 @@ public: virtual void findNearestToDest(Mult::Mult_Object *obj); virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y); - virtual int8 getPass(int x, int y, int heightOff = -1) { - if (!_passMap) - return 0; - - if (heightOff == -1) - heightOff = _passWidth; - return _passMap[y * heightOff + x]; - } - - virtual void setPass(int x, int y, int8 pass, int heightOff = -1) { - if (!_passMap) - return; - - if (heightOff == -1) - heightOff = _passWidth; - _passMap[y * heightOff + x] = pass; - } - Map_v2(GobEngine *vm); virtual ~Map_v2(); diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp index d8898c83d34..aa6603fd55a 100644 --- a/engines/gob/map_v1.cpp +++ b/engines/gob/map_v1.cpp @@ -44,7 +44,8 @@ void Map_v1::init() { if (_passMap || _itemsMap) return; - _mapWidth = 26; + _passWidth = 26; + _mapWidth = 26; _mapHeight = 28; _passMap = new int8[_mapHeight * _mapWidth]; @@ -56,9 +57,9 @@ void Map_v1::init() { memset(_itemsMap[i], 0, _mapWidth * sizeof(int16)); } - _wayPointsCount = 40; - _wayPoints = new Point[40]; - memset(_wayPoints, 0, sizeof(Point)); + _wayPointCount = 40; + _wayPoints = new WayPoint[40]; + memset(_wayPoints, 0, sizeof(WayPoint)); } void Map_v1::loadMapObjects(const char *avjFile) { @@ -97,7 +98,12 @@ void Map_v1::loadMapObjects(const char *avjFile) { _wayPoints[i].x = mapData.readUint16LE(); _wayPoints[i].y = mapData.readUint16LE(); } - mapData.read(_itemPoses, szMap_ItemPos * 20); + + for (int i = 0; i < 20; i++) { + _itemPoses[i].x = mapData.readByte(); + _itemPoses[i].y = mapData.readByte(); + _itemPoses[i].orient = mapData.readByte(); + } } mapData.skip(32 + 76 + 4 + 20); diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp index e2f92070038..15bc709411e 100644 --- a/engines/gob/map_v2.cpp +++ b/engines/gob/map_v2.cpp @@ -100,11 +100,11 @@ void Map_v2::loadMapObjects(const char *avjFile) { Common::SeekableReadStream &mapData = *resource->stream(); - _widthByte = mapData.readByte(); - if (_widthByte == 4) { + _mapVersion = mapData.readByte(); + if (_mapVersion == 4) { _screenWidth = 640; _screenHeight = 400; - } else if (_widthByte == 3) { + } else if (_mapVersion == 3) { _passWidth = 65; _screenWidth = 640; _screenHeight = 200; @@ -114,14 +114,14 @@ void Map_v2::loadMapObjects(const char *avjFile) { _screenHeight = 200; } - _wayPointsCount = mapData.readByte(); + _wayPointCount = mapData.readByte(); _tilesWidth = mapData.readSint16LE(); _tilesHeight = mapData.readSint16LE(); _bigTiles = !(_tilesHeight & 0xFF00); _tilesHeight &= 0xFF; - if (_widthByte == 4) { + if (_mapVersion == 4) { _screenWidth = mapData.readSint16LE(); _screenHeight = mapData.readSint16LE(); } @@ -133,19 +133,19 @@ void Map_v2::loadMapObjects(const char *avjFile) { mapData.skip(_mapWidth * _mapHeight); if (resource->getData()[0] == 1) - wayPointsCount = _wayPointsCount = 40; + wayPointsCount = _wayPointCount = 40; else - wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount; + wayPointsCount = _wayPointCount == 0 ? 1 : _wayPointCount; delete[] _wayPoints; - _wayPoints = new Point[wayPointsCount]; - for (int i = 0; i < _wayPointsCount; i++) { + _wayPoints = new WayPoint[wayPointsCount]; + for (int i = 0; i < _wayPointCount; i++) { _wayPoints[i].x = mapData.readSByte(); _wayPoints[i].y = mapData.readSByte(); _wayPoints[i].notWalkable = mapData.readSByte(); } - if (_widthByte == 4) { + if (_mapVersion == 4) { _mapWidth = VAR(17); _passWidth = _mapWidth; } @@ -258,17 +258,24 @@ void Map_v2::findNearestToDest(Mult::Mult_Object *obj) { void Map_v2::optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y) { if (obj->nearestWayPoint < obj->nearestDest) { + for (int i = obj->nearestWayPoint; i <= obj->nearestDest; i++) { if (checkDirectPath(obj, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1) obj->nearestWayPoint = i; } + } else { - for (int i = obj->nearestWayPoint; - i >= obj->nearestDest && (_wayPoints[i].notWalkable != 1); i--) { + + for (int i = obj->nearestWayPoint; i >= obj->nearestDest; i++) { + if (_wayPoints[i].notWalkable == 1) + break; + if (checkDirectPath(obj, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1) obj->nearestWayPoint = i; } + } + } } // End of namespace Gob diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 862d1424a81..882a67bd452 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -1,6 +1,7 @@ MODULE := engines/gob MODULE_OBJS := \ + console.o \ dataio.o \ detection.o \ draw.o \ @@ -9,7 +10,6 @@ MODULE_OBJS := \ draw_bargon.o \ draw_fascin.o \ draw_playtoons.o \ - driver_vga.o \ expression.o \ game.o \ global.o \ @@ -49,6 +49,7 @@ MODULE_OBJS := \ scenery_v1.o \ scenery_v2.o \ script.o \ + surface.o \ totfile.o \ util.o \ variables.o \ diff --git a/engines/gob/mult.h b/engines/gob/mult.h index 7766508922d..fc83e2dbe36 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -232,7 +232,7 @@ public: int8 *_orderArray; - SurfaceDescPtr _animSurf; + SurfacePtr _animSurf; int16 _animLeft; int16 _animTop; int16 _animWidth; diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index 84869066e17..4be0a49b450 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -320,8 +320,7 @@ void Mult_v1::playMultInit() { 320, 200, 0); _vm->_draw->_spritesArray[Draw::kAnimSurface] = _animSurf; - _vm->_video->drawSprite(*_vm->_draw->_backSurface, - *_animSurf, 0, 0, 319, 199, 0, 0, 0); + _animSurf->blit(*_vm->_draw->_backSurface, 0, 0, 319, 199, 0, 0); _animDataAllocated = true; } else @@ -350,8 +349,7 @@ void Mult_v1::drawStatics(bool &stop) { _vm->_scenery->_curStatic = _multData->staticIndices[_vm->_scenery->_curStatic]; _vm->_scenery->renderStatic(_vm->_scenery->_curStatic, _vm->_scenery->_curStaticLayer); - _vm->_video->drawSprite(*_vm->_draw->_backSurface, *_animSurf, - 0, 0, 319, 199, 0, 0, 0); + _animSurf->blit(*_vm->_draw->_backSurface, 0, 0, 319, 199, 0, 0); } } diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index ab513d78bbb..6fc292950f1 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -272,9 +272,9 @@ void Mult_v2::loadImds(Common::SeekableReadStream &data) { memcpy(_multData->imdFiles, _vm->_game->_script->getData() + _vm->_game->_script->pos(), size * 14); - // WORKAROUND: The Windows version of Lost in Time has VMD not IMD files, - // but they are still referenced as IMD. - if ((_vm->getGameType() == kGameTypeLostInTime) && + // WORKAROUND: The Windows versions of Lost in Time and Gob3 have VMD not + // IMD files, but they are still referenced as IMD. + if (((_vm->getGameType() == kGameTypeLostInTime) || (_vm->getGameType() == kGameTypeGob3)) && (_vm->getPlatform() == Common::kPlatformWindows)) { for (int i = 0; i < size; i++) { @@ -582,9 +582,8 @@ void Mult_v2::playMultInit() { _vm->_draw->initSpriteSurf(Draw::kAnimSurface, width, height, 0); _animSurf = _vm->_draw->_spritesArray[Draw::kAnimSurface]; - _vm->_video->drawSprite(*_vm->_draw->_spritesArray[Draw::kBackSurface], - *_vm->_draw->_spritesArray[Draw::kAnimSurface], 0, 0, - _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0, 0); + _vm->_draw->_spritesArray[Draw::kAnimSurface]->blit(*_vm->_draw->_spritesArray[Draw::kBackSurface], + 0, 0, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0); for (_counter = 0; _counter < _objCount; _counter++) _multData->palAnimIndices[_counter] = _counter; @@ -639,9 +638,8 @@ void Mult_v2::drawStatics(bool &stop) { _vm->_scenery->_curStatic = -1; } - _vm->_video->drawSprite(*_vm->_draw->_spritesArray[Draw::kBackSurface], - *_vm->_draw->_spritesArray[Draw::kAnimSurface], 0, 0, - _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0, 0); + _vm->_draw->_spritesArray[Draw::kAnimSurface]->blit(*_vm->_draw->_spritesArray[Draw::kBackSurface], + 0, 0, _vm->_video->_surfWidth, _vm->_video->_surfHeight, 0, 0); } } diff --git a/engines/gob/palanim.cpp b/engines/gob/palanim.cpp index f3770b0425b..755d28c6e92 100644 --- a/engines/gob/palanim.cpp +++ b/engines/gob/palanim.cpp @@ -88,7 +88,7 @@ bool PalAnim::fadeStep(int16 oper) { if (oper == 0) { if (_vm->_global->_setAllPalette) { if (_vm->_global->_inVM != 0) - error("PalAnim::fadeStep(): _vm->_global->_inVM != 0 not supported."); + error("PalAnim::fadeStep(): _vm->_global->_inVM != 0 not supported"); for (int i = 0; i < 256; i++) { newRed = fadeColor(_vm->_global->_redPalette[i], _toFadeRed[i]); diff --git a/engines/gob/save/savefile.cpp b/engines/gob/save/savefile.cpp index e1c4c62b127..79e931fe309 100644 --- a/engines/gob/save/savefile.cpp +++ b/engines/gob/save/savefile.cpp @@ -331,14 +331,18 @@ bool SavePartSprite::readPalette(const byte *palette) { return true; } -bool SavePartSprite::readSprite(const SurfaceDesc &sprite) { +bool SavePartSprite::readSprite(const Surface &sprite) { // The sprite's dimensions have to fit if (((uint32)sprite.getWidth()) != _width) return false; if (((uint32)sprite.getHeight()) != _height) return false; - memcpy(_dataSprite, sprite.getVidMem(), _width * _height); + // Only 8bit sprites supported for now + if (sprite.getBPP() != 1) + return false; + + memcpy(_dataSprite, sprite.getData(), _width * _height); return true; } @@ -357,14 +361,18 @@ bool SavePartSprite::writePalette(byte *palette) const { return true; } -bool SavePartSprite::writeSprite(SurfaceDesc &sprite) const { +bool SavePartSprite::writeSprite(Surface &sprite) const { // The sprite's dimensions have to fit if (((uint32)sprite.getWidth()) != _width) return false; if (((uint32)sprite.getHeight()) != _height) return false; - memcpy(sprite.getVidMem(), _dataSprite, _width * _height); + // Only 8bit sprites supported for now + if (sprite.getBPP() != 1) + return false; + + memcpy(sprite.getData(), _dataSprite, _width * _height); return true; } diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h index 615be8e0f29..980616bb744 100644 --- a/engines/gob/save/savefile.h +++ b/engines/gob/save/savefile.h @@ -33,15 +33,16 @@ namespace Gob { class GobEngine; -class SurfaceDesc; +class Surface; -/** A class wrapping a save part header. - * - * A save part header consists of 4 fields: - * ID : The 8 character ID \0SCVMGOB - * Type : The 4 character ID for this part's type - * Version : This part's version. Each type has its own version counter - * Size : The size of the contents, i.e. excluding this header +/** + * A class wrapping a save part header. + * + * A save part header consists of 4 fields: + * ID : The 8 character ID \0SCVMGOB + * Type : The 4 character ID for this part's type + * Version : This part's version. Each type has its own version counter + * Size : The size of the contents, i.e. excluding this header */ class SaveHeader { public: @@ -162,7 +163,7 @@ public: /** Read a palette into the part. */ bool readPalette(const byte *palette); /** Read a sprite into the part. */ - bool readSprite(const SurfaceDesc &sprite); + bool readSprite(const Surface &sprite); /** Read size bytes of raw data into the sprite. */ bool readSpriteRaw(const byte *data, uint32 size); @@ -170,7 +171,7 @@ public: /** Write a palette out of the part. */ bool writePalette(byte *palette) const; /** Write a sprite out of the part. */ - bool writeSprite(SurfaceDesc &sprite) const; + bool writeSprite(Surface &sprite) const; private: uint32 _width; @@ -186,13 +187,13 @@ public: static const uint32 kVersion = 1; static const uint32 kID = MKID_BE('INFO'); - /** The constructor. - * - * @param descMaxLength The maximal number of bytes that fit into the description. - * @param gameID An ID for the game (Gob1, Gob2, Gob3, ...). - * @param gameVersion An ID for game specific versioning - * @param endian Endianness of the platform the game originally ran on. - * @param varCount The number of script variables. + /** + * The constructor. + * @param descMaxLength The maximal number of bytes that fit into the description. + * @param gameID An ID for the game (Gob1, Gob2, Gob3, ...). + * @param gameVersion An ID for game specific versioning + * @param endian Endianness of the platform the game originally ran on. + * @param varCount The number of script variables. */ SavePartInfo(uint32 descMaxLength, uint32 gameID, uint32 gameVersion, byte endian, uint32 varCount); @@ -228,10 +229,10 @@ public: static const uint32 kVersion = 1; static const uint32 kID = MKID_BE('CONT'); - /** The constructor. - * - * @param partCount The number parts this container shall hold. - * @param slot The save slot this save's for. + /** + * The constructor. + * @param partCount The number parts this container shall hold. + * @param slot The save slot this save's for. */ SaveContainer(uint32 partCount, uint32 slot); ~SaveContainer(); diff --git a/engines/gob/save/savehandler.cpp b/engines/gob/save/savehandler.cpp index 14cd82480d5..8b7a661278f 100644 --- a/engines/gob/save/savehandler.cpp +++ b/engines/gob/save/savehandler.cpp @@ -245,7 +245,7 @@ bool TempSpriteHandler::load(int16 dataVar, int32 size, int32 offset) { if ((index < 0) || (index >= SPRITES_COUNT)) return false; - SurfaceDescPtr sprite = _vm->_draw->_spritesArray[index]; + SurfacePtr sprite = _vm->_draw->_spritesArray[index]; // Target sprite exists? if (!sprite) @@ -275,7 +275,7 @@ bool TempSpriteHandler::load(int16 dataVar, int32 size, int32 offset) { } bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) { - SurfaceDescPtr sprite; + SurfacePtr sprite; if (isDummy(size)) return true; @@ -297,7 +297,7 @@ bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) { } bool TempSpriteHandler::createSprite(int16 dataVar, int32 size, - int32 offset, SurfaceDescPtr *sprite) { + int32 offset, SurfacePtr *sprite) { delete _sprite; _sprite = 0; @@ -311,7 +311,7 @@ bool TempSpriteHandler::createSprite(int16 dataVar, int32 size, if ((index < 0) || (index >= SPRITES_COUNT)) return false; - SurfaceDescPtr sprt = _vm->_draw->_spritesArray[index]; + SurfacePtr sprt = _vm->_draw->_spritesArray[index]; // Sprite exists? if (!sprt) diff --git a/engines/gob/save/savehandler.h b/engines/gob/save/savehandler.h index 6a7e563a8f0..723215cf084 100644 --- a/engines/gob/save/savehandler.h +++ b/engines/gob/save/savehandler.h @@ -27,7 +27,7 @@ #define GOB_SAVE_SAVEHANDLER_H #include "common/savefile.h" -#include "engines/gob/video.h" // for SurfaceDescPtr +#include "engines/gob/video.h" // for SurfacePtr namespace Gob { @@ -139,7 +139,7 @@ public: /** Create a fitting sprite. */ bool createSprite(int16 dataVar, int32 size, - int32 offset, SurfaceDescPtr *sprite = 0); + int32 offset, SurfacePtr *sprite = 0); protected: SavePartSprite *_sprite; diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index a667d6615df..ec33137739a 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -65,7 +65,7 @@ Scenery::Scenery(GobEngine *vm) : _vm(vm) { _pCaptureCounter = 0; - for (int i = 0; i < 70; i++ ) { + for (int i = 0; i < 70; i++) { _staticPictToSprite[i] = 0; _animPictToSprite[i] = 0; } @@ -196,7 +196,7 @@ int16 Scenery::loadStatic(char search) { _spriteResId[sprIndex] = sprResId; _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); - _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); + _vm->_draw->_spritesArray[sprIndex]->clear(); _vm->_draw->_destSurface = sprIndex; _vm->_draw->_spriteLeft = sprResId; _vm->_draw->_transparency = 0; @@ -526,7 +526,7 @@ int16 Scenery::loadAnim(char search) { _spriteResId[sprIndex] = sprResId; _vm->_draw->initSpriteSurf(sprIndex, width, height, 2); - _vm->_video->clearSurf(*_vm->_draw->_spritesArray[sprIndex]); + _vm->_draw->_spritesArray[sprIndex]->clear(); _vm->_draw->_destSurface = sprIndex; _vm->_draw->_spriteLeft = sprResId; _vm->_draw->_transparency = 0; @@ -623,6 +623,16 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, if (frame >= (int32)_vm->_vidPlayer->getFrameCount(obj.videoSlot - 1)) frame = _vm->_vidPlayer->getFrameCount(obj.videoSlot - 1) - 1; + if (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) >= 255) { + // Allow for object videos with more than 255 frames, although the + // object frame counter is just a byte. + + uint32 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) + 1; + uint16 frameWrap = curFrame / 256; + + frame = ((frame + 1) % 256) + frameWrap * 256; + } + if (frame != (int32)_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1)) { // Seek to frame @@ -723,7 +733,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, _vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - (destX + _vm->_draw->_spriteRight); - _vm->_vidPlayer->copyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(), + _vm->_vidPlayer->copyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getData(), _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop, _vm->_draw->_spriteRight, _vm->_draw->_spriteBottom, _vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp index 28123668cc7..d643ae511bd 100644 --- a/engines/gob/sound/adlib.cpp +++ b/engines/gob/sound/adlib.cpp @@ -240,7 +240,7 @@ void AdLib::setKey(byte voice, byte note, bool on, bool spec) { freq = _freqs[_notLin[voice]][note - octa * 12]; writeOPL(0xA0 + voice, freq & 0xFF); - writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | 0x20 * on); + writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | (0x20 * (on ? 1 : 0))); if (!freq) warning("AdLib::setKey Voice %d, note %02X unknown", voice, note); diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp index 8f0b1df23ef..2e1673b12af 100644 --- a/engines/gob/sound/cdrom.cpp +++ b/engines/gob/sound/cdrom.cpp @@ -24,12 +24,12 @@ */ #include "common/endian.h" +#include "common/str.h" #include "common/util.h" #include "sound/audiocd.h" #include "gob/gob.h" #include "gob/sound/cdrom.h" -#include "gob/helper.h" #include "gob/dataio.h" namespace Gob { @@ -92,7 +92,7 @@ void CDROM::startTrack(const char *trackName) { return; } - strncpy0(_curTrack, trackName, 15); + Common::strlcpy(_curTrack, trackName, 16); stopPlaying(); _curTrackBuffer = matchPtr; diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp new file mode 100644 index 00000000000..554edfc7535 --- /dev/null +++ b/engines/gob/surface.cpp @@ -0,0 +1,584 @@ +/* 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 "gob/surface.h" + +#include "common/system.h" +#include "common/util.h" +#include "common/frac.h" + +#include "graphics/primitives.h" + +namespace Gob { + +static void plotPixel(int x, int y, int color, void *data) { + Surface *dest = (Surface *)data; + + dest->putPixel(x, y, color); +} + + +Pixel::Pixel(byte *vidMem, uint8 bpp) : _vidMem(vidMem), _bpp(bpp) { + assert((_bpp == 1) || (_bpp == 2)); +} + +Pixel &Pixel::operator++() { + _vidMem += _bpp; + return *this; +} + +Pixel Pixel::operator++(int x) { + Pixel p = *this; + ++(*this); + return p; +} + +Pixel &Pixel::operator--() { + _vidMem -= _bpp; + return *this; +} + +Pixel Pixel::operator--(int x) { + Pixel p = *this; + --(*this); + return p; +} + +Pixel &Pixel::operator+=(int x) { + _vidMem += x * _bpp; + return *this; +} + +Pixel &Pixel::operator-=(int x) { + _vidMem -= x * _bpp; + return *this; +} + +uint32 Pixel::get() const { + if (_bpp == 1) + return *((byte *) _vidMem); + if (_bpp == 2) + return *((uint16 *) _vidMem); + + return 0; +} + +void Pixel::set(uint32 p) { + if (_bpp == 1) + *((byte *) _vidMem) = (byte) p; + if (_bpp == 2) + *((uint16 *) _vidMem) = (uint16) p; +} + + +ConstPixel::ConstPixel(const byte *vidMem, uint8 bpp) : _vidMem(vidMem), _bpp(bpp) { + assert((_bpp == 1) || (_bpp == 2)); +} + +ConstPixel &ConstPixel::operator++() { + _vidMem += _bpp; + return *this; +} + +ConstPixel ConstPixel::operator++(int x) { + ConstPixel p = *this; + ++(*this); + return p; +} + +ConstPixel &ConstPixel::operator--() { + _vidMem -= _bpp; + return *this; +} + +ConstPixel ConstPixel::operator--(int x) { + ConstPixel p = *this; + --(*this); + return p; +} + +ConstPixel &ConstPixel::operator+=(int x) { + _vidMem += x * _bpp; + return *this; +} + +ConstPixel &ConstPixel::operator-=(int x) { + _vidMem -= x * _bpp; + return *this; +} + +uint32 ConstPixel::get() const { + if (_bpp == 1) + return *((const byte *) _vidMem); + if (_bpp == 2) + return *((const uint16 *) _vidMem); + + return 0; +} + + +Surface::Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem) : + _width(width), _height(height), _bpp(bpp), _vidMem(vidMem) { + + assert((_width > 0) && (_height > 0)); + assert((_bpp == 1) || (_bpp == 2)); + + if (!_vidMem) { + _vidMem = new byte[_bpp * _width * _height]; + _ownVidMem = true; + + memset(_vidMem, 0, _bpp * _width * _height); + } else + _ownVidMem = false; +} + +Surface::~Surface() { + if (_ownVidMem) + delete[] _vidMem; +} + +uint16 Surface::getWidth() const { + return _width; +} + +uint16 Surface::getHeight() const { + return _height; +} + +uint16 Surface::getBPP() const { + return _bpp; +} + +void Surface::resize(uint16 width, uint16 height) { + assert((width > 0) && (height > 0)); + + if (_ownVidMem) + delete[] _vidMem; + + _width = width; + _height = height; + + _vidMem = new byte[_bpp * _width * _height]; + _ownVidMem = true; + + memset(_vidMem, 0, _bpp * _width * _height); +} + +byte *Surface::getData(uint16 x, uint16 y) { + return _vidMem + (y * _width * _bpp) + (x * _bpp); +} + +const byte *Surface::getData(uint16 x, uint16 y) const { + return _vidMem + (y * _width * _bpp) + (x * _bpp); +} + +Pixel Surface::get(uint16 x, uint16 y) { + byte *vidMem = getData(x, y); + + return Pixel(vidMem, _bpp); +} + +ConstPixel Surface::get(uint16 x, uint16 y) const { + const byte *vidMem = getData(x, y); + + return ConstPixel(vidMem, _bpp); +} + +bool Surface::clipBlitRect(int16 &left, int16 &top, int16 &right, int16 &bottom, int16 &x, int16 &y, + uint16 dWidth, uint16 dHeight, uint16 sWidth, uint16 sHeight) { + + if ((x >= dWidth) || (y >= dHeight)) + // Nothing to do + return false; + + // Just in case those are swapped + if (left > right) + SWAP(left, right); + if (top > bottom) + SWAP(top, bottom); + + if ((left >= sWidth) || (top >= sHeight) || (right < 0) || (bottom < 0)) + // Nothing to do + return false; + + // Adjust from coordinates + if (left < 0) { + x -= left; + left = 0; + } + if (top < 0) { + y -= top; + top = 0; + } + + // Adjust to coordinates + if (x < 0) { + left -= x; + x = 0; + } + if (y < 0) { + top -= y; + y = 0; + } + + // Limit by source and destination dimensions + right = MIN(right , MIN(sWidth , dWidth - x + left) - 1); + bottom = MIN(bottom, MIN(sHeight, dHeight - y + top ) - 1); + + if ((right < left) || (bottom < top)) + // Nothing to do + return false; + + // Clip to sane values + right = MAX(right , 0); + bottom = MAX(bottom, 0); + + return true; +} + +void Surface::blit(const Surface &from, int16 left, int16 top, int16 right, int16 bottom, + int16 x, int16 y, int32 transp) { + + // Color depths have to fit + assert(_bpp == from._bpp); + + // Clip + if (!clipBlitRect(left, top, right, bottom, x, y, _width, _height, from._width, from._height)) + return; + + // Area to actually copy + uint16 width = right - left + 1; + uint16 height = bottom - top + 1; + + if ((width == 0) || (height == 0)) + // Nothing to do + return; + + if ((left == 0) && (_width == from._width) && (_width == width) && (transp == -1)) { + // If these conditions are met, we can directly use memcpy + + // Pointers to the blit destination and source start points + byte *dst = getData(x , y); + const byte *src = from.getData(left, top); + + memcpy(dst, src, width * height * _bpp); + return; + } + + if (transp == -1) { + // We don't have to look for transparency => we can use memcpy line-wise + + // Pointers to the blit destination and source start points + byte *dst = getData(x , y); + const byte *src = from.getData(left, top); + + while (height-- > 0) { + memcpy(dst, src, width * _bpp); + + dst += _width * _bpp; + src += from._width * from._bpp; + } + + return; + } + + // Otherwise, we have to copy by pixel + + // Pointers to the blit destination and source start points + Pixel dst = get(x , y); + ConstPixel src = from.get(left, top); + + while (height-- > 0) { + Pixel dstRow = dst; + ConstPixel srcRow = src; + + for (uint16 i = 0; i < width; i++, dstRow++, srcRow++) + if (srcRow.get() != ((uint32) transp)) + dstRow.set(srcRow.get()); + + dst += _width; + src += from._width; + } +} + +void Surface::blit(const Surface &from, int16 x, int16 y, int32 transp) { + blit(from, 0, 0, from._width - 1, from._height - 1, x, y, transp); +} + +void Surface::blit(const Surface &from, int32 transp) { + blit(from, 0, 0, from._width - 1, from._height - 1, 0, 0, transp); +} + +void Surface::blitScaled(const Surface &from, int16 left, int16 top, int16 right, int16 bottom, + int16 x, int16 y, Common::Rational scale, int32 transp) { + + if (scale == 1) { + // Yeah, "scaled" + + blit(from, left, top, right, bottom, x, y, transp); + return; + } + + // Color depths have to fit + assert(_bpp == from._bpp); + + uint16 dWidth = (uint16) floor((_width / scale).toDouble()); + uint16 dHeight = (uint16) floor((_height / scale).toDouble()); + + // Clip + if (!clipBlitRect(left, top, right, bottom, x, y, dWidth, dHeight, from._width, from._height)) + return; + + // Area to actually copy + uint16 width = right - left + 1; + uint16 height = bottom - top + 1; + + if ((width == 0) || (height == 0)) + // Nothing to do + return; + + width = MIN((int32) floor((width * scale).toDouble()), _width); + height = MIN((int32) floor((height * scale).toDouble()), _height); + + // Pointers to the blit destination and source start points + byte *dst = getData(x , y); + const byte *src = from.getData(left, top); + + frac_t step = scale.getInverse().toFrac(); + + frac_t posW = 0, posH = 0; + while (height-- > 0) { + byte *dstRow = dst; + const byte *srcRow = src; + + posW = 0; + + for (uint16 i = 0; i < width; i++, dstRow += _bpp) { + memcpy(dstRow, srcRow, _bpp); + + posW += step; + while (posW >= ((frac_t) FRAC_ONE)) { + srcRow += from._bpp; + posW -= FRAC_ONE; + } + } + + posH += step; + while (posH >= ((frac_t) FRAC_ONE)) { + src += from._width * from._bpp; + posH -= FRAC_ONE; + } + + dst += _width * _bpp; + } + +} + +void Surface::blitScaled(const Surface &from, int16 x, int16 y, Common::Rational scale, int32 transp) { + blitScaled(from, 0, 0, from._width - 1, from._height - 1, x, y, scale, transp); +} + +void Surface::blitScaled(const Surface &from, Common::Rational scale, int32 transp) { + blitScaled(from, 0, 0, from._width - 1, from._height - 1, 0, 0, scale, transp); +} + +void Surface::fillRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uint32 color) { + // Just in case those are swapped + if (left > right) + SWAP(left, right); + if (top > bottom) + SWAP(top, bottom); + + if ((left >= _width) || (top >= _height)) + // Nothing to do + return; + + // Area to actually fill + uint16 width = CLIP(right - left + 1, 0, _width - left); + uint16 height = CLIP(bottom - top + 1, 0, _height - top); + + if ((width == 0) || (height == 0)) + // Nothing to do + return; + + if ((left == 0) && (width == _width) && (_bpp == 1)) { + // We can directly use memset + + byte *dst = getData(left, top); + + memset(dst, (byte) color, width * height); + return; + } + + if (_bpp == 1) { + // We can use memset line-wise + + byte *dst = getData(left, top); + + while (height-- > 0) { + memset(dst, (byte) color, width); + dst += _width; + } + + return; + } + + assert(_bpp == 2); + + // Otherwise, we have to fill by pixel + + Pixel p = get(left, top); + while (height-- > 0) { + for (uint16 i = 0; i < width; i++, ++p) + p.set(color); + + p += _width - width; + } +} + +void Surface::fill(uint32 color) { + if (_bpp == 1) { + // We can directly use memset + + memset(_vidMem, (byte) color, _width * _height); + return; + } + + fillRect(0, 0, _width - 1, _height - 1, color); +} + +void Surface::clear() { + fill(0); +} + +void Surface::putPixel(uint16 x, uint16 y, uint32 color) { + if ((x >= _width) || (y >= _height)) + return; + + get(x, y).set(color); +} + +void Surface::drawLine(uint16 x0, uint16 y0, uint16 x1, uint16 y1, uint32 color) { + Graphics::drawLine(x0, y0, x1, y1, color, &plotPixel, this); +} + +/* + * The original's version of the Bresenham Algorithm was a bit "unclean" + * and produced strange edges at 45, 135, 225 and 315 degrees, so using the + * version found in the Wikipedia article about the + * "Bresenham's line algorithm" instead + */ +void Surface::drawCircle(uint16 x0, uint16 y0, uint16 radius, uint32 color, int16 pattern) { + int16 f = 1 - radius; + int16 ddFx = 0; + int16 ddFy = -2 * radius; + int16 x = 0; + int16 y = radius; + + if (pattern == 0) { + putPixel(x0, y0 + radius, color); + putPixel(x0, y0 - radius, color); + putPixel(x0 + radius, y0, color); + putPixel(x0 - radius, y0, color); + } else + warning("Surface::drawCircle - pattern %d", pattern); + + while (x < y) { + if (f >= 0) { + y--; + ddFy += 2; + f += ddFy; + } + x++; + ddFx += 2; + f += ddFx + 1; + + switch (pattern) { + case -1: + fillRect(x0 - y, y0 + x, x0 + y, y0 + x, color); + fillRect(x0 - x, y0 + y, x0 + x, y0 + y, color); + fillRect(x0 - y, y0 - x, x0 + y, y0 - x, color); + fillRect(x0 - x, y0 - y, x0 + x, y0 - y, color); + break; + case 0: + putPixel(x0 + x, y0 + y, color); + putPixel(x0 - x, y0 + y, color); + putPixel(x0 + x, y0 - y, color); + putPixel(x0 - x, y0 - y, color); + putPixel(x0 + y, y0 + x, color); + putPixel(x0 - y, y0 + x, color); + putPixel(x0 + y, y0 - x, color); + putPixel(x0 - y, y0 - x, color); + break; + default: + fillRect(x0 + y - pattern, y0 + x - pattern, x0 + y, y0 + x, color); + fillRect(x0 + x - pattern, y0 + y - pattern, x0 + x, y0 + y, color); + fillRect(x0 - y, y0 + x - pattern, x0 - y + pattern, y0 + x, color); + fillRect(x0 - x, y0 + y - pattern, x0 - x + pattern, y0 + y, color); + fillRect(x0 + y - pattern, y0 - x, x0 + y, y0 - x + pattern, color); + fillRect(x0 + x - pattern, y0 - y, x0 + x, y0 - y + pattern, color); + fillRect(x0 - y, y0 - x, x0 - y + pattern, y0 - x + pattern, color); + fillRect(x0 - x, y0 - y, x0 - x + pattern, y0 - y + pattern, color); + break; + } + } +} + +void Surface::blitToScreen(uint16 left, uint16 top, uint16 right, uint16 bottom, uint16 x, uint16 y) const { + // Color depths have to fit + assert(g_system->getScreenFormat().bytesPerPixel == _bpp); + + uint16 sWidth = g_system->getWidth(); + uint16 sHeight = g_system->getHeight(); + + if ((x >= sWidth) || (y >= sHeight)) + // Nothing to do + return; + + // Just in case those are swapped + if (left > right) + SWAP(left, right); + if (top > bottom) + SWAP(top, bottom); + + if ((left >= _width) || (top >= _height)) + // Nothing to do + return; + + // Area to actually copy + uint16 width = MAX(MIN(MIN(right - left + 1, _width - left), sWidth - x), 0); + uint16 height = MAX(MIN(MIN(bottom - top + 1, _height - top ), sHeight - y), 0); + + if ((width == 0) || (height == 0)) + // Nothing to do + return; + + // Pointers to the blit destination and source start points + const byte *src = getData(left, top); + + g_system->copyRectToScreen(src, _width * _bpp, x, y, width, height); +} + +} // End of namespace Gob diff --git a/engines/gob/surface.h b/engines/gob/surface.h new file mode 100644 index 00000000000..9a26dbc79bf --- /dev/null +++ b/engines/gob/surface.h @@ -0,0 +1,131 @@ +/* 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 GOB_SURFACE_H +#define GOB_SURFACE_H + +#include "common/scummsys.h" +#include "common/ptr.h" +#include "common/rational.h" + +namespace Gob { + +/** An iterator over a surface's image data, automatically handles different color depths. */ +class Pixel { +public: + Pixel(byte *vidMem, uint8 bpp); + + Pixel &operator++(); + Pixel operator++(int x); + + Pixel &operator--(); + Pixel operator--(int x); + + Pixel &operator+=(int x); + Pixel &operator-=(int x); + + uint32 get() const; + void set(uint32 p); + +private: + byte *_vidMem; + uint8 _bpp; +}; + +/** A const iterator over a surface's image data, automatically handles different color depths. */ +class ConstPixel { +public: + ConstPixel(const byte *vidMem, uint8 bpp); + + ConstPixel &operator++(); + ConstPixel operator++(int x); + + ConstPixel &operator--(); + ConstPixel operator--(int x); + + ConstPixel &operator+=(int x); + ConstPixel &operator-=(int x); + + uint32 get() const; + +private: + const byte *_vidMem; + uint8 _bpp; +}; + +class Surface { +public: + Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem = 0); + ~Surface(); + + uint16 getWidth () const; + uint16 getHeight() const; + uint16 getBPP () const; + + byte *getData(uint16 x = 0, uint16 y = 0); + const byte *getData(uint16 x = 0, uint16 y = 0) const; + + void resize(uint16 width, uint16 height); + + Pixel get(uint16 x = 0, uint16 y = 0); + ConstPixel get(uint16 x = 0, uint16 y = 0) const; + + void blit(const Surface &from, int16 left, int16 top, int16 right, int16 bottom, + int16 x, int16 y, int32 transp = -1); + void blit(const Surface &from, int16 x, int16 y, int32 transp = -1); + void blit(const Surface &from, int32 transp = -1); + + void blitScaled(const Surface &from, int16 left, int16 top, int16 right, int16 bottom, + int16 x, int16 y, Common::Rational scale, int32 transp = -1); + void blitScaled(const Surface &from, int16 x, int16 y, Common::Rational scale, int32 transp = -1); + void blitScaled(const Surface &from, Common::Rational scale, int32 transp = -1); + + void fillRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uint32 color); + void fill(uint32 color); + void clear(); + + void putPixel(uint16 x, uint16 y, uint32 color); + void drawLine(uint16 x0, uint16 y0, uint16 x1, uint16 y1, uint32 color); + void drawCircle(uint16 x0, uint16 y0, uint16 radius, uint32 color, int16 pattern = 0); + + void blitToScreen(uint16 left, uint16 top, uint16 right, uint16 bottom, uint16 x, uint16 y) const; + +private: + uint16 _width; + uint16 _height; + uint8 _bpp; + + bool _ownVidMem; + byte *_vidMem; + + static bool clipBlitRect(int16 &left, int16 &top, int16 &right, int16 &bottom, int16 &x, int16 &y, + uint16 dWidth, uint16 dHeight, uint16 sWidth, uint16 sHeight); +}; + +typedef Common::SharedPtr SurfacePtr; + +} // End of namespace Gob + +#endif // GOB_SURFACE_H diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index c895c6301d4..8e2b3d89cd8 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -121,6 +121,10 @@ void Util::processInput(bool scroll) { _fastMode ^= 2; else if (event.kbd.keycode == Common::KEYCODE_p) _vm->pauseGame(); + else if (event.kbd.keycode == Common::KEYCODE_d) { + _vm->getDebugger()->attach(); + _vm->getDebugger()->onFrame(); + } break; } addKeyToBuffer(event.kbd); @@ -146,7 +150,7 @@ void Util::processInput(bool scroll) { // WORKAROUND: // Force a check of the mouse in order to fix the sofa bug. This apply only for Gob3, and only // in the impacted TOT file so that the second screen animation is not broken. - if ((_vm->getGameType() == kGameTypeGob3) && !strncmp(_vm->_game->_curTotFile, "EMAP1008.TOT", 12)) + if ((_vm->getGameType() == kGameTypeGob3) && !scumm_stricmp(_vm->_game->_curTotFile, "EMAP1008.TOT")) _vm->_game->evaluateScroll(); } } @@ -316,8 +320,11 @@ void Util::clearPalette() { _vm->validateVideoMode(_vm->_global->_videoMode); if (_vm->_global->_setAllPalette) { - memset(colors, 0, 1024); - g_system->setPalette(colors, 0, 256); + if (_vm->getPixelFormat().bytesPerPixel == 1) { + memset(colors, 0, 1024); + g_system->setPalette(colors, 0, 256); + } + return; } diff --git a/engines/gob/variables.cpp b/engines/gob/variables.cpp index 11c5f08bb22..4f6bad52f0a 100644 --- a/engines/gob/variables.cpp +++ b/engines/gob/variables.cpp @@ -24,10 +24,10 @@ */ #include "common/endian.h" +#include "common/str.h" #include "gob/gob.h" #include "gob/variables.h" -#include "gob/helper.h" namespace Gob { @@ -112,7 +112,7 @@ uint32 Variables::readOff32(uint32 offset) const { } void Variables::readOffString(uint32 offset, char *value, uint32 length) { - strncpy0(value, (const char *)(_vars + offset), length - 1); + Common::strlcpy(value, (const char *)(_vars + offset), length); } const uint8 *Variables::getAddressVar8(uint32 var) const { diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index e2c25c3a220..ee73f14dfa7 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -30,7 +30,6 @@ #include "graphics/cursorman.h" #include "graphics/fontman.h" #include "graphics/surface.h" -#include "graphics/dither.h" #include "gob/gob.h" #include "gob/video.h" @@ -39,8 +38,6 @@ #include "gob/dataio.h" #include "gob/draw.h" -#include "gob/driver_vga.h" - namespace Gob { Font::Font(const byte *data) : _dataPtr(data) { @@ -90,22 +87,53 @@ uint16 Font::getCharCount() const { return _endItem - _startItem + 1; } -uint8 Font::getFirstChar() const { - return _startItem; -} - -uint8 Font::getLastChar() const { - return _endItem; -} - -uint8 Font::getCharSize() const { - return _itemSize; -} - bool Font::isMonospaced() const { return _charWidths == 0; } +void Font::drawLetter(Surface &surf, uint8 c, uint16 x, uint16 y, + uint32 color1, uint32 color2, bool transp) const { + + uint16 data; + + const byte *src = getCharData(c); + if (!src) { + warning("Font::drawLetter(): getCharData() == 0"); + return; + } + + Pixel dst = surf.get(x, y); + + int nWidth = _itemWidth; + if (nWidth & 7) + nWidth = (nWidth & 0xF8) + 8; + + nWidth >>= 3; + + for (int i = 0; i < _itemHeight; i++) { + int width = _itemWidth; + + for (int k = 0; k < nWidth; k++) { + + data = *src++; + for (int j = 0; j < MIN(8, width); j++) { + if (data & 0x80) + dst.set(color1); + else if (!transp) + dst.set(color2); + + dst++; + data <<= 1; + } + + width -= 8; + + } + + dst += surf.getWidth() - _itemWidth; + } +} + const byte *Font::getCharData(uint8 c) const { if (_endItem == 0) { warning("Font::getCharData(): _endItem == 0"); @@ -119,55 +147,8 @@ const byte *Font::getCharData(uint8 c) const { } -SurfaceDesc::SurfaceDesc(int16 vidMode, int16 width, int16 height, - byte *vidMem) : _width(width), _height(height) { - - if (vidMem) { - _vidMode = vidMode; - _ownVidMem = false; - _vidMem = vidMem; - } else { - _vidMode = vidMode; - _ownVidMem = true; - _vidMem = new byte[width * height]; - assert(_vidMem); - memset(_vidMem, 0, width * height); - } -} - -void SurfaceDesc::setVidMem(byte *vidMem) { - assert(vidMem); - - if (hasOwnVidMem()) - delete[] _vidMem; - - _ownVidMem = false; - _vidMem = vidMem; -} - -void SurfaceDesc::resize(int16 width, int16 height) { - if (hasOwnVidMem()) - delete[] _vidMem; - - _width = width; - _height = height; - _ownVidMem = true; - _vidMem = new byte[width * height]; - assert(_vidMem); - memset(_vidMem, 0, width * height); -} - -void SurfaceDesc::swap(SurfaceDesc &surf) { - SWAP(_width, surf._width); - SWAP(_height, surf._height); - SWAP(_vidMode, surf._vidMode); - SWAP(_ownVidMem, surf._ownVidMem); - SWAP(_vidMem, surf._vidMem); -} - Video::Video(GobEngine *vm) : _vm(vm) { _doRangeClamp = false; - _videoDriver = 0; _surfWidth = 320; _surfHeight = 200; @@ -186,24 +167,9 @@ Video::Video(GobEngine *vm) : _vm(vm) { _lastSparse = 0xFFFFFFFF; _dirtyAll = false; - - _palLUT = new Graphics::PaletteLUT(5, Graphics::PaletteLUT::kPaletteYUV); -} - -char Video::initDriver(int16 vidMode) { - if (_videoDriver) - return 1; - - _videoDriver = new VGAVideoDriver(); - return 1; } Video::~Video() { - delete _palLUT; -} - -void Video::freeDriver() { - delete _videoDriver; } void Video::initPrimary(int16 mode) { @@ -215,9 +181,6 @@ void Video::initPrimary(int16 mode) { mode = 3; _vm->_global->_oldMode = mode; - if (mode != 3) - Video::initDriver(mode); - if (mode != 3) { initSurfDesc(mode, _surfWidth, _surfHeight, PRIMARY_SURFACE); @@ -226,8 +189,8 @@ void Video::initPrimary(int16 mode) { } } -SurfaceDescPtr Video::initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags) { - SurfaceDescPtr descPtr; +SurfacePtr Video::initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags) { + SurfacePtr descPtr; if (flags & PRIMARY_SURFACE) assert((width == _surfWidth) && (height == _surfHeight)); @@ -240,14 +203,13 @@ SurfaceDescPtr Video::initSurfDesc(int16 vidMode, int16 width, int16 height, int descPtr = _vm->_global->_primarySurfDesc; descPtr->resize(width, height); - descPtr->_vidMode = vidMode; } else { assert(!(flags & DISABLE_SPR_ALLOC)); if (!(flags & SCUMMVM_CURSOR)) width = (width + 7) & 0xFFF8; - descPtr = SurfaceDescPtr(new SurfaceDesc(vidMode, width, height)); + descPtr = SurfacePtr(new Surface(width, height, _vm->getPixelFormat().bytesPerPixel)); } return descPtr; } @@ -257,14 +219,16 @@ void Video::clearScreen() { } void Video::setSize(bool defaultTo1XScaler) { - initGraphics(_vm->_width, _vm->_height, defaultTo1XScaler); + if (_vm->isTrueColor()) + initGraphics(_vm->_width, _vm->_height, defaultTo1XScaler, 0); + else + initGraphics(_vm->_width, _vm->_height, defaultTo1XScaler); } void Video::retrace(bool mouse) { if (mouse) CursorMan.showMouse((_vm->_draw->_showCursor & 2) != 0); if (_vm->_global->_primarySurfDesc) { - int screenOffset = _scrollOffsetY * _surfWidth + _scrollOffsetX; int screenX = _screenDeltaX; int screenY = _screenDeltaY; int screenWidth = MIN(_surfWidth - _scrollOffsetX, _vm->_width); @@ -275,18 +239,15 @@ void Video::retrace(bool mouse) { if (_splitSurf) { - screenOffset = 0; screenX = 0; screenY = _vm->_height - _splitSurf->getHeight(); screenWidth = MIN(_vm->_width, _splitSurf->getWidth()); screenHeight = _splitSurf->getHeight(); - g_system->copyRectToScreen(_splitSurf->getVidMem() + screenOffset, - _splitSurf->getWidth(), screenX, screenY, screenWidth, screenHeight); + _splitSurf->blitToScreen(0, 0, screenWidth - 1, screenHeight - 1, screenX, screenY); } else if (_splitHeight2 > 0) { - screenOffset = _splitStart * _surfWidth; screenX = 0; screenY = _vm->_height - _splitHeight2; screenWidth = MIN(_surfWidth, _vm->_width); @@ -318,191 +279,58 @@ void Video::sparseRetrace(int max) { _lastSparse = timeKey; } -void Video::putPixel(int16 x, int16 y, int16 color, SurfaceDesc &dest) { - if ((x >= dest.getWidth()) || (x < 0) || - (y >= dest.getHeight()) || (y < 0)) - return; +void Video::drawPacked(byte *sprBuf, int16 width, int16 height, + int16 x, int16 y, byte transp, Surface &dest) { - _videoDriver->putPixel(x, y, color, dest); -} + int destRight = x + width; + int destBottom = y + height; -void Video::fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, - int16 bottom, int16 color) { + Pixel dst = dest.get(x, y); - if (_doRangeClamp) { - if (left > right) - SWAP(left, right); - if (top > bottom) - SWAP(top, bottom); + int curx = x; + int cury = y; - if ((left >= dest.getWidth()) || (right < 0) || - (top >= dest.getHeight()) || (bottom < 0)) - return; + while (1) { + uint8 val = *sprBuf++; + unsigned int repeat = val & 7; + val &= 0xF8; + + if (!(val & 8)) { + repeat <<= 8; + repeat |= *sprBuf++; + } + repeat++; + val >>= 4; + + for (unsigned int i = 0; i < repeat; ++i) { + if (curx < dest.getWidth() && cury < dest.getHeight()) + if (!transp || val) + dst.set(val); + + dst++; + curx++; + if (curx == destRight) { + dst += dest.getWidth() + x - curx; + curx = x; + cury++; + if (cury == destBottom) + return; + } + } - left = CLIP(left, (int16)0, (int16)(dest.getWidth() - 1)); - top = CLIP(top, (int16)0, (int16)(dest.getHeight() - 1)); - right = CLIP(right, (int16)0, (int16)(dest.getWidth() - 1)); - bottom = CLIP(bottom, (int16)0, (int16)(dest.getHeight() - 1)); } - - _videoDriver->fillRect(dest, left, top, right, bottom, color); -} - -void Video::drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, - int16 y1, int16 color) { - - if ((x0 == x1) || (y0 == y1)) - Video::fillRect(dest, x0, y0, x1, y1, color); - else - _videoDriver->drawLine(dest, x0, y0, x1, y1, color); -} - -/* - * The original's version of the Bresenham Algorithm was a bit "unclean" - * and produced strange edges at 45, 135, 225 and 315 degrees, so using the - * version found in the Wikipedia article about the - * "Bresenham's line algorithm" instead - */ -void Video::drawCircle(SurfaceDesc &dest, int16 x0, int16 y0, - int16 radius, int16 color) { - int16 f = 1 - radius; - int16 ddFx = 0; - int16 ddFy = -2 * radius; - int16 x = 0; - int16 y = radius; - int16 tmpPattern = (_vm->_draw->_pattern & 0xFF); - - if (tmpPattern == 0) { - putPixel(x0, y0 + radius, color, dest); - putPixel(x0, y0 - radius, color, dest); - putPixel(x0 + radius, y0, color, dest); - putPixel(x0 - radius, y0, color, dest); - } else - warning ("Video::drawCircle - pattern %d", _vm->_draw->_pattern); - - while (x < y) { - if (f >= 0) { - y--; - ddFy += 2; - f += ddFy; - } - x++; - ddFx += 2; - f += ddFx + 1; - - switch (tmpPattern) { - case -1: - fillRect(dest, x0 - y, y0 + x, x0 + y, y0 + x, color); - fillRect(dest, x0 - x, y0 + y, x0 + x, y0 + y, color); - fillRect(dest, x0 - y, y0 - x, x0 + y, y0 - x, color); - fillRect(dest, x0 - x, y0 - y, x0 + x, y0 - y, color); - break; - case 0: - putPixel(x0 + x, y0 + y, color, dest); - putPixel(x0 - x, y0 + y, color, dest); - putPixel(x0 + x, y0 - y, color, dest); - putPixel(x0 - x, y0 - y, color, dest); - putPixel(x0 + y, y0 + x, color, dest); - putPixel(x0 - y, y0 + x, color, dest); - putPixel(x0 + y, y0 - x, color, dest); - putPixel(x0 - y, y0 - x, color, dest); - break; - default: - fillRect(dest, x0 + y - tmpPattern, y0 + x - tmpPattern, x0 + y, y0 + x, color); - fillRect(dest, x0 + x - tmpPattern, y0 + y - tmpPattern, x0 + x, y0 + y, color); - fillRect(dest, x0 - y, y0 + x - tmpPattern, x0 - y + tmpPattern, y0 + x, color); - fillRect(dest, x0 - x, y0 + y - tmpPattern, x0 - x + tmpPattern, y0 + y, color); - fillRect(dest, x0 + y - tmpPattern, y0 - x, x0 + y, y0 - x + tmpPattern, color); - fillRect(dest, x0 + x - tmpPattern, y0 - y, x0 + x, y0 - y + tmpPattern, color); - fillRect(dest, x0 - y, y0 - x, x0 - y + tmpPattern, y0 - x + tmpPattern, color); - fillRect(dest, x0 - x, y0 - y, x0 - x + tmpPattern, y0 - y + tmpPattern, color); - break; - } - } -} - -void Video::clearSurf(SurfaceDesc &dest) { - Video::fillRect(dest, 0, 0, dest.getWidth() - 1, dest.getHeight() - 1, 0); -} - -void Video::drawSprite(SurfaceDesc &source, SurfaceDesc &dest, - int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) { - int16 destRight; - int16 destBottom; - - if (_doRangeClamp) { - if (left > right) - SWAP(left, right); - if (top > bottom) - SWAP(top, bottom); - - if ((left >= source.getWidth()) || (right < 0) || - (top >= source.getHeight()) || (bottom < 0)) - return; - - if (left < 0) { - x -= left; - left = 0; - } - if (top < 0) { - y -= top; - top = 0; - } - right = CLIP(right, (int16)0, (int16)(source.getWidth() - 1)); - bottom = CLIP(bottom, (int16)0, (int16)(source.getHeight() - 1)); - if (right - left >= source.getWidth()) - right = left + source.getWidth() - 1; - if (bottom - top >= source.getHeight()) - bottom = top + source.getHeight() - 1; - - if (x < 0) { - left -= x; - x = 0; - } - if (y < 0) { - top -= y; - y = 0; - } - if ((x >= dest.getWidth()) || (left > right) || - (y >= dest.getHeight()) || (top > bottom)) - return; - - destRight = x + right - left; - destBottom = y + bottom - top; - if (destRight >= dest.getWidth()) - right -= destRight - dest.getWidth() + 1; - - if (destBottom >= dest.getHeight()) - bottom -= destBottom - dest.getHeight() + 1; - } - - _videoDriver->drawSprite(source, dest, left, top, right, bottom, x, y, transp); -} - -void Video::drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, - int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) { - - _videoDriver->drawSpriteDouble(source, dest, left, top, right, bottom, x, y, transp); -} - -void Video::drawLetter(int16 item, int16 x, int16 y, const Font &font, - int16 color1, int16 color2, int16 transp, SurfaceDesc &dest) { - assert(item != 0x00); - _videoDriver->drawLetter((unsigned char)item, x, y, font, color1, color2, transp, dest); } void Video::drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, int16 transp, SurfaceDesc &dest) { + int16 x, int16 y, int16 transp, Surface &dest) { if (spriteUncompressor(sprBuf, width, height, x, y, transp, dest)) return; - _vm->validateVideoMode(dest._vidMode); - - _videoDriver->drawPackedSprite(sprBuf, width, height, x, y, transp, dest); + drawPacked(sprBuf, width, height, x, y, transp, dest); } -void Video::drawPackedSprite(const char *path, SurfaceDesc &dest, int width) { +void Video::drawPackedSprite(const char *path, Surface &dest, int width) { byte *data; data = _vm->_dataIO->getData(path); @@ -521,7 +349,8 @@ void Video::setPalElem(int16 index, char red, char green, char blue, _vm->_global->_bluePalette[index] = blue; setPalColor(pal, red, green, blue); - g_system->setPalette(pal, index, 1); + if (_vm->getPixelFormat().bytesPerPixel == 1) + g_system->setPalette(pal, index, 1); } void Video::setPalette(PalDesc *palDesc) { @@ -534,7 +363,8 @@ void Video::setPalette(PalDesc *palDesc) { for (int i = 0; i < numcolors; i++) setPalColor(pal + i * 4, palDesc->vgaPal[i]); - g_system->setPalette(pal, 0, numcolors); + if (_vm->getPixelFormat().bytesPerPixel == 1) + g_system->setPalette(pal, 0, numcolors); } void Video::setFullPalette(PalDesc *palDesc) { @@ -549,7 +379,8 @@ void Video::setFullPalette(PalDesc *palDesc) { setPalColor(pal + i * 4, colors[i]); } - g_system->setPalette(pal, 0, 256); + if (_vm->getPixelFormat().bytesPerPixel == 1) + g_system->setPalette(pal, 0, 256); } else Video::setPalette(palDesc); } @@ -587,61 +418,26 @@ void Video::dirtyRectsAdd(int16 left, int16 top, int16 right, int16 bottom) { } void Video::dirtyRectsApply(int left, int top, int width, int height, int x, int y) { - byte *vidMem = _vm->_global->_primarySurfDesc->getVidMem(); - if (_dirtyAll) { - g_system->copyRectToScreen(vidMem + top * _surfWidth + left, - _surfWidth, x, y, width, height); + _vm->_global->_primarySurfDesc->blitToScreen(left, top, left + width - 1, top + height - 1, x, y); return; } - int right = left + width; - int bottom = top + height; + int right = left + width; + int bottom = top + height; Common::List::const_iterator it; for (it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { - int l = MAX(left, it->left); - int t = MAX(top, it->top); - int r = MIN(right, it->right); + int l = MAX(left , it->left); + int t = MAX(top , it->top); + int r = MIN(right , it->right); int b = MIN(bottom, it->bottom); - int w = r - l; - int h = b - t; - if ((w <= 0) || (h <= 0)) + if ((r <= l) || (b <= t)) continue; - byte *v = vidMem + t * _surfWidth + l; - - g_system->copyRectToScreen(v, _surfWidth, x + (l - left), y + (t - top), w, h); + _vm->_global->_primarySurfDesc->blitToScreen(l, t, r - 1, b - 1, x + (l - left), y + (t - top)); } } -void Video::initOSD() { - const byte palOSD[] = { - 0, 0, 0, 0, - 0, 0, 171, 0, - 0, 171, 0, 0, - 0, 171, 171, 0, - 171, 0, 0, 0 - }; - - g_system->setPalette(palOSD, 0, 5); -} - -void Video::drawOSDText(const char *text) { - const Graphics::Font &font(*FontMan.getFontByUsage(Graphics::FontManager::kOSDFont)); - uint32 color = 0x2; - Graphics::Surface surf; - - surf.create(g_system->getWidth(), font.getFontHeight(), 1); - - font.drawString(&surf, text, 0, 0, surf.w, color, Graphics::kTextAlignCenter); - - int y = g_system->getHeight() / 2 - font.getFontHeight() / 2; - g_system->copyRectToScreen((byte *)surf.pixels, surf.pitch, 0, y, surf.w, surf.h); - g_system->updateScreen(); - - surf.free(); -} - } // End of namespace Gob diff --git a/engines/gob/video.h b/engines/gob/video.h index b8a46598b71..5c490424968 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -31,29 +31,23 @@ #include "common/ptr.h" #include "gob/gob.h" - -namespace Graphics { - class PaletteLUT; -} +#include "gob/surface.h" namespace Gob { class Font { public: + Font(const byte *data); + ~Font(); + uint8 getCharWidth (uint8 c) const; uint8 getCharWidth () const; uint8 getCharHeight() const; - uint16 getCharCount () const; - uint8 getFirstChar () const; - uint8 getLastChar () const; - uint8 getCharSize () const; bool isMonospaced() const; - const byte *getCharData(uint8 c) const; - - Font(const byte *data); - ~Font(); + void drawLetter(Surface &surf, uint8 c, uint16 x, uint16 y, + uint32 color1, uint32 color2, bool transp) const; private: const byte *_dataPtr; @@ -66,46 +60,19 @@ private: uint8 _endItem; int8 _itemSize; int8 _bitWidth; + + uint16 getCharCount() const; + const byte *getCharData(uint8 c) const; }; -// Some Surfaces are simultaneous in Draw::spritesArray and discrete -// variables, so if in doubt you should use a SurfaceDescPtr shared -// pointer object to refer to any SurfaceDesc. -class SurfaceDesc { -public: - int16 _vidMode; - - int16 getWidth() const { return _width; } - int16 getHeight() const { return _height; } - byte *getVidMem() { return _vidMem; } - const byte *getVidMem() const { return _vidMem; } - bool hasOwnVidMem() const { return _ownVidMem; } - - void setVidMem(byte *vidMem); - void resize(int16 width, int16 height); - void swap(SurfaceDesc &surf); - - SurfaceDesc(int16 vidMode, int16 width, int16 height, byte *vidMem = 0); - ~SurfaceDesc() { if (_ownVidMem) delete[] _vidMem; } - -private: - int16 _width; - int16 _height; - byte *_vidMem; - bool _ownVidMem; -}; - -typedef Common::SharedPtr SurfaceDescPtr; - - class Video { public: -#define GDR_VERSION 4 +#define GDR_VERSION 4 -#define PRIMARY_SURFACE 0x80 -#define RETURN_PRIMARY 0x01 -#define DISABLE_SPR_ALLOC 0x20 -#define SCUMMVM_CURSOR 0x100 +#define PRIMARY_SURFACE 0x80 +#define RETURN_PRIMARY 0x01 +#define DISABLE_SPR_ALLOC 0x20 +#define SCUMMVM_CURSOR 0x100 #include "common/pack-start.h" // START STRUCT PACKING @@ -132,7 +99,7 @@ public: int16 _scrollOffsetX; int16 _scrollOffsetY; - SurfaceDescPtr _splitSurf; + SurfacePtr _splitSurf; int16 _splitHeight1; int16 _splitHeight2; int16 _splitStart; @@ -140,11 +107,8 @@ public: int16 _screenDeltaX; int16 _screenDeltaY; - Graphics::PaletteLUT *_palLUT; - - void freeDriver(); void initPrimary(int16 mode); - SurfaceDescPtr initSurfDesc(int16 vidMode, int16 width, + SurfacePtr initSurfDesc(int16 vidMode, int16 width, int16 height, int16 flags); void setSize(bool defaultTo1XScaler); @@ -154,25 +118,9 @@ public: void waitRetrace(bool mouse = true); void sparseRetrace(int max); - void putPixel(int16 x, int16 y, int16 color, SurfaceDesc &dest); - virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, - int16 right, int16 bottom, int16 color); - void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, - int16 color); - void drawCircle(SurfaceDesc &dest, int16 x0, int16 y0, - int16 radius, int16 color); - void clearSurf(SurfaceDesc &dest); - void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, - int16 left, int16 top, int16 right, int16 bottom, - int16 x, int16 y, int16 transp); - void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, - int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); - void drawLetter(int16 item, int16 x, int16 y, const Font &font, - int16 color1, int16 color2, int16 transp, SurfaceDesc &dest); void drawPackedSprite(byte *sprBuf, int16 width, int16 height, - int16 x, int16 y, int16 transp, SurfaceDesc &dest); - void drawPackedSprite(const char *path, SurfaceDesc &dest, - int width = 320); + int16 x, int16 y, int16 transp, Surface &dest); + void drawPackedSprite(const char *path, Surface &dest, int width = 320); void setPalColor(byte *pal, byte red, byte green, byte blue) { pal[0] = red << 2; @@ -196,18 +144,12 @@ public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 x, int16 y, int16 transp, - SurfaceDesc &destDesc) = 0; - - virtual void init() {} - - virtual void setPrePalette() { } + Surface &destDesc) = 0; Video(class GobEngine *vm); virtual ~Video(); protected: - class VideoDriver *_videoDriver; - bool _dirtyAll; Common::List _dirtyRects; @@ -216,16 +158,13 @@ protected: GobEngine *_vm; - char initDriver(int16 vidMode); - - void initOSD(); - void drawOSDText(const char *text); + void drawPacked(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, byte transp, Surface &dest); }; class Video_v1 : public Video { public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc &destDesc); + int16 x, int16 y, int16 transp, Surface &destDesc); Video_v1(GobEngine *vm); virtual ~Video_v1() {} @@ -234,7 +173,7 @@ public: class Video_v2 : public Video_v1 { public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc &destDesc); + int16 x, int16 y, int16 transp, Surface &destDesc); Video_v2(GobEngine *vm); virtual ~Video_v2() {} @@ -243,14 +182,7 @@ public: class Video_v6 : public Video_v2 { public: virtual char spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc &destDesc); - - virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, - int16 right, int16 bottom, int16 color); - - virtual void init(); - - virtual void setPrePalette(); + int16 x, int16 y, int16 transp, Surface &destDesc); Video_v6(GobEngine *vm); virtual ~Video_v6() {} @@ -260,30 +192,17 @@ private: void buildPalLUT(); - void shadeRect(SurfaceDesc &dest, + void shadeRect(Surface &dest, int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength); - void drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc &surfDesc); - void drawYUVData(const byte *srcData, SurfaceDesc &destDesc, + void drawPacked(const byte *sprBuf, int16 x, int16 y, Surface &surfDesc); + void drawYUVData(const byte *srcData, Surface &destDesc, int16 width, int16 height, int16 x, int16 y); - void drawYUV(SurfaceDesc &destDesc, int16 x, int16 y, + void drawYUV(Surface &destDesc, int16 x, int16 y, int16 dataWidth, int16 dataHeight, int16 width, int16 height, const byte *dataY, const byte *dataU, const byte *dataV); }; -class VideoDriver { -public: - VideoDriver() {} - virtual ~VideoDriver() {} - virtual void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; - virtual void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; - virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color) = 0; - virtual void putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest) = 0; - virtual void drawLetter(unsigned char item, int16 x, int16 y, const Font &font, byte color1, byte color2, byte transp, SurfaceDesc &dest) = 0; - virtual void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, byte color) = 0; - virtual void drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, byte transp, SurfaceDesc &dest) = 0; -}; - } // End of namespace Gob #endif // GOB_VIDEO_H diff --git a/engines/gob/video_v1.cpp b/engines/gob/video_v1.cpp index 699ac5f9346..5c2f17d7dd2 100644 --- a/engines/gob/video_v1.cpp +++ b/engines/gob/video_v1.cpp @@ -34,9 +34,9 @@ Video_v1::Video_v1(GobEngine *vm) : Video(vm) { } char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc &destDesc) { + int16 x, int16 y, int16 transp, Surface &destDesc) { byte *memBuffer; - byte *srcPtr, *destPtr, *linePtr; + byte *srcPtr; byte temp; uint16 sourceLeft; uint16 cmdVar; @@ -46,7 +46,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 bufPos; int16 strLen; - _vm->validateVideoMode(destDesc._vidMode); + //_vm->validateVideoMode(destDesc._vidMode); if (sprBuf[0] != 1) return 0; @@ -55,9 +55,8 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, return 0; if (sprBuf[2] == 2) { - SurfaceDesc sourceDesc(0x13, srcWidth, srcHeight, sprBuf + 3); - Video::drawSprite(sourceDesc, destDesc, 0, 0, srcWidth - 1, - srcHeight - 1, x, y, transp); + Surface sourceDesc(srcWidth, srcHeight, 1, sprBuf + 3); + destDesc.blit(sourceDesc, 0, 0, srcWidth - 1, srcHeight - 1, x, y, (transp == 0) ? -1 : 0); return 1; } else { memBuffer = new byte[4114]; @@ -66,12 +65,12 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, srcPtr = sprBuf + 3; sourceLeft = READ_LE_UINT16(srcPtr); - destPtr = destDesc.getVidMem() + destDesc.getWidth() * y + x; + Pixel destPtr = destDesc.get(x, y); curWidth = 0; curHeight = 0; - linePtr = destPtr; + Pixel linePtr = destPtr; srcPtr += 4; for (offset = 0; offset < 4078; offset++) @@ -88,7 +87,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, if ((cmdVar & 1) != 0) { temp = *srcPtr++; if ((temp != 0) || (transp == 0)) - *destPtr = temp; + destPtr.set(temp); destPtr++; curWidth++; if (curWidth >= srcWidth) { @@ -116,7 +115,7 @@ char Video_v1::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, for (counter2 = 0; counter2 < strLen; counter2++) { temp = memBuffer[(offset + counter2) % 4096]; if ((temp != 0) || (transp == 0)) - *destPtr = temp; + destPtr.set(temp); destPtr++; curWidth++; diff --git a/engines/gob/video_v2.cpp b/engines/gob/video_v2.cpp index 98cf4a5d4f6..c908ccf7b17 100644 --- a/engines/gob/video_v2.cpp +++ b/engines/gob/video_v2.cpp @@ -34,9 +34,9 @@ Video_v2::Video_v2(GobEngine *vm) : Video_v1(vm) { } char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc &destDesc) { + int16 x, int16 y, int16 transp, Surface &destDesc) { byte *memBuffer; - byte *srcPtr, *destPtr, *linePtr; + byte *srcPtr; byte temp; uint32 sourceLeft; uint16 cmdVar; @@ -47,7 +47,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, int16 strLen; int16 lenCmd; - _vm->validateVideoMode(destDesc._vidMode); + //_vm->validateVideoMode(destDesc._vidMode); if (sprBuf[0] != 1) return 0; @@ -56,9 +56,8 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, return 0; if (sprBuf[2] == 2) { - SurfaceDesc sourceDesc(0x13, srcWidth, srcHeight, sprBuf + 3); - Video::drawSprite(sourceDesc, destDesc, 0, 0, srcWidth - 1, - srcHeight - 1, x, y, transp); + Surface sourceDesc(srcWidth, srcHeight, 1, sprBuf + 3); + destDesc.blit(sourceDesc, 0, 0, srcWidth - 1, srcHeight - 1, x, y, (transp == 0) ? -1 : 0); return 1; } else if (sprBuf[2] == 1) { memBuffer = new byte[4370]; @@ -70,12 +69,12 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, sourceLeft = READ_LE_UINT32(srcPtr); - destPtr = destDesc.getVidMem() + destDesc.getWidth() * y + x; + Pixel destPtr = destDesc.get(x, y); curWidth = 0; curHeight = 0; - linePtr = destPtr; + Pixel linePtr = destPtr; srcPtr += 4; if ((READ_LE_UINT16(srcPtr) == 0x1234) && (READ_LE_UINT16(srcPtr + 2) == 0x5678)) { @@ -99,7 +98,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, temp = *srcPtr++; if ((temp != 0) || (transp == 0)) - *destPtr = temp; + destPtr.set(temp); destPtr++; curWidth++; @@ -133,7 +132,7 @@ char Video_v2::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, temp = memBuffer[(offset + counter2) % 4096]; if ((temp != 0) || (transp == 0)) - *destPtr = temp; + destPtr.set(temp); destPtr++; curWidth++; diff --git a/engines/gob/video_v6.cpp b/engines/gob/video_v6.cpp index 7285cd89580..7bf728034bc 100644 --- a/engines/gob/video_v6.cpp +++ b/engines/gob/video_v6.cpp @@ -25,7 +25,8 @@ #include "common/endian.h" #include "common/savefile.h" -#include "graphics/dither.h" + +#include "graphics/conversion.h" #include "gob/gob.h" #include "gob/video.h" @@ -38,46 +39,8 @@ namespace Gob { Video_v6::Video_v6(GobEngine *vm) : Video_v2(vm) { } -void Video_v6::setPrePalette() { - byte *tpal = (byte *)_vm->_draw->_vgaPalette; - const byte *fpal = (const byte *)_ditherPalette; - - for (int i = 0; i < 256; i++) { - byte r, g, b; - - Graphics::PaletteLUT::YUV2RGB(fpal[i * 3 + 0], fpal[i * 3 + 1], fpal[i * 3 + 2], - r, g, b); - - tpal[i * 3 + 0] = r >> 2; - tpal[i * 3 + 1] = g >> 2; - tpal[i * 3 + 2] = b >> 2; - } - _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - -} - -void Video_v6::init() { - initOSD(); - - buildPalLUT(); -} - -void Video_v6::buildPalLUT() { - char text[30]; - - _palLUT->setPalette(_ditherPalette, Graphics::PaletteLUT::kPaletteYUV, 8, 0); - - sprintf(text, "Building palette table"); - drawOSDText(text); - - for (int i = 0; (i < 32) && !_vm->shouldQuit(); i++) - _palLUT->buildNext(); -} - char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, - int16 x, int16 y, int16 transp, SurfaceDesc &destDesc) { - _vm->validateVideoMode(destDesc._vidMode); + int16 x, int16 y, int16 transp, Surface &destDesc) { if ((sprBuf[0] == 1) && (sprBuf[1] == 3)) { drawPacked(sprBuf, x, y, destDesc); @@ -93,9 +56,7 @@ char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, if (Video_v2::spriteUncompressor(sprBuf, srcWidth, srcHeight, x, y, transp, destDesc)) return 1; - _vm->validateVideoMode(destDesc._vidMode); - - _videoDriver->drawPackedSprite(sprBuf, srcWidth, srcHeight, x, y, transp, destDesc); + Video::drawPacked(sprBuf, srcWidth, srcHeight, x, y, transp, destDesc); return 1; } @@ -104,7 +65,8 @@ char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight, return 1; } -void Video_v6::fillRect(SurfaceDesc &dest, +/* +void Video_v6::fillRect(Surface &dest, int16 left, int16 top, int16 right, int16 bottom, int16 color) { if (!(color & 0xFF00)) { @@ -136,17 +98,21 @@ void Video_v6::fillRect(SurfaceDesc &dest, byte strength = 16 - (((uint16) color) >> 12); shadeRect(dest, left, top, right, bottom, color, strength); } +*/ -void Video_v6::shadeRect(SurfaceDesc &dest, +void Video_v6::shadeRect(Surface &dest, int16 left, int16 top, int16 right, int16 bottom, byte color, byte strength) { + warning("TODO: Video_v6::shadeRect()"); + + /* int width = right - left + 1; int height = bottom - top + 1; int dWidth = dest.getWidth(); byte *vidMem = dest.getVidMem() + dWidth * top + left; byte sY, sU, sV; - _palLUT->getEntry(color, sY, sU, sV); + //_palLUT->getEntry(color, sY, sU, sV); int shadeY = sY * (16 - strength); int shadeU = sU * (16 - strength); @@ -176,9 +142,10 @@ void Video_v6::shadeRect(SurfaceDesc &dest, } delete dither; + */ } -void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc &surfDesc) { +void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, Surface &surfDesc) { const byte *data = sprBuf + 2; int16 width = READ_LE_UINT16(data); @@ -204,7 +171,7 @@ void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc &sur delete[] uncBuf; } -void Video_v6::drawYUVData(const byte *srcData, SurfaceDesc &destDesc, +void Video_v6::drawYUVData(const byte *srcData, Surface &destDesc, int16 width, int16 height, int16 x, int16 y) { int16 dataWidth = width; @@ -223,106 +190,46 @@ void Video_v6::drawYUVData(const byte *srcData, SurfaceDesc &destDesc, } -void Video_v6::drawYUV(SurfaceDesc &destDesc, int16 x, int16 y, +void Video_v6::drawYUV(Surface &destDesc, int16 x, int16 y, int16 dataWidth, int16 dataHeight, int16 width, int16 height, const byte *dataY, const byte *dataU, const byte *dataV) { - byte *vidMem = destDesc.getVidMem() + y * destDesc.getWidth() + x; + const Graphics::PixelFormat &pixelFormat = _vm->getPixelFormat(); if ((x + width - 1) >= destDesc.getWidth()) width = destDesc.getWidth() - x; if ((y + height - 1) >= destDesc.getHeight()) height = destDesc.getHeight() - y; - Graphics::SierraLight *dither = - new Graphics::SierraLight(width, _palLUT); + Pixel dst = destDesc.get(x, y); for (int i = 0; i < height; i++) { - byte *dest = vidMem; + Pixel dstRow = dst; + const byte *srcY = dataY + i * dataWidth; const byte *srcU = dataU + (i >> 2) * (dataWidth >> 2); const byte *srcV = dataV + (i >> 2) * (dataWidth >> 2); for (int j = 0; j < (width >> 2); j++, srcU++, srcV++) { - for (int n = 0; n < 4; n++, dest++, srcY++) { + for (int n = 0; n < 4; n++, dstRow++, srcY++) { byte dY = *srcY << 1, dU = *srcU << 1, dV = *srcV << 1; - *dest = (dY == 0) ? 0 : dither->dither(dY, dU, dV, j * 4 + n); + byte r, g, b; + Graphics::YUV2RGB(dY, dU, dV, r, g, b); + + if (dY != 0) { + uint32 c = pixelFormat.RGBToColor(r, g, b); + + dstRow.set((c == 0) ? 1 : c); + } else + dstRow.set(0); + } } - dither->nextLine(); - vidMem += destDesc.getWidth(); + dst += destDesc.getWidth(); } - delete dither; } -const byte Video_v6::_ditherPalette[768] = { - 0x00,0x80,0x80,0x26,0x6B,0xC0,0x4B,0x56,0x4B,0x71,0x41,0x8B, - 0x0E,0xC0,0x76,0x34,0xAB,0xB6,0x59,0x96,0x41,0xBE,0x81,0x81, - 0xCF,0x77,0x75,0xC1,0x9B,0x6C,0x7F,0x81,0x81,0x7F,0x81,0x81, - 0x0A,0x8C,0x8A,0x0A,0xB0,0x79,0x0E,0x9D,0x76,0x0E,0x79,0x76, - 0x10,0x77,0x75,0x09,0x7B,0x8B,0x16,0x74,0xA6,0x16,0x74,0xA6, - 0x12,0x91,0x93,0x13,0xB5,0x72,0x1B,0x9E,0x6D,0x1A,0x7A,0x6D, - 0x1C,0x71,0x6C,0x1B,0x72,0x8C,0x1B,0x71,0xAE,0x1B,0x71,0xAE, - 0x21,0x93,0x93,0x21,0xB8,0x6F,0x27,0xA3,0x64,0x27,0x7F,0x65, - 0x29,0x69,0x68,0x28,0x69,0x8E,0x23,0x6F,0xB7,0x2A,0x69,0xB2, - 0x36,0x94,0x92,0x35,0xB9,0x6E,0x35,0xA6,0x5D,0x34,0x80,0x5D, - 0x39,0x61,0x6B,0x3A,0x60,0x8F,0x34,0x6E,0xB9,0x39,0x60,0xB5, - 0x46,0x93,0x95,0x48,0xB6,0x6F,0x45,0xA6,0x5C,0x47,0x80,0x5C, - 0x4B,0x56,0x6D,0x4B,0x56,0x91,0x47,0x6F,0xB7,0x4A,0x57,0xB5, - 0x5A,0x94,0x92,0x59,0xB9,0x6E,0x59,0xA6,0x5D,0x59,0x82,0x5D, - 0x5B,0x4D,0x6D,0x5A,0x4E,0x92,0x5B,0x6F,0xB7,0x5C,0x4D,0xB6, - 0x6D,0x94,0x93,0x6D,0xB8,0x6F,0x6D,0xA5,0x5D,0x6C,0x7F,0x5E, - 0x6C,0x4A,0x70,0x6D,0x4A,0x94,0x6C,0x6E,0xB9,0x6C,0x4A,0xBA, - 0x7E,0x94,0x93,0x80,0xB6,0x6F,0x7D,0xA6,0x5D,0x7F,0x81,0x5B, - 0x7F,0x4A,0x6F,0x7F,0x4A,0x92,0x7E,0x6F,0xB7,0x7E,0x4B,0xB7, - 0x92,0x94,0x93,0x90,0xB8,0x6F,0x91,0xA5,0x5C,0x90,0x81,0x5D, - 0x91,0x4B,0x6D,0x91,0x4C,0x93,0x93,0x6F,0xB7,0x92,0x4B,0xB7, - 0xA5,0x91,0x93,0xA2,0xB2,0x6F,0xA5,0xA6,0x5D,0xA4,0x80,0x5D, - 0xA3,0x4A,0x6F,0xA4,0x49,0x93,0xA4,0x6F,0xB9,0xA3,0x4B,0xB9, - 0xB6,0x94,0x93,0xB4,0xA9,0x71,0xB6,0xA5,0x5C,0xB8,0x80,0x5C, - 0xB7,0x4B,0x6F,0xB6,0x4C,0x93,0xB5,0x70,0xB3,0xB5,0x4C,0xB3, - 0xC9,0x93,0x92,0xC3,0xA0,0x72,0xC7,0x9E,0x5E,0xC9,0x82,0x5D, - 0xCA,0x4B,0x6E,0xCA,0x4B,0x93,0xC2,0x73,0xA9,0xC2,0x4F,0xA9, - 0xDD,0x92,0x93,0xD4,0x97,0x74,0xD9,0x94,0x60,0xDD,0x80,0x5E, - 0xDB,0x4B,0x6F,0xDD,0x4A,0x93,0xCE,0x76,0xA1,0xCE,0x52,0xA1, - 0xE8,0x8B,0x8E,0xE6,0x8C,0x76,0xE7,0x8C,0x61,0xE6,0x86,0x62, - 0xE3,0x51,0x78,0xEA,0x4D,0x8D,0xDC,0x79,0x97,0xDC,0x55,0x97, - 0xFA,0x81,0x81,0xF8,0x82,0x83,0xF4,0x85,0x77,0xF2,0x79,0x79, - 0xF4,0x65,0x86,0xF8,0x75,0x83,0xEF,0x87,0x89,0xF0,0x67,0x89, - 0xEE,0x81,0x81,0xE8,0x8B,0x85,0xED,0x88,0x71,0xEA,0x71,0x73, - 0xEE,0x5D,0x81,0xEA,0x71,0x8D,0xE4,0x87,0x91,0xE4,0x63,0x91, - 0xDB,0x81,0x81,0xD7,0x95,0x83,0xDB,0x93,0x6F,0xDB,0x6F,0x6F, - 0xDC,0x5C,0x80,0xDD,0x6E,0x93,0xD7,0x83,0x9B,0xD6,0x5F,0x9B, - 0xCA,0x81,0x81,0xC8,0x9D,0x82,0xC8,0x94,0x6E,0xCA,0x6F,0x6E, - 0xC9,0x5D,0x81,0xCA,0x6F,0x93,0xC9,0x82,0xA5,0xC8,0x5E,0xA5, - 0xB6,0x81,0x81,0xB6,0xA5,0x80,0xB7,0x93,0x6F,0xB7,0x6F,0x6F, - 0xB6,0x5D,0x81,0xB6,0x70,0x93,0xB8,0x80,0xA5,0xB7,0x5C,0xA5, - 0xA3,0x81,0x81,0xA4,0xA7,0x81,0xA3,0x92,0x6F,0xA3,0x6E,0x6F, - 0xA5,0x5C,0x7F,0xA5,0x6D,0x93,0xA4,0x80,0xA5,0xA4,0x5C,0xA5, - 0x92,0x81,0x81,0x93,0xA5,0x81,0x90,0x94,0x6F,0x92,0x6F,0x6D, - 0x92,0x5D,0x81,0x92,0x70,0x93,0x91,0x82,0xA7,0x91,0x5E,0xA7, - 0x7F,0x81,0x81,0x7F,0xA5,0x81,0x80,0x92,0x70,0x7F,0x6E,0x6F, - 0x7F,0x5D,0x81,0x7D,0x70,0x93,0x80,0x80,0xA5,0x80,0x5C,0xA5, - 0x6B,0x81,0x81,0x6C,0xA7,0x80,0x6D,0x94,0x6F,0x6C,0x6E,0x6F, - 0x6D,0x5B,0x80,0x6D,0x6E,0x93,0x6C,0x81,0xA5,0x6C,0x5D,0xA5, - 0x5A,0x81,0x81,0x5A,0xA5,0x81,0x59,0x95,0x6E,0x5A,0x6F,0x6E, - 0x5B,0x5D,0x81,0x59,0x70,0x93,0x5A,0x81,0xA7,0x5A,0x5D,0xA7, - 0x47,0x81,0x81,0x47,0xA5,0x80,0x47,0x92,0x6F,0x47,0x6E,0x6F, - 0x46,0x5D,0x81,0x46,0x6F,0x95,0x49,0x81,0xA5,0x48,0x5D,0xA5, - 0x32,0x81,0x81,0x33,0xA7,0x81,0x35,0x95,0x6E,0x34,0x6F,0x6F, - 0x36,0x62,0x7E,0x35,0x6E,0x93,0x34,0x80,0xA5,0x36,0x62,0xA4, - 0x23,0x81,0x81,0x23,0xA5,0x80,0x20,0x94,0x6F,0x22,0x6F,0x6D, - 0x26,0x6B,0x7E,0x21,0x6F,0x93,0x22,0x82,0xA7,0x25,0x6C,0xA4, - 0x0E,0x81,0x81,0x0F,0xA5,0x81,0x13,0x91,0x73,0x15,0x75,0x71, - 0x14,0x75,0x7D,0x11,0x77,0x93,0x15,0x7D,0xA1,0x16,0x74,0xA1, - 0x00,0x80,0x80,0x07,0xA0,0x7B,0x05,0x8F,0x7D,0x09,0x7B,0x7A, - 0x07,0x7D,0x7B,0x07,0x7C,0x8C,0x0E,0x78,0x98,0x0E,0x78,0x98, - 0x7F,0x81,0x81,0x80,0x83,0x81,0xF7,0x7C,0x84,0x9E,0x83,0x80, - 0x7F,0x81,0x81,0x4B,0x56,0xFE,0x93,0x2D,0x17,0xDE,0x03,0x95, - 0x1C,0xFE,0x6C,0x67,0xD4,0xEA,0xAF,0xAB,0x03,0xFA,0x81,0x81 -}; - } // End of namespace Gob diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index 9e49bfc0923..020c72d0c1e 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -25,7 +25,6 @@ #include "gob/videoplayer.h" -#include "gob/helper.h" #include "gob/global.h" #include "gob/dataio.h" #include "gob/video.h" @@ -155,8 +154,8 @@ int VideoPlayer::openVideo(bool primary, const Common::String &file, Properties video->decoder->setXY(0, 0); } else { video->surface = _vm->_draw->_spritesArray[properties.sprite]; - video->decoder->setSurfaceMemory(video->surface->getVidMem(), - video->surface->getWidth(), video->surface->getHeight(), 1); + video->decoder->setSurfaceMemory(video->surface->getData(), + video->surface->getWidth(), video->surface->getHeight(), video->surface->getBPP()); if (!ownSurf || (ownSurf && screenSize)) { if ((properties.x >= 0) || (properties.y >= 0)) diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index d91d0a38457..c1542544559 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -137,7 +137,7 @@ private: Graphics::CoktelDecoder *decoder; Common::String fileName; - SurfaceDescPtr surface; + SurfacePtr surface; Video(); diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index b30c2361d21..a6a92eb5215 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -54,7 +54,8 @@ static const GroovieGameDescription gameDescriptions[] = { { "t7g", "", AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM }, kGroovieT7G, 0 }, @@ -64,7 +65,8 @@ static const GroovieGameDescription gameDescriptions[] = { { "t7g", "", AD_ENTRY1s("T7GMac", "a139540fa2be2247005ccf888b7231e3", 1830783), - Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, Common::GUIO_NONE + Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM }, kGroovieT7G, 0 }, @@ -78,7 +80,8 @@ static const GroovieGameDescription gameDescriptions[] = { { "intro.gjd", 0, NULL, 31711554}, { NULL, 0, NULL, 0} }, - Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE + Common::RU_RUS, Common::kPlatformPC, ADGF_NO_FLAGS, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM }, kGroovieT7G, 0 }, @@ -89,7 +92,8 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "", AD_ENTRY1s("disk.1", "5c0428cd3659fc7bbcd0aa16485ed5da", 227), - Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, Common::GUIO_NONE + Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM }, kGroovieV2, 1 }, @@ -99,7 +103,8 @@ static const GroovieGameDescription gameDescriptions[] = { { "11h", "Demo", AD_ENTRY1s("disk.1", "aacb32ce07e0df2894bd83a3dee40c12", 70), - Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, Common::GUIO_NOLAUNCHLOAD + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, Common::GUIO_NOLAUNCHLOAD | + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM }, kGroovieV2, 1 }, diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp index dc1d7ae73a2..b9d6dbf6878 100644 --- a/engines/groovie/font.cpp +++ b/engines/groovie/font.cpp @@ -62,6 +62,10 @@ bool T7GFont::load(Common::SeekableReadStream &stream) { delete[] _glyphs; _glyphs = new Glyph[numGlyphs]; + // Ensure we're ready to read the first glyph. (Most versions don't + // need it, but the russian one does. This fixes bug #3095031.) + stream.seek(glyphOffsets[0]); + // Read the glyphs _maxHeight = _maxWidth = 0; for (int i = 0; (i < numGlyphs) && !stream.eos(); i++) { diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index cdf5171ab9e..131604e75c9 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -321,13 +321,18 @@ void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf } void GroovieEngine::syncSoundSettings() { - _musicPlayer->setUserVolume(ConfMan.getInt("music_volume")); - // VDX videos just contain one digital audio track, which can be used for + bool mute = ConfMan.getBool("mute"); + + // Set the music volume + _musicPlayer->setUserVolume(mute ? 0 : ConfMan.getInt("music_volume")); + + // Videos just contain one digital audio track, which can be used for // both SFX or Speech, but the engine doesn't know what they contain, so // we have to use just one volume setting for videos. // We use "speech" because most users will want to change the videos // volume when they can't hear the speech because of the music. - _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("speech_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, + mute ? 0 : ConfMan.getInt("speech_volume")); } bool GroovieEngine::canLoadGameStateCurrently() { diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index 8ae5f4157f5..f8fad8d91ff 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -44,7 +44,7 @@ namespace Common { * now fully completable. All remaining Groovie games use V2 of the engine, * which is under slow development. * - * Supported games: + * Games using this engine: * - The 7th Guest (completable) * - The 11th Hour * - Clandestiny diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 6959a6a6f1c..6ccc68c4983 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -427,10 +427,14 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) setTimbreAD(9, _timbres[i]); } } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) { + _driver->sendMT32Reset(); + // MT-32 _musicType = MT_MT32; loadTimbres(gtlName + ".mt"); } else { + _driver->sendGMReset(); + // GM _musicType = 0; } diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp index d19eee0041b..0064a39434c 100644 --- a/engines/hugo/detection.cpp +++ b/engines/hugo/detection.cpp @@ -189,21 +189,14 @@ REGISTER_PLUGIN_STATIC(HUGO, PLUGIN_TYPE_ENGINE, Hugo::HugoMetaEngine); namespace Hugo { void HugoEngine::initGame(const HugoGameDescription *gd) { - char tmpStr[8]; - _gameType = gd->gameType; _platform = gd->desc.platform; _packedFl = (getFeatures() & GF_PACKED); _gameVariant = _gameType - 1 + ((_platform == Common::kPlatformWindows) ? 0 : 3); -//Generate filenames - if (gd->desc.platform == Common::kPlatformWindows) - sprintf(tmpStr, "%s%c", gd->desc.gameid, 'w'); - else - sprintf(tmpStr, "%s%c", gd->desc.gameid, 'd'); - - sprintf(_initFilename, "%s-00.SAV", tmpStr); - sprintf(_saveFilename, "%s-%s.SAV", tmpStr, "%d"); + // Generate filenames + _initFilename = _targetName + "-00.SAV"; + _saveFilename = _targetName + "-%d.SAV"; } } // End of namespace Hugo diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp index ddd193c2a63..2380ab9f300 100644 --- a/engines/hugo/display.cpp +++ b/engines/hugo/display.cpp @@ -34,15 +34,12 @@ #include "common/system.h" -#include "hugo/game.h" #include "hugo/hugo.h" #include "hugo/display.h" -#include "hugo/file.h" #include "hugo/util.h" namespace Hugo { -#define CENTER -1 // Used to center text in x #define NUM_COLORS 16 // Num colors to save in palette #define DMAX 16 // Size of add/restore rect lists #define BMAX (DMAX * 2) // Size of dirty rect blit list @@ -51,21 +48,17 @@ namespace Hugo { #define INY(Y, B) (Y >= B->y && Y <= B->y + B->dy) #define OVERLAP(A, B) ((INX(A->x, B) || INX(A->x + A->dx, B) || INX(B->x, A) || INX(B->x + B->dx, A)) && (INY(A->y, B) || INY(A->y + A->dy, B) || INY(B->y, A) || INY(B->y + B->dy, A))) -struct rect_t { // Rectangle used in Display list - int16 x; // Position in dib - int16 y; // Position in dib - int16 dx; // width - int16 dy; // height -}; +Screen::Screen(HugoEngine *vm) : _vm(vm) { -Screen::Screen(HugoEngine &vm) : _vm(vm) { +} +Screen::~Screen() { } void Screen::createPal() { debugC(1, kDebugDisplay, "createPal"); - g_system->setPalette(_vm._palette, 0, NUM_COLORS); + g_system->setPalette(_vm->_palette, 0, NUM_COLORS); } void Screen::initDisplay() { @@ -76,17 +69,16 @@ void Screen::initDisplay() { // Move an image from source to destination void Screen::moveImage(image_pt srcImage, uint16 x1, uint16 y1, uint16 dx, uint16 dy, uint16 width1, image_pt dstImage, uint16 x2, uint16 y2, uint16 width2) { + debugC(3, kDebugDisplay, "moveImage(srcImage, %d, %d, %d, %d, %d, dstImage, %d, %d, %d)", x1, y1, dx, dy, width1, x2, y2, width2); + int16 wrap_src = width1 - dx; // Wrap to next src row int16 wrap_dst = width2 - dx; // Wrap to next dst row - int16 x; - - debugC(3, kDebugDisplay, "moveImage(srcImage, %d, %d, %d, %d, %d, dstImage, %d, %d, %d)", x1, y1, dx, dy, width1, x2, y2, width2); srcImage += y1 * width1 + x1; // Offset into src image dstImage += y2 * width2 + x2; // offset into dst image while (dy--) { // For each row - for (x = dx; x--;) // For each column + for (int16 x = dx; x--;) // For each column *dstImage++ = *srcImage++; srcImage += wrap_src; // Wrap to next line dstImage += wrap_dst; @@ -136,17 +128,6 @@ void Screen::setBackgroundColor(long color) { // How??? Translate existing pixels in dib before objects rendered? } -// Write the supplied character in the supplied color to x,y pixel coords -void Screen::writeChar(int16 x, int16 y, char c, byte color) { - debugC(1, kDebugDisplay, "writeChar(%d, %d, %c, %d)", x, y, c, color); - - warning("STUB: writeChar()"); - // x = (int16)((long) x * config.cx / XPIX); - // y = (int16)((long) y * config.cy / YPIX); - // SetTextColor(hDC, GetPalIndex(color)); - // TextOut(hDC, x, y, &c, 1); -} - // Return the overlay state (Foreground/Background) of the currently // processed object by looking down the current column for an overlay // base bit set (in which case the object is foreground). @@ -154,7 +135,7 @@ overlayState_t Screen::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) { debugC(4, kDebugDisplay, "findOvl"); for (; y < seq_p->lines; y++) { // Each line in object - image_pt ovb_p = _vm.getBaseBoundaryOverlay() + ((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits + image_pt ovb_p = _vm->getBaseBoundaryOverlay() + ((uint16)(dst_p - _frontBuffer) >> 3); // Ptr into overlay bits if (*ovb_p & (0x80 >> ((uint16)(dst_p - _frontBuffer) & 7))) // Overlay bit is set return FG; // Found a bit - must be foreground dst_p += XPIX; @@ -166,33 +147,27 @@ overlayState_t Screen::findOvl(seq_t *seq_p, image_pt dst_p, uint16 y) { // Merge an object frame into _frontBuffer at sx, sy and update rectangle list. // If fore TRUE, force object above any overlay void Screen::displayFrame(int sx, int sy, seq_t *seq, bool foreFl) { - overlayState_t overlayState = UNDEF; // Overlay state of object - image_pt image; // Ptr to object image data - image_pt subFrontBuffer; // Ptr to offset in _frontBuffer - image_pt overlay; // Ptr to overlay data - int16 frontBufferwrap; // Wrap dst_p to next line - int16 imageWrap; // Wrap src_p to next line - uint16 x, y; // Index into object data - debugC(3, kDebugDisplay, "displayFrame(%d, %d, seq, %d)", sx, sy, (foreFl) ? 1 : 0); - image = seq->imagePtr; // Source ptr - subFrontBuffer = &_frontBuffer[sy * XPIX + sx]; // Destination ptr - overlay = &_vm.getFirstOverlay()[(sy * XPIX + sx) >> 3]; // Overlay ptr - frontBufferwrap = XPIX - seq->x2 - 1; // Wraps dest_p after each line - imageWrap = seq->bytesPerLine8 - seq->x2 - 1; + image_pt image = seq->imagePtr; // Ptr to object image data + image_pt subFrontBuffer = &_frontBuffer[sy * XPIX + sx]; // Ptr to offset in _frontBuffer + image_pt overlay = &_vm->getFirstOverlay()[(sy * XPIX + sx) >> 3]; // Ptr to overlay data + int16 frontBufferwrap = XPIX - seq->x2 - 1; // Wraps dest_p after each line + int16 imageWrap = seq->bytesPerLine8 - seq->x2 - 1; - for (y = 0; y < seq->lines; y++) { // Each line in object - for (x = 0; x <= seq->x2; x++) { + overlayState_t overlayState = UNDEF; // Overlay state of object + for (uint16 y = 0; y < seq->lines; y++) { // Each line in object + for (uint16 x = 0; x <= seq->x2; x++) { if (*image) { // Non-transparent - overlay = _vm.getFirstOverlay() + ((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits + overlay = _vm->getFirstOverlay() + ((uint16)(subFrontBuffer - _frontBuffer) >> 3); // Ptr into overlay bits if (*overlay & (0x80 >> ((uint16)(subFrontBuffer - _frontBuffer) & 7))) { // Overlay bit is set if (overlayState == UNDEF) // Overlay defined yet? overlayState = findOvl(seq, subFrontBuffer, y);// No, find it. if (foreFl || overlayState == FG) // Object foreground *subFrontBuffer = *image; // Copy pixel - } else // No overlay + } else { // No overlay *subFrontBuffer = *image; // Copy pixel + } } image++; subFrontBuffer++; @@ -225,24 +200,24 @@ void Screen::merge(rect_t *rectA, rect_t *rectB) { // of blist. bmax is the max size of the blist. Note that blist can // have holes, in which case dx = 0. Returns used length of blist. int16 Screen::mergeLists(rect_t *list, rect_t *blist, int16 len, int16 blen, int16 bmax) { - int16 coalesce[BMAX]; // List of overlapping rects - debugC(4, kDebugDisplay, "mergeLists"); + int16 coalesce[BMAX]; // List of overlapping rects // Process the list for (int16 a = 0; a < len; a++, list++) { // Compile list of overlapping rectangles in blit list int16 c = 0; rect_t *bp = blist; - for (int16 b = 0; b < blen; b++, bp++) + for (int16 b = 0; b < blen; b++, bp++) { if (bp->dx) // blist entry used if (OVERLAP(list, bp)) coalesce[c++] = b; + } // Any overlapping blit rects? - if (c == 0) // None, add a new entry + if (c == 0) { // None, add a new entry blist[blen++] = *list; - else { // At least one overlapping + } else { // At least one overlapping // Merge add-list entry with first blist entry bp = &blist[coalesce[0]]; merge(list, bp); @@ -261,15 +236,15 @@ int16 Screen::mergeLists(rect_t *list, rect_t *blist, int16 len, int16 blen, int // Process the display list // Trailing args are int16 x,y,dx,dy for the D_ADD operation void Screen::displayList(dupdate_t update, ...) { + debugC(6, kDebugDisplay, "displayList"); + static int16 addIndex, restoreIndex; // Index into add/restore lists static rect_t restoreList[DMAX]; // The restore list static rect_t addList[DMAX]; // The add list static rect_t blistList[BMAX]; // The blit list int16 blitLength = 0; // Length of blit list - rect_t *p; // Ptr to dlist entry va_list marker; // Args used for D_ADD operation - - debugC(6, kDebugDisplay, "displayList"); + rect_t *p; // Ptr to dlist entry switch (update) { case D_INIT: // Init lists, restore whole screen @@ -278,7 +253,7 @@ void Screen::displayList(dupdate_t update, ...) { break; case D_ADD: // Add a rectangle to list if (addIndex >= DMAX) { - Utils::Warn(false, "%s", "Display list exceeded"); + Utils::Warn("%s", "Display list exceeded"); return; } va_start(marker, update); // Initialize variable arguments @@ -294,8 +269,8 @@ void Screen::displayList(dupdate_t update, ...) { // Don't blit if newscreen just loaded because _frontBuffer will // get blitted via InvalidateRect() at end of this cycle // and blitting here causes objects to appear too soon. - if (_vm.getGameStatus().newScreenFl) { - _vm.getGameStatus().newScreenFl = false; + if (_vm->getGameStatus().newScreenFl) { + _vm->getGameStatus().newScreenFl = false; break; } @@ -304,9 +279,10 @@ void Screen::displayList(dupdate_t update, ...) { blitLength = mergeLists(addList, blistList, addIndex, blitLength, BMAX); // Blit the combined blit-list - for (restoreIndex = 0, p = blistList; restoreIndex < blitLength; restoreIndex++, p++) + for (restoreIndex = 0, p = blistList; restoreIndex < blitLength; restoreIndex++, p++) { if (p->dx) // Marks a used entry displayRect(p->x, p->y, p->dx, p->dy); + } break; case D_RESTORE: // Restore each rectangle for (restoreIndex = 0, p = addList; restoreIndex < addIndex; restoreIndex++, p++) { @@ -320,22 +296,19 @@ void Screen::displayList(dupdate_t update, ...) { } void Screen::writeChr(int sx, int sy, byte color, char *local_fontdata) { - /* - Write supplied character (font data) at sx,sy in supplied color - Font data as follows: - - *(fontdata+1) = Font Height (pixels) - *(fontdata+1) = Font Width (pixels) - *(fontdata+x) = Font Bitmap (monochrome) - */ - +// Write supplied character (font data) at sx,sy in supplied color +// Font data as follows: +// +// *(fontdata+1) = Font Height (pixels) +// *(fontdata+1) = Font Width (pixels) +// *(fontdata+x) = Font Bitmap (monochrome) debugC(2, kDebugDisplay, "writeChr(%d, %d, %d, %d)", sx, sy, color, local_fontdata[0]); byte height = local_fontdata[0]; byte width = 8; //local_fontdata[1]; // This can probably be optimized quite a bit... - for (int y = 0; y < height; ++y) + for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int pixel = y * width + x; int bitpos = pixel % 8; @@ -343,8 +316,8 @@ void Screen::writeChr(int sx, int sy, byte color, char *local_fontdata) { byte bitTest = (1 << bitpos); if ((local_fontdata[2 + offset] & bitTest) == bitTest) _frontBuffer[(sy + y) * 320 + sx + x] = color; - //printf("offset: %u, bitpos %u\n", offset, bitpos); } + } } // Returns height of characters in current font @@ -352,40 +325,38 @@ int16 Screen::fontHeight() { debugC(2, kDebugDisplay, "fontHeight"); static int16 height[NUM_FONTS] = {5, 7, 8}; - return(height[_fnt - FIRST_FONT]); + return height[_fnt - FIRST_FONT]; } // Returns length of supplied string in pixels -int16 Screen::stringLength(char *s) { - int16 sum; - byte **fontArr = _font[_fnt]; - +int16 Screen::stringLength(const char *s) { debugC(2, kDebugDisplay, "stringLength(%s)", s); - for (sum = 0; *s; s++) + byte **fontArr = _font[_fnt]; + int16 sum = 0; + for (; *s; s++) sum += *(fontArr[(uint)*s] + 1) + 1; - return(sum); + return sum; } // Return x which would center supplied string -int16 Screen::center(char *s) { +int16 Screen::center(const char *s) { debugC(1, kDebugDisplay, "center(%s)", s); - return ((int16)((XPIX - stringLength(s)) >> 1)); + return (int16)((XPIX - stringLength(s)) >> 1); } // Write string at sx,sy in supplied color in current font // If sx == CENTER, center it -void Screen::writeStr(int16 sx, int16 sy, char *s, byte color) { - byte **font = _font[_fnt]; - +void Screen::writeStr(int16 sx, int16 sy, const char *s, byte color) { debugC(2, kDebugDisplay, "writeStr(%d, %d, %s, %d)", sx, sy, s, color); if (sx == CENTER) sx = center(s); + byte **font = _font[_fnt]; for (; *s; s++) { writeChr(sx, sy, color, (char *)font[(uint)*s]); sx += *(font[(uint)*s] + 1) + 1; @@ -393,7 +364,7 @@ void Screen::writeStr(int16 sx, int16 sy, char *s, byte color) { } // Shadowed version of writestr -void Screen::shadowStr(int16 sx, int16 sy, char *s, byte color) { +void Screen::shadowStr(int16 sx, int16 sy, const char *s, byte color) { debugC(1, kDebugDisplay, "shadowStr(%d, %d, %s, %d)", sx, sy, s, color); if (sx == CENTER) @@ -403,44 +374,10 @@ void Screen::shadowStr(int16 sx, int16 sy, char *s, byte color) { writeStr(sx, sy, s, color); } -// Load font file, construct font ptrs and reverse data bytes -void Screen::loadFont(int16 fontId) { - byte height, width; - static bool fontLoadedFl[NUM_FONTS] = {false, false, false}; - - debugC(2, kDebugDisplay, "loadFont(%d)", fontId); - - _fnt = fontId - FIRST_FONT; // Set current font number - - if (fontLoadedFl[_fnt]) // If already loaded, return - return; - - fontLoadedFl[_fnt] = true; - _vm.file().readUIFItem(fontId, _fontdata[_fnt]); - - // Compile font ptrs. Note: First ptr points to height,width of font - _font[_fnt][0] = _fontdata[_fnt]; // Store height,width of fonts - - int16 offset = 2; // Start at fontdata[2] ([0],[1] used for height,width) - - // Setup the font array (127 characters) - for (int i = 1; i < 128; i++) { - _font[_fnt][i] = _fontdata[_fnt] + offset; - height = *(_fontdata[_fnt] + offset); - width = *(_fontdata[_fnt] + offset + 1); - - int16 size = height * ((width + 7) >> 3); - for (int j = 0; j < size; j++) - Utils::reverseByte(&_fontdata[_fnt][offset + 2 + j]); - - offset += 2 + size; - } -} - void Screen::userHelp() { // Introduce user to the game // DOS versions Only - Utils::Box(BOX_ANY , "%s", + Utils::Box(BOX_ANY , "%s", "F1 - Press F1 again\n" " for instructions\n" "F2 - Sound on/off\n" @@ -453,4 +390,64 @@ void Screen::userHelp() { "ESC - Return to game"); } +void Screen::drawStatusText() { + debugC(4, kDebugDisplay, "drawStatusText"); + + loadFont(U_FONT8); + uint16 sdx = stringLength(_vm->_statusLine); + uint16 sdy = fontHeight() + 1; // + 1 for shadow + uint16 posX = 0; + uint16 posY = YPIX - sdy; + + // Display the string and add rect to display list + writeStr(posX, posY, _vm->_statusLine, _TLIGHTYELLOW); + displayList(D_ADD, posX, posY, sdx, sdy); + + sdx = stringLength(_vm->_scoreLine); + posY = 0; + writeStr(posX, posY, _vm->_scoreLine, _TCYAN); + displayList(D_ADD, posX, posY, sdx, sdy); +} + +void Screen::drawShape(int x, int y, int color1, int color2) { + for (int i = 0; i < shapeSize; i++) { + for (int j = 0; j < i; j++) { + _backBuffer[320 * (y + i) + (x + shapeSize + j - i)] = color1; + _frontBuffer[320 * (y + i) + (x + shapeSize + j - i)] = color1; + _backBuffer[320 * (y + i) + (x + shapeSize + j)] = color2; + _frontBuffer[320 * (y + i) + (x + shapeSize + j)] = color2; + _backBuffer[320 * (y + (2 * shapeSize - 1) - i) + (x + shapeSize + j - i)] = color1; + _frontBuffer[320 * (y + (2 * shapeSize - 1) - i) + (x + shapeSize + j - i)] = color1; + _backBuffer[320 * (y + (2 * shapeSize - 1) - i) + (x + shapeSize + j)] = color2; + _frontBuffer[320 * (y + (2 * shapeSize - 1) - i) + (x + shapeSize + j)] = color2; + } + } +} + +void Screen::drawRectangle(bool filledFl, uint16 x1, uint16 y1, uint16 x2, uint16 y2, int color) { + assert(x1 <= x2); + assert(y1 <= y2); + + if (filledFl) { + for (int i = y1; i < y2; i++) { + for (int j = x1; j < x2; j++) { + _backBuffer[320 * i + j] = color; + _frontBuffer[320 * i + j] = color; + } + } + } else { + warning("STUB: drawRectangle()"); + } +} + +// Initialize screen components and display results +void Screen::initNewScreenDisplay() { + displayList(D_INIT); + setBackgroundColor(_TBLACK); + displayBackground(); + + // Stop premature object display in Display_list(D_DISPLAY) + _vm->getGameStatus().newScreenFl = true; +} } // End of namespace Hugo + diff --git a/engines/hugo/display.h b/engines/hugo/display.h index 5062664c186..d56f3e55aa3 100644 --- a/engines/hugo/display.h +++ b/engines/hugo/display.h @@ -32,58 +32,76 @@ #ifndef HUGO_DISPLAY_H #define HUGO_DISPLAY_H -namespace Hugo { -enum overlayState_t {UNDEF, FG, BG}; // Overlay state -struct rect_t; +namespace Hugo { +#define shapeSize 24 + +enum overlayState_t {UNDEF, FG, BG}; // Overlay state +struct rect_t { // Rectangle used in Display list + int16 x; // Position in dib + int16 y; // Position in dib + int16 dx; // width + int16 dy; // height +}; class Screen { public: - Screen(HugoEngine &vm); + Screen(HugoEngine *vm); + virtual ~Screen(); + + virtual void loadFont(int16 fontId) = 0; int16 fontHeight(); - int16 stringLength(char *s); + int16 stringLength(const char *s); void displayBackground(); void displayFrame(int sx, int sy, seq_t *seq, bool foreFl); void displayList(dupdate_t update, ...); void displayRect(int16 x, int16 y, int16 dx, int16 dy); + void drawRectangle(bool filledFl, uint16 x1, uint16 y1, uint16 x2, uint16 y2, int color); + void drawShape(int x, int y, int color1, int color2); + void drawStatusText(); void initDisplay(); - void loadFont(int16 fontId); + void initNewScreenDisplay(); void moveImage(image_pt srcImage, uint16 x1, uint16 y1, uint16 dx, uint16 dy, uint16 width1, image_pt dstImage, uint16 x2, uint16 y2, uint16 width2); void remapPal(uint16 oldIndex, uint16 newIndex); void restorePal(Common::SeekableReadStream *f); void savePal(Common::WriteStream *f); void setBackgroundColor(long color); - void shadowStr(int16 sx, int16 sy, char *s, byte color); + void shadowStr(int16 sx, int16 sy, const char *s, byte color); void userHelp(); - void writeChar(int16 x, int16 y, char c, byte color); - void writeStr(int16 sx, int16 sy, char *s, byte color); + void writeChr(int sx, int sy, byte color, char *local_fontdata); + void writeStr(int16 sx, int16 sy, const char *s, byte color); icondib_t &getIconBuffer() { return _iconBuffer; } + viewdib_t &getBackBuffer() { return _backBuffer; } + viewdib_t &getBackBufferBackup() { return _backBufferBackup; } + viewdib_t &getFrontBuffer() { return _frontBuffer; } + viewdib_t &getGUIBuffer() { return _GUIBuffer; } -private: - HugoEngine &_vm; +protected: + HugoEngine *_vm; // Fonts used in dib (non-GDI) byte _fnt; // Current font number byte _fontdata[NUM_FONTS][FONTSIZE]; // Font data byte *_font[NUM_FONTS][FONT_LEN]; // Ptrs to each char +private: viewdib_t _frontBuffer; viewdib_t _backBuffer; viewdib_t _GUIBuffer; // User interface images @@ -94,8 +112,23 @@ private: overlayState_t findOvl(seq_t *seq_p, image_pt dst_p, uint16 y); void merge(rect_t *rectA, rect_t *rectB); int16 mergeLists(rect_t *list, rect_t *blist, int16 len, int16 blen, int16 bmax); - void writeChr(int sx, int sy, byte color, char *local_fontdata); - int16 center(char *s); + int16 center(const char *s); +}; + +class Screen_v1d : public Screen { +public: + Screen_v1d(HugoEngine *vm); + ~Screen_v1d(); + + void loadFont(int16 fontId); +}; + +class Screen_v1w : public Screen { +public: + Screen_v1w(HugoEngine *vm); + ~Screen_v1w(); + + void loadFont(int16 fontId); }; } // End of namespace Hugo diff --git a/engines/hugo/display_v1d.cpp b/engines/hugo/display_v1d.cpp new file mode 100644 index 00000000000..a46f5a8bec0 --- /dev/null +++ b/engines/hugo/display_v1d.cpp @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// Display.c - DIB related code for HUGOWIN + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/display.h" +#include "hugo/util.h" + +namespace Hugo { + +Screen_v1d::Screen_v1d(HugoEngine *vm) : Screen(vm) { +} + +Screen_v1d::~Screen_v1d() { +} + +// Load font file, construct font ptrs and reverse data bytes +// TODO: This uses hardcoded fonts in hugo.dat, it should be replaced +// by a proper implementation of .FON files +void Screen_v1d::loadFont(int16 fontId) { + debugC(2, kDebugDisplay, "loadFont(%d)", fontId); + + static bool fontLoadedFl[NUM_FONTS] = {false, false, false}; + + _fnt = fontId - FIRST_FONT; // Set current font number + + if (fontLoadedFl[_fnt]) // If already loaded, return + return; + + fontLoadedFl[_fnt] = true; + + memcpy(_fontdata[_fnt], _vm->_arrayFont[_fnt], _vm->_arrayFontSize[_fnt]); + _font[_fnt][0] = _fontdata[_fnt]; // Store height,width of fonts + + int16 offset = 2; // Start at fontdata[2] ([0],[1] used for height,width) + + // Setup the font array (127 characters) + for (int i = 1; i < 128; i++) { + _font[_fnt][i] = _fontdata[_fnt] + offset; + byte height = *(_fontdata[_fnt] + offset); + byte width = *(_fontdata[_fnt] + offset + 1); + + int16 size = height * ((width + 7) >> 3); + for (int j = 0; j < size; j++) + Utils::reverseByte(&_fontdata[_fnt][offset + 2 + j]); + + offset += 2 + size; + } +} +} // End of namespace Hugo + diff --git a/engines/hugo/display_v1w.cpp b/engines/hugo/display_v1w.cpp new file mode 100644 index 00000000000..3dd8328c43a --- /dev/null +++ b/engines/hugo/display_v1w.cpp @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// Display.c - DIB related code for HUGOWIN + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/display.h" +#include "hugo/file.h" +#include "hugo/util.h" + +namespace Hugo { + +Screen_v1w::Screen_v1w(HugoEngine *vm) : Screen(vm) { +} + +Screen_v1w::~Screen_v1w() { +} + +// Load font file, construct font ptrs and reverse data bytes +void Screen_v1w::loadFont(int16 fontId) { + debugC(2, kDebugDisplay, "loadFont(%d)", fontId); + + static bool fontLoadedFl[NUM_FONTS] = {false, false, false}; + + _fnt = fontId - FIRST_FONT; // Set current font number + + if (fontLoadedFl[_fnt]) // If already loaded, return + return; + + fontLoadedFl[_fnt] = true; + _vm->_file->readUIFItem(fontId, _fontdata[_fnt]); + + // Compile font ptrs. Note: First ptr points to height,width of font + _font[_fnt][0] = _fontdata[_fnt]; // Store height,width of fonts + + int16 offset = 2; // Start at fontdata[2] ([0],[1] used for height,width) + + // Setup the font array (127 characters) + for (int i = 1; i < 128; i++) { + _font[_fnt][i] = _fontdata[_fnt] + offset; + byte height = *(_fontdata[_fnt] + offset); + byte width = *(_fontdata[_fnt] + offset + 1); + + int16 size = height * ((width + 7) >> 3); + for (int j = 0; j < size; j++) + Utils::reverseByte(&_fontdata[_fnt][offset + 2 + j]); + + offset += 2 + size; + } +} +} // End of namespace Hugo + diff --git a/engines/hugo/engine.cpp b/engines/hugo/engine.cpp deleted file mode 100644 index ab31f5da932..00000000000 --- a/engines/hugo/engine.cpp +++ /dev/null @@ -1,973 +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$ - * - */ - -/* - * This code is based on original Hugo 1-3 Trilogy source code - * - * Copyright (c) 1989-1995 David P. Gray - * - */ - -#include "common/system.h" -#include "common/random.h" -#include "common/EventRecorder.h" - -#include "hugo/game.h" -#include "hugo/hugo.h" -#include "hugo/engine.h" -#include "hugo/global.h" -#include "hugo/file.h" -#include "hugo/schedule.h" -#include "hugo/display.h" -#include "hugo/parser.h" -#include "hugo/route.h" -#include "hugo/util.h" -#include "hugo/sound.h" - -namespace Hugo { - -#define EDGE 10 // Closest object can get to edge of screen -#define EDGE2 (EDGE * 2) // Push object further back on edge collision -#define SHIFT 8 // Place hero this far inside bounding box -#define MAX_OBJECTS 128 // Used in Update_images() -#define BOUND(X, Y) ((_boundary[Y * XBYTES + X / 8] & (0x80 >> X % 8)) != 0) // Boundary bit set - -config_t _config; // User's config -maze_t _maze = {false, 0, 0, 0, 0, 0, 0, 0, 0}; // Default to not in maze -hugo_boot_t _boot; // Boot info structure file -char _textBoxBuffer[MAX_BOX]; // Buffer for text box -command_t _line = ""; // Line of user text input - - -// Sets the playlist to be the default tune selection -void HugoEngine::initPlaylist(bool playlist[MAX_TUNES]) { - debugC(1, kDebugEngine, "initPlaylist"); - - for (int16 i = 0; i < MAX_TUNES; i++) - playlist[i] = false; - for (int16 i = 0; _defltTunes[i] != -1; i++) - playlist[_defltTunes[i]] = true; -} - -// Initialize the dynamic game status -void HugoEngine::initStatus() { - debugC(1, kDebugEngine, "initStatus"); - _status.initSaveFl = false; // Don't force initial save - _status.storyModeFl = false; // Not in story mode - _status.gameOverFl = false; // Hero not knobbled yet - _status.recordFl = false; // Not record mode - _status.playbackFl = false; // Not playback mode - _status.demoFl = false; // Not demo mode - _status.textBoxFl = false; // Not processing a text box -// Strangerke - Not used ? -// _status.mmtime = false; // Multimedia timer support - _status.lookFl = false; // Toolbar "look" button - _status.recallFl = false; // Toolbar "recall" button - _status.leftButtonFl = false; // Left mouse button pressed - _status.rightButtonFl = false; // Right mouse button pressed - _status.newScreenFl = false; // Screen not just loaded - _status.jumpExitFl = false; // Can't jump to a screen exit - _status.godModeFl = false; // No special cheats allowed - _status.helpFl = false; // Not calling WinHelp() - _status.path[0] = 0; // Path to write files - _status.saveSlot = 0; // Slot to save/restore game - _status.screenWidth = 0; // Desktop screen width - - // Initialize every start of new game - _status.tick = 0; // Tick count - _status.saveTick = 0; // Time of last save - _status.viewState = V_IDLE; // View state - _status.inventoryState = I_OFF; // Inventory icon bar state - _status.inventoryHeight = 0; // Inventory icon bar pos - _status.inventoryObjId = -1; // Inventory object selected (none) - _status.routeIndex = -1; // Hero not following a route - _status.go_for = GO_SPACE; // Hero walking to space - _status.go_id = -1; // Hero not walking to anything -} - -// Initialize default config values. Must be done before Initialize(). -// Reset needed to save config.cx,cy which get splatted during OnFileNew() -void HugoEngine::initConfig(inst_t action) { - static int16 cx, cy; // Save window size, pos - int16 i; - - debugC(1, kDebugEngine, "initConfig(%d)", action); - - switch (action) { - case INSTALL: - _config.musicFl = true; // Music state initially on - _config.soundFl = true; // Sound state initially on - _config.turboFl = false; // Turbo state initially off - _config.backgroundMusicFl = false; // No music when inactive - _config.cx = VIEW_DX * 2; // Window view size - _config.cy = VIEW_DY * 2; - - _config.musicVolume = 85; // Music volume % - _config.soundVolume = 100; // Sound volume % - initPlaylist(_config.playlist); // Initialize default tune playlist - - file().readBootFile(); // Read startup structure - - cx = _config.cx; // Save these around OnFileNew() - cy = _config.cy; - break; - case RESET: - _config.cx = cx; // Restore cx, cy - _config.cy = cy; - - // Find first tune and play it - for (i = 0; i < MAX_TUNES; i++) - if (_config.playlist[i]) { - sound().playMusic(i); - break; - } - - file().initSavedGame(); // Initialize saved game - break; - case RESTORE: - warning("Unhandled action RESTORE"); - break; - } -} -void HugoEngine::initialize() { - debugC(1, kDebugEngine, "initialize"); - - sound().initSound(); - scheduler().initEventQueue(); // Init scheduler stuff - screen().initDisplay(); // Create Dibs and palette - file().openDatabaseFiles(); // Open database files - calcMaxScore(); // Initialise maxscore - - _rnd = new Common::RandomSource(); - g_eventRec.registerRandomSource(*_rnd, "hugo"); - - _rnd->setSeed(42); // Kick random number generator - - switch (getGameType()) { - case kGameTypeHugo1: - _episode = "\"HUGO'S HOUSE OF HORRORS\""; - _picDir = ""; - break; - case kGameTypeHugo2: - _episode = "\"Hugo's Mystery Adventure\""; - _picDir = "hugo2/"; - break; - case kGameTypeHugo3: - _episode = "\"Hugo's Amazon Adventure\""; - _picDir = "hugo3/"; - break; - default: - error("Unknown game"); - } -} - -// Restore all resources before termination -void HugoEngine::shutdown() { - debugC(1, kDebugEngine, "shutdown"); - - file().closeDatabaseFiles(); - if (_status.recordFl || _status.playbackFl) - file().closePlaybackFile(); - freeObjects(); -} - -void HugoEngine::readObjectImages() { - debugC(1, kDebugEngine, "readObjectImages"); - - for (int i = 0; i < _numObj; i++) - file().readImage(i, &_objects[i]); -} - -// Read the uif image file (inventory icons) -void HugoEngine::readUIFImages() { - debugC(1, kDebugEngine, "readUIFImages"); - - file().readUIFItem(UIF_IMAGES, screen().getGUIBuffer()); // Read all uif images -} - -// Read scenery, overlay files for given screen number -void HugoEngine::readScreenFiles(int screenNum) { - debugC(1, kDebugEngine, "readScreenFiles(%d)", screenNum); - - file().readBackground(screenNum); // Scenery file - memcpy(screen().getBackBuffer(), screen().getFrontBuffer(), sizeof(screen().getFrontBuffer()));// Make a copy - file().readOverlay(screenNum, _boundary, BOUNDARY); // Boundary file - file().readOverlay(screenNum, _overlay, OVERLAY); // Overlay file - file().readOverlay(screenNum, _ovlBase, OVLBASE); // Overlay base file -} - -// Update all object positions. Process object 'local' events -// including boundary events and collisions -void HugoEngine::moveObjects() { - object_t *obj; - seq_t *currImage; - int x1, x2, y1, y2; // object coordinates - int dx, dy; // Allowable motion wrt boundary - int8 radius; // Radius for chase (8 bit signed) - - debugC(4, kDebugEngine, "moveObjects"); - - // If route mode enabled, do special route processing - if (_status.routeIndex >= 0) - route().processRoute(); - - // Perform any adjustments to velocity based on special path types - // and store all (visible) object baselines into the boundary file. - // Don't store foreground or background objects - for (int i = 0; i < _numObj; i++) { - obj = &_objects[i]; // Get pointer to object - currImage = obj->currImagePtr; // Get ptr to current image - if (obj->screenIndex == *_screen_p) { - switch (obj->pathType) { - case CHASE: - case CHASE2: - radius = obj->radius; // Default to object's radius - if (radius < 0) // If radius infinity, use closer value - radius = DX; - - dx = _hero->x + _hero->currImagePtr->x1 - obj->x - currImage->x1; - dy = _hero->y + _hero->currImagePtr->y2 - obj->y - currImage->y2 - 1; - if (abs(dx) <= radius) - obj->vx = 0; - else - obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath); - if (abs(dy) <= radius) - obj->vy = 0; - else - obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath); - - // Set first image in sequence (if multi-seq object) - switch (obj->seqNumb) { - case 4: - if (!obj->vx) { // Got 4 directions - if (obj->vx != obj->oldvx) { // vx just stopped - if (dy >= 0) - obj->currImagePtr = obj->seqList[DOWN].seqPtr; - else - obj->currImagePtr = obj->seqList[_UP].seqPtr; - } - } else if (obj->vx != obj->oldvx) { - if (dx > 0) - obj->currImagePtr = obj->seqList[RIGHT].seqPtr; - else - obj->currImagePtr = obj->seqList[LEFT].seqPtr; - } - break; - case 3: - case 2: - if (obj->vx != obj->oldvx) { // vx just stopped - if (dx > 0) // Left & right only - obj->currImagePtr = obj->seqList[RIGHT].seqPtr; - else - obj->currImagePtr = obj->seqList[LEFT].seqPtr; - } - break; - } - - if (obj->vx || obj->vy) - obj->cycling = CYCLE_FORWARD; - else { - obj->cycling = NOT_CYCLING; - boundaryCollision(obj); // Must have got hero! - } - obj->oldvx = obj->vx; - obj->oldvy = obj->vy; - currImage = obj->currImagePtr; // Get (new) ptr to current image - break; - case WANDER2: - case WANDER: - if (!_rnd->getRandomNumber(3 * NORMAL_TPS)) { // Kick on random interval - obj->vx = _rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath; - obj->vy = _rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath; - - // Set first image in sequence (if multi-seq object) - if (obj->seqNumb > 1) { - if (!obj->vx && (obj->seqNumb >= 4)) { - if (obj->vx != obj->oldvx) { // vx just stopped - if (obj->vy > 0) - obj->currImagePtr = obj->seqList[DOWN].seqPtr; - else - obj->currImagePtr = obj->seqList[_UP].seqPtr; - } - } else if (obj->vx != obj->oldvx) { - if (obj->vx > 0) - obj->currImagePtr = obj->seqList[RIGHT].seqPtr; - else - obj->currImagePtr = obj->seqList[LEFT].seqPtr; - } - } - obj->oldvx = obj->vx; - obj->oldvy = obj->vy; - currImage = obj->currImagePtr; // Get (new) ptr to current image - } - if (obj->vx || obj->vy) - obj->cycling = CYCLE_FORWARD; - break; - default: - ; // Really, nothing - } - // Store boundaries - if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2); - } - } - - // Move objects, allowing for boundaries - for (int i = 0; i < _numObj; i++) { - obj = &_objects[i]; // Get pointer to object - if ((obj->screenIndex == *_screen_p) && (obj->vx || obj->vy)) { - // Only process if it's moving - - // Do object movement. Delta_x,y return allowed movement in x,y - // to move as close to a boundary as possible without crossing it. - currImage = obj->currImagePtr; // Get ptr to current image - x1 = obj->x + currImage->x1; // Left edge of object - x2 = obj->x + currImage->x2; // Right edge - y1 = obj->y + currImage->y1; // Top edge - y2 = obj->y + currImage->y2; // Bottom edge - - if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - clearBoundary(x1, x2, y2); // Clear our own boundary - dx = deltaX(x1, x2, obj->vx, y2); - if (dx != obj->vx) { - // An object boundary collision! - boundaryCollision(obj); - obj->vx = 0; - } - - dy = deltaY(x1, x2, obj->vy, y2); - - if (dy != obj->vy) { - // An object boundary collision! - boundaryCollision(obj); - obj->vy = 0; - } - - if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - storeBoundary(x1, x2, y2); // Re-store our own boundary - - obj->x += dx; // Update object position - obj->y += dy; - - // Don't let object go outside screen - if (x1 < EDGE) - obj->x = EDGE2; - if (x2 > (XPIX - EDGE)) - obj->x = XPIX - EDGE2 - (x2 - x1); - if (y1 < EDGE) - obj->y = EDGE2; - if (y2 > (YPIX - EDGE)) - obj->y = YPIX - EDGE2 - (y2 - y1); - - if ((obj->vx == 0) && (obj->vy == 0) && (obj->pathType != WANDER2) && (obj->pathType != CHASE2)) - obj->cycling = NOT_CYCLING; - } - } - - // Clear all object baselines from the boundary file. - for (int i = 0; i < _numObj; i++) { - obj = &_objects[i]; // Get pointer to object - currImage = obj->currImagePtr; // Get ptr to current image - if ((obj->screenIndex == *_screen_p) && (obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) - clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2); - } - - // If maze mode is enabled, do special maze processing - if (_maze.enabledFl) - processMaze(); -} - -// Return maximum allowed movement (from zero to vx) such that object does -// not cross a boundary (either background or another object) -int HugoEngine::deltaX(int x1, int x2, int vx, int y) { -// Explanation of algorithm: The boundaries are drawn as contiguous -// lines 1 pixel wide. Since DX,DY are not necessarily 1, we must -// detect boundary crossing. If vx positive, examine each pixel from -// x1 old to x2 new, else x2 old to x1 new, both at the y2 line. -// If vx zero, no need to check. If vy non-zero then examine each -// pixel on the line segment x1 to x2 from y old to y new. -// Fix from Hugo I v1.5: -// Note the diff is munged in the return statement to cater for a special -// cases arising from differences in image widths from one sequence to -// another. The problem occurs reversing direction at a wall where the -// new image intersects before the object can move away. This is cured -// by comparing the intersection with half the object width pos. If the -// intersection is in the other half wrt the intended direction, use the -// desired vx, else use the computed delta. i.e. believe the desired vx - int b; - - debugC(3, kDebugEngine, "deltaX(%d, %d, %d, %d)", x1, x2, vx, y); - - if (vx == 0) - return(0); // Object stationary - - y *= XBYTES; // Offset into boundary file - if (vx > 0) { - // Moving to right - for (int i = x1 >> 3; i <= (x2 + vx) >> 3; i++) // Search by byte - if ((b = Utils::firstBit((byte)(_boundary[y + i] | _objBound[y + i]))) < 8) { // b is index or 8 - // Compute x of boundary and test if intersection - b += i << 3; - if ((b >= x1) && (b <= x2 + vx)) - return((b < x1 + ((x2 - x1) >> 1)) ? vx : b - x2 - 1); // return dx - } - } else { - // Moving to left - for (int i = x2 >> 3; i >= (x1 + vx) >> 3; i--)// Search by byte - if ((b = Utils::lastBit((byte)(_boundary[y + i] | _objBound[y + i]))) < 8) { // b is index or 8 - // Compute x of boundary and test if intersection - b += i << 3; - if ((b >= x1 + vx) && (b <= x2)) - return((b > x1 + ((x2 - x1) >> 1)) ? vx : b - x1 + 1); // return dx - } - } - return(vx); -} - -// Similar to Delta_x, but for movement in y direction. Special case of -// bytes at end of line segment; must only count boundary bits falling on -// line segment. -int HugoEngine::deltaY(int x1, int x2, int vy, int y) { - int inc, i, j, b; - - debugC(3, kDebugEngine, "deltaY(%d, %d, %d, %d)", x1, x2, vy, y); - - if (vy == 0) - return(0); // Object stationary - - inc = (vy > 0) ? 1 : -1; - for (j = y + inc; j != (y + vy + inc); j += inc) //Search by byte - for (i = x1 >> 3; i <= x2 >> 3; i++) - if ((b = _boundary[j * XBYTES + i] | _objBound[j * XBYTES + i]) != 0) { // Any bit set - // Make sure boundary bits fall on line segment - if (i == (x2 >> 3)) // Adjust right end - b &= 0xff << ((i << 3) + 7 - x2); - else if (i == (x1 >> 3)) // Adjust left end - b &= 0xff >> (x1 - (i << 3)); - if (b) - return(j - y - inc); - } - return(vy); -} - -// Store a horizontal line segment in the object boundary file -void HugoEngine::storeBoundary(int x1, int x2, int y) { - byte *b; // ptr to boundary byte - - debugC(5, kDebugEngine, "storeBoundary(%d, %d, %d)", x1, x2, y); - - for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line - b = &_objBound[y * XBYTES + i]; // get boundary byte - if (i == x2 >> 3) // Adjust right end - *b |= 0xff << ((i << 3) + 7 - x2); - else if (i == x1 >> 3) // Adjust left end - *b |= 0xff >> (x1 - (i << 3)); - else - *b = 0xff; - } -} - -// Clear a horizontal line segment in the object boundary file -void HugoEngine::clearBoundary(int x1, int x2, int y) { - int i; - byte *b; // ptr to boundary byte - - debugC(5, kDebugEngine, "clearBoundary(%d, %d, %d)", x1, x2, y); - - for (i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line - b = &_objBound[y * XBYTES + i]; // get boundary byte - if (i == x2 >> 3) // Adjust right end - *b &= ~(0xff << ((i << 3) + 7 - x2)); - else if (i == x1 >> 3) // Adjust left end - *b &= ~(0xff >> (x1 - (i << 3))); - else - *b = 0; - } -} - -// Maze mode is enabled. Check to see whether hero has crossed the maze -// bounding box, if so, go to the next room */ -void HugoEngine::processMaze() { - seq_t *currImage; - int x1, x2, y1, y2; // hero coordinates - - debugC(1, kDebugEngine, "processMaze"); - - currImage = _hero->currImagePtr; // Get ptr to current image - x1 = _hero->x + currImage->x1; // Left edge of object - x2 = _hero->x + currImage->x2; // Right edge - y1 = _hero->y + currImage->y1; // Top edge - y2 = _hero->y + currImage->y2; // Bottom edge - - if (x1 < _maze.x1) { - // Exit west - _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p - 1; - _actListArr[_alNewscrIndex][0].a2.x = _maze.x2 - SHIFT - (x2 - x1); - _actListArr[_alNewscrIndex][0].a2.y = _hero->y; - _status.routeIndex = -1; - scheduler().insertActionList(_alNewscrIndex); - } else if (x2 > _maze.x2) { - // Exit east - _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p + 1; - _actListArr[_alNewscrIndex][0].a2.x = _maze.x1 + SHIFT; - _actListArr[_alNewscrIndex][0].a2.y = _hero->y; - _status.routeIndex = -1; - scheduler().insertActionList(_alNewscrIndex); - } else if (y1 < _maze.y1 - SHIFT) { - // Exit north - _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p - _maze.size; - _actListArr[_alNewscrIndex][0].a2.x = _maze.x3; - _actListArr[_alNewscrIndex][0].a2.y = _maze.y2 - SHIFT - (y2 - y1); - _status.routeIndex = -1; - scheduler().insertActionList(_alNewscrIndex); - } else if (y2 > _maze.y2 - SHIFT / 2) { - // Exit south - _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p + _maze.size; - _actListArr[_alNewscrIndex][0].a2.x = _maze.x4; - _actListArr[_alNewscrIndex][0].a2.y = _maze.y1 + SHIFT; - _status.routeIndex = -1; - scheduler().insertActionList(_alNewscrIndex); - } -} - -// Compare function for the quicksort. The sort is to order the objects in -// increasing vertical position, using y+y2 as the baseline -// Returns -1 if ay2 < by2 else 1 if ay2 > by2 else 0 -int HugoEngine::y2comp(const void *a, const void *b) { - int ay2, by2; - - debugC(6, kDebugEngine, "y2comp"); - - const object_t *p1 = &s_Engine->_objects[*(const byte *)a]; - const object_t *p2 = &s_Engine->_objects[*(const byte *)b]; - - if (p1 == p2) - // Why does qsort try the same indexes? - return (0); - - if (p1->priority == BACKGROUND) - return (-1); - - if (p2->priority == BACKGROUND) - return (1); - - if (p1->priority == FOREGROUND) - return (1); - - if (p2->priority == FOREGROUND) - return (-1); - - ay2 = p1->y + p1->currImagePtr->y2; - by2 = p2->y + p2->currImagePtr->y2; - - return(ay2 - by2); -} - -// Draw all objects on screen as follows: -// 1. Sort 'FLOATING' objects in order of y2 (base of object) -// 2. Display new object frames/positions in dib -// Finally, cycle any animating objects to next frame -void HugoEngine::updateImages() { - int i, j, num_objs; - object_t *obj; // Pointer to object - seq_t *seqPtr; // Save curr_seq_p - byte objindex[MAX_OBJECTS]; // Array of indeces to objects - - debugC(5, kDebugEngine, "updateImages"); - - // Initialise the index array to visible objects in current screen - for (i = 0, num_objs = 0; i < _numObj; i++) { - obj = &_objects[i]; - if ((obj->screenIndex == *_screen_p) && (obj->cycling >= ALMOST_INVISIBLE)) - objindex[num_objs++] = i; - } - - // Sort the objects into increasing y+y2 (painter's algorithm) - qsort(objindex, num_objs, sizeof(objindex[0]), y2comp); - - // Add each visible object to display list - for (i = 0; i < num_objs; i++) { - obj = &_objects[objindex[i]]; - // Count down inter-frame timer - if (obj->frameTimer) - obj->frameTimer--; - - if (obj->cycling > ALMOST_INVISIBLE) // Only if visible - switch (obj->cycling) { - case NOT_CYCLING: - screen().displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); - break; - case CYCLE_FORWARD: - if (obj->frameTimer) // Not time to see next frame yet - screen().displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); - else - screen().displayFrame(obj->x, obj->y, obj->currImagePtr->nextSeqPtr, obj->priority == OVEROVL); - break; - case CYCLE_BACKWARD: - seqPtr = obj->currImagePtr; - if (!obj->frameTimer) // Show next frame - while (seqPtr->nextSeqPtr != obj->currImagePtr) - seqPtr = seqPtr->nextSeqPtr; - screen().displayFrame(obj->x, obj->y, seqPtr, obj->priority == OVEROVL); - break; - default: - break; - } - } - - // Cycle any animating objects - for (i = 0; i < num_objs; i++) { - obj = &_objects[objindex[i]]; - if (obj->cycling != INVISIBLE) { - // Only if it's visible - if (obj->cycling == ALMOST_INVISIBLE) - obj->cycling = INVISIBLE; - - // Now Rotate to next picture in sequence - switch (obj->cycling) { - case NOT_CYCLING: - break; - case CYCLE_FORWARD: - if (!obj->frameTimer) { - // Time to step to next frame - obj->currImagePtr = obj->currImagePtr->nextSeqPtr; - // Find out if this is last frame of sequence - // If so, reset frame_timer and decrement n_cycle - if (obj->frameInterval || obj->cycleNumb) { - obj->frameTimer = obj->frameInterval; - for (j = 0; j < obj->seqNumb; j++) - if (obj->currImagePtr->nextSeqPtr == obj->seqList[j].seqPtr) - if (obj->cycleNumb) // Decr cycleNumb if Non-continous - if (!--obj->cycleNumb) - obj->cycling = NOT_CYCLING; - } - } - break; - case CYCLE_BACKWARD: - if (!obj->frameTimer) { - // Time to step to prev frame - seqPtr = obj->currImagePtr; - while (obj->currImagePtr->nextSeqPtr != seqPtr) - obj->currImagePtr = obj->currImagePtr->nextSeqPtr; - // Find out if this is first frame of sequence - // If so, reset frame_timer and decrement n_cycle - if (obj->frameInterval || obj->cycleNumb) { - obj->frameTimer = obj->frameInterval; - for (j = 0; j < obj->seqNumb; j++) - if (obj->currImagePtr == obj->seqList[j].seqPtr) - if (obj->cycleNumb) // Decr cycleNumb if Non-continous - if (!--obj->cycleNumb) - obj->cycling = NOT_CYCLING; - } - } - break; - default: - break; - } - obj->oldx = obj->x; - obj->oldy = obj->y; - } - } -} - -// Return object index of the topmost object under the cursor, or -1 if none -// Objects are filtered if not "useful" -int16 HugoEngine::findObject(uint16 x, uint16 y) { - object_t *obj; - seq_t *curImage; - int16 objIndex = -1; // Index of found object - uint16 y2Max = 0; // Greatest y2 - int i; - - debugC(3, kDebugEngine, "findObject(%d, %d)", x, y); - - // Check objects on screen - for (i = 0, obj = _objects; i < _numObj; i++, obj++) { - // Object must be in current screen and "useful" - if (obj->screenIndex == *_screen_p && (obj->genericCmd || obj->objValue || obj->cmdIndex)) { - curImage = obj->currImagePtr; - // Object must have a visible image... - if (curImage != NULL && obj->cycling != INVISIBLE) { - // If cursor inside object - if (x >= (uint16)obj->x && x <= obj->x + curImage->x2 && y >= (uint16)obj->y && y <= obj->y + curImage->y2) - // If object is closest so far - if (obj->y + curImage->y2 > y2Max) { - y2Max = obj->y + curImage->y2; - objIndex = i; // Found an object! - } - } else - // ...or a dummy object that has a hotspot rectangle - if (curImage == NULL && obj->vxPath != 0 && !obj->carriedFl) { - // If cursor inside special rectangle - if ((int16)x >= obj->oldx && (int16)x < obj->oldx + obj->vxPath && (int16)y >= obj->oldy && (int16)y < obj->oldy + obj->vyPath) - // If object is closest so far - if (obj->oldy + obj->vyPath - 1 > (int16)y2Max) { - y2Max = obj->oldy + obj->vyPath - 1; - objIndex = i; // Found an object! - } - } - } - } - return objIndex; -} - -// Find a clear space around supplied object that hero can walk to -bool HugoEngine::findObjectSpace(object_t *obj, int16 *destx, int16 *desty) { -// bool found = false; // TRUE if we found a clear space - bool foundFl; - seq_t *curImage = obj->currImagePtr; - int16 x; - int16 y = obj->y + curImage->y2 - 1; - - debugC(1, kDebugEngine, "findObjectSpace(obj, %d, %d)", *destx, *desty); - -// if (!found) // Try left rear corner - for (foundFl = true, *destx = x = obj->x + curImage->x1; x < *destx + HERO_MAX_WIDTH; x++) - if (BOUND(x, y)) - foundFl = false; - - if (!foundFl) // Try right rear corner - for (foundFl = true, *destx = x = obj->x + curImage->x2 - HERO_MAX_WIDTH + 1; x <= obj->x + (int16)curImage->x2; x++) - if (BOUND(x, y)) - foundFl = false; - - if (!foundFl) // Try left front corner - for (foundFl = true, y += 2, *destx = x = obj->x + curImage->x1; x < *destx + HERO_MAX_WIDTH; x++) - if (BOUND(x, y)) - foundFl = false; - - if (!foundFl) // Try right rear corner - for (foundFl = true, *destx = x = obj->x + curImage->x2 - HERO_MAX_WIDTH + 1; x <= obj->x + (int16)curImage->x2; x++) - if (BOUND(x, y)) - foundFl = false; - - *desty = y; - return(foundFl); -} - -// Search background command list for this screen for supplied object. -// Return first associated verb (not "look") or NULL if none found. -char *HugoEngine::useBG(char *name) { - int i; - objectList_t p = _backgroundObjects[*_screen_p]; - - debugC(1, kDebugEngine, "useBG(%s)", name); - - for (i = 0; *_arrayVerbs[p[i].verbIndex]; i++) - if ((name == _arrayNouns[p[i].nounIndex][0] && - p[i].verbIndex != _look) && - ((p[i].roomState == DONT_CARE) || (p[i].roomState == _screenStates[*_screen_p]))) - return (_arrayVerbs[p[i].verbIndex][0]); - - return (NULL); -} - -// If status.objid = -1, pick up objid, else use status.objid on objid, -// if objid can't be picked up, use it directly -void HugoEngine::useObject(int16 objId) { - object_t *obj = &_objects[objId]; // Ptr to object - uses_t *use; // Ptr to use entry - target_t *target; // Ptr to target entry - bool foundFl; // TRUE if found target entry - char *verb; // Background verb to use directly - - debugC(1, kDebugEngine, "useObject(%d)", objId); - - if (_status.inventoryObjId == -1) { - // Get or use objid directly - if ((obj->genericCmd & TAKE) || obj->objValue) // Get collectible item - sprintf(_line, "%s %s", _arrayVerbs[_take][0], _arrayNouns[obj->nounIndex][0]); - else if (obj->cmdIndex != 0) // Use non-collectible item if able - sprintf(_line, "%s %s", _arrayVerbs[_cmdList[obj->cmdIndex][1].verbIndex][0], _arrayNouns[obj->nounIndex][0]); - else if ((verb = useBG(_arrayNouns[obj->nounIndex][0])) != NULL) - sprintf(_line, "%s %s", verb, _arrayNouns[obj->nounIndex][0]); - else - return; // Can't use object directly - } else { - // Use status.objid on objid - // Default to first cmd verb - sprintf(_line, "%s %s %s", _arrayVerbs[_cmdList[_objects[_status.inventoryObjId].cmdIndex][1].verbIndex][0], _arrayNouns[_objects[_status.inventoryObjId].nounIndex][0], _arrayNouns[obj->nounIndex][0]); - - // Check valid use of objects and override verb if necessary - for (use = _uses; use->objId != _numObj; use++) - if (_status.inventoryObjId == use->objId) { - // Look for secondary object, if found use matching verb - for (foundFl = false, target = use->targets; _arrayNouns[target->nounIndex] != NULL; target++) - if (_arrayNouns[target->nounIndex][0] == _arrayNouns[obj->nounIndex][0]) { - foundFl = true; - sprintf(_line, "%s %s %s", _arrayVerbs[target->verbIndex][0], _arrayNouns[_objects[_status.inventoryObjId].nounIndex][0], _arrayNouns[obj->nounIndex][0]); - } - - // No valid use of objects found, print failure string - if (!foundFl) { - // Deselect dragged icon if inventory not active - if (_status.inventoryState != I_ACTIVE) - _status.inventoryObjId = -1; - Utils::Box(BOX_ANY, "%s", _textData[use->dataIndex]); - return; - } - } - } - - if (_status.inventoryState == I_ACTIVE) // If inventory active, remove it - _status.inventoryState = I_UP; - _status.inventoryObjId = -1; // Deselect any dragged icon - parser().lineHandler(); // and process command -} - -// Issue "Look at " command -// Note special case of swapped hero image -void HugoEngine::lookObject(object_t *obj) { - debugC(1, kDebugEngine, "lookObject"); - - if (obj == _hero) { - // Hero swapped - look at other - obj = &_objects[_heroImage]; - } - parser().command("%s %s", _arrayVerbs[_look][0], _arrayNouns[obj->nounIndex][0]); -} - -// Free all object images -void HugoEngine::freeObjects() { - object_t *obj; - seq_t *seq; - - debugC(1, kDebugEngine, "freeObjects"); - - // Nothing to do if not allocated yet - if (_hero->seqList[0].seqPtr == NULL) - return; - - // Free all sequence lists and image data - for (int i = 0; i < _numObj; i++) { - obj = &_objects[i]; - for (int j = 0; j < obj->seqNumb; j++) { // for each sequence - seq = obj->seqList[j].seqPtr; // Free image - if (seq == NULL) // Failure during database load - break; - do { - free(seq->imagePtr); - seq = seq->nextSeqPtr; - } while (seq != obj->seqList[j].seqPtr); - free(seq); // Free sequence record - } - } -} - -// Add action lists for this screen to event queue -void HugoEngine::screenActions(int screenNum) { - uint16 *screenAct = _screenActs[screenNum]; - - debugC(1, kDebugEngine, "screenActions(%d)", screenNum); - - if (screenAct) { - for (int i = 0; screenAct[i]; i++) - scheduler().insertActionList(screenAct[i]); - } -} - -// Set the new screen number into the hero object and any carried objects -void HugoEngine::setNewScreen(int screenNum) { - debugC(1, kDebugEngine, "setNewScreen(%d)", screenNum); - - *_screen_p = screenNum; // HERO object - for (int i = HERO + 1; i < _numObj; i++) // Any others - if (_objects[i].carriedFl) // being carried - _objects[i].screenIndex = screenNum; -} - -// An object has collided with a boundary. See if any actions are required -void HugoEngine::boundaryCollision(object_t *obj) { - int x, y, dx, dy; - int8 radius; // 8 bits signed - hotspot_t *hotspot; - - debugC(1, kDebugEngine, "boundaryCollision"); - - if (obj == _hero) { - // Hotspots only relevant to HERO - if (obj->vx > 0) - x = obj->x + obj->currImagePtr->x2; - else - x = obj->x + obj->currImagePtr->x1; - y = obj->y + obj->currImagePtr->y2; - - for (int i = 0; _hotspots[i].screenIndex >= 0; i++) { - hotspot = &_hotspots[i]; - if (hotspot->screenIndex == obj->screenIndex) - if ((x >= hotspot->x1) && (x <= hotspot->x2) && (y >= hotspot->y1) && (y <= hotspot->y2)) { - scheduler().insertActionList(hotspot->actIndex); - break; - } - } - } else { - // Check whether an object collided with HERO - dx = _hero->x + _hero->currImagePtr->x1 - obj->x - obj->currImagePtr->x1; - dy = _hero->y + _hero->currImagePtr->y2 - obj->y - obj->currImagePtr->y2; - // If object's radius is infinity, use a closer value - radius = obj->radius; - if (radius < 0) - radius = DX * 2; - if ((abs(dx) <= radius) && (abs(dy) <= radius)) - scheduler().insertActionList(obj->actIndex); - } -} - -// Initialize screen components and display results -void HugoEngine::initNewScreenDisplay() { - debugC(1, kDebugEngine, "initNewScreenDisplay"); - - screen().displayList(D_INIT); - screen().setBackgroundColor(_TBLACK); - screen().displayBackground(); - - // Stop premature object display in Display_list(D_DISPLAY) - _status.newScreenFl = true; -} - -// Add up all the object values and all the bonus points -void HugoEngine::calcMaxScore() { - int i; - - debugC(1, kDebugEngine, "calcMaxScore"); - - for (i = 0; i < _numObj; i++) - _maxscore += _objects[i].objValue; - - for (i = 0; i < _numBonuses; i++) - _maxscore += _points[i].score; -} - -// Exit game, advertise trilogy, show copyright -void HugoEngine::endGame() { - debugC(1, kDebugEngine, "endGame"); - - if (!_boot.registered) - Utils::Box(BOX_ANY, "%s", _textEngine[kEsAdvertise]); - Utils::Box(BOX_ANY, "%s\n%s", _episode, COPYRIGHT); - _status.viewState = V_EXIT; -} - -} // End of namespace Hugo diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp index 41eb3c88e4d..ebda0e9035e 100644 --- a/engines/hugo/file.cpp +++ b/engines/hugo/file.cpp @@ -31,19 +31,18 @@ */ #include "common/system.h" -#include "common/file.h" #include "common/savefile.h" -#include "hugo/game.h" #include "hugo/hugo.h" #include "hugo/file.h" #include "hugo/global.h" #include "hugo/schedule.h" #include "hugo/display.h" #include "hugo/util.h" +#include "hugo/object.h" namespace Hugo { -FileManager::FileManager(HugoEngine &vm) : _vm(vm) { +FileManager::FileManager(HugoEngine *vm) : _vm(vm) { } FileManager::~FileManager() { @@ -52,18 +51,17 @@ FileManager::~FileManager() { byte *FileManager::convertPCC(byte *p, uint16 y, uint16 bpl, image_pt dataPtr) { // Convert 4 planes (RGBI) data to 8-bit DIB format // Return original plane data ptr - uint16 r, g, b, i; // Byte index within each plane - int8 bit; // Bit index within a byte - debugC(2, kDebugFile, "convertPCC(byte *p, %d, %d, image_pt data_p)", y, bpl); dataPtr += y * bpl * 8; // Point to correct DIB line - for (r = 0, g = bpl, b = g + bpl, i = b + bpl; r < bpl; r++, g++, b++, i++) // Each byte in all planes - for (bit = 7; bit >= 0; bit--) // Each bit in byte + for (int16 r = 0, g = bpl, b = g + bpl, i = b + bpl; r < bpl; r++, g++, b++, i++) { // Each byte in all planes + for (int8 bit = 7; bit >= 0; bit--) { // Each bit in byte *dataPtr++ = (((p[r] >> bit & 1) << 0) | ((p[g] >> bit & 1) << 1) | ((p[b] >> bit & 1) << 2) | ((p[i] >> bit & 1) << 3)); + } + } return p; } @@ -71,28 +69,10 @@ seq_t *FileManager::readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool // Read a pcx file of length len. Use supplied seq_p and image_p or // allocate space if NULL. Name used for errors. Returns address of seq_p // Set first TRUE to initialize b_index (i.e. not reading a sequential image in file). - - struct { // Structure of PCX file header - byte mfctr, vers, enc, bpx; - uint16 x1, y1, x2, y2; // bounding box - uint16 xres, yres; - byte palette[48]; // EGA color palette - byte vmode, planes; - uint16 bytesPerLine; // Bytes per line - byte fill2[60]; - } PCC_header; // Header of a PCC file - - byte c, d; // code and data bytes from PCX file - byte pline[XPIX]; // Hold 4 planes of data - byte *p = pline; // Ptr to above - byte i; // PCX repeat count - uint16 bytesPerLine4; // BPL in 4-bit format - uint16 size; // Size of image - uint16 y = 0; // Current line index - debugC(1, kDebugFile, "readPCX(..., %s)", name); // Read in the PCC header and check consistency + static PCC_header_t PCC_header; PCC_header.mfctr = f.readByte(); PCC_header.vers = f.readByte(); PCC_header.enc = f.readByte(); @@ -112,31 +92,38 @@ seq_t *FileManager::readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool if (PCC_header.mfctr != 10) Utils::Error(PCCH_ERR, "%s", name); - // Allocate memory for seq_t if NULL - if (seqPtr == NULL) - if ((seqPtr = (seq_t *)malloc(sizeof(seq_t))) == NULL) + // Allocate memory for seq_t if 0 + if (seqPtr == 0) { + if ((seqPtr = (seq_t *)malloc(sizeof(seq_t))) == 0) Utils::Error(HEAP_ERR, "%s", name); + } // Find size of image data in 8-bit DIB format // Note save of x2 - marks end of valid data before garbage - bytesPerLine4 = PCC_header.bytesPerLine * 4; // 4-bit bpl + uint16 bytesPerLine4 = PCC_header.bytesPerLine * 4; // 4-bit bpl seqPtr->bytesPerLine8 = bytesPerLine4 * 2; // 8-bit bpl seqPtr->lines = PCC_header.y2 - PCC_header.y1 + 1; seqPtr->x2 = PCC_header.x2 - PCC_header.x1 + 1; - size = seqPtr->lines * seqPtr->bytesPerLine8; + // Size of the image + uint16 size = seqPtr->lines * seqPtr->bytesPerLine8; // Allocate memory for image data if NULL - if (imagePtr == NULL) - if ((imagePtr = (byte *)malloc((size_t) size)) == NULL) + if (imagePtr == 0) { + if ((imagePtr = (byte *)malloc((size_t) size)) == 0) Utils::Error(HEAP_ERR, "%s", name); + } + seqPtr->imagePtr = imagePtr; // Process the image data, converting to 8-bit DIB format + uint16 y = 0; // Current line index + byte pline[XPIX]; // Hold 4 planes of data + byte *p = pline; // Ptr to above while (y < seqPtr->lines) { - c = f.readByte(); + byte c = f.readByte(); if ((c & REP_MASK) == REP_MASK) { - d = f.readByte(); // Read data byte - for (i = 0; i < (c & LEN_MASK); i++) { + byte d = f.readByte(); // Read data byte + for (int i = 0; i < (c & LEN_MASK); i++) { *p++ = d; if ((uint16)(p - pline) == bytesPerLine4) p = convertPCC(pline, y++, PCC_header.bytesPerLine, imagePtr); @@ -152,61 +139,59 @@ seq_t *FileManager::readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool void FileManager::readImage(int objNum, object_t *objPtr) { // Read object file of PCC images into object supplied - byte x, y, j, k; - uint16 x2; // Limit on x in image data - seq_t *seqPtr = 0; // Ptr to sequence structure - image_pt dibPtr; // Ptr to DIB data - objBlock_t objBlock; // Info on file within database - bool firstFl = true; // Initializes pcx read function - debugC(1, kDebugFile, "readImage(%d, object_t *objPtr)", objNum); if (!objPtr->seqNumb) // This object has no images return; - if (_vm.isPacked()) { + if (_vm->isPacked()) { _objectsArchive.seek((uint32)objNum * sizeof(objBlock_t), SEEK_SET); + objBlock_t objBlock; // Info on file within database objBlock.objOffset = _objectsArchive.readUint32LE(); objBlock.objLength = _objectsArchive.readUint32LE(); _objectsArchive.seek(objBlock.objOffset, SEEK_SET); } else { char *buf = (char *) malloc(2048 + 1); // Buffer for file access - strcat(strcat(strcpy(buf, _vm._picDir), _vm._arrayNouns[objPtr->nounIndex][0]), OBJEXT); + strcat(strcat(strcpy(buf, _vm->_picDir), _vm->_arrayNouns[objPtr->nounIndex][0]), OBJEXT); if (!_objectsArchive.open(buf)) { - warning("File %s not found, trying again with %s%s", buf, _vm._arrayNouns[objPtr->nounIndex][0], OBJEXT); - strcat(strcpy(buf, _vm._arrayNouns[objPtr->nounIndex][0]), OBJEXT); + warning("File %s not found, trying again with %s%s", buf, _vm->_arrayNouns[objPtr->nounIndex][0], OBJEXT); + strcat(strcpy(buf, _vm->_arrayNouns[objPtr->nounIndex][0]), OBJEXT); if (!_objectsArchive.open(buf)) Utils::Error(FILE_ERR, "%s", buf); } } + bool firstFl = true; // Initializes pcx read function + seq_t *seqPtr = 0; // Ptr to sequence structure + // Now read the images into an images list - for (j = 0; j < objPtr->seqNumb; j++) { // for each sequence - for (k = 0; k < objPtr->seqList[j].imageNbr; k++) { // each image + for (int j = 0; j < objPtr->seqNumb; j++) { // for each sequence + for (int k = 0; k < objPtr->seqList[j].imageNbr; k++) { // each image if (k == 0) { // First image // Read this image - allocate both seq and image memory - seqPtr = readPCX(_objectsArchive, NULL, NULL, firstFl, _vm._arrayNouns[objPtr->nounIndex][0]); + seqPtr = readPCX(_objectsArchive, 0, 0, firstFl, _vm->_arrayNouns[objPtr->nounIndex][0]); objPtr->seqList[j].seqPtr = seqPtr; firstFl = false; } else { // Subsequent image // Read this image - allocate both seq and image memory - seqPtr->nextSeqPtr = readPCX(_objectsArchive, NULL, NULL, firstFl, _vm._arrayNouns[objPtr->nounIndex][0]); + seqPtr->nextSeqPtr = readPCX(_objectsArchive, 0, 0, firstFl, _vm->_arrayNouns[objPtr->nounIndex][0]); seqPtr = seqPtr->nextSeqPtr; } // Compute the bounding box - x1, x2, y1, y2 // Note use of x2 - marks end of valid data in row - x2 = seqPtr->x2; + uint16 x2 = seqPtr->x2; seqPtr->x1 = seqPtr->x2; seqPtr->x2 = 0; seqPtr->y1 = seqPtr->lines; seqPtr->y2 = 0; - dibPtr = seqPtr->imagePtr; - for (y = 0; y < seqPtr->lines; y++, dibPtr += seqPtr->bytesPerLine8 - x2) - for (x = 0; x < x2; x++) - if (*dibPtr++) { // Some data found + + image_pt dibPtr = seqPtr->imagePtr; + for (int y = 0; y < seqPtr->lines; y++, dibPtr += seqPtr->bytesPerLine8 - x2) { + for (int x = 0; x < x2; x++) { + if (*dibPtr++) { // Some data found if (x < seqPtr->x1) seqPtr->x1 = x; if (x > seqPtr->x2) @@ -216,7 +201,10 @@ void FileManager::readImage(int objNum, object_t *objPtr) { if (y > seqPtr->y2) seqPtr->y2 = y; } + } + } } + assert(seqPtr); seqPtr->nextSeqPtr = objPtr->seqList[j].seqPtr; // loop linked list to head } @@ -231,36 +219,34 @@ void FileManager::readImage(int objNum, object_t *objPtr) { case CYCLE_BACKWARD: objPtr->currImagePtr = seqPtr; break; + default: + warning("Unexpected cycling: %d", objPtr->cycling); } - if (!_vm.isPacked()) + if (!_vm->isPacked()) _objectsArchive.close(); } sound_pt FileManager::getSound(int16 sound, uint16 *size) { // Read sound (or music) file data. Call with SILENCE to free-up // any allocated memory. Also returns size of data - - static sound_hdr_t s_hdr[MAX_SOUNDS]; // Sound lookup table - sound_pt soundPtr; // Ptr to sound data - Common::File fp; // Handle to SOUND_FILE -// bool music = sound < NUM_TUNES; // TRUE if music, else sound file - debugC(1, kDebugFile, "getSound(%d, %d)", sound, *size); // No more to do if SILENCE (called for cleanup purposes) - if (sound == _vm._soundSilence) - return(NULL); + if (sound == _vm->_soundSilence) + return 0; // Open sounds file + Common::File fp; // Handle to SOUND_FILE if (!fp.open(SOUND_FILE)) { -// Error(FILE_ERR, "%s", SOUND_FILE); warning("Hugo Error: File not found %s", SOUND_FILE); - return(NULL); + return 0; } // If this is the first call, read the lookup table static bool has_read_header = false; + static sound_hdr_t s_hdr[MAX_SOUNDS]; // Sound lookup table + if (!has_read_header) { if (fp.read(s_hdr, sizeof(s_hdr)) != sizeof(s_hdr)) Utils::Error(FILE_ERR, "%s", SOUND_FILE); @@ -272,9 +258,10 @@ sound_pt FileManager::getSound(int16 sound, uint16 *size) { Utils::Error(SOUND_ERR, "%s", SOUND_FILE); // Allocate memory for sound or music, if possible - if ((soundPtr = (byte *)malloc(s_hdr[sound].size)) == 0) { - Utils::Warn(false, "%s", "Low on memory"); - return(NULL); + sound_pt soundPtr = (byte *)malloc(s_hdr[sound].size); // Ptr to sound data + if (soundPtr == 0) { + Utils::Warn("%s", "Low on memory"); + return 0; } // Seek to data and read it @@ -297,56 +284,21 @@ bool FileManager::fileExists(char *filename) { return false; } -void FileManager::saveSeq(object_t *obj) { -// Save sequence number and image number in given object - byte j, k; - seq_t *q; - bool found; - - debugC(1, kDebugFile, "saveSeq"); - - for (j = 0, found = false; !found && (j < obj->seqNumb); j++) { - q = obj->seqList[j].seqPtr; - for (k = 0; !found && (k < obj->seqList[j].imageNbr); k++) { - if (obj->currImagePtr == q) { - found = true; - obj->curSeqNum = j; - obj->curImageNum = k; - } else - q = q->nextSeqPtr; - } - } -} - -void FileManager::restoreSeq(object_t *obj) { -// Set up cur_seq_p from stored sequence and image number in object - int j; - seq_t *q; - - debugC(1, kDebugFile, "restoreSeq"); - - q = obj->seqList[obj->curSeqNum].seqPtr; - for (j = 0; j < obj->curImageNum; j++) - q = q->nextSeqPtr; - obj->currImagePtr = q; -} - void FileManager::saveGame(int16 slot, const char *descrip) { // Save game to supplied slot (-1 is INITFILE) - int i; - char path[256]; // Full path of saved game - debugC(1, kDebugFile, "saveGame(%d, %s)", slot, descrip); // Get full path of saved game file - note test for INITFILE - if (slot == -1) - sprintf(path, "%s", _vm._initFilename); - else - sprintf(path, _vm._saveFilename, slot); + Common::String path; // Full path of saved game - Common::WriteStream *out = 0; - if (!(out = _vm.getSaveFileManager()->openForSaving(path))) { - warning("Can't create file '%s', game not saved", path); + if (slot == -1) + path = _vm->_initFilename; + else + path = Common::String::printf(_vm->_saveFilename.c_str(), slot); + + Common::WriteStream *out = _vm->getSaveFileManager()->openForSaving(path); + if (!out) { + warning("Can't create file '%s', game not saved", path.c_str()); return; } @@ -357,19 +309,19 @@ void FileManager::saveGame(int16 slot, const char *descrip) { out->write(descrip, DESCRIPLEN); // Save objects - for (i = 0; i < _vm._numObj; i++) { + for (int i = 0; i < _vm->_numObj; i++) { // Save where curr_seq_p is pointing to - saveSeq(&_vm._objects[i]); - out->write(&_vm._objects[i], sizeof(object_t)); + _vm->_object->saveSeq(&_vm->_object->_objects[i]); + out->write(&_vm->_object->_objects[i], sizeof(object_t)); } - const status_t &gameStatus = _vm.getGameStatus(); + const status_t &gameStatus = _vm->getGameStatus(); // Save whether hero image is swapped - out->write(&_vm._heroImage, sizeof(_vm._heroImage)); + out->write(&_vm->_heroImage, sizeof(_vm->_heroImage)); // Save score - int score = _vm.getScore(); + int score = _vm->getScore(); out->write(&score, sizeof(score)); // Save story mode @@ -382,16 +334,16 @@ void FileManager::saveGame(int16 slot, const char *descrip) { out->write(&gameStatus.gameOverFl, sizeof(gameStatus.gameOverFl)); // Save screen states - out->write(_vm._screenStates, sizeof(*_vm._screenStates) * _vm._numScreens); + out->write(_vm->_screenStates, sizeof(*_vm->_screenStates) * _vm->_numScreens); // Save points table - out->write(_vm._points, sizeof(point_t) * _vm._numBonuses); + out->write(_vm->_points, sizeof(point_t) * _vm->_numBonuses); // Now save current time and all current events in event queue - _vm.scheduler().saveEvents(out); + _vm->_scheduler->saveEvents(out); // Save palette table - _vm.screen().savePal(out); + _vm->_screen->savePal(out); // Save maze status out->write(&_maze, sizeof(maze_t)); @@ -403,27 +355,21 @@ void FileManager::saveGame(int16 slot, const char *descrip) { void FileManager::restoreGame(int16 slot) { // Restore game from supplied slot number (-1 is INITFILE) - int i; - char path[256]; // Full path of saved game - object_t *p; - seqList_t seqList[MAX_SEQUENCES]; -// cmdList *cmds; // Save command list pointer - uint16 cmdIndex; // Save command list pointer -// char ver[sizeof(VER)]; // Compare versions - debugC(1, kDebugFile, "restoreGame(%d)", slot); // Initialize new-game status - _vm.initStatus(); + _vm->initStatus(); // Get full path of saved game file - note test for INITFILE - if (slot == -1) - sprintf(path, "%s", _vm._initFilename); - else - sprintf(path, _vm._saveFilename, slot); + Common::String path; // Full path of saved game - Common::SeekableReadStream *in = 0; - if (!(in = _vm.getSaveFileManager()->openForLoading(path))) + if (slot == -1) + path = _vm->_initFilename; + else + path = Common::String::printf(_vm->_saveFilename.c_str(), slot); + + Common::SeekableReadStream *in = _vm->getSaveFileManager()->openForLoading(path); + if (!in) return; // Check version, can't restore from different versions @@ -438,50 +384,52 @@ void FileManager::restoreGame(int16 slot) { in->seek(DESCRIPLEN, SEEK_CUR); // If hero image is currently swapped, swap it back before restore - if (_vm._heroImage != HERO) - _vm.scheduler().swapImages(HERO, _vm._heroImage); + if (_vm->_heroImage != HERO) + _vm->_object->swapImages(HERO, _vm->_heroImage); // Restore objects, retain current seqList which points to dynamic mem // Also, retain cmnd_t pointers - for (i = 0; i < _vm._numObj; i++) { - p = &_vm._objects[i]; + for (int i = 0; i < _vm->_numObj; i++) { + object_t *p = &_vm->_object->_objects[i]; + seqList_t seqList[MAX_SEQUENCES]; memcpy(seqList, p->seqList, sizeof(seqList_t)); - cmdIndex = p->cmdIndex; + uint16 cmdIndex = p->cmdIndex; in->read(p, sizeof(object_t)); p->cmdIndex = cmdIndex; memcpy(p->seqList, seqList, sizeof(seqList_t)); } - in->read(&_vm._heroImage, sizeof(_vm._heroImage)); + in->read(&_vm->_heroImage, sizeof(_vm->_heroImage)); // If hero swapped in saved game, swap it - if ((i = _vm._heroImage) != HERO) - _vm.scheduler().swapImages(HERO, _vm._heroImage); - _vm._heroImage = i; + int heroImg = _vm->_heroImage; + if (heroImg != HERO) + _vm->_object->swapImages(HERO, _vm->_heroImage); + _vm->_heroImage = heroImg; - status_t &gameStatus = _vm.getGameStatus(); + status_t &gameStatus = _vm->getGameStatus(); int score; in->read(&score, sizeof(score)); - _vm.setScore(score); + _vm->setScore(score); in->read(&gameStatus.storyModeFl, sizeof(gameStatus.storyModeFl)); in->read(&gameStatus.jumpExitFl, sizeof(gameStatus.jumpExitFl)); in->read(&gameStatus.gameOverFl, sizeof(gameStatus.gameOverFl)); - in->read(_vm._screenStates, sizeof(*_vm._screenStates) * _vm._numScreens); + in->read(_vm->_screenStates, sizeof(*_vm->_screenStates) * _vm->_numScreens); // Restore points table - in->read(_vm._points, sizeof(point_t) * _vm._numBonuses); + in->read(_vm->_points, sizeof(point_t) * _vm->_numBonuses); // Restore ptrs to currently loaded objects - for (i = 0; i < _vm._numObj; i++) - restoreSeq(&_vm._objects[i]); + for (int i = 0; i < _vm->_numObj; i++) + _vm->_object->restoreSeq(&_vm->_object->_objects[i]); // Now restore time of the save and the event queue - _vm.scheduler().restoreEvents(in); + _vm->_scheduler->restoreEvents(in); // Restore palette and change it if necessary - _vm.screen().restorePal(in); + _vm->_screen->restorePal(in); // Restore maze status in->read(&_maze, sizeof(maze_t)); @@ -496,109 +444,67 @@ void FileManager::initSavedGame() { // the initial game file but useful to force a write during development // when the size is changeable. // The net result is a valid INITFILE, with status.savesize initialized. - Common::File f; // Handle of saved game file - char path[256]; // Full path of INITFILE - debugC(1, kDebugFile, "initSavedGame"); - // Get full path of INITFILE - sprintf(path, "%s", _vm._initFilename); - - // Force save of initial game - if (_vm.getGameStatus().initSaveFl) + if (_vm->getGameStatus().initSaveFl) saveGame(-1, ""); // If initial game doesn't exist, create it - Common::SeekableReadStream *in = 0; - if (!(in = _vm.getSaveFileManager()->openForLoading(path))) { + Common::SeekableReadStream *in = _vm->getSaveFileManager()->openForLoading(_vm->_initFilename); + if (!in) { saveGame(-1, ""); - if (!(in = _vm.getSaveFileManager()->openForLoading(path))) { - Utils::Error(WRITE_ERR, "%s", path); + in = _vm->getSaveFileManager()->openForLoading(_vm->_initFilename); + if (!in) { + Utils::Error(WRITE_ERR, "%s", _vm->_initFilename.c_str()); return; } } // Must have an open saved game now - _vm.getGameStatus().saveSize = in->size(); + _vm->getGameStatus().saveSize = in->size(); delete in; // Check sanity - maybe disk full or path set to read-only drive? - if (_vm.getGameStatus().saveSize == -1) - Utils::Error(WRITE_ERR, "%s", path); + if (_vm->getGameStatus().saveSize == -1) + Utils::Error(WRITE_ERR, "%s", _vm->_initFilename.c_str()); } -// Record and playback handling stuff: -typedef struct { -// int key; // Character - uint32 time; // Time at which character was pressed -} pbdata_t; -static pbdata_t pbdata; -FILE *fpb; - void FileManager::openPlaybackFile(bool playbackFl, bool recordFl) { debugC(1, kDebugFile, "openPlaybackFile(%d, %d)", (playbackFl) ? 1 : 0, (recordFl) ? 1 : 0); +/* if (playbackFl) { if (!(fpb = fopen(PBFILE, "r+b"))) Utils::Error(FILE_ERR, "%s", PBFILE); - } else if (recordFl) + } else if (recordFl) { fpb = fopen(PBFILE, "wb"); + } +*/ pbdata.time = 0; // Say no key available } void FileManager::closePlaybackFile() { - fclose(fpb); -} - -char *FileManager::fetchString(int index) { -//TODO : HUGO 1 DOS uses _stringtData instead of a strings.dat -// Fetch string from file, decode and return ptr to string in memory - uint32 off1, off2; - - debugC(1, kDebugFile, "fetchString(%d)", index); - - // Get offset to string[index] (and next for length calculation) - _stringArchive.seek((uint32)index * sizeof(uint32), SEEK_SET); - if (_stringArchive.read((char *)&off1, sizeof(uint32)) == 0) - Utils::Error(FILE_ERR, "%s", "String offset"); - if (_stringArchive.read((char *)&off2, sizeof(uint32)) == 0) - Utils::Error(FILE_ERR, "%s", "String offset"); - - // Check size of string - if ((off2 - off1) >= MAX_BOX) - Utils::Error(FILE_ERR, "%s", "Fetched string too long!"); - - // Position to string and read it into gen purpose _textBoxBuffer - _stringArchive.seek(off1, SEEK_SET); - if (_stringArchive.read(_textBoxBuffer, (uint16)(off2 - off1)) == 0) - Utils::Error(FILE_ERR, "%s", "Fetch_string"); - - // Null terminate, decode and return it - _textBoxBuffer[off2-off1] = '\0'; - _vm.scheduler().decodeString(_textBoxBuffer); - return _textBoxBuffer; +// fclose(fpb); } void FileManager::printBootText() { // Read the encrypted text from the boot file and print it - Common::File ofp; - int i; - char *buf; - debugC(1, kDebugFile, "printBootText"); + Common::File ofp; if (!ofp.open(BOOTFILE)) { - if (_vm._gameVariant == 3) { + if (_vm->_gameVariant == 3) { //TODO initialize properly _boot structure warning("printBootText - Skipping as H1 Dos may be a freeware"); return; - } else + } else { Utils::Error(FILE_ERR, "%s", BOOTFILE); + } } // Allocate space for the text and print it - buf = (char *)malloc(_boot.exit_len + 1); + char *buf = (char *)malloc(_boot.exit_len + 1); if (buf) { // Skip over the boot structure (already read) and read exit text ofp.seek((long)sizeof(_boot), SEEK_SET); @@ -606,6 +512,7 @@ void FileManager::printBootText() { Utils::Error(FILE_ERR, "%s", BOOTFILE); // Decrypt the exit text, using CRYPT substring + int i; for (i = 0; i < _boot.exit_len; i++) buf[i] ^= CRYPT[i % strlen(CRYPT)]; @@ -622,20 +529,17 @@ void FileManager::printBootText() { void FileManager::readBootFile() { // Reads boot file for program environment. Fatal error if not there or // file checksum is bad. De-crypts structure while checking checksum - byte checksum; - byte *p; - Common::File ofp; - uint32 i; - debugC(1, kDebugFile, "readBootFile"); + Common::File ofp; if (!ofp.open(BOOTFILE)) { - if (_vm._gameVariant == 3) { + if (_vm->_gameVariant == 3) { //TODO initialize properly _boot structure warning("readBootFile - Skipping as H1 Dos may be a freeware"); return; - } else + } else { Utils::Error(FILE_ERR, "%s", BOOTFILE); + } } if (ofp.size() < (int32)sizeof(_boot)) @@ -647,8 +551,10 @@ void FileManager::readBootFile() { ofp.read(_boot.distrib, sizeof(_boot.distrib)); _boot.exit_len = ofp.readUint16LE(); - p = (byte *)&_boot; - for (i = 0, checksum = 0; i < sizeof(_boot); i++) { + byte *p = (byte *)&_boot; + + byte checksum = 0; + for (uint32 i = 0; i < sizeof(_boot); i++) { checksum ^= p[i]; p[i] ^= CRYPT[i % strlen(CRYPT)]; } @@ -660,16 +566,16 @@ void FileManager::readBootFile() { uif_hdr_t *FileManager::getUIFHeader(uif_t id) { // Returns address of uif_hdr[id], reading it in if first call - static uif_hdr_t UIFHeader[MAX_UIFS]; // Lookup for uif fonts/images - static bool firstFl = true; - Common::File ip; // Image data file - debugC(1, kDebugFile, "getUIFHeader(%d)", id); + static bool firstFl = true; + static uif_hdr_t UIFHeader[MAX_UIFS]; // Lookup for uif fonts/images + // Initialize offset lookup if not read yet if (firstFl) { firstFl = false; // Open unbuffered to do far read + Common::File ip; // Image data file if (!ip.open(UIF_FILE)) Utils::Error(FILE_ERR, "%s", UIF_FILE); @@ -688,24 +594,22 @@ uif_hdr_t *FileManager::getUIFHeader(uif_t id) { void FileManager::readUIFItem(int16 id, byte *buf) { // Read uif item into supplied buffer. - Common::File ip; // UIF_FILE handle - uif_hdr_t *UIFHeaderPtr; // Lookup table of items - seq_t seq; // Dummy seq_t for image data - debugC(1, kDebugFile, "readUIFItem(%d, ...)", id); // Open uif file to read data + Common::File ip; // UIF_FILE handle if (!ip.open(UIF_FILE)) Utils::Error(FILE_ERR, "%s", UIF_FILE); // Seek to data - UIFHeaderPtr = getUIFHeader((uif_t)id); + uif_hdr_t *UIFHeaderPtr = getUIFHeader((uif_t)id); ip.seek(UIFHeaderPtr->offset, SEEK_SET); // We support pcx images and straight data + seq_t dummySeq; // Dummy seq_t for image data switch (id) { case UIF_IMAGES: // Read uif images file - readPCX(ip, &seq, buf, true, UIF_FILE); + readPCX(ip, &dummySeq, buf, true, UIF_FILE); break; default: // Read file data into supplied array if (ip.read(buf, UIFHeaderPtr->size) != UIFHeaderPtr->size) @@ -721,457 +625,34 @@ void FileManager::instructions() { // Only in DOS versions Common::File f; - char line[1024], *wrkLine; - char readBuf[2]; - - wrkLine = line; if (!f.open(HELPFILE)) { warning("help.dat not found"); return; } + char readBuf[2]; while (f.read(readBuf, 1)) { + char line[1024], *wrkLine; + wrkLine = line; wrkLine[0] = readBuf[0]; wrkLine++; do { f.read(wrkLine, 1); } while (*wrkLine++ != EOP); - wrkLine[-2] = '\0'; /* Remove EOP and previous CR */ + wrkLine[-2] = '\0'; // Remove EOP and previous CR Utils::Box(BOX_ANY, "%s", line); wrkLine = line; - f.read(readBuf, 2); /* Remove CRLF after EOP */ + f.read(readBuf, 2); // Remove CRLF after EOP } f.close(); } +// Read the uif image file (inventory icons) +void FileManager::readUIFImages() { + debugC(1, kDebugFile, "readUIFImages"); -FileManager_v1::FileManager_v1(HugoEngine &vm) : FileManager(vm) { + readUIFItem(UIF_IMAGES, _vm->_screen->getGUIBuffer()); // Read all uif images } -FileManager_v1::~FileManager_v1() { -} - -void FileManager_v1::openDatabaseFiles() { - debugC(1, kDebugFile, "openDatabaseFiles"); -} - -void FileManager_v1::closeDatabaseFiles() { - debugC(1, kDebugFile, "closeDatabaseFiles"); -} - -void FileManager_v1::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { -// Open and read in an overlay file, close file - uint32 i = 0; - image_pt tmpImage = image; // temp ptr to overlay file - - debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); - - const char *ovl_ext[] = {".b", ".o", ".ob"}; - char *buf = (char *) malloc(2048 + 1); // Buffer for file access - - strcat(strcpy(buf, _vm._screenNames[screenNum]), ovl_ext[overlayType]); - - if (!fileExists(buf)) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - - if (!_sceneryArchive1.open(buf)) - Utils::Error(FILE_ERR, "%s", buf); - - _sceneryArchive1.read(tmpImage, OVL_SIZE); - _sceneryArchive1.close(); -} - -void FileManager_v1::readBackground(int screenIndex) { -// Read a PCX image into dib_a - seq_t seq; // Image sequence structure for Read_pcx - - debugC(1, kDebugFile, "readBackground(%d)", screenIndex); - - char *buf = (char *) malloc(2048 + 1); // Buffer for file access - strcat(strcat(strcpy(buf, _vm._picDir), _vm._screenNames[screenIndex]), BKGEXT); - if (!_sceneryArchive1.open(buf)) { - warning("File %s not found, trying again with %s.ART", buf, _vm._screenNames[screenIndex]); - strcat(strcpy(buf, _vm._screenNames[screenIndex]), ".ART"); - if (!_sceneryArchive1.open(buf)) - Utils::Error(FILE_ERR, "%s", buf); - } - // Read the image into dummy seq and static dib_a - readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); - - _sceneryArchive1.close(); -} - -FileManager_v2::FileManager_v2(HugoEngine &vm) : FileManager(vm) { -} - -FileManager_v2::~FileManager_v2() { -} - -void FileManager_v2::openDatabaseFiles() { - debugC(1, kDebugFile, "openDatabaseFiles"); - - if (!_stringArchive.open(STRING_FILE)) - Utils::Error(FILE_ERR, "%s", STRING_FILE); - if (!_sceneryArchive1.open("scenery.dat")) - Utils::Error(FILE_ERR, "%s", "scenery.dat"); - if (!_objectsArchive.open(OBJECTS_FILE)) - Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); -} - -void FileManager_v2::closeDatabaseFiles() { - debugC(1, kDebugFile, "closeDatabaseFiles"); - - _stringArchive.close(); - _sceneryArchive1.close(); - _objectsArchive.close(); -} - -void FileManager_v2::readBackground(int screenIndex) { -// Read a PCX image into dib_a - seq_t seq; // Image sequence structure for Read_pcx - sceneBlock_t sceneBlock; // Read a database header entry - - debugC(1, kDebugFile, "readBackground(%d)", screenIndex); - - _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); - sceneBlock.b_off = _sceneryArchive1.readUint32LE(); - sceneBlock.b_len = _sceneryArchive1.readUint32LE(); - sceneBlock.o_off = _sceneryArchive1.readUint32LE(); - sceneBlock.o_len = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); - - _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); - - // Read the image into dummy seq and static dib_a - readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); -} - -void FileManager_v2::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { -// Open and read in an overlay file, close file - uint32 i = 0; - int16 j, k; - int8 data; // Must be 8 bits signed - image_pt tmpImage = image; // temp ptr to overlay file - sceneBlock_t sceneBlock; // Database header entry - - debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); - - _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); - sceneBlock.b_off = _sceneryArchive1.readUint32LE(); - sceneBlock.b_len = _sceneryArchive1.readUint32LE(); - sceneBlock.o_off = _sceneryArchive1.readUint32LE(); - sceneBlock.o_len = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); - - switch (overlayType) { - case BOUNDARY: - _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); - i = sceneBlock.b_len; - break; - case OVERLAY: - _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); - i = sceneBlock.o_len; - break; - case OVLBASE: - _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); - i = sceneBlock.ob_len; - break; - default: - Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); - break; - } - if (i == 0) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - - // Read in the overlay file using MAC Packbits. (We're not proud!) - k = 0; // byte count - do { - data = _sceneryArchive1.readByte(); // Read a code byte - if ((byte)data == 0x80) // Noop - k = k; - else if (data >= 0) { // Copy next data+1 literally - for (i = 0; i <= (byte)data; i++, k++) - *tmpImage++ = _sceneryArchive1.readByte(); - } else { // Repeat next byte -data+1 times - j = _sceneryArchive1.readByte(); - - for (i = 0; i < (byte)(-data + 1); i++, k++) - *tmpImage++ = j; - } - } while (k < OVL_SIZE); -} - -FileManager_v3::FileManager_v3(HugoEngine &vm) : FileManager(vm) { -} - -FileManager_v3::~FileManager_v3() { -} - -void FileManager_v3::openDatabaseFiles() { - debugC(1, kDebugFile, "openDatabaseFiles"); - - if (!_stringArchive.open(STRING_FILE)) - Utils::Error(FILE_ERR, "%s", STRING_FILE); - if (!_sceneryArchive1.open("scenery.dat")) - Utils::Error(FILE_ERR, "%s", "scenery.dat"); - if (!_objectsArchive.open(OBJECTS_FILE)) - Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); -} - -void FileManager_v3::closeDatabaseFiles() { - debugC(1, kDebugFile, "closeDatabaseFiles"); - - _stringArchive.close(); - _sceneryArchive1.close(); - _objectsArchive.close(); -} - -void FileManager_v3::readBackground(int screenIndex) { -// Read a PCX image into dib_a - seq_t seq; // Image sequence structure for Read_pcx - sceneBlock_t sceneBlock; // Read a database header entry - - debugC(1, kDebugFile, "readBackground(%d)", screenIndex); - - _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); - sceneBlock.b_off = _sceneryArchive1.readUint32LE(); - sceneBlock.b_len = _sceneryArchive1.readUint32LE(); - sceneBlock.o_off = _sceneryArchive1.readUint32LE(); - sceneBlock.o_len = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); - - _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); - - // Read the image into dummy seq and static dib_a - readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); -} - -void FileManager_v3::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { -// Open and read in an overlay file, close file - uint32 i = 0; - image_pt tmpImage = image; // temp ptr to overlay file - sceneBlock_t sceneBlock; // Database header entry - - debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); - - _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); - sceneBlock.b_off = _sceneryArchive1.readUint32LE(); - sceneBlock.b_len = _sceneryArchive1.readUint32LE(); - sceneBlock.o_off = _sceneryArchive1.readUint32LE(); - sceneBlock.o_len = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); - - switch (overlayType) { - case BOUNDARY: - _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); - i = sceneBlock.b_len; - break; - case OVERLAY: - _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); - i = sceneBlock.o_len; - break; - case OVLBASE: - _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); - i = sceneBlock.ob_len; - break; - default: - Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); - break; - } - if (i == 0) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - - _sceneryArchive1.read(tmpImage, OVL_SIZE); -} - -FileManager_v4::FileManager_v4(HugoEngine &vm) : FileManager(vm) { -} - -FileManager_v4::~FileManager_v4() { -} - -void FileManager_v4::readBackground(int screenIndex) { -// Read a PCX image into dib_a - seq_t seq; // Image sequence structure for Read_pcx - sceneBlock_t sceneBlock; // Read a database header entry - Common::File sceneryArchive; - - debugC(1, kDebugFile, "readBackground(%d)", screenIndex); - - _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); - sceneBlock.b_off = _sceneryArchive1.readUint32LE(); - sceneBlock.b_len = _sceneryArchive1.readUint32LE(); - sceneBlock.o_off = _sceneryArchive1.readUint32LE(); - sceneBlock.o_len = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); - - if (screenIndex < 20) { - _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); - - // Read the image into dummy seq and static dib_a - readPCX(_sceneryArchive1, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); - } else { - _sceneryArchive2.seek(sceneBlock.scene_off, SEEK_SET); - - // Read the image into dummy seq and static dib_a - readPCX(_sceneryArchive2, &seq, _vm.screen().getFrontBuffer(), true, _vm._screenNames[screenIndex]); - } -} - -void FileManager_v4::openDatabaseFiles() { - debugC(1, kDebugFile, "openDatabaseFiles"); - - if (!_stringArchive.open(STRING_FILE)) - Utils::Error(FILE_ERR, "%s", STRING_FILE); - if (!_sceneryArchive1.open("scenery1.dat")) - Utils::Error(FILE_ERR, "%s", "scenery1.dat"); - if (!_sceneryArchive2.open("scenery2.dat")) - Utils::Error(FILE_ERR, "%s", "scenery2.dat"); - if (!_objectsArchive.open(OBJECTS_FILE)) - Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); -} - -void FileManager_v4::closeDatabaseFiles() { - debugC(1, kDebugFile, "closeDatabaseFiles"); - - _stringArchive.close(); - _sceneryArchive1.close(); - _sceneryArchive2.close(); - _objectsArchive.close(); -} - -void FileManager_v4::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { -// Open and read in an overlay file, close file - uint32 i = 0; - int16 j, k; - int8 data; // Must be 8 bits signed - image_pt tmpImage = image; // temp ptr to overlay file - sceneBlock_t sceneBlock; // Database header entry - Common::File sceneryArchive; - - debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); - - _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); - - sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); - sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); - sceneBlock.b_off = _sceneryArchive1.readUint32LE(); - sceneBlock.b_len = _sceneryArchive1.readUint32LE(); - sceneBlock.o_off = _sceneryArchive1.readUint32LE(); - sceneBlock.o_len = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); - sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); - - if (screenNum < 20) { - switch (overlayType) { - case BOUNDARY: - _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); - i = sceneBlock.b_len; - break; - case OVERLAY: - _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); - i = sceneBlock.o_len; - break; - case OVLBASE: - _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); - i = sceneBlock.ob_len; - break; - default: - Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); - break; - } - if (i == 0) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - - // Read in the overlay file using MAC Packbits. (We're not proud!) - k = 0; // byte count - do { - data = _sceneryArchive1.readByte(); // Read a code byte - if ((byte)data == 0x80) // Noop - k = k; - else if (data >= 0) { // Copy next data+1 literally - for (i = 0; i <= (byte)data; i++, k++) - *tmpImage++ = _sceneryArchive1.readByte(); - } else { // Repeat next byte -data+1 times - j = _sceneryArchive1.readByte(); - - for (i = 0; i < (byte)(-data + 1); i++, k++) - *tmpImage++ = j; - } - } while (k < OVL_SIZE); - } else { - switch (overlayType) { - case BOUNDARY: - _sceneryArchive2.seek(sceneBlock.b_off, SEEK_SET); - i = sceneBlock.b_len; - break; - case OVERLAY: - _sceneryArchive2.seek(sceneBlock.o_off, SEEK_SET); - i = sceneBlock.o_len; - break; - case OVLBASE: - _sceneryArchive2.seek(sceneBlock.ob_off, SEEK_SET); - i = sceneBlock.ob_len; - break; - default: - Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); - break; - } - if (i == 0) { - for (i = 0; i < OVL_SIZE; i++) - image[i] = 0; - return; - } - - // Read in the overlay file using MAC Packbits. (We're not proud!) - k = 0; // byte count - do { - data = _sceneryArchive2.readByte(); // Read a code byte - if ((byte)data == 0x80) // Noop - k = k; - else if (data >= 0) { // Copy next data+1 literally - for (i = 0; i <= (byte)data; i++, k++) - *tmpImage++ = _sceneryArchive2.readByte(); - } else { // Repeat next byte -data+1 times - j = _sceneryArchive2.readByte(); - - for (i = 0; i < (byte)(-data + 1); i++, k++) - *tmpImage++ = j; - } - } while (k < OVL_SIZE); - } -} } // End of namespace Hugo diff --git a/engines/hugo/file.h b/engines/hugo/file.h index 71bd0bf75c3..881cf3c4d70 100644 --- a/engines/hugo/file.h +++ b/engines/hugo/file.h @@ -35,18 +35,33 @@ // TODO get rid of those defines #define HELPFILE "help.dat" -#define EOP '#' /* Marks end of a page in help file */ +#define EOP '#' // Marks end of a page in help file + +struct PCC_header_t { // Structure of PCX file header + byte mfctr, vers, enc, bpx; + uint16 x1, y1, x2, y2; // bounding box + uint16 xres, yres; + byte palette[48]; // EGA color palette + byte vmode, planes; + uint16 bytesPerLine; // Bytes per line + byte fill2[60]; +}; // Header of a PCC file + +// Record and playback handling stuff: +struct pbdata_t { +// int key; // Character + uint32 time; // Time at which character was pressed +}; namespace Hugo { class FileManager { public: - FileManager(HugoEngine &vm); + FileManager(HugoEngine *vm); virtual ~FileManager(); bool fileExists(char *filename); - char *fetchString(int index); sound_pt getSound(short sound, uint16 *size); void closePlaybackFile(); @@ -54,11 +69,10 @@ public: void instructions(); void readBootFile(); void readImage(int objNum, object_t *objPtr); + void readUIFImages(); void readUIFItem(short id, byte *buf); void restoreGame(short slot); - void restoreSeq(object_t *obj); void saveGame(short slot, const char *descrip); - void saveSeq(object_t *obj); virtual void openDatabaseFiles() = 0; virtual void closeDatabaseFiles() = 0; @@ -66,12 +80,14 @@ public: virtual void readBackground(int screenIndex) = 0; virtual void readOverlay(int screenNum, image_pt image, ovl_t overlayType) = 0; -protected: - HugoEngine &_vm; + virtual char *fetchString(int index) = 0; - Common::File _stringArchive; /* Handle for string file */ - Common::File _sceneryArchive1; /* Handle for scenery file */ - Common::File _objectsArchive; /* Handle for objects file */ +protected: + HugoEngine *_vm; + + Common::File _stringArchive; // Handle for string file + Common::File _sceneryArchive1; // Handle for scenery file + Common::File _objectsArchive; // Handle for objects file seq_t *readPCX(Common::File &f, seq_t *seqPtr, byte *imagePtr, bool firstFl, const char *name); private: @@ -79,6 +95,9 @@ private: byte *convertPCC(byte *p, uint16 y, uint16 bpl, image_pt data_p); uif_hdr_t *getUIFHeader(uif_t id); + pbdata_t pbdata; +// FILE *fpb; + //Strangerke : Not used? void openPlaybackFile(bool playbackFl, bool recordFl); void printBootText(); @@ -86,51 +105,50 @@ private: // char pbget(); }; -class FileManager_v1 : public FileManager { +class FileManager_v1d : public FileManager { public: - FileManager_v1(HugoEngine &vm); - ~FileManager_v1(); + FileManager_v1d(HugoEngine *vm); + ~FileManager_v1d(); void openDatabaseFiles(); void closeDatabaseFiles(); void readBackground(int screenIndex); void readOverlay(int screenNum, image_pt image, ovl_t overlayType); + char *fetchString(int index); }; -class FileManager_v2 : public FileManager { +class FileManager_v2d : public FileManager { public: - FileManager_v2(HugoEngine &vm); - ~FileManager_v2(); + FileManager_v2d(HugoEngine *vm); + ~FileManager_v2d(); void openDatabaseFiles(); void closeDatabaseFiles(); void readBackground(int screenIndex); void readOverlay(int screenNum, image_pt image, ovl_t overlayType); + char *fetchString(int index); }; -class FileManager_v3 : public FileManager { +class FileManager_v3d : public FileManager_v2d { public: - FileManager_v3(HugoEngine &vm); - ~FileManager_v3(); - - void openDatabaseFiles(); - void closeDatabaseFiles(); - void readBackground(int screenIndex); - void readOverlay(int screenNum, image_pt image, ovl_t overlayType); -}; - -class FileManager_v4 : public FileManager { -public: - FileManager_v4(HugoEngine &vm); - ~FileManager_v4(); + FileManager_v3d(HugoEngine *vm); + ~FileManager_v3d(); void openDatabaseFiles(); void closeDatabaseFiles(); void readBackground(int screenIndex); void readOverlay(int screenNum, image_pt image, ovl_t overlayType); private: - Common::File _sceneryArchive2; /* Handle for scenery file */ - + Common::File _sceneryArchive2; // Handle for scenery file }; + +class FileManager_v1w : public FileManager_v2d { +public: + FileManager_v1w(HugoEngine *vm); + ~FileManager_v1w(); + + void readOverlay(int screenNum, image_pt image, ovl_t overlayType); +}; + } // End of namespace Hugo #endif //HUGO_FILE_H diff --git a/engines/hugo/file_v1d.cpp b/engines/hugo/file_v1d.cpp new file mode 100644 index 00000000000..115a691ffcf --- /dev/null +++ b/engines/hugo/file_v1d.cpp @@ -0,0 +1,101 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/util.h" + +namespace Hugo { +FileManager_v1d::FileManager_v1d(HugoEngine *vm) : FileManager(vm) { +} + +FileManager_v1d::~FileManager_v1d() { +} + +void FileManager_v1d::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); +} + +void FileManager_v1d::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); +} + +void FileManager_v1d::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + const char *ovl_ext[] = {".b", ".o", ".ob"}; + char *buf = (char *) malloc(2048 + 1); // Buffer for file access + + strcat(strcpy(buf, _vm->_screenNames[screenNum]), ovl_ext[overlayType]); + + if (!fileExists(buf)) { + for (uint32 i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + if (!_sceneryArchive1.open(buf)) + Utils::Error(FILE_ERR, "%s", buf); + + image_pt tmpImage = image; // temp ptr to overlay file + + _sceneryArchive1.read(tmpImage, OVL_SIZE); + _sceneryArchive1.close(); +} + +void FileManager_v1d::readBackground(int screenIndex) { +// Read a PCX image into dib_a + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + char *buf = (char *) malloc(2048 + 1); // Buffer for file access + strcat(strcpy(buf, _vm->_screenNames[screenIndex]), ".ART"); + if (!_sceneryArchive1.open(buf)) + Utils::Error(FILE_ERR, "%s", buf); + // Read the image into dummy seq and static dib_a + seq_t dummySeq; // Image sequence structure for Read_pcx + readPCX(_sceneryArchive1, &dummySeq, _vm->_screen->getFrontBuffer(), true, _vm->_screenNames[screenIndex]); + + _sceneryArchive1.close(); +} + +char *FileManager_v1d::fetchString(int index) { + debugC(1, kDebugFile, "fetchString(%d)", index); + + return _vm->_stringtData[index]; +} + +} // End of namespace Hugo + diff --git a/engines/hugo/file_v1w.cpp b/engines/hugo/file_v1w.cpp new file mode 100644 index 00000000000..5218876cafa --- /dev/null +++ b/engines/hugo/file_v1w.cpp @@ -0,0 +1,90 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/file.h" +#include "hugo/util.h" + +namespace Hugo { +FileManager_v1w::FileManager_v1w(HugoEngine *vm) : FileManager_v2d(vm) { +} + +FileManager_v1w::~FileManager_v1w() { +} + +void FileManager_v1w::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + image_pt tmpImage = image; // temp ptr to overlay file + _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock_t sceneBlock; // Database header entry + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + uint32 i = 0; + switch (overlayType) { + case BOUNDARY: + _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + _sceneryArchive1.read(tmpImage, OVL_SIZE); +} + +} // End of namespace Hugo + diff --git a/engines/hugo/file_v2d.cpp b/engines/hugo/file_v2d.cpp new file mode 100644 index 00000000000..c4b17b3e659 --- /dev/null +++ b/engines/hugo/file_v2d.cpp @@ -0,0 +1,177 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/file.h" +#include "hugo/global.h" +#include "hugo/schedule.h" +#include "hugo/display.h" +#include "hugo/util.h" + +namespace Hugo { +FileManager_v2d::FileManager_v2d(HugoEngine *vm) : FileManager(vm) { +} + +FileManager_v2d::~FileManager_v2d() { +} + +void FileManager_v2d::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); + + if (!_stringArchive.open(STRING_FILE)) + Utils::Error(FILE_ERR, "%s", STRING_FILE); + if (!_sceneryArchive1.open("scenery.dat")) + Utils::Error(FILE_ERR, "%s", "scenery.dat"); + if (!_objectsArchive.open(OBJECTS_FILE)) + Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); +} + +void FileManager_v2d::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); + + _stringArchive.close(); + _sceneryArchive1.close(); + _objectsArchive.close(); +} + +void FileManager_v2d::readBackground(int screenIndex) { +// Read a PCX image into dib_a + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock_t sceneBlock; // Read a database header entry + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); + + // Read the image into dummy seq and static dib_a + seq_t dummySeq; // Image sequence structure for Read_pcx + readPCX(_sceneryArchive1, &dummySeq, _vm->_screen->getFrontBuffer(), true, _vm->_screenNames[screenIndex]); +} + +void FileManager_v2d::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + image_pt tmpImage = image; // temp ptr to overlay file + _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock_t sceneBlock; // Database header entry + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + uint32 i = 0; + switch (overlayType) { + case BOUNDARY: + _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + // Read in the overlay file using MAC Packbits. (We're not proud!) + int16 k = 0; // byte count + do { + int8 data = _sceneryArchive1.readByte(); // Read a code byte + if ((byte)data == 0x80) // Noop + k = k; + else if (data >= 0) { // Copy next data+1 literally + for (i = 0; i <= (byte)data; i++, k++) + *tmpImage++ = _sceneryArchive1.readByte(); + } else { // Repeat next byte -data+1 times + int16 j = _sceneryArchive1.readByte(); + + for (i = 0; i < (byte)(-data + 1); i++, k++) + *tmpImage++ = j; + } + } while (k < OVL_SIZE); +} + +char *FileManager_v2d::fetchString(int index) { +// Fetch string from file, decode and return ptr to string in memory + debugC(1, kDebugFile, "fetchString(%d)", index); + + // Get offset to string[index] (and next for length calculation) + _stringArchive.seek((uint32)index * sizeof(uint32), SEEK_SET); + uint32 off1, off2; + if (_stringArchive.read((char *)&off1, sizeof(uint32)) == 0) + Utils::Error(FILE_ERR, "%s", "String offset"); + if (_stringArchive.read((char *)&off2, sizeof(uint32)) == 0) + Utils::Error(FILE_ERR, "%s", "String offset"); + + // Check size of string + if ((off2 - off1) >= MAX_BOX) + Utils::Error(FILE_ERR, "%s", "Fetched string too long!"); + + // Position to string and read it into gen purpose _textBoxBuffer + _stringArchive.seek(off1, SEEK_SET); + if (_stringArchive.read(_textBoxBuffer, (uint16)(off2 - off1)) == 0) + Utils::Error(FILE_ERR, "%s", "Fetch_string"); + + // Null terminate, decode and return it + _textBoxBuffer[off2-off1] = '\0'; + _vm->_scheduler->decodeString(_textBoxBuffer); + return _textBoxBuffer; +} +} // End of namespace Hugo + diff --git a/engines/hugo/file_v3d.cpp b/engines/hugo/file_v3d.cpp new file mode 100644 index 00000000000..f1e4bf0a153 --- /dev/null +++ b/engines/hugo/file_v3d.cpp @@ -0,0 +1,200 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/file.h" +#include "hugo/global.h" +#include "hugo/display.h" +#include "hugo/util.h" + +namespace Hugo { +FileManager_v3d::FileManager_v3d(HugoEngine *vm) : FileManager_v2d(vm) { +} + +FileManager_v3d::~FileManager_v3d() { +} + +void FileManager_v3d::readBackground(int screenIndex) { +// Read a PCX image into dib_a + debugC(1, kDebugFile, "readBackground(%d)", screenIndex); + + _sceneryArchive1.seek((uint32) screenIndex * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock_t sceneBlock; // Read a database header entry + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + seq_t dummySeq; // Image sequence structure for Read_pcx + if (screenIndex < 20) { + _sceneryArchive1.seek(sceneBlock.scene_off, SEEK_SET); + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive1, &dummySeq, _vm->_screen->getFrontBuffer(), true, _vm->_screenNames[screenIndex]); + } else { + _sceneryArchive2.seek(sceneBlock.scene_off, SEEK_SET); + // Read the image into dummy seq and static dib_a + readPCX(_sceneryArchive2, &dummySeq, _vm->_screen->getFrontBuffer(), true, _vm->_screenNames[screenIndex]); + } +} + +void FileManager_v3d::openDatabaseFiles() { + debugC(1, kDebugFile, "openDatabaseFiles"); + + if (!_stringArchive.open(STRING_FILE)) + Utils::Error(FILE_ERR, "%s", STRING_FILE); + if (!_sceneryArchive1.open("scenery1.dat")) + Utils::Error(FILE_ERR, "%s", "scenery1.dat"); + if (!_sceneryArchive2.open("scenery2.dat")) + Utils::Error(FILE_ERR, "%s", "scenery2.dat"); + if (!_objectsArchive.open(OBJECTS_FILE)) + Utils::Error(FILE_ERR, "%s", OBJECTS_FILE); +} + +void FileManager_v3d::closeDatabaseFiles() { + debugC(1, kDebugFile, "closeDatabaseFiles"); + + _stringArchive.close(); + _sceneryArchive1.close(); + _sceneryArchive2.close(); + _objectsArchive.close(); +} + +void FileManager_v3d::readOverlay(int screenNum, image_pt image, ovl_t overlayType) { +// Open and read in an overlay file, close file + debugC(1, kDebugFile, "readOverlay(%d, ...)", screenNum); + + image_pt tmpImage = image; // temp ptr to overlay file + _sceneryArchive1.seek((uint32)screenNum * sizeof(sceneBlock_t), SEEK_SET); + + sceneBlock_t sceneBlock; // Database header entry + sceneBlock.scene_off = _sceneryArchive1.readUint32LE(); + sceneBlock.scene_len = _sceneryArchive1.readUint32LE(); + sceneBlock.b_off = _sceneryArchive1.readUint32LE(); + sceneBlock.b_len = _sceneryArchive1.readUint32LE(); + sceneBlock.o_off = _sceneryArchive1.readUint32LE(); + sceneBlock.o_len = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_off = _sceneryArchive1.readUint32LE(); + sceneBlock.ob_len = _sceneryArchive1.readUint32LE(); + + uint32 i = 0; + + if (screenNum < 20) { + switch (overlayType) { + case BOUNDARY: + _sceneryArchive1.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive1.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive1.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + // Read in the overlay file using MAC Packbits. (We're not proud!) + int16 k = 0; // byte count + do { + int8 data = _sceneryArchive1.readByte();// Read a code byte + if ((byte)data == 0x80) // Noop + k = k; + else if (data >= 0) { // Copy next data+1 literally + for (i = 0; i <= (byte)data; i++, k++) + *tmpImage++ = _sceneryArchive1.readByte(); + } else { // Repeat next byte -data+1 times + int16 j = _sceneryArchive1.readByte(); + + for (i = 0; i < (byte)(-data + 1); i++, k++) + *tmpImage++ = j; + } + } while (k < OVL_SIZE); + } else { + switch (overlayType) { + case BOUNDARY: + _sceneryArchive2.seek(sceneBlock.b_off, SEEK_SET); + i = sceneBlock.b_len; + break; + case OVERLAY: + _sceneryArchive2.seek(sceneBlock.o_off, SEEK_SET); + i = sceneBlock.o_len; + break; + case OVLBASE: + _sceneryArchive2.seek(sceneBlock.ob_off, SEEK_SET); + i = sceneBlock.ob_len; + break; + default: + Utils::Error(FILE_ERR, "%s", "Bad ovl_type"); + break; + } + if (i == 0) { + for (i = 0; i < OVL_SIZE; i++) + image[i] = 0; + return; + } + + // Read in the overlay file using MAC Packbits. (We're not proud!) + int16 k = 0; // byte count + do { + int8 data = _sceneryArchive2.readByte();// Read a code byte + if ((byte)data == 0x80) // Noop + k = k; + else if (data >= 0) { // Copy next data+1 literally + for (i = 0; i <= (byte)data; i++, k++) + *tmpImage++ = _sceneryArchive2.readByte(); + } else { // Repeat next byte -data+1 times + int16 j = _sceneryArchive2.readByte(); + + for (i = 0; i < (byte)(-data + 1); i++, k++) + *tmpImage++ = j; + } + } while (k < OVL_SIZE); + } +} +} // End of namespace Hugo + diff --git a/engines/hugo/game.h b/engines/hugo/game.h index d032a4b8170..869aa1baa48 100644 --- a/engines/hugo/game.h +++ b/engines/hugo/game.h @@ -48,13 +48,7 @@ namespace Hugo { // Copy helpedit\hugow_?.hlp to .\hugowin?.hlp // Type "PPG" in the game to enter cheat mode. -#define DEBUG false // Allow me to do special things (EDIT, GOTO) -#define STORY true // Skip any intro stuff if FALSE -//#define DATABASE TRUE // Use database instead of individual files. Individual files are used by Hugo1 DOS! -//#define BETA FALSE // Puts big msg in intro/about box -#define EPISODE_NUM 1 // Episode we are building -#define TITLE "Hugo for Windows" -#define COPYRIGHT "Copyright © 1995-97, David P. Gray" +#define COPYRIGHT "Copyright 1989-1997 David P Gray, All Rights Reserved." // Started code on 04/01/95 // Don't forget to update Hugowin.rc2 with version info //#define VER "1.0" // 10/01/95 Initial Release @@ -62,7 +56,7 @@ namespace Hugo { //#define VER "v1.2"// 10/12/95 Added "background music" checkbox in volume dlg //#define VER "v1.3"// 10/23/95 Support game 1 as shareware //#define VER "v1.4"// 12/06/95 Faster graphics, logical palette -#define VER "v1.5" // 10/07/97 Added order form, new web site +//#define VER "v1.5" // 10/07/97 Added order form, new web site // Game specific equates #define MAX_TUNES 16 // Max number of tunes @@ -95,6 +89,7 @@ namespace Hugo { #define WARNLEN 512 #define ERRLEN 512 #define STEP_DY 8 // Pixels per step movement +#define CENTER -1 // Used to center text in x // Only for non-database #define BKGEXT ".PCX" // Extension of background files @@ -111,6 +106,13 @@ namespace Hugo { // Macros: #define TPS ((_config.turboFl) ? TURBO_TPS : NORMAL_TPS) +#define MAX_UIFS 32 // Max possible uif items in hdr +#define NUM_FONTS 3 // Number of dib fonts +#define FIRST_FONT U_FONT5 +#define FONT_LEN 128 // Number of chars in font +#define FONTSIZE 1200 // Max size of font data + +#define CRYPT "Copyright 1992, David P Gray, Gray Design Associates" enum TEXTCOLORS { _TBLACK, _TBLUE, _TGREEN, _TCYAN, @@ -119,33 +121,8 @@ enum TEXTCOLORS { _TLIGHTRED, _TLIGHTMAGENTA, _TLIGHTYELLOW, _TBRIGHTWHITE }; -#define CRYPT "Copyright 1992, David P Gray, Gray Design Associates" - -struct hugo_boot_t { // Common HUGO boot file - char checksum; // Checksum for boot structure (not exit text) - char registered; // TRUE if registered version, else FALSE - char pbswitch[8]; // Playback switch string - char distrib[32]; // Distributor branding string - uint16 exit_len; // Length of exit text (next in file) -}; - -#define MAX_UIFS 32 // Max possible uif items in hdr -#define NUM_FONTS 3 // Number of dib fonts -#define FIRST_FONT U_FONT5 -#define FONT_LEN 128 // Number of chars in font -#define FONTSIZE 1200 // Max size of font data - -struct uif_hdr_t { // UIF font/image look up - uint16 size; // Size of uif item - uint32 offset; // Offset of item in file -}; - enum uif_t {U_FONT5, U_FONT6, U_FONT8, UIF_IMAGES, NUM_UIF_ITEMS}; -// Game specific type definitions -typedef byte *image_pt; // ptr to an object image (sprite) -typedef byte *sound_pt; // ptr to sound (or music) data - // Enumerate overlay file types enum ovl_t {BOUNDARY, OVERLAY, OVLBASE}; @@ -213,21 +190,6 @@ enum invact_t {INV_INIT, INV_LEFT, INV_RIGHT, INV_GET}; // Purpose of an automatic route enum go_t {GO_SPACE, GO_EXIT, GO_LOOK, GO_GET}; -// Following are points for achieving certain actions. -struct point_t { - byte score; // The value of the point - bool scoredFl; // Whether scored yet -}; - -// Structure for initializing maze processing -struct maze_t { - bool enabledFl; // TRUE when maze processing enabled - byte size; // Size of (square) maze matrix - int x1, y1, x2, y2; // maze hotspot bounding box - int x3, x4; // north, south x entry coordinates - byte firstScreenIndex; // index of first screen in maze -}; - // Following defines the action types and action list enum action_t { // Parameters: ANULL = 0xff, // Special NOP used to 'delete' events in DEL_EVENTS @@ -284,6 +246,37 @@ enum action_t { // Parameters: OLD_SONG = 49 // Added by Strangerke - Set currently playing sound, old way: that is, using a string index instead of a reference in a file }; +struct hugo_boot_t { // Common HUGO boot file + char checksum; // Checksum for boot structure (not exit text) + char registered; // TRUE if registered version, else FALSE + char pbswitch[8]; // Playback switch string + char distrib[32]; // Distributor branding string + uint16 exit_len; // Length of exit text (next in file) +}; + +struct uif_hdr_t { // UIF font/image look up + uint16 size; // Size of uif item + uint32 offset; // Offset of item in file +}; + +// Game specific type definitions +typedef byte *image_pt; // ptr to an object image (sprite) +typedef byte *sound_pt; // ptr to sound (or music) data + +// Following are points for achieving certain actions. +struct point_t { + byte score; // The value of the point + bool scoredFl; // Whether scored yet +}; + +// Structure for initializing maze processing +struct maze_t { + bool enabledFl; // TRUE when maze processing enabled + byte size; // Size of (square) maze matrix + int x1, y1, x2, y2; // maze hotspot bounding box + int x3, x4; // north, south x entry coordinates + byte firstScreenIndex; // index of first screen in maze +}; struct act0 { // Type 0 - Schedule action_t actType; // The type of action @@ -803,6 +796,7 @@ struct status_t { // Game status (not saved) bool jumpExitFl; // Allowed to jump to a screen exit bool godModeFl; // Allow DEBUG features in live version bool helpFl; // Calling WinHelp (don't disable music) + bool doQuitFl; uint32 tick; // Current time in ticks uint32 saveTick; // Time of last save in ticks vstate_t viewState; // View state machine @@ -824,8 +818,6 @@ struct config_t { // User's config (saved) bool musicFl; // State of Music button/menu item bool soundFl; // State of Sound button/menu item bool turboFl; // State of Turbo button/menu item -// int16 wx, wy; // Position of viewport - int16 cx, cy; // Size of viewport bool backgroundMusicFl; // Continue music when task inactive byte musicVolume; // Music volume percentage byte soundVolume; // Sound volume percentage @@ -850,7 +842,7 @@ extern hugo_boot_t _boot; // Boot info structure extern char _textBoxBuffer[]; // Useful box text buffer extern command_t _line; // Line of user text input -/* Structure of scenery file lookup entry */ +// Structure of scenery file lookup entry struct sceneBlock_t { uint32 scene_off; uint32 scene_len; @@ -862,7 +854,7 @@ struct sceneBlock_t { uint32 ob_len; }; -/* Structure of object file lookup entry */ +// Structure of object file lookup entry struct objBlock_t { uint32 objOffset; uint32 objLength; diff --git a/engines/hugo/global.h b/engines/hugo/global.h index 1437eb3734b..0ab21ddb9c6 100644 --- a/engines/hugo/global.h +++ b/engines/hugo/global.h @@ -34,18 +34,19 @@ namespace Hugo { #define HERO 0 // In all enums, HERO is the first element -#define DESCRIPLEN 32 /* Length of description string */ -#define MAX_SOUNDS 64 /* Max number of sounds */ -#define BOOTFILE "HUGO.BSF" /* Name of boot structure file */ -#define LEN_MASK 0x3F /* Lower 6 bits are length */ +#define DESCRIPLEN 32 // Length of description string +#define MAX_SOUNDS 64 // Max number of sounds +#define BOOTFILE "HUGO.BSF" // Name of boot structure file +#define LEN_MASK 0x3F // Lower 6 bits are length #define PBFILE "playback.dat" -/* Name scenery and objects picture databases */ +// Name scenery and objects picture databases #define OBJECTS_FILE "objects.dat" #define STRING_FILE "strings.dat" #define SOUND_FILE "sounds.dat" -/* User interface database (Windows Only) */ +// User interface database (Windows Only) +// This file contains, between others, the bitmaps of the fonts used in the application #define UIF_FILE "uif.dat" static const int kSavegameVersion = 1; diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index 316c16f0187..2a4dd61487b 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -24,7 +24,9 @@ */ #include "common/system.h" +#include "common/random.h" #include "common/events.h" +#include "common/EventRecorder.h" #include "common/debug-channels.h" #include "hugo/hugo.h" @@ -37,26 +39,34 @@ #include "hugo/inventory.h" #include "hugo/parser.h" #include "hugo/route.h" +#include "hugo/util.h" #include "hugo/sound.h" #include "hugo/intro.h" +#include "hugo/object.h" #include "engines/util.h" namespace Hugo { -HugoEngine *HugoEngine::s_Engine = NULL; +HugoEngine *HugoEngine::s_Engine = 0; overlay_t HugoEngine::_boundary; overlay_t HugoEngine::_overlay; overlay_t HugoEngine::_ovlBase; overlay_t HugoEngine::_objBound; +config_t _config; // User's config +maze_t _maze; // Default to not in maze +hugo_boot_t _boot; // Boot info structure file +char _textBoxBuffer[MAX_BOX]; // Buffer for text box +command_t _line; // Line of user text input + HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(syst), _gameDescription(gd), _mouseX(0), _mouseY(0), _textData(0), _stringtData(0), _screenNames(0), _textEngine(0), _textIntro(0), _textMouse(0), _textParser(0), _textSchedule(0), _textUtil(0), _arrayNouns(0), _arrayVerbs(0), _arrayReqs(0), _hotspots(0), _invent(0), _uses(0), _catchallList(0), _backgroundObjects(0), - _points(0), _cmdList(0), _screenActs(0), _objects(0), _actListArr(0), _heroImage(0), _defltTunes(0), _palette(0), _introX(0), - _introY(0), _maxInvent(0), _numBonuses(0), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0), _screenStates(0), _numObj(0), - _score(0), _maxscore(0) + _points(0), _cmdList(0), _screenActs(0), _actListArr(0), _heroImage(0), _defltTunes(0), _palette(0), _introX(0), _introY(0), + _maxInvent(0), _numBonuses(0), _numScreens(0), _tunesNbr(0), _soundSilence(0), _soundTest(0), _screenStates(0), _numObj(0), + _score(0), _maxscore(0), _backgroundObjectsSize(0), _screenActsSize(0), _actListArrSize(0), _usesSize(0) { DebugMan.addDebugChannel(kDebugSchedule, "Schedule", "Script Schedule debug level"); @@ -67,61 +77,85 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy DebugMan.addDebugChannel(kDebugFile, "File", "File IO debug level"); DebugMan.addDebugChannel(kDebugRoute, "Route", "Route debug level"); DebugMan.addDebugChannel(kDebugInventory, "Inventory", "Inventory debug level"); + DebugMan.addDebugChannel(kDebugObject, "Object", "Object debug level"); + + for (int j = 0; j < NUM_FONTS; j++) + _arrayFont[j] = 0; } HugoEngine::~HugoEngine() { - delete _soundHandler; - delete _route; - delete _parser; - delete _inventoryHandler; - delete _mouseHandler; - delete _screen; - delete _scheduler; - delete _fileManager; - - free(_palette); - free(_introX); - free(_introY); - -#if 0 - freeTexts(_textData); - freeTexts(_stringtData); - freeTexts(_textEngine); - freeTexts(_textIntro); - freeTexts(_textMouse); - freeTexts(_textParser); - freeTexts(_textSchedule); - freeTexts(_textUtil); -#endif free(_textData); free(_stringtData); + + for (int i = 0; _arrayNouns[i]; i++) + free(_arrayNouns[i]); + free(_arrayNouns); + + for (int i = 0; _arrayVerbs[i]; i++) + free(_arrayVerbs[i]); + free(_arrayVerbs); + free(_screenNames); + free(_palette); free(_textEngine); free(_textIntro); + free(_introX); + free(_introY); free(_textMouse); free(_textParser); free(_textSchedule); free(_textUtil); - - warning("Missing: free _arrayNouns"); - warning("Missing: free _arrayVerbs"); - free(_arrayReqs); free(_hotspots); free(_invent); + + for (int i = 0; i < _usesSize; i++) + free(_uses[i].targets); free(_uses); + free(_catchallList); - warning("Missing: free _background_objects"); + for (int i = 0; i < _backgroundObjectsSize; i++) + free(_backgroundObjects[i]); + free(_backgroundObjects); free(_points); - warning("Missing: free _cmdList"); - warning("Missing: free _screenActs"); - warning("Missing: free _objects"); + for (int i = 0; i < _cmdListSize; i++) + free(_cmdList[i]); + free(_cmdList); + + for (int i = 0; i < _screenActsSize; i++) + free(_screenActs[i]); + free(_screenActs); + + _object->freeObjectArr(); + + for (int i = 0; i < _actListArrSize; i++) + free(_actListArr[i]); + free(_actListArr); free(_defltTunes); free(_screenStates); + + if (_arrayFont[0]) + free(_arrayFont[0]); + + if (_arrayFont[1]) + free(_arrayFont[1]); + + if (_arrayFont[2]) + free(_arrayFont[2]); + + delete _object; + delete _sound; + delete _route; + delete _parser; + delete _inventory; + delete _mouse; + delete _screen; + delete _scheduler; + delete _file; } GameType HugoEngine::getGameType() const { @@ -140,43 +174,59 @@ Common::Error HugoEngine::run() { s_Engine = this; initGraphics(320, 200, false); - _screen = new Screen(*this); - _mouseHandler = new MouseHandler(*this); - _inventoryHandler = new InventoryHandler(*this); - _parser = new Parser(*this); - _route = new Route(*this); - _soundHandler = new SoundHandler(*this); + _mouse = new MouseHandler(this); + _inventory = new InventoryHandler(this); + _route = new Route(this); + _sound = new SoundHandler(this); switch (_gameVariant) { case 0: // H1 Win - _fileManager = new FileManager_v3(*this); - _scheduler = new Scheduler_v2(*this); - _introHandler = new intro_1w(*this); + _file = new FileManager_v1w(this); + _scheduler = new Scheduler_v1w(this); + _intro = new intro_v1w(this); + _screen = new Screen_v1w(this); + _parser = new Parser_v1w(this); + _object = new ObjectHandler_v1w(this); break; case 1: - _fileManager = new FileManager_v2(*this); - _scheduler = new Scheduler_v2(*this); - _introHandler = new intro_2w(*this); + _file = new FileManager_v2d(this); + _scheduler = new Scheduler_v1w(this); + _intro = new intro_v2w(this); + _screen = new Screen_v1w(this); + _parser = new Parser_v1w(this); + _object = new ObjectHandler_v1w(this); break; case 2: - _fileManager = new FileManager_v2(*this); - _scheduler = new Scheduler_v2(*this); - _introHandler = new intro_3w(*this); + _file = new FileManager_v2d(this); + _scheduler = new Scheduler_v1w(this); + _intro = new intro_v3w(this); + _screen = new Screen_v1w(this); + _parser = new Parser_v1w(this); + _object = new ObjectHandler_v1w(this); break; case 3: // H1 DOS - _fileManager = new FileManager_v1(*this); - _scheduler = new Scheduler_v1(*this); - _introHandler = new intro_1d(*this); + _file = new FileManager_v1d(this); + _scheduler = new Scheduler_v1d(this); + _intro = new intro_v1d(this); + _screen = new Screen_v1d(this); + _parser = new Parser_v1d(this); + _object = new ObjectHandler_v1d(this); break; case 4: - _fileManager = new FileManager_v2(*this); - _scheduler = new Scheduler_v1(*this); - _introHandler = new intro_2d(*this); + _file = new FileManager_v2d(this); + _scheduler = new Scheduler_v2d(this); + _intro = new intro_v2d(this); + _screen = new Screen_v1d(this); + _parser = new Parser_v2d(this); + _object = new ObjectHandler_v2d(this); break; case 5: - _fileManager = new FileManager_v4(*this); - _scheduler = new Scheduler_v2(*this); - _introHandler = new intro_3d(*this); + _file = new FileManager_v3d(this); + _scheduler = new Scheduler_v3d(this); + _intro = new intro_v3d(this); + _screen = new Screen_v1d(this); + _parser = new Parser_v3d(this); + _object = new ObjectHandler_v1d(this); break; } @@ -194,27 +244,25 @@ Common::Error HugoEngine::run() { initialize(); initConfig(RESET); // Reset user's config - file().restoreGame(-1); + _file->restoreGame(-1); initMachine(); // Start the state machine _status.viewState = V_INTROINIT; - bool doQuitFl = false; + _status.doQuitFl = false; - while (!doQuitFl) { + while (!_status.doQuitFl) { g_system->updateScreen(); - // WORKAROUND: Force the mouse cursor to be displayed. This fixes the disappearing mouse cursor issue. - g_system->showMouse(true); runMachine(); // Handle input Common::Event event; while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: - parser().keyHandler(event.kbd.keycode, 0); + _parser->keyHandler(event.kbd.keycode, 0); break; case Common::EVENT_MOUSEMOVE: _mouseX = event.mouse.x; @@ -233,7 +281,7 @@ Common::Error HugoEngine::run() { _status.rightButtonFl = false; break; case Common::EVENT_QUIT: - doQuitFl = true; + _status.doQuitFl = true; break; default: break; @@ -244,10 +292,13 @@ Common::Error HugoEngine::run() { } void HugoEngine::initMachine() { - file().readBackground(_numScreens - 1); // Splash screen + if (_gameVariant == kGameVariantH1Dos) + readScreenFiles(0); + else + _file->readBackground(_numScreens - 1); // Splash screen readObjectImages(); // Read all object images if (_platform == Common::kPlatformWindows) - readUIFImages(); // Read all uif images (only in Win versions) + _file->readUIFImages(); // Read all uif images (only in Win versions) } void HugoEngine::runMachine() { @@ -255,7 +306,6 @@ void HugoEngine::runMachine() { static uint32 lastTime; status_t &gameStatus = getGameStatus(); - // Don't process if we're in a textbox if (gameStatus.textBoxFl) return; @@ -271,43 +321,42 @@ void HugoEngine::runMachine() { switch (gameStatus.viewState) { case V_IDLE: // Not processing state machine - intro().preNewGame(); // Any processing before New Game selected + _intro->preNewGame(); // Any processing before New Game selected break; case V_INTROINIT: // Initialization before intro begins - intro().introInit(); + _intro->introInit(); + g_system->showMouse(false); gameStatus.viewState = V_INTRO; break; case V_INTRO: // Do any game-dependant preamble - if (intro().introPlay()) { // Process intro screen - scheduler().newScreen(0); // Initialize first screen + if (_intro->introPlay()) { // Process intro screen + _scheduler->newScreen(0); // Initialize first screen gameStatus.viewState = V_PLAY; } break; case V_PLAY: // Playing game - parser().charHandler(); // Process user cmd input - moveObjects(); // Process object movement - scheduler().runScheduler(); // Process any actions - screen().displayList(D_RESTORE); // Restore previous background - updateImages(); // Draw into _frontBuffer, compile display list - mouse().mouseHandler(); // Mouse activity - adds to display list - parser().drawStatusText(); - screen().displayList(D_DISPLAY); // Blit the display list to screen + g_system->showMouse(true); + _parser->charHandler(); // Process user cmd input + _object->moveObjects(); // Process object movement + _scheduler->runScheduler(); // Process any actions + _screen->displayList(D_RESTORE); // Restore previous background + _object->updateImages(); // Draw into _frontBuffer, compile display list + _mouse->mouseHandler(); // Mouse activity - adds to display list + _screen->drawStatusText(); + _screen->displayList(D_DISPLAY); // Blit the display list to screen break; case V_INVENT: // Accessing inventory - inventory().runInventory(); // Process Inventory state machine + _inventory->runInventory(); // Process Inventory state machine break; case V_EXIT: // Game over or user exited gameStatus.viewState = V_IDLE; + _status.doQuitFl = true; break; } } bool HugoEngine::loadHugoDat() { Common::File in; - int numElem, numSubElem, numSubAct; - char buf[256]; - int majVer, minVer; - in.open("hugo.dat"); if (!in.isOpen()) { @@ -318,6 +367,7 @@ bool HugoEngine::loadHugoDat() { } // Read header + char buf[256]; in.read(buf, 4); buf[4] = '\0'; @@ -328,8 +378,8 @@ bool HugoEngine::loadHugoDat() { return false; } - majVer = in.readByte(); - minVer = in.readByte(); + int majVer = in.readByte(); + int minVer = in.readByte(); if ((majVer != HUGO_DAT_VER_MAJ) || (minVer != HUGO_DAT_VER_MIN)) { snprintf(buf, 256, "File 'hugo.dat' is wrong version. Expected %d.%d but got %d.%d. Get it from the ScummVM website", HUGO_DAT_VER_MAJ, HUGO_DAT_VER_MIN, majVer, minVer); @@ -360,23 +410,32 @@ bool HugoEngine::loadHugoDat() { // Read palette _paletteSize = in.readUint16BE(); _palette = (byte *)malloc(sizeof(byte) * _paletteSize); - for (int i = 0; i < _paletteSize; i++) { + for (int i = 0; i < _paletteSize; i++) _palette[i] = in.readByte(); - } // Read textEngine _textEngine = loadTexts(in); // Read textIntro - _textIntro = loadTexts(in); + _textIntro = loadTextsVariante(in, 0); // Read x_intro and y_intro - _introXSize = in.readUint16BE(); - _introX = (byte *)malloc(sizeof(byte) * _introXSize); - _introY = (byte *)malloc(sizeof(byte) * _introXSize); - for (int i = 0; i < _introXSize; i++) { - _introX[i] = in.readByte(); - _introY[i] = in.readByte(); + for (int varnt = 0; varnt < _numVariant; varnt++) { + int numRows = in.readUint16BE(); + if (varnt == _gameVariant) { + _introXSize = numRows; + _introX = (byte *)malloc(sizeof(byte) * _introXSize); + _introY = (byte *)malloc(sizeof(byte) * _introXSize); + for (int i = 0; i < _introXSize; i++) { + _introX[i] = in.readByte(); + _introY[i] = in.readByte(); + } + } else { + for (int i = 0; i < numRows; i++) { + in.readByte(); + in.readByte(); + } + } } // Read textMouse @@ -425,6 +484,7 @@ bool HugoEngine::loadHugoDat() { } } + int numElem, numSubElem, numSubAct; //Read _invent for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); @@ -443,6 +503,7 @@ bool HugoEngine::loadHugoDat() { for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); if (varnt == _gameVariant) { + _usesSize = numElem; _uses = (uses_t *)malloc(sizeof(uses_t) * numElem); for (int i = 0; i < numElem; i++) { _uses[i].objId = in.readSint16BE(); @@ -496,8 +557,9 @@ bool HugoEngine::loadHugoDat() { for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); if (varnt == _gameVariant) { - _backgroundObjects = (background_t **)malloc(sizeof(background_t *) * numElem); - for (int i = 0; i < numElem; i++) { + _backgroundObjectsSize = numElem; + _backgroundObjects = (background_t **)malloc(sizeof(background_t *) * _backgroundObjectsSize); + for (int i = 0; i < _backgroundObjectsSize; i++) { numSubElem = in.readUint16BE(); _backgroundObjects[i] = (background_t *)malloc(sizeof(background_t) * numSubElem); for (int j = 0; j < numSubElem; j++) { @@ -513,9 +575,9 @@ bool HugoEngine::loadHugoDat() { for (int i = 0; i < numElem; i++) { numSubElem = in.readUint16BE(); for (int j = 0; j < numSubElem; j++) { - in.readUint16BE();; - in.readUint16BE();; - in.readSint16BE();; + in.readUint16BE(); + in.readUint16BE(); + in.readSint16BE(); in.readByte(); in.readByte(); in.readByte(); @@ -544,8 +606,9 @@ bool HugoEngine::loadHugoDat() { for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); if (varnt == _gameVariant) { - _cmdList = (cmd **)malloc(sizeof(cmd *) * numElem); - for (int i = 0; i < numElem; i++) { + _cmdListSize = numElem; + _cmdList = (cmd **)malloc(sizeof(cmd *) * _cmdListSize); + for (int i = 0; i < _cmdListSize; i++) { numSubElem = in.readUint16BE(); _cmdList[i] = (cmd *)malloc(sizeof(cmd) * numSubElem); for (int j = 0; j < numSubElem; j++) { @@ -581,12 +644,13 @@ bool HugoEngine::loadHugoDat() { for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); if (varnt == _gameVariant) { - _screenActs = (uint16 **)malloc(sizeof(uint16 *) * numElem); - for (int i = 0; i < numElem; i++) { + _screenActsSize = numElem; + _screenActs = (uint16 **)malloc(sizeof(uint16 *) * _screenActsSize); + for (int i = 0; i < _screenActsSize; i++) { numSubElem = in.readUint16BE(); - if (numSubElem == 0) + if (numSubElem == 0) { _screenActs[i] = 0; - else { + } else { _screenActs[i] = (uint16 *)malloc(sizeof(uint16) * numSubElem); for (int j = 0; j < numSubElem; j++) _screenActs[i][j] = in.readUint16BE(); @@ -599,119 +663,21 @@ bool HugoEngine::loadHugoDat() { in.readUint16BE(); } } - } -// TODO: For Hugo3, if not in story mode, set _objects[2].state to 3 - for (int varnt = 0; varnt < _numVariant; varnt++) { - numElem = in.readUint16BE(); - if (varnt == _gameVariant) { - _objects = (object_t *)malloc(sizeof(object_t) * numElem); - for (int i = 0; i < numElem; i++) { - _objects[i].nounIndex = in.readUint16BE(); - _objects[i].dataIndex = in.readUint16BE(); - numSubElem = in.readUint16BE(); - if (numSubElem == 0) - _objects[i].stateDataIndex = 0; - else - _objects[i].stateDataIndex = (uint16 *)malloc(sizeof(uint16) * numSubElem); - for (int j = 0; j < numSubElem; j++) - _objects[i].stateDataIndex[j] = in.readUint16BE(); - _objects[i].pathType = (path_t) in.readSint16BE(); - _objects[i].vxPath = in.readSint16BE(); - _objects[i].vyPath = in.readSint16BE(); - _objects[i].actIndex = in.readUint16BE(); - _objects[i].seqNumb = in.readByte(); - _objects[i].currImagePtr = 0; - if (_objects[i].seqNumb == 0) { - _objects[i].seqList[0].imageNbr = 0; - _objects[i].seqList[0].seqPtr = 0; - } - for (int j = 0; j < _objects[i].seqNumb; j++) { - _objects[i].seqList[j].imageNbr = in.readUint16BE(); - _objects[i].seqList[j].seqPtr = 0; - } - _objects[i].cycling = (cycle_t)in.readByte(); - _objects[i].cycleNumb = in.readByte(); - _objects[i].frameInterval = in.readByte(); - _objects[i].frameTimer = in.readByte(); - _objects[i].radius = in.readByte(); - _objects[i].screenIndex = in.readByte(); - _objects[i].x = in.readSint16BE(); - _objects[i].y = in.readSint16BE(); - _objects[i].oldx = in.readSint16BE(); - _objects[i].oldy = in.readSint16BE(); - _objects[i].vx = in.readByte(); - _objects[i].vy = in.readByte(); - _objects[i].objValue = in.readByte(); - _objects[i].genericCmd = in.readSint16BE(); - _objects[i].cmdIndex = in.readUint16BE(); - _objects[i].carriedFl = (in.readByte() != 0); - _objects[i].state = in.readByte(); - _objects[i].verbOnlyFl = (in.readByte() != 0); - _objects[i].priority = in.readByte(); - _objects[i].viewx = in.readSint16BE(); - _objects[i].viewy = in.readSint16BE(); - _objects[i].direction = in.readSint16BE(); - _objects[i].curSeqNum = in.readByte(); - _objects[i].curImageNum = in.readByte(); - _objects[i].oldvx = in.readByte(); - _objects[i].oldvy = in.readByte(); - } - } else { - for (int i = 0; i < numElem; i++) { - in.readUint16BE(); - in.readUint16BE(); - numSubElem = in.readUint16BE(); - for (int j = 0; j < numSubElem; j++) - in.readUint16BE(); - in.readSint16BE(); - in.readSint16BE(); - in.readSint16BE(); - in.readUint16BE(); - numSubElem = in.readByte(); - for (int j = 0; j < numSubElem; j++) - in.readUint16BE(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readSint16BE(); - in.readSint16BE(); - in.readSint16BE(); - in.readSint16BE(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readSint16BE(); - in.readUint16BE(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readSint16BE(); - in.readSint16BE(); - in.readUint16BE(); - in.readByte(); - in.readByte(); - in.readByte(); - in.readByte(); - } - } - } + _object->loadObjectArr(in); //#define HERO 0 - _hero = &_objects[HERO]; // This always points to hero - _screen_p = &(_objects[HERO].screenIndex); // Current screen is hero's - _heroImage = HERO; // Current in use hero image + _hero = &_object->_objects[HERO]; // This always points to hero + _screen_p = &(_object->_objects[HERO].screenIndex); // Current screen is hero's + _heroImage = HERO; // Current in use hero image //read _actListArr for (int varnt = 0; varnt < _numVariant; varnt++) { numElem = in.readUint16BE(); if (varnt == _gameVariant) { - _actListArr = (act **)malloc(sizeof(act *) * numElem); - for (int i = 0; i < numElem; i++) { + _actListArrSize = numElem; + _actListArr = (act **)malloc(sizeof(act *) * _actListArrSize); + for (int i = 0; i < _actListArrSize; i++) { numSubElem = in.readUint16BE(); _actListArr[i] = (act *) malloc(sizeof(act) * (numSubElem + 1)); for (int j = 0; j < numSubElem; j++) { @@ -1332,6 +1298,34 @@ bool HugoEngine::loadHugoDat() { _alNewscrIndex = numElem; } + if (_gameVariant > 2) { + _arrayFontSize[0] = in.readUint16BE(); + _arrayFont[0] = (byte *)malloc(sizeof(byte) * _arrayFontSize[0]); + for (int j = 0; j < _arrayFontSize[0]; j++) + _arrayFont[0][j] = in.readByte(); + + _arrayFontSize[1] = in.readUint16BE(); + _arrayFont[1] = (byte *)malloc(sizeof(byte) * _arrayFontSize[1]); + for (int j = 0; j < _arrayFontSize[1]; j++) + _arrayFont[1][j] = in.readByte(); + + _arrayFontSize[2] = in.readUint16BE(); + _arrayFont[2] = (byte *)malloc(sizeof(byte) * _arrayFontSize[2]); + for (int j = 0; j < _arrayFontSize[2]; j++) + _arrayFont[2][j] = in.readByte(); + } else { + numElem = in.readUint16BE(); + for (int j = 0; j < numElem; j++) + in.readByte(); + + numElem = in.readUint16BE(); + for (int j = 0; j < numElem; j++) + in.readByte(); + + numElem = in.readUint16BE(); + for (int j = 0; j < numElem; j++) + in.readByte(); + } return true; } @@ -1352,6 +1346,7 @@ char **HugoEngine::loadTextsVariante(Common::File &in, uint16 *arraySize) { res = (char **)malloc(sizeof(char *) * numTexts); res[0] = pos; in.read(res[0], entryLen); + res[0] += DATAALIGNMENT; } else { in.read(pos, entryLen); } @@ -1374,25 +1369,23 @@ char **HugoEngine::loadTextsVariante(Common::File &in, uint16 *arraySize) { uint16 **HugoEngine::loadLongArray(Common::File &in) { uint16 **resArray = 0; - uint16 *resRow = 0; - uint16 dummy, numRows, numElems; for (int varnt = 0; varnt < _numVariant; varnt++) { - numRows = in.readUint16BE(); + uint16 numRows = in.readUint16BE(); if (varnt == _gameVariant) { resArray = (uint16 **)malloc(sizeof(uint16 *) * (numRows + 1)); resArray[numRows] = 0; } for (int i = 0; i < numRows; i++) { - numElems = in.readUint16BE(); + uint16 numElems = in.readUint16BE(); if (varnt == _gameVariant) { - resRow = (uint16 *)malloc(sizeof(uint16) * numElems); + uint16 *resRow = (uint16 *)malloc(sizeof(uint16) * numElems); for (int j = 0; j < numElems; j++) resRow[j] = in.readUint16BE(); resArray[i] = resRow; } else { for (int j = 0; j < numElems; j++) - dummy = in.readUint16BE(); + in.readUint16BE(); } } } @@ -1400,28 +1393,25 @@ uint16 **HugoEngine::loadLongArray(Common::File &in) { } char ***HugoEngine::loadTextsArray(Common::File &in) { - int numNouns; - int numTexts; - int entryLen; - int len; char ***resArray = 0; - char **res = 0; - char *pos = 0; + uint16 arraySize; for (int varnt = 0; varnt < _numVariant; varnt++) { - numNouns = in.readUint16BE(); + arraySize = in.readUint16BE(); if (varnt == _gameVariant) { - resArray = (char ** *)malloc(sizeof(char **) * (numNouns + 1)); - resArray[numNouns] = 0; + resArray = (char ***)malloc(sizeof(char **) * (arraySize + 1)); + resArray[arraySize] = 0; } - for (int i = 0; i < numNouns; i++) { - numTexts = in.readUint16BE(); - entryLen = in.readUint16BE(); - pos = (char *)malloc(entryLen); + for (int i = 0; i < arraySize; i++) { + int numTexts = in.readUint16BE(); + int entryLen = in.readUint16BE(); + char *pos = (char *)malloc(entryLen); + char **res = 0; if (varnt == _gameVariant) { res = (char **)malloc(sizeof(char *) * numTexts); res[0] = pos; in.read(res[0], entryLen); + res[0] += DATAALIGNMENT; } else { in.read(pos, entryLen); } @@ -1433,7 +1423,7 @@ char ***HugoEngine::loadTextsArray(Common::File &in) { res[j] = pos; pos -= 2; - len = READ_BE_UINT16(pos); + int len = READ_BE_UINT16(pos); pos += 2 + len; } @@ -1448,12 +1438,8 @@ char ***HugoEngine::loadTextsArray(Common::File &in) { char **HugoEngine::loadTexts(Common::File &in) { int numTexts = in.readUint16BE(); char **res = (char **)malloc(sizeof(char *) * numTexts); - int entryLen; - char *pos = 0; - int len; - - entryLen = in.readUint16BE(); - pos = (char *)malloc(entryLen); + int entryLen = in.readUint16BE(); + char *pos = (char *)malloc(entryLen); in.read(pos, entryLen); @@ -1462,7 +1448,7 @@ char **HugoEngine::loadTexts(Common::File &in) { for (int i = 1; i < numTexts; i++) { pos -= 2; - len = READ_BE_UINT16(pos); + int len = READ_BE_UINT16(pos); pos += 2 + len; res[i] = pos; } @@ -1478,4 +1464,392 @@ void HugoEngine::freeTexts(char **ptr) { free(ptr); } +// Sets the playlist to be the default tune selection +void HugoEngine::initPlaylist(bool playlist[MAX_TUNES]) { + debugC(1, kDebugEngine, "initPlaylist"); + + for (int16 i = 0; i < MAX_TUNES; i++) + playlist[i] = false; + for (int16 i = 0; _defltTunes[i] != -1; i++) + playlist[_defltTunes[i]] = true; +} + +// Initialize the dynamic game status +void HugoEngine::initStatus() { + debugC(1, kDebugEngine, "initStatus"); + _status.initSaveFl = true; // Force initial save + _status.storyModeFl = false; // Not in story mode + _status.gameOverFl = false; // Hero not knobbled yet + _status.recordFl = false; // Not record mode + _status.playbackFl = false; // Not playback mode + _status.demoFl = false; // Not demo mode + _status.textBoxFl = false; // Not processing a text box +// Strangerke - Not used ? +// _status.mmtime = false; // Multimedia timer support + _status.lookFl = false; // Toolbar "look" button + _status.recallFl = false; // Toolbar "recall" button + _status.leftButtonFl = false; // Left mouse button pressed + _status.rightButtonFl = false; // Right mouse button pressed + _status.newScreenFl = false; // Screen not just loaded + _status.jumpExitFl = false; // Can't jump to a screen exit + _status.godModeFl = false; // No special cheats allowed + _status.helpFl = false; // Not calling WinHelp() + _status.doQuitFl = false; + _status.path[0] = 0; // Path to write files + _status.saveSlot = 0; // Slot to save/restore game + _status.screenWidth = 0; // Desktop screen width + + // Initialize every start of new game + _status.tick = 0; // Tick count + _status.saveTick = 0; // Time of last save + _status.viewState = V_IDLE; // View state + _status.inventoryState = I_OFF; // Inventory icon bar state + _status.inventoryHeight = 0; // Inventory icon bar pos + _status.inventoryObjId = -1; // Inventory object selected (none) + _status.routeIndex = -1; // Hero not following a route + _status.go_for = GO_SPACE; // Hero walking to space + _status.go_id = -1; // Hero not walking to anything +} + +// Initialize default config values. Must be done before Initialize(). +// Reset needed to save config.cx,cy which get splatted during OnFileNew() +void HugoEngine::initConfig(inst_t action) { + debugC(1, kDebugEngine, "initConfig(%d)", action); + + switch (action) { + case INSTALL: + _config.musicFl = true; // Music state initially on + _config.soundFl = true; // Sound state initially on + _config.turboFl = false; // Turbo state initially off + _config.backgroundMusicFl = false; // No music when inactive + _config.musicVolume = 85; // Music volume % + _config.soundVolume = 100; // Sound volume % + initPlaylist(_config.playlist); // Initialize default tune playlist + + _file->readBootFile(); // Read startup structure + break; + case RESET: + // Find first tune and play it + for (int16 i = 0; i < MAX_TUNES; i++) { + if (_config.playlist[i]) { + _sound->playMusic(i); + break; + } + } + + _file->initSavedGame(); // Initialize saved game + break; + case RESTORE: + warning("Unhandled action RESTORE"); + break; + } +} + +void HugoEngine::initialize() { + debugC(1, kDebugEngine, "initialize"); + + _maze.enabledFl = false; + _line[0] = '\0'; + + _sound->initSound(); + _scheduler->initEventQueue(); // Init scheduler stuff + _screen->initDisplay(); // Create Dibs and palette + _file->openDatabaseFiles(); // Open database files + calcMaxScore(); // Initialise maxscore + + _rnd = new Common::RandomSource(); + g_eventRec.registerRandomSource(*_rnd, "hugo"); + + _rnd->setSeed(42); // Kick random number generator + + switch (getGameType()) { + case kGameTypeHugo1: + _episode = "\"HUGO'S HOUSE OF HORRORS\""; + _picDir = ""; + break; + case kGameTypeHugo2: + _episode = "\"Hugo's Mystery Adventure\""; + _picDir = "hugo2/"; + break; + case kGameTypeHugo3: + _episode = "\"Hugo's Amazon Adventure\""; + _picDir = "hugo3/"; + break; + default: + error("Unknown game"); + } +} + +// Restore all resources before termination +void HugoEngine::shutdown() { + debugC(1, kDebugEngine, "shutdown"); + + _file->closeDatabaseFiles(); + if (_status.recordFl || _status.playbackFl) + _file->closePlaybackFile(); + _object->freeObjects(); +} + +void HugoEngine::readObjectImages() { + debugC(1, kDebugEngine, "readObjectImages"); + + for (int i = 0; i < _numObj; i++) + _file->readImage(i, &_object->_objects[i]); +} + +// Read scenery, overlay files for given screen number +void HugoEngine::readScreenFiles(int screenNum) { + debugC(1, kDebugEngine, "readScreenFiles(%d)", screenNum); + + _file->readBackground(screenNum); // Scenery file + memcpy(_screen->getBackBuffer(), _screen->getFrontBuffer(), sizeof(_screen->getFrontBuffer()));// Make a copy + _file->readOverlay(screenNum, _boundary, BOUNDARY); // Boundary file + _file->readOverlay(screenNum, _overlay, OVERLAY); // Overlay file + _file->readOverlay(screenNum, _ovlBase, OVLBASE); // Overlay base file +} + +// Return maximum allowed movement (from zero to vx) such that object does +// not cross a boundary (either background or another object) +int HugoEngine::deltaX(int x1, int x2, int vx, int y) { +// Explanation of algorithm: The boundaries are drawn as contiguous +// lines 1 pixel wide. Since DX,DY are not necessarily 1, we must +// detect boundary crossing. If vx positive, examine each pixel from +// x1 old to x2 new, else x2 old to x1 new, both at the y2 line. +// If vx zero, no need to check. If vy non-zero then examine each +// pixel on the line segment x1 to x2 from y old to y new. +// Fix from Hugo I v1.5: +// Note the diff is munged in the return statement to cater for a special +// cases arising from differences in image widths from one sequence to +// another. The problem occurs reversing direction at a wall where the +// new image intersects before the object can move away. This is cured +// by comparing the intersection with half the object width pos. If the +// intersection is in the other half wrt the intended direction, use the +// desired vx, else use the computed delta. i.e. believe the desired vx + + debugC(3, kDebugEngine, "deltaX(%d, %d, %d, %d)", x1, x2, vx, y); + + if (vx == 0) + return 0 ; // Object stationary + + y *= XBYTES; // Offset into boundary file + if (vx > 0) { + // Moving to right + for (int i = x1 >> 3; i <= (x2 + vx) >> 3; i++) {// Search by byte + int b = Utils::firstBit((byte)(_boundary[y + i] | _objBound[y + i])); + if (b < 8) { // b is index or 8 + // Compute x of boundary and test if intersection + b += i << 3; + if ((b >= x1) && (b <= x2 + vx)) + return (b < x1 + ((x2 - x1) >> 1)) ? vx : b - x2 - 1; // return dx + } + } + } else { + // Moving to left + for (int i = x2 >> 3; i >= (x1 + vx) >> 3; i--) {// Search by byte + int b = Utils::lastBit((byte)(_boundary[y + i] | _objBound[y + i])); + if (b < 8) { // b is index or 8 + // Compute x of boundary and test if intersection + b += i << 3; + if ((b >= x1 + vx) && (b <= x2)) + return (b > x1 + ((x2 - x1) >> 1)) ? vx : b - x1 + 1; // return dx + } + } + } + return vx; +} + +// Similar to Delta_x, but for movement in y direction. Special case of +// bytes at end of line segment; must only count boundary bits falling on +// line segment. +int HugoEngine::deltaY(int x1, int x2, int vy, int y) { + debugC(3, kDebugEngine, "deltaY(%d, %d, %d, %d)", x1, x2, vy, y); + + if (vy == 0) + return 0; // Object stationary + + int inc = (vy > 0) ? 1 : -1; + for (int j = y + inc; j != (y + vy + inc); j += inc) { //Search by byte + for (int i = x1 >> 3; i <= x2 >> 3; i++) { + int b = _boundary[j * XBYTES + i] | _objBound[j * XBYTES + i]; + if (b != 0) { // Any bit set + // Make sure boundary bits fall on line segment + if (i == (x2 >> 3)) // Adjust right end + b &= 0xff << ((i << 3) + 7 - x2); + else if (i == (x1 >> 3)) // Adjust left end + b &= 0xff >> (x1 - (i << 3)); + if (b) + return j - y - inc; + } + } + } + return vy; +} + +// Store a horizontal line segment in the object boundary file +void HugoEngine::storeBoundary(int x1, int x2, int y) { + debugC(5, kDebugEngine, "storeBoundary(%d, %d, %d)", x1, x2, y); + + for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line + byte *b = &_objBound[y * XBYTES + i]; // get boundary byte + if (i == x2 >> 3) // Adjust right end + *b |= 0xff << ((i << 3) + 7 - x2); + else if (i == x1 >> 3) // Adjust left end + *b |= 0xff >> (x1 - (i << 3)); + else + *b = 0xff; + } +} + +// Clear a horizontal line segment in the object boundary file +void HugoEngine::clearBoundary(int x1, int x2, int y) { + debugC(5, kDebugEngine, "clearBoundary(%d, %d, %d)", x1, x2, y); + + for (int i = x1 >> 3; i <= x2 >> 3; i++) { // For each byte in line + byte *b = &_objBound[y * XBYTES + i]; // get boundary byte + if (i == x2 >> 3) // Adjust right end + *b &= ~(0xff << ((i << 3) + 7 - x2)); + else if (i == x1 >> 3) // Adjust left end + *b &= ~(0xff >> (x1 - (i << 3))); + else + *b = 0; + } +} + +// Maze mode is enabled. Check to see whether hero has crossed the maze +// bounding box, if so, go to the next room */ +void HugoEngine::processMaze() { + debugC(1, kDebugEngine, "processMaze"); + + seq_t *currImage = _hero->currImagePtr; // Get ptr to current image + + // hero coordinates + int x1 = _hero->x + currImage->x1; // Left edge of object + int x2 = _hero->x + currImage->x2; // Right edge + int y1 = _hero->y + currImage->y1; // Top edge + int y2 = _hero->y + currImage->y2; // Bottom edge + + if (x1 < _maze.x1) { + // Exit west + _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p - 1; + _actListArr[_alNewscrIndex][0].a2.x = _maze.x2 - SHIFT - (x2 - x1); + _actListArr[_alNewscrIndex][0].a2.y = _hero->y; + _status.routeIndex = -1; + _scheduler->insertActionList(_alNewscrIndex); + } else if (x2 > _maze.x2) { + // Exit east + _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p + 1; + _actListArr[_alNewscrIndex][0].a2.x = _maze.x1 + SHIFT; + _actListArr[_alNewscrIndex][0].a2.y = _hero->y; + _status.routeIndex = -1; + _scheduler->insertActionList(_alNewscrIndex); + } else if (y1 < _maze.y1 - SHIFT) { + // Exit north + _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p - _maze.size; + _actListArr[_alNewscrIndex][0].a2.x = _maze.x3; + _actListArr[_alNewscrIndex][0].a2.y = _maze.y2 - SHIFT - (y2 - y1); + _status.routeIndex = -1; + _scheduler->insertActionList(_alNewscrIndex); + } else if (y2 > _maze.y2 - SHIFT / 2) { + // Exit south + _actListArr[_alNewscrIndex][3].a8.screenIndex = *_screen_p + _maze.size; + _actListArr[_alNewscrIndex][0].a2.x = _maze.x4; + _actListArr[_alNewscrIndex][0].a2.y = _maze.y1 + SHIFT; + _status.routeIndex = -1; + _scheduler->insertActionList(_alNewscrIndex); + } +} + +// Search background command list for this screen for supplied object. +// Return first associated verb (not "look") or 0 if none found. +char *HugoEngine::useBG(char *name) { + debugC(1, kDebugEngine, "useBG(%s)", name); + + objectList_t p = _backgroundObjects[*_screen_p]; + for (int i = 0; *_arrayVerbs[p[i].verbIndex]; i++) { + if ((name == _arrayNouns[p[i].nounIndex][0] && + p[i].verbIndex != _look) && + ((p[i].roomState == DONT_CARE) || (p[i].roomState == _screenStates[*_screen_p]))) + return _arrayVerbs[p[i].verbIndex][0]; + } + + return 0; +} + +// Add action lists for this screen to event queue +void HugoEngine::screenActions(int screenNum) { + debugC(1, kDebugEngine, "screenActions(%d)", screenNum); + + uint16 *screenAct = _screenActs[screenNum]; + if (screenAct) { + for (int i = 0; screenAct[i]; i++) + _scheduler->insertActionList(screenAct[i]); + } +} + +// Set the new screen number into the hero object and any carried objects +void HugoEngine::setNewScreen(int screenNum) { + debugC(1, kDebugEngine, "setNewScreen(%d)", screenNum); + + *_screen_p = screenNum; // HERO object + for (int i = HERO + 1; i < _numObj; i++) { // Any others + if (_object->isCarried(i)) // being carried + _object->_objects[i].screenIndex = screenNum; + } +} + +// An object has collided with a boundary. See if any actions are required +void HugoEngine::boundaryCollision(object_t *obj) { + debugC(1, kDebugEngine, "boundaryCollision"); + + if (obj == _hero) { + // Hotspots only relevant to HERO + int x; + if (obj->vx > 0) + x = obj->x + obj->currImagePtr->x2; + else + x = obj->x + obj->currImagePtr->x1; + int y = obj->y + obj->currImagePtr->y2; + + for (int i = 0; _hotspots[i].screenIndex >= 0; i++) { + hotspot_t *hotspot = &_hotspots[i]; + if (hotspot->screenIndex == obj->screenIndex) + if ((x >= hotspot->x1) && (x <= hotspot->x2) && (y >= hotspot->y1) && (y <= hotspot->y2)) { + _scheduler->insertActionList(hotspot->actIndex); + break; + } + } + } else { + // Check whether an object collided with HERO + int dx = _hero->x + _hero->currImagePtr->x1 - obj->x - obj->currImagePtr->x1; + int dy = _hero->y + _hero->currImagePtr->y2 - obj->y - obj->currImagePtr->y2; + // If object's radius is infinity, use a closer value + int8 radius = obj->radius; + if (radius < 0) + radius = DX * 2; + if ((abs(dx) <= radius) && (abs(dy) <= radius)) + _scheduler->insertActionList(obj->actIndex); + } +} + +// Add up all the object values and all the bonus points +void HugoEngine::calcMaxScore() { + debugC(1, kDebugEngine, "calcMaxScore"); + + for (int i = 0; i < _numObj; i++) + _maxscore += _object->_objects[i].objValue; + + for (int i = 0; i < _numBonuses; i++) + _maxscore += _points[i].score; +} + +// Exit game, advertise trilogy, show copyright +void HugoEngine::endGame() { + debugC(1, kDebugEngine, "endGame"); + + if (!_boot.registered) + Utils::Box(BOX_ANY, "%s", _textEngine[kEsAdvertise]); + Utils::Box(BOX_ANY, "%s\n%s", _episode, COPYRIGHT); + _status.viewState = V_EXIT; +} + } // End of namespace Hugo diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h index 532f18d2ebc..0964029cab7 100644 --- a/engines/hugo/hugo.h +++ b/engines/hugo/hugo.h @@ -32,15 +32,29 @@ // This include is here temporarily while the engine is being refactored. #include "hugo/game.h" -#define HUGO_DAT_VER_MAJ 0 // 1 byte -#define HUGO_DAT_VER_MIN 19 // 1 byte -#define DATAALIGNMENT 4 +#define HUGO_DAT_VER_MAJ 0 // 1 byte +#define HUGO_DAT_VER_MIN 25 // 1 byte +#define DATAALIGNMENT 4 +#define EDGE 10 // Closest object can get to edge of screen +#define EDGE2 (EDGE * 2) // Push object further back on edge collision +#define SHIFT 8 // Place hero this far inside bounding box namespace Common { class RandomSource; } +/** + * This is the namespace of the Hugo engine. + * + * Status of this engine: ??? + * + * Games using this engine: + * - Hugo's House of Horror + * - Whodunit? + * - Jungle of Doom + */ namespace Hugo { + enum GameType { kGameTypeNone = 0, kGameTypeHugo1, @@ -48,21 +62,35 @@ enum GameType { kGameTypeHugo3 }; -enum HugoebugChannels { - kDebugSchedule = 1 << 0, - kDebugEngine = 1 << 1, - kDebugDisplay = 1 << 2, - kDebugMouse = 1 << 3, - kDebugParser = 1 << 4, - kDebugFile = 1 << 5, - kDebugRoute = 1 << 6, - kDebugInventory = 1 << 7 +enum GameVariant { + kGameVariantH1Win = 0, + kGameVariantH2Win, + kGameVariantH3Win, + kGameVariantH1Dos, + kGameVariantH2Dos, + kGameVariantH3Dos +}; + +enum HugoDebugChannels { + kDebugSchedule = 1 << 0, + kDebugEngine = 1 << 1, + kDebugDisplay = 1 << 2, + kDebugMouse = 1 << 3, + kDebugParser = 1 << 4, + kDebugFile = 1 << 5, + kDebugRoute = 1 << 6, + kDebugInventory = 1 << 7, + kDebugObject = 1 << 8 }; enum HugoGameFeatures { GF_PACKED = (1 << 0) // Database }; +// Strings used by the engine +enum seqTextEngine { + kEsAdvertise = 0 +}; struct HugoGameDescription; class FileManager; @@ -74,6 +102,8 @@ class Parser; class Route; class SoundHandler; class IntroHandler; +class ObjectHandler; + class HugoEngine : public Engine { public: @@ -97,6 +127,8 @@ public: byte *_introX; byte *_introY; byte *_screenStates; + byte *_arrayFont[3]; + int16 _arrayFontSize[3]; char **_textData; char **_stringtData; char **_screenNames; @@ -112,13 +144,17 @@ public: hotspot_t *_hotspots; int16 *_invent; uses_t *_uses; + uint16 _usesSize; background_t *_catchallList; background_t **_backgroundObjects; + uint16 _backgroundObjectsSize; point_t *_points; cmd **_cmdList; + uint16 _cmdListSize; uint16 **_screenActs; - object_t *_objects; + uint16 _screenActsSize; act **_actListArr; + uint16 _actListArrSize; int16 *_defltTunes; uint16 _look; uint16 _take; @@ -131,8 +167,10 @@ public: const char *_episode; const char *_picDir; - char _initFilename[20]; - char _saveFilename[20]; + Common::String _initFilename, _saveFilename; + + command_t _statusLine; + command_t _scoreLine; const HugoGameDescription *_gameDescription; uint32 getFeatures() const; @@ -143,38 +181,10 @@ public: // Temporary, until the engine is fully objectified. static HugoEngine &get() { - assert(s_Engine != NULL); + assert(s_Engine != 0); return *s_Engine; } - FileManager &file() { - return *_fileManager; - } - Scheduler &scheduler() { - return *_scheduler; - } - Screen &screen() { - return *_screen; - } - MouseHandler &mouse() { - return *_mouseHandler; - } - InventoryHandler &inventory() { - return *_inventoryHandler; - } - Parser &parser() { - return *_parser; - } - Route &route() { - return *_route; - } - SoundHandler &sound() { - return *_soundHandler; - } - IntroHandler &intro() { - return *_introHandler; - } - void initGame(const HugoGameDescription *gd); void initGamePart(const HugoGameDescription *gd); bool loadHugoDat(); @@ -186,23 +196,22 @@ public: return _mouseY; } - void initStatus(); - void readObjectImages(); - void readUIFImages(); - void updateImages(); - void moveObjects(); - void useObject(int16 objId); - bool findObjectSpace(object_t *obj, int16 *destx, int16 *desty); - int16 findObject(uint16 x, uint16 y); - void lookObject(object_t *obj); - void storeBoundary(int x1, int x2, int y); + void boundaryCollision(object_t *obj); void clearBoundary(int x1, int x2, int y); void endGame(); + void initStatus(); + void processMaze(); + void readObjectImages(); void readScreenFiles(int screen); - void setNewScreen(int screen); - void initNewScreenDisplay(); void screenActions(int screen); + void setNewScreen(int screen); void shutdown(); + void storeBoundary(int x1, int x2, int y); + + char *useBG(char *name); + + int deltaX(int x1, int x2, int vx, int y); + int deltaY(int x1, int x2, int vy, int y); overlay_t &getBoundaryOverlay() { return _boundary; @@ -216,11 +225,9 @@ public: overlay_t &getFirstOverlay() { return _overlay; } - status_t &getGameStatus() { return _status; } - int getScore() const { return _score; } @@ -240,6 +247,17 @@ public: return _introXSize; } + FileManager *_file; + Scheduler *_scheduler; + Screen *_screen; + MouseHandler *_mouse; + InventoryHandler *_inventory; + Parser *_parser; + Route *_route; + SoundHandler *_sound; + IntroHandler *_intro; + ObjectHandler *_object; + protected: // Engine APIs @@ -270,16 +288,6 @@ private: Common::Platform _platform; bool _packedFl; - FileManager *_fileManager; - Scheduler *_scheduler; - Screen *_screen; - MouseHandler *_mouseHandler; - InventoryHandler *_inventoryHandler; - Parser *_parser; - Route *_route; - SoundHandler *_soundHandler; - IntroHandler *_introHandler; - int _score; // Holds current score int _maxscore; // Holds maximum score @@ -292,19 +300,10 @@ private: void initPlaylist(bool playlist[MAX_TUNES]); void initConfig(inst_t action); void initialize(); - int deltaX(int x1, int x2, int vx, int y); - int deltaY(int x1, int x2, int vy, int y); - void processMaze(); - //int y2comp (const void *a, const void *b); - char *useBG(char *name); - void freeObjects(); - void boundaryCollision(object_t *obj); void calcMaxScore(); void initMachine(); void runMachine(); - static int y2comp(const void *a, const void *b); - }; } // End of namespace Hugo diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp index c2198d87bce..d63a979fe10 100644 --- a/engines/hugo/intro.cpp +++ b/engines/hugo/intro.cpp @@ -32,155 +32,15 @@ #include "common/system.h" -#include "hugo/game.h" #include "hugo/hugo.h" #include "hugo/intro.h" -#include "hugo/file.h" -#include "hugo/display.h" -#include "hugo/util.h" - namespace Hugo { -IntroHandler::IntroHandler(HugoEngine &vm) : _vm(vm) { +IntroHandler::IntroHandler(HugoEngine *vm) : _vm(vm) { } IntroHandler::~IntroHandler() { } -intro_1w::intro_1w(HugoEngine &vm) : IntroHandler(vm) { -} - -intro_1w::~intro_1w() { -} - -void intro_1w::preNewGame() { - // Auto-start a new game - _vm.file().restoreGame(-1); - _vm.getGameStatus().viewState = V_INTROINIT; -} - -void intro_1w::introInit() { -} - -bool intro_1w::introPlay() { - return true; -} - -intro_2w::intro_2w(HugoEngine &vm) : IntroHandler(vm) { -} - -intro_2w::~intro_2w() { -} - -void intro_2w::preNewGame() { -} - -void intro_2w::introInit() { -} - -bool intro_2w::introPlay() { - return true; -} - -intro_3w::intro_3w(HugoEngine &vm) : IntroHandler(vm) { -} - -intro_3w::~intro_3w() { -} - -void intro_3w::preNewGame() { -} - -void intro_3w::introInit() { -// Hugo 3 - show map and set up for introPlay() -//#if STORY - _vm.file().readBackground(22); // display screen MAP_3w - _vm.screen().displayBackground(); - introTicks = 0; -//#endif -} - -bool intro_3w::introPlay() { - byte introSize = _vm.getIntroSize(); - -// Hugo 3 - Preamble screen before going into game. Draws path of Hugo's plane. -// Called every tick. Returns TRUE when complete -//TODO : Add proper check of story mode -//#if STORY -// SetBkMode(TRANSPARENT); - if (introTicks < introSize) { - // Scale viewport x_intro,y_intro to screen (offsetting y) - _vm.screen().writeChar(_vm._introX[introTicks], _vm._introY[introTicks] - DIBOFF_Y, 'x', _TBRIGHTWHITE); - - // Text boxes at various times - switch (introTicks) { - case 4: - Utils::Box(BOX_OK, "%s", _vm._textIntro[kIntro1]); - break; - case 9: - Utils::Box(BOX_OK, "%s", _vm._textIntro[kIntro2]); - break; - case 35: - Utils::Box(BOX_OK, "%s", _vm._textIntro[kIntro3]); - break; - } - } - - return (++introTicks >= introSize); -//#else //STORY -// return true; -//#endif //STORY -} - -intro_1d::intro_1d(HugoEngine &vm) : IntroHandler(_vm) { -} - -intro_1d::~intro_1d() { -} - -void intro_1d::preNewGame() { -} - -void intro_1d::introInit() { -} - -bool intro_1d::introPlay() { - warning("STUB: intro_1d::introPlay()"); - return true; -} -//TODO : Add code for intro H2 DOS -intro_2d::intro_2d(HugoEngine &vm) : IntroHandler(_vm) { -} - -intro_2d::~intro_2d() { -} - -void intro_2d::preNewGame() { -} - -void intro_2d::introInit() { -} - -bool intro_2d::introPlay() { - return true; -} - -//TODO : Add code for intro H3 DOS -intro_3d::intro_3d(HugoEngine &vm) : IntroHandler(_vm) { -} - -intro_3d::~intro_3d() { -} - -void intro_3d::preNewGame() { -} - -void intro_3d::introInit() { -} - -bool intro_3d::introPlay() { - return true; -} - } // End of namespace Hugo diff --git a/engines/hugo/intro.h b/engines/hugo/intro.h index 555ae4326ab..f1de01e609d 100644 --- a/engines/hugo/intro.h +++ b/engines/hugo/intro.h @@ -43,7 +43,7 @@ enum seqTextIntro { class IntroHandler { public: - IntroHandler(HugoEngine &vm); + IntroHandler(HugoEngine *vm); virtual ~IntroHandler(); virtual void preNewGame() = 0; @@ -51,64 +51,64 @@ public: virtual bool introPlay() = 0; protected: - HugoEngine &_vm; + HugoEngine *_vm; int16 introTicks; // Count calls to introPlay() }; -class intro_1w : public IntroHandler { +class intro_v1w : public IntroHandler { public: - intro_1w(HugoEngine &vm); - ~intro_1w(); + intro_v1w(HugoEngine *vm); + ~intro_v1w(); void preNewGame(); void introInit(); bool introPlay(); }; -class intro_1d : public IntroHandler { +class intro_v1d : public IntroHandler { public: - intro_1d(HugoEngine &vm); - ~intro_1d(); + intro_v1d(HugoEngine *vm); + ~intro_v1d(); void preNewGame(); void introInit(); bool introPlay(); }; -class intro_2w : public IntroHandler { +class intro_v2w : public IntroHandler { public: - intro_2w(HugoEngine &vm); - ~intro_2w(); + intro_v2w(HugoEngine *vm); + ~intro_v2w(); void preNewGame(); void introInit(); bool introPlay(); }; -class intro_2d : public IntroHandler { +class intro_v2d : public IntroHandler { public: - intro_2d(HugoEngine &vm); - ~intro_2d(); + intro_v2d(HugoEngine *vm); + ~intro_v2d(); void preNewGame(); void introInit(); bool introPlay(); }; -class intro_3w : public IntroHandler { +class intro_v3w : public IntroHandler { public: - intro_3w(HugoEngine &vm); - ~intro_3w(); + intro_v3w(HugoEngine *vm); + ~intro_v3w(); void preNewGame(); void introInit(); bool introPlay(); }; -class intro_3d : public IntroHandler { +class intro_v3d : public IntroHandler { public: - intro_3d(HugoEngine &vm); - ~intro_3d(); + intro_v3d(HugoEngine *vm); + ~intro_v3d(); void preNewGame(); void introInit(); diff --git a/engines/hugo/intro_v1d.cpp b/engines/hugo/intro_v1d.cpp new file mode 100644 index 00000000000..61626e8172d --- /dev/null +++ b/engines/hugo/intro_v1d.cpp @@ -0,0 +1,172 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/intro.h" +#include "hugo/display.h" + +namespace Hugo { +intro_v1d::intro_v1d(HugoEngine *vm) : IntroHandler(vm) { +} + +intro_v1d::~intro_v1d() { +} + +void intro_v1d::preNewGame() { +} + +void intro_v1d::introInit() { + introTicks = 0; +} + +bool intro_v1d::introPlay() { + static int state = 0; + byte introSize = _vm->getIntroSize(); + + if (introTicks < introSize) { + switch (state++) { + case 0: + _vm->_screen->drawRectangle(true, 0, 0, 319, 199, _TMAGENTA); + _vm->_screen->drawRectangle(true, 10, 10, 309, 189, _TBLACK); + break; + + case 1: + _vm->_screen->drawShape(20, 92,_TLIGHTMAGENTA,_TMAGENTA); + _vm->_screen->drawShape(250,92,_TLIGHTMAGENTA,_TMAGENTA); + + // HACK: use of TROMAN, size 10-5 + _vm->_screen->loadFont(0); + + char buffer[80]; + if (_boot.registered) + strcpy(buffer, "Registered Version"); + else + strcpy(buffer, "Shareware Version"); + _vm->_screen->writeStr(CENTER, 163, buffer, _TLIGHTMAGENTA); + _vm->_screen->writeStr(CENTER, 176, COPYRIGHT, _TLIGHTMAGENTA); + + if (scumm_stricmp(_boot.distrib, "David P. Gray")) { + sprintf(buffer, "Distributed by %s.", _boot.distrib); + _vm->_screen->writeStr(CENTER, 75, buffer, _TMAGENTA); + } + + // HACK: use of SCRIPT size 24-16 + _vm->_screen->loadFont(2); + + strcpy(buffer, "Hugo's"); + _vm->_screen->writeStr(CENTER, 20, buffer, _TMAGENTA); + + // HACK: use of TROMAN, size 30-24 + strcpy(buffer, "House of Horrors !"); + _vm->_screen->writeStr(CENTER, 50, buffer, _TLIGHTMAGENTA); + break; + case 2: + _vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK); + // HACK: use of TROMAN, size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "S t a r r i n g :"); + _vm->_screen->writeStr(CENTER, 95, buffer, _TMAGENTA); + break; + case 3: + // HACK: use of TROMAN size 20-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "Hugo !"); + _vm->_screen->writeStr(CENTER, 115, buffer, _TLIGHTMAGENTA); + break; + case 4: + _vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK); + // HACK: use of TROMAN size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "P r o d u c e d b y :"); + _vm->_screen->writeStr(CENTER, 95, buffer, _TMAGENTA); + break; + case 5: + // HACK: use of TROMAN size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "David P Gray !"); + _vm->_screen->writeStr(CENTER, 115, buffer, _TLIGHTMAGENTA); + break; + case 6: + _vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK); + // HACK: use of TROMAN size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "D i r e c t e d b y :"); + _vm->_screen->writeStr(CENTER, 95, buffer, _TMAGENTA); + break; + case 7: + // HACK: use of TROMAN size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "David P Gray !"); + _vm->_screen->writeStr(CENTER, 115, buffer, _TLIGHTMAGENTA); + break; + case 8: + _vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK); + // HACK: use of TROMAN size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "M u s i c b y :"); + _vm->_screen->writeStr(CENTER, 95, buffer, _TMAGENTA); + break; + case 9: + // HACK: use of TROMAN size 16-9 + _vm->_screen->loadFont(2); + + strcpy(buffer, "David P Gray !"); + _vm->_screen->writeStr(CENTER, 115, buffer, _TLIGHTMAGENTA); + break; + case 10: + _vm->_screen->drawRectangle(true, 82, 92, 237, 138, _TBLACK); + // HACK: use of TROMAN size 20-14 + _vm->_screen->loadFont(2); + + strcpy(buffer, "E n j o y !"); + _vm->_screen->writeStr(CENTER, 100, buffer, _TLIGHTMAGENTA); + break; + } + + _vm->_screen->displayBackground(); + g_system->updateScreen(); + g_system->delayMillis(1000); + } + + return (++introTicks >= introSize); +} + +} // End of namespace Hugo diff --git a/engines/hugo/intro_v1w.cpp b/engines/hugo/intro_v1w.cpp new file mode 100644 index 00000000000..74efc4ff8cd --- /dev/null +++ b/engines/hugo/intro_v1w.cpp @@ -0,0 +1,61 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/intro.h" +#include "hugo/file.h" + + + +namespace Hugo { +intro_v1w::intro_v1w(HugoEngine *vm) : IntroHandler(vm) { +} + +intro_v1w::~intro_v1w() { +} + +void intro_v1w::preNewGame() { + // Auto-start a new game + _vm->_file->restoreGame(-1); + _vm->getGameStatus().viewState = V_INTROINIT; +} + +void intro_v1w::introInit() { +} + +bool intro_v1w::introPlay() { + return true; +} + +} // End of namespace Hugo diff --git a/engines/hugo/intro_v2d.cpp b/engines/hugo/intro_v2d.cpp new file mode 100644 index 00000000000..0c9f85d1ea5 --- /dev/null +++ b/engines/hugo/intro_v2d.cpp @@ -0,0 +1,77 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/intro.h" +#include "hugo/file.h" +#include "hugo/display.h" + +namespace Hugo { + +intro_v2d::intro_v2d(HugoEngine *vm) : IntroHandler(vm) { +} + +intro_v2d::~intro_v2d() { +} + +void intro_v2d::preNewGame() { +} + +void intro_v2d::introInit() { + _vm->_screen->loadFont(0); + _vm->_file->readBackground(_vm->_numScreens - 1); // display splash screen + + char buffer[128]; + + if (_boot.registered) + sprintf(buffer, "%s Registered Version", COPYRIGHT); + else + sprintf(buffer, "%s Shareware Version", COPYRIGHT); + _vm->_screen->writeStr(CENTER, 186, buffer, _TLIGHTRED); + + if (scumm_stricmp(_boot.distrib, "David P. Gray")) { + sprintf(buffer, "Distributed by %s.", _boot.distrib); + _vm->_screen->writeStr(CENTER, 1, buffer, _TLIGHTRED); + } + + _vm->_screen->displayBackground(); + g_system->updateScreen(); + g_system->delayMillis(5000); +} + +bool intro_v2d::introPlay() { + return true; +} + +} // End of namespace Hugo diff --git a/engines/hugo/intro_v2w.cpp b/engines/hugo/intro_v2w.cpp new file mode 100644 index 00000000000..414846bfc7f --- /dev/null +++ b/engines/hugo/intro_v2w.cpp @@ -0,0 +1,57 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/intro.h" + + +namespace Hugo { + +intro_v2w::intro_v2w(HugoEngine *vm) : IntroHandler(vm) { +} + +intro_v2w::~intro_v2w() { +} + +void intro_v2w::preNewGame() { +} + +void intro_v2w::introInit() { +} + +bool intro_v2w::introPlay() { + return true; +} + +} // End of namespace Hugo diff --git a/engines/hugo/intro_v3d.cpp b/engines/hugo/intro_v3d.cpp new file mode 100644 index 00000000000..8e0c0cc22cc --- /dev/null +++ b/engines/hugo/intro_v3d.cpp @@ -0,0 +1,109 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/intro.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/util.h" + + +namespace Hugo { +intro_v3d::intro_v3d(HugoEngine *vm) : IntroHandler(vm) { +} + +intro_v3d::~intro_v3d() { +} + +void intro_v3d::preNewGame() { +} + +void intro_v3d::introInit() { + _vm->_screen->loadFont(0); + _vm->_file->readBackground(_vm->_numScreens - 1); // display splash screen + + char buffer[128]; + if (_boot.registered) + sprintf(buffer, "%s Registered Version", COPYRIGHT); + else + sprintf(buffer,"%s Shareware Version", COPYRIGHT); + + _vm->_screen->writeStr(CENTER, 190, buffer, _TBROWN); + + if (scumm_stricmp(_boot.distrib, "David P. Gray")) { + sprintf(buffer, "Distributed by %s.", _boot.distrib); + _vm->_screen->writeStr(CENTER, 0, buffer, _TBROWN); + } + + _vm->_screen->displayBackground(); + g_system->updateScreen(); + g_system->delayMillis(5000); + + _vm->_file->readBackground(22); // display screen MAP_3d + _vm->_screen->displayBackground(); + introTicks = 0; +} + +bool intro_v3d::introPlay() { + byte introSize = _vm->getIntroSize(); + +// Hugo 3 - Preamble screen before going into game. Draws path of Hugo's plane. +// Called every tick. Returns TRUE when complete +//TODO : Add proper check of story mode +//#if STORY + if (introTicks < introSize) { + _vm->_screen->writeStr(_vm->_introX[introTicks], _vm->_introY[introTicks] - DIBOFF_Y, "x", _TBRIGHTWHITE); + _vm->_screen->displayBackground(); + + // Text boxes at various times + switch (introTicks) { + case 4: + Utils::Box(BOX_OK, "%s", _vm->_textIntro[kIntro1]); + break; + case 9: + Utils::Box(BOX_OK, "%s", _vm->_textIntro[kIntro2]); + break; + case 35: + Utils::Box(BOX_OK, "%s", _vm->_textIntro[kIntro3]); + break; + } + } + + return (++introTicks >= introSize); +//#else //STORY +// return true; +//#endif //STORY +} + +} // End of namespace Hugo diff --git a/engines/hugo/intro_v3w.cpp b/engines/hugo/intro_v3w.cpp new file mode 100644 index 00000000000..a0bc624760b --- /dev/null +++ b/engines/hugo/intro_v3w.cpp @@ -0,0 +1,94 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/intro.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/util.h" + +namespace Hugo { + +intro_v3w::intro_v3w(HugoEngine *vm) : IntroHandler(vm) { +} + +intro_v3w::~intro_v3w() { +} + +void intro_v3w::preNewGame() { +} + +void intro_v3w::introInit() { +// Hugo 3 - show map and set up for introPlay() +//#if STORY + _vm->_file->readBackground(22); // display screen MAP_3w + _vm->_screen->displayBackground(); + introTicks = 0; + _vm->_screen->loadFont(0); +//#endif +} + +bool intro_v3w::introPlay() { + byte introSize = _vm->getIntroSize(); + +// Hugo 3 - Preamble screen before going into game. Draws path of Hugo's plane. +// Called every tick. Returns TRUE when complete +//TODO : Add proper check of story mode +//#if STORY + if (introTicks < introSize) { + // Scale viewport x_intro,y_intro to screen (offsetting y) + _vm->_screen->writeStr(_vm->_introX[introTicks], _vm->_introY[introTicks] - DIBOFF_Y, "x", _TBRIGHTWHITE); + _vm->_screen->displayBackground(); + + + // Text boxes at various times + switch (introTicks) { + case 4: + Utils::Box(BOX_OK, "%s", _vm->_textIntro[kIntro1]); + break; + case 9: + Utils::Box(BOX_OK, "%s", _vm->_textIntro[kIntro2]); + break; + case 35: + Utils::Box(BOX_OK, "%s", _vm->_textIntro[kIntro3]); + break; + } + } + + return (++introTicks >= introSize); +//#else //STORY +// return true; +//#endif //STORY +} +} // End of namespace Hugo diff --git a/engines/hugo/inventory.cpp b/engines/hugo/inventory.cpp index c5f09ad653b..ad0d5cbce92 100644 --- a/engines/hugo/inventory.cpp +++ b/engines/hugo/inventory.cpp @@ -40,12 +40,13 @@ #include "hugo/mouse.h" #include "hugo/inventory.h" #include "hugo/parser.h" +#include "hugo/object.h" namespace Hugo { #define MAX_DISP (XPIX / INV_DX) // Max icons displayable -InventoryHandler::InventoryHandler(HugoEngine &vm) : _vm(vm) { +InventoryHandler::InventoryHandler(HugoEngine *vm) : _vm(vm) { } // Construct the inventory scrollbar in dib_i @@ -54,17 +55,15 @@ InventoryHandler::InventoryHandler(HugoEngine &vm) : _vm(vm) { // scrollFl is TRUE if scroll arrows required // firstObjId is index of first (scrolled) inventory object to display void InventoryHandler::constructInventory(int16 imageTotNumb, int displayNumb, bool scrollFl, int16 firstObjId) { - int16 ux, uy, ix; // Coordinates of icons - debugC(1, kDebugInventory, "constructInventory(%d, %d, %d, %d)", imageTotNumb, displayNumb, (scrollFl) ? 0 : 1, firstObjId); // Clear out icon buffer - memset(_vm.screen().getIconBuffer(), 0, sizeof(_vm.screen().getIconBuffer())); + memset(_vm->_screen->getIconBuffer(), 0, sizeof(_vm->_screen->getIconBuffer())); // If needed, copy arrows - reduce number of icons displayable if (scrollFl) { // Display at first and last icon positions - _vm.screen().moveImage(_vm.screen().getGUIBuffer(), 0, 0, INV_DX, INV_DY, XPIX, _vm.screen().getIconBuffer(), 0, 0, XPIX); - _vm.screen().moveImage(_vm.screen().getGUIBuffer(), INV_DX, 0, INV_DX, INV_DY, XPIX, _vm.screen().getIconBuffer(), INV_DX *(MAX_DISP - 1), 0, XPIX); + _vm->_screen->moveImage(_vm->_screen->getGUIBuffer(), 0, 0, INV_DX, INV_DY, XPIX, _vm->_screen->getIconBuffer(), 0, 0, XPIX); + _vm->_screen->moveImage(_vm->_screen->getGUIBuffer(), INV_DX, 0, INV_DX, INV_DY, XPIX, _vm->_screen->getIconBuffer(), INV_DX *(MAX_DISP - 1), 0, XPIX); displayNumb = MIN(displayNumb, MAX_DISP - NUM_ARROWS); } else // No, override first index - we can show 'em all! firstObjId = 0; @@ -73,19 +72,19 @@ void InventoryHandler::constructInventory(int16 imageTotNumb, int displayNumb, b int16 displayed = 0; int16 carried = 0; for (int16 i = 0; i < imageTotNumb; i++) { - if (_vm._objects[_vm._invent[i]].carriedFl) { + if (_vm->_object->isCarried(_vm->_invent[i])) { // Check still room to display and past first scroll index if (displayed < displayNumb && carried >= firstObjId) { // Compute source coordinates in dib_u - ux = (i + NUM_ARROWS) * INV_DX % XPIX; - uy = (i + NUM_ARROWS) * INV_DX / XPIX * INV_DY; + int16 ux = (i + NUM_ARROWS) * INV_DX % XPIX; + int16 uy = (i + NUM_ARROWS) * INV_DX / XPIX * INV_DY; // Compute dest coordinates in dib_i - ix = ((scrollFl) ? displayed + 1 : displayed) * INV_DX; + int16 ix = ((scrollFl) ? displayed + 1 : displayed) * INV_DX; displayed++; // Count number displayed // Copy the icon - _vm.screen().moveImage(_vm.screen().getGUIBuffer(), ux, uy, INV_DX, INV_DY, XPIX, _vm.screen().getIconBuffer(), ix, 0, XPIX); + _vm->_screen->moveImage(_vm->_screen->getGUIBuffer(), ux, uy, INV_DX, INV_DY, XPIX, _vm->_screen->getIconBuffer(), ix, 0, XPIX); } carried++; // Count number carried } @@ -95,24 +94,23 @@ void InventoryHandler::constructInventory(int16 imageTotNumb, int displayNumb, b // Process required action for inventory // Returns objId under cursor (or -1) for INV_GET int16 InventoryHandler::processInventory(invact_t action, ...) { - static int16 firstIconId = 0; // Index of first icon to display - int16 i, j; - int16 objId = -1; // Return objid under cursor - int16 imageNumb; // Total number of inventory items - int displayNumb; // Total number displayed/carried - int16 cursorx, cursory; // Current cursor position - bool scrollFl; // TRUE if scroll arrows needed - va_list marker; // Args used for D_ADD operation - debugC(1, kDebugInventory, "processInventory(invact_t action, ...)"); + static int16 firstIconId = 0; // Index of first icon to display + + int16 imageNumb; // Total number of inventory items + int displayNumb; // Total number displayed/carried // Compute total number and number displayed, i.e. number carried - for (imageNumb = 0, displayNumb = 0; imageNumb < _vm._maxInvent && _vm._invent[imageNumb] != -1; imageNumb++) - if (_vm._objects[_vm._invent[imageNumb]].carriedFl) + for (imageNumb = 0, displayNumb = 0; imageNumb < _vm->_maxInvent && _vm->_invent[imageNumb] != -1; imageNumb++) { + if (_vm->_object->isCarried(_vm->_invent[imageNumb])) displayNumb++; + } // Will we need the scroll arrows? - scrollFl = displayNumb > MAX_DISP; + bool scrollFl = displayNumb > MAX_DISP; + va_list marker; // Args used for D_ADD operation + int16 cursorx, cursory; // Current cursor position + int16 objId = -1; // Return objid under cursor switch (action) { case INV_INIT: // Initialize inventory display @@ -135,11 +133,11 @@ int16 InventoryHandler::processInventory(invact_t action, ...) { cursory -= DIBOFF_Y; // Icon bar is at true zero if (cursory > 0 && cursory < INV_DY) { // Within icon bar? - i = cursorx / INV_DX; // Compute icon index - if (scrollFl) { // Scroll buttons displayed - if (i == 0) // Left scroll button + int16 i = cursorx / INV_DX; // Compute icon index + if (scrollFl) { // Scroll buttons displayed + if (i == 0) { // Left scroll button objId = LEFT_ARROW; - else { + } else { if (i == MAX_DISP - 1) // Right scroll button objId = RIGHT_ARROW; else // Adjust for scroll @@ -148,12 +146,16 @@ int16 InventoryHandler::processInventory(invact_t action, ...) { } // If not an arrow, find object id - limit to valid range - if (objId == -1 && i < displayNumb) + if (objId == -1 && i < displayNumb) { // Find objid by counting # carried objects == i+1 - for (j = 0, i++; i > 0 && j < _vm._numObj; j++) - if (_vm._objects[j].carriedFl) + int16 j; + for (j = 0, i++; i > 0 && j < _vm->_numObj; j++) { + if (_vm->_object->isCarried(j)) { if (--i == 0) objId = j; + } + } + } } break; } @@ -161,7 +163,7 @@ int16 InventoryHandler::processInventory(invact_t action, ...) { } void InventoryHandler::runInventory() { - status_t &gameStatus = _vm.getGameStatus(); + status_t &gameStatus = _vm->getGameStatus(); debugC(1, kDebugInventory, "runInventory"); @@ -175,15 +177,15 @@ void InventoryHandler::runInventory() { gameStatus.inventoryHeight = 0; // Move visible portion to _frontBuffer, restore uncovered portion, display results - _vm.screen().moveImage(_vm.screen().getIconBuffer(), 0, 0, XPIX, gameStatus.inventoryHeight, XPIX, _vm.screen().getFrontBuffer(), 0, DIBOFF_Y, XPIX); - _vm.screen().moveImage(_vm.screen().getBackBufferBackup(), 0, gameStatus.inventoryHeight + DIBOFF_Y, XPIX, STEP_DY, XPIX, _vm.screen().getFrontBuffer(), 0, gameStatus.inventoryHeight + DIBOFF_Y, XPIX); - _vm.screen().displayRect(0, DIBOFF_Y, XPIX, gameStatus.inventoryHeight + STEP_DY); + _vm->_screen->moveImage(_vm->_screen->getIconBuffer(), 0, 0, XPIX, gameStatus.inventoryHeight, XPIX, _vm->_screen->getFrontBuffer(), 0, DIBOFF_Y, XPIX); + _vm->_screen->moveImage(_vm->_screen->getBackBufferBackup(), 0, gameStatus.inventoryHeight + DIBOFF_Y, XPIX, STEP_DY, XPIX, _vm->_screen->getFrontBuffer(), 0, gameStatus.inventoryHeight + DIBOFF_Y, XPIX); + _vm->_screen->displayRect(0, DIBOFF_Y, XPIX, gameStatus.inventoryHeight + STEP_DY); if (gameStatus.inventoryHeight == 0) { // Finished moving up? // Yes, restore dibs and exit back to game state machine - _vm.screen().moveImage(_vm.screen().getBackBufferBackup(), 0, 0, XPIX, YPIX, XPIX, _vm.screen().getBackBuffer(), 0, 0, XPIX); - _vm.screen().moveImage(_vm.screen().getBackBuffer(), 0, 0, XPIX, YPIX, XPIX, _vm.screen().getFrontBuffer(), 0, 0, XPIX); - _vm.updateImages(); // Add objects back into display list for restore + _vm->_screen->moveImage(_vm->_screen->getBackBufferBackup(), 0, 0, XPIX, YPIX, XPIX, _vm->_screen->getBackBuffer(), 0, 0, XPIX); + _vm->_screen->moveImage(_vm->_screen->getBackBuffer(), 0, 0, XPIX, YPIX, XPIX, _vm->_screen->getFrontBuffer(), 0, 0, XPIX); + _vm->_object->updateImages(); // Add objects back into display list for restore gameStatus.inventoryState = I_OFF; gameStatus.viewState = V_PLAY; } @@ -193,9 +195,9 @@ void InventoryHandler::runInventory() { // and get any icon/text out of _frontBuffer if (gameStatus.inventoryHeight == 0) { processInventory(INV_INIT); // Initialize dib_i - _vm.screen().displayList(D_RESTORE); // Restore _frontBuffer - _vm.updateImages(); // Rebuild _frontBuffer without icons/text - _vm.screen().displayList(D_DISPLAY); // Blit display list to screen + _vm->_screen->displayList(D_RESTORE); // Restore _frontBuffer + _vm->_object->updateImages(); // Rebuild _frontBuffer without icons/text + _vm->_screen->displayList(D_DISPLAY); // Blit display list to screen } gameStatus.inventoryHeight += STEP_DY; // Move the icon bar down @@ -203,8 +205,8 @@ void InventoryHandler::runInventory() { gameStatus.inventoryHeight = INV_DY; // Move visible portion to _frontBuffer, display results - _vm.screen().moveImage(_vm.screen().getIconBuffer(), 0, 0, XPIX, gameStatus.inventoryHeight, XPIX, _vm.screen().getFrontBuffer(), 0, DIBOFF_Y, XPIX); - _vm.screen().displayRect(0, DIBOFF_Y, XPIX, gameStatus.inventoryHeight); + _vm->_screen->moveImage(_vm->_screen->getIconBuffer(), 0, 0, XPIX, gameStatus.inventoryHeight, XPIX, _vm->_screen->getFrontBuffer(), 0, DIBOFF_Y, XPIX); + _vm->_screen->displayRect(0, DIBOFF_Y, XPIX, gameStatus.inventoryHeight); if (gameStatus.inventoryHeight == INV_DY) { // Finished moving down? // Yes, prepare view dibs for special inventory display since @@ -212,17 +214,17 @@ void InventoryHandler::runInventory() { // 1. Save backing store _backBuffer in temporary dib_c // 2. Make snapshot of _frontBuffer the new _backBuffer backing store // 3. Reset the display list - _vm.screen().moveImage(_vm.screen().getBackBuffer(), 0, 0, XPIX, YPIX, XPIX, _vm.screen().getBackBufferBackup(), 0, 0, XPIX); - _vm.screen().moveImage(_vm.screen().getFrontBuffer(), 0, 0, XPIX, YPIX, XPIX, _vm.screen().getBackBuffer(), 0, 0, XPIX); - _vm.screen().displayList(D_INIT); + _vm->_screen->moveImage(_vm->_screen->getBackBuffer(), 0, 0, XPIX, YPIX, XPIX, _vm->_screen->getBackBufferBackup(), 0, 0, XPIX); + _vm->_screen->moveImage(_vm->_screen->getFrontBuffer(), 0, 0, XPIX, YPIX, XPIX, _vm->_screen->getBackBuffer(), 0, 0, XPIX); + _vm->_screen->displayList(D_INIT); gameStatus.inventoryState = I_ACTIVE; } break; case I_ACTIVE: // Inventory active - _vm.parser().charHandler(); // Still allow commands - _vm.screen().displayList(D_RESTORE); // Restore previous background - _vm.mouse().mouseHandler(); // Mouse activity - adds to display list - _vm.screen().displayList(D_DISPLAY); // Blit the display list to screen + _vm->_parser->charHandler(); // Still allow commands + _vm->_screen->displayList(D_RESTORE); // Restore previous background + _vm->_mouse->mouseHandler(); // Mouse activity - adds to display list + _vm->_screen->displayList(D_DISPLAY); // Blit the display list to screen break; } } diff --git a/engines/hugo/inventory.h b/engines/hugo/inventory.h index 5cc1af28c24..36fca71a431 100644 --- a/engines/hugo/inventory.h +++ b/engines/hugo/inventory.h @@ -40,13 +40,13 @@ namespace Hugo { class InventoryHandler { public: - InventoryHandler(HugoEngine &vm); + InventoryHandler(HugoEngine *vm); int16 processInventory(invact_t action, ...); void runInventory(); private: - HugoEngine &_vm; + HugoEngine *_vm; void constructInventory(int16 imageTotNumb, int displayNumb, bool scrollFl, int16 firstObjId); }; diff --git a/engines/hugo/module.mk b/engines/hugo/module.mk index f7aa45a2c28..75c9f9d5e2f 100644 --- a/engines/hugo/module.mk +++ b/engines/hugo/module.mk @@ -3,15 +3,39 @@ MODULE := engines/hugo MODULE_OBJS := \ detection.o \ display.o \ - engine.o \ + display_v1d.o \ + display_v1w.o \ file.o \ + file_v1d.o \ + file_v2d.o \ + file_v3d.o \ + file_v1w.o \ hugo.o \ intro.o \ + intro_v1d.o \ + intro_v2d.o \ + intro_v3d.o \ + intro_v1w.o \ + intro_v2w.o \ + intro_v3w.o \ inventory.o \ mouse.o \ + object.o \ + object_v1d.o \ + object_v1w.o \ + object_v2d.o \ + object_v3d.o \ parser.o \ + parser_v1w.o \ + parser_v1d.o \ + parser_v2d.o \ + parser_v3d.o \ route.o \ schedule.o \ + schedule_v1d.o \ + schedule_v1w.o \ + schedule_v2d.o \ + schedule_v3d.o \ sound.o \ util.o diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp index a3f695b92a3..9fc8a333734 100644 --- a/engines/hugo/mouse.cpp +++ b/engines/hugo/mouse.cpp @@ -43,6 +43,7 @@ #include "hugo/inventory.h" #include "hugo/route.h" #include "hugo/util.h" +#include "hugo/object.h" namespace Hugo { @@ -59,83 +60,78 @@ enum seqTextMouse { kMsExit = 1 }; -MouseHandler::MouseHandler(HugoEngine &vm) : _vm(vm) { +MouseHandler::MouseHandler(HugoEngine *vm) : _vm(vm) { } // Shadow-blit supplied string into dib_a at cx,cy and add to display list void MouseHandler::cursorText(char *buffer, int16 cx, int16 cy, uif_t fontId, int16 color) { - debugC(1, kDebugMouse, "cursorText(%s, %d, %d, %d, %d)", buffer, cx, cy, fontId, color); - if (_vm.getPlatform() == Common::kPlatformWindows) - _vm.screen().loadFont(fontId); + _vm->_screen->loadFont(fontId); // Find bounding rect for string - int16 sdx = _vm.screen().stringLength(buffer); - int16 sdy = _vm.screen().fontHeight() + 1; // + 1 for shadow + int16 sdx = _vm->_screen->stringLength(buffer); + int16 sdy = _vm->_screen->fontHeight() + 1; // + 1 for shadow int16 sx = (cx < XPIX / 2) ? cx + SX_OFF : cx - sdx - SX_OFF / 2; int16 sy = cy + SY_OFF; // Display the string and add rect to display list - _vm.screen().shadowStr(sx, sy, buffer, _TBRIGHTWHITE); - _vm.screen().displayList(D_ADD, sx, sy, sdx, sdy); + _vm->_screen->shadowStr(sx, sy, buffer, _TBRIGHTWHITE); + _vm->_screen->displayList(D_ADD, sx, sy, sdx, sdy); } - // Find the exit hotspot containing cx, cy. // Return hotspot index or -1 if not found. int16 MouseHandler::findExit(int16 cx, int16 cy) { - int i; - hotspot_t *hotspot; - debugC(2, kDebugMouse, "findExit(%d, %d)", cx, cy); - for (i = 0, hotspot = _vm._hotspots; hotspot->screenIndex >= 0; i++, hotspot++) - if (hotspot->screenIndex == *_vm._screen_p) + int i = 0; + for (hotspot_t *hotspot = _vm->_hotspots; hotspot->screenIndex >= 0; i++, hotspot++) { + if (hotspot->screenIndex == *_vm->_screen_p) { if (cx >= hotspot->x1 && cx <= hotspot->x2 && cy >= hotspot->y1 && cy <= hotspot->y2) - return(i); - return(-1); + return i; + } + } + return -1; } // Process a mouse right click at coord cx, cy over object objid void MouseHandler::processRightClick(int16 objId, int16 cx, int16 cy) { - object_t *obj; - int16 x, y; - bool foundFl = false; // TRUE if route found to object - debugC(1, kDebugMouse, "Process_rclick(%d, %d, %d)", objId, cx, cy); - status_t &gameStatus = _vm.getGameStatus(); + status_t &gameStatus = _vm->getGameStatus(); - if (gameStatus.storyModeFl || _vm._hero->pathType == QUIET) // Make sure user has control + if (gameStatus.storyModeFl || _vm->_hero->pathType == QUIET) // Make sure user has control return; + bool foundFl = false; // TRUE if route found to object // Check if this was over iconbar if (gameStatus.inventoryState == I_ACTIVE && cy < INV_DY + DIBOFF_Y) { // Clicked over iconbar object if (gameStatus.inventoryObjId == -1) gameStatus.inventoryObjId = objId; // Not using so select new object else if (gameStatus.inventoryObjId == objId) - gameStatus.inventoryObjId = -1; // Same icon - deselect it + gameStatus.inventoryObjId = -1; // Same icon - deselect it else - _vm.useObject(objId); // Use status.objid on object + _vm->_object->useObject(objId); // Use status.objid on object } else { // Clicked over viewport object - obj = &_vm._objects[objId]; + object_t *obj = &_vm->_object->_objects[objId]; + int16 x, y; switch (obj->viewx) { // Where to walk to case -1: // Walk to object position - if (_vm.findObjectSpace(obj, &x, &y)) - foundFl = _vm.route().startRoute(GO_GET, objId, x, y); - if (!foundFl) // Can't get there, try to use from here - _vm.useObject(objId); + if (_vm->_object->findObjectSpace(obj, &x, &y)) + foundFl = _vm->_route->startRoute(GO_GET, objId, x, y); + if (!foundFl) // Can't get there, try to use from here + _vm->_object->useObject(objId); break; case 0: // Immediate use - _vm.useObject(objId); // Pick up or use object + _vm->_object->useObject(objId); // Pick up or use object break; default: // Walk to view point if possible - if (!_vm.route().startRoute(GO_GET, objId, obj->viewx, obj->viewy)) { - if (_vm._hero->cycling == INVISIBLE) // If invisible do - _vm.useObject(objId); // immediate use + if (!_vm->_route->startRoute(GO_GET, objId, obj->viewx, obj->viewy)) { + if (_vm->_hero->cycling == INVISIBLE)// If invisible do + _vm->_object->useObject(objId); // immediate use else - Utils::Box(BOX_ANY, "%s", _vm._textMouse[kMsNoWayText]); // Can't get there + Utils::Box(BOX_ANY, "%s", _vm->_textMouse[kMsNoWayText]); // Can't get there } break; } @@ -149,47 +145,46 @@ void MouseHandler::processRightClick(int16 objId, int16 cx, int16 cy) { // 4. Nothing - attempt to walk there // 5. Exit - walk to exit hotspot void MouseHandler::processLeftClick(int16 objId, int16 cx, int16 cy) { - int16 i, x, y; - object_t *obj; - bool foundFl = false; // TRUE if route found to object - debugC(1, kDebugMouse, "Process_lclick(%d, %d, %d)", objId, cx, cy); - status_t &gameStatus = _vm.getGameStatus(); + int16 i, x, y; + object_t *obj; - if (gameStatus.storyModeFl || _vm._hero->pathType == QUIET) // Make sure user has control + status_t &gameStatus = _vm->getGameStatus(); + + if (gameStatus.storyModeFl || _vm->_hero->pathType == QUIET) // Make sure user has control return; switch (objId) { case -1: // Empty space - attempt to walk there - _vm.route().startRoute(GO_SPACE, 0, cx, cy); + _vm->_route->startRoute(GO_SPACE, 0, cx, cy); break; case LEFT_ARROW: // A scroll arrow - scroll the iconbar case RIGHT_ARROW: // Scroll the iconbar and display results - _vm.inventory().processInventory((objId == LEFT_ARROW) ? INV_LEFT : INV_RIGHT); - _vm.screen().moveImage(_vm.screen().getIconBuffer(), 0, 0, XPIX, INV_DY, XPIX, _vm.screen().getFrontBuffer(), 0, DIBOFF_Y, XPIX); - _vm.screen().moveImage(_vm.screen().getIconBuffer(), 0, 0, XPIX, INV_DY, XPIX, _vm.screen().getBackBuffer(), 0, DIBOFF_Y, XPIX); - _vm.screen().displayList(D_ADD, 0, DIBOFF_Y, XPIX, INV_DY); + _vm->_inventory->processInventory((objId == LEFT_ARROW) ? INV_LEFT : INV_RIGHT); + _vm->_screen->moveImage(_vm->_screen->getIconBuffer(), 0, 0, XPIX, INV_DY, XPIX, _vm->_screen->getFrontBuffer(), 0, DIBOFF_Y, XPIX); + _vm->_screen->moveImage(_vm->_screen->getIconBuffer(), 0, 0, XPIX, INV_DY, XPIX, _vm->_screen->getBackBuffer(), 0, DIBOFF_Y, XPIX); + _vm->_screen->displayList(D_ADD, 0, DIBOFF_Y, XPIX, INV_DY); break; case EXIT_HOTSPOT: // Walk to exit hotspot i = findExit(cx, cy); - x = _vm._hotspots[i].viewx; - y = _vm._hotspots[i].viewy; + x = _vm->_hotspots[i].viewx; + y = _vm->_hotspots[i].viewy; if (x >= 0) { // Hotspot refers to an exit // Special case of immediate exit if (gameStatus.jumpExitFl) { // Get rid of iconbar if necessary if (gameStatus.inventoryState != I_OFF) gameStatus.inventoryState = I_UP; - _vm.scheduler().insertActionList(_vm._hotspots[i].actIndex); + _vm->_scheduler->insertActionList(_vm->_hotspots[i].actIndex); } else { // Set up route to exit spot - if (_vm._hotspots[i].direction == Common::KEYCODE_RIGHT) + if (_vm->_hotspots[i].direction == Common::KEYCODE_RIGHT) x -= HERO_MAX_WIDTH; - else if (_vm._hotspots[i].direction == Common::KEYCODE_LEFT) + else if (_vm->_hotspots[i].direction == Common::KEYCODE_LEFT) x += HERO_MAX_WIDTH; - if (!_vm.route().startRoute(GO_EXIT, i, x, y)) - Utils::Box(BOX_ANY, "%s", _vm._textMouse[kMsNoWayText]); // Can't get there + if (!_vm->_route->startRoute(GO_EXIT, i, x, y)) + Utils::Box(BOX_ANY, "%s", _vm->_textMouse[kMsNoWayText]); // Can't get there } // Get rid of any attached icon @@ -197,28 +192,29 @@ void MouseHandler::processLeftClick(int16 objId, int16 cx, int16 cy) { } break; default: // Look at an icon or object - obj = &_vm._objects[objId]; + obj = &_vm->_object->_objects[objId]; // Over iconbar - immediate description if (gameStatus.inventoryState == I_ACTIVE && cy < INV_DY + DIBOFF_Y) - _vm.lookObject(obj); + _vm->_object->lookObject(obj); else { + bool foundFl = false; // TRUE if route found to object switch (obj->viewx) { // Clicked over viewport object case -1: // Walk to object position - if (_vm.findObjectSpace(obj, &x, &y)) - foundFl = _vm.route().startRoute(GO_LOOK, objId, x, y); - if (!foundFl) // Can't get there, immediate description - _vm.lookObject(obj); + if (_vm->_object->findObjectSpace(obj, &x, &y)) + foundFl = _vm->_route->startRoute(GO_LOOK, objId, x, y); + if (!foundFl) // Can't get there, immediate description + _vm->_object->lookObject(obj); break; case 0: // Immediate description - _vm.lookObject(obj); + _vm->_object->lookObject(obj); break; default: // Walk to view point if possible - if (!_vm.route().startRoute(GO_LOOK, objId, obj->viewx, obj->viewy)) { - if (_vm._hero->cycling == INVISIBLE) // If invisible do - _vm.lookObject(obj); // immediate decription + if (!_vm->_route->startRoute(GO_LOOK, objId, obj->viewx, obj->viewy)) { + if (_vm->_hero->cycling == INVISIBLE) // If invisible do + _vm->_object->lookObject(obj); // immediate decription else - Utils::Box(BOX_ANY, "%s", _vm._textMouse[kMsNoWayText]); // Can't get there + Utils::Box(BOX_ANY, "%s", _vm->_textMouse[kMsNoWayText]); // Can't get there } break; } @@ -229,20 +225,14 @@ void MouseHandler::processLeftClick(int16 objId, int16 cx, int16 cy) { // Process mouse activity void MouseHandler::mouseHandler() { - int16 iconId; // Find index of dragged icon - int iconx, icony; // Icon position (in dib_a) - int16 ux, uy; // Icon position (in dib_u) - int16 objId = -1; // Current source object - char *name; // Name of object to display - debugC(2, kDebugMouse, "mouseHandler"); - int16 cx = _vm.getMouseX(); - int16 cy = _vm.getMouseY(); + int16 cx = _vm->getMouseX(); + int16 cy = _vm->getMouseY(); - status_t &gameStatus = _vm.getGameStatus(); + status_t &gameStatus = _vm->getGameStatus(); - gameStatus.cx = cx; // Save cursor coords + gameStatus.cx = cx; // Save cursor coords gameStatus.cy = cy; // Don't process if outside client area @@ -252,36 +242,39 @@ void MouseHandler::mouseHandler() { // Display dragged inventory icon if one currently selected if (gameStatus.inventoryObjId != -1) { // Find index of icon - for (iconId = 0; iconId < _vm._maxInvent; iconId++) - if (gameStatus.inventoryObjId == _vm._invent[iconId]) + int16 iconId; // Find index of dragged icon + for (iconId = 0; iconId < _vm->_maxInvent; iconId++) { + if (gameStatus.inventoryObjId == _vm->_invent[iconId]) break; + } // Compute source coordinates in dib_u - ux = (iconId + NUM_ARROWS) * INV_DX % XPIX; - uy = (iconId + NUM_ARROWS) * INV_DX / XPIX * INV_DY; + int16 ux = (iconId + NUM_ARROWS) * INV_DX % XPIX; + int16 uy = (iconId + NUM_ARROWS) * INV_DX / XPIX * INV_DY; // Compute destination coordinates in dib_a - iconx = cx + IX_OFF; - icony = cy + IY_OFF; + int iconx = cx + IX_OFF; + int icony = cy + IY_OFF; iconx = MAX(iconx, 0); // Keep within dib_a bounds iconx = MIN(iconx, XPIX - INV_DX); icony = MAX(icony, 0); icony = MIN(icony, YPIX - INV_DY); // Copy the icon and add to display list - _vm.screen().moveImage(_vm.screen().getGUIBuffer(), ux, uy, INV_DX, INV_DY, XPIX, _vm.screen().getFrontBuffer(), iconx, icony, XPIX); - _vm.screen().displayList(D_ADD, iconx, icony, INV_DX, INV_DY); + _vm->_screen->moveImage(_vm->_screen->getGUIBuffer(), ux, uy, INV_DX, INV_DY, XPIX, _vm->_screen->getFrontBuffer(), iconx, icony, XPIX); + _vm->_screen->displayList(D_ADD, iconx, icony, INV_DX, INV_DY); } + int16 objId = -1; // Current source object // Process cursor over an object or icon if (gameStatus.inventoryState == I_ACTIVE) // Check inventory icon bar first - objId = _vm.inventory().processInventory(INV_GET, cx, cy); + objId = _vm->_inventory->processInventory(INV_GET, cx, cy); if (objId == -1) // No match, check rest of view - objId = _vm.findObject(cx, cy); + objId = _vm->_object->findObject(cx, cy); if (objId >= 0) { // Got a match // Display object name next to cursor (unless CURSOR_NOCHAR) // Note test for swapped hero name - name = _vm._arrayNouns[_vm._objects[(objId == HERO) ? _vm._heroImage : objId].nounIndex][CURSOR_NAME]; + char *name = _vm->_arrayNouns[_vm->_object->_objects[(objId == HERO) ? _vm->_heroImage : objId].nounIndex][CURSOR_NAME]; if (name[0] != CURSOR_NOCHAR) cursorText(name, cx, cy, U_FONT8, _TBRIGHTWHITE); @@ -293,9 +286,9 @@ void MouseHandler::mouseHandler() { // Process cursor over an exit hotspot if (objId == -1) { int i = findExit(cx, cy); - if (i != -1 && _vm._hotspots[i].viewx >= 0) { + if (i != -1 && _vm->_hotspots[i].viewx >= 0) { objId = EXIT_HOTSPOT; - cursorText(_vm._textMouse[kMsExit], cx, cy, U_FONT8, _TBRIGHTWHITE); + cursorText(_vm->_textMouse[kMsExit], cx, cy, U_FONT8, _TBRIGHTWHITE); } } diff --git a/engines/hugo/mouse.h b/engines/hugo/mouse.h index 3ac5f19f328..0fcb651b3a9 100644 --- a/engines/hugo/mouse.h +++ b/engines/hugo/mouse.h @@ -36,12 +36,12 @@ namespace Hugo { class MouseHandler { public: - MouseHandler(HugoEngine &vm); + MouseHandler(HugoEngine *vm); void mouseHandler(); private: - HugoEngine &_vm; + HugoEngine *_vm; void cursorText(char *buffer, int16 cx, int16 cy, uif_t fontId, int16 color); int16 findExit(int16 cx, int16 cy); diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp new file mode 100644 index 00000000000..77a25ca343c --- /dev/null +++ b/engines/hugo/object.cpp @@ -0,0 +1,429 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" +#include "common/random.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/object.h" +#include "hugo/global.h" +#include "hugo/display.h" +#include "hugo/file.h" +#include "hugo/route.h" +#include "hugo/util.h" +#include "hugo/parser.h" + +namespace Hugo { + +ObjectHandler::ObjectHandler(HugoEngine *vm) : _vm(vm) { +} + +ObjectHandler::~ObjectHandler() { +} + +void ObjectHandler::saveSeq(object_t *obj) { +// Save sequence number and image number in given object + debugC(1, kDebugObject, "saveSeq"); + + bool found = false; + for (int j = 0; !found && (j < obj->seqNumb); j++) { + seq_t *q = obj->seqList[j].seqPtr; + for (int k = 0; !found && (k < obj->seqList[j].imageNbr); k++) { + if (obj->currImagePtr == q) { + found = true; + obj->curSeqNum = j; + obj->curImageNum = k; + } else { + q = q->nextSeqPtr; + } + } + } +} + +void ObjectHandler::restoreSeq(object_t *obj) { +// Set up cur_seq_p from stored sequence and image number in object + debugC(1, kDebugObject, "restoreSeq"); + + seq_t *q = obj->seqList[obj->curSeqNum].seqPtr; + for (int j = 0; j < obj->curImageNum; j++) + q = q->nextSeqPtr; + obj->currImagePtr = q; +} + +// If status.objid = -1, pick up objid, else use status.objid on objid, +// if objid can't be picked up, use it directly +void ObjectHandler::useObject(int16 objId) { + debugC(1, kDebugObject, "useObject(%d)", objId); + + char *verb; // Background verb to use directly + object_t *obj = &_objects[objId]; // Ptr to object + if (_vm->getGameStatus().inventoryObjId == -1) { + // Get or use objid directly + if ((obj->genericCmd & TAKE) || obj->objValue) // Get collectible item + sprintf(_line, "%s %s", _vm->_arrayVerbs[_vm->_take][0], _vm->_arrayNouns[obj->nounIndex][0]); + else if (obj->genericCmd & LOOK) // Look item + sprintf(_line, "%s %s", _vm->_arrayVerbs[_vm->_look][0], _vm->_arrayNouns[obj->nounIndex][0]); + else if (obj->genericCmd & DROP) // Drop item + sprintf(_line, "%s %s", _vm->_arrayVerbs[_vm->_drop][0], _vm->_arrayNouns[obj->nounIndex][0]); + else if (obj->cmdIndex != 0) // Use non-collectible item if able + sprintf(_line, "%s %s", _vm->_arrayVerbs[_vm->_cmdList[obj->cmdIndex][1].verbIndex][0], _vm->_arrayNouns[obj->nounIndex][0]); + else if ((verb = _vm->useBG(_vm->_arrayNouns[obj->nounIndex][0])) != 0) + sprintf(_line, "%s %s", verb, _vm->_arrayNouns[obj->nounIndex][0]); + else + return; // Can't use object directly + } else { + // Use status.objid on objid + // Default to first cmd verb + sprintf(_line, "%s %s %s", _vm->_arrayVerbs[_vm->_cmdList[_objects[_vm->getGameStatus().inventoryObjId].cmdIndex][1].verbIndex][0], + _vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0], + _vm->_arrayNouns[obj->nounIndex][0]); + + // Check valid use of objects and override verb if necessary + for (uses_t *use = _vm->_uses; use->objId != _vm->_numObj; use++) { + if (_vm->getGameStatus().inventoryObjId == use->objId) { + // Look for secondary object, if found use matching verb + bool foundFl = false; + for (target_t *target = use->targets; _vm->_arrayNouns[target->nounIndex] != 0; target++) + if (_vm->_arrayNouns[target->nounIndex][0] == _vm->_arrayNouns[obj->nounIndex][0]) { + foundFl = true; + sprintf(_line, "%s %s %s", _vm->_arrayVerbs[target->verbIndex][0], + _vm->_arrayNouns[_objects[_vm->getGameStatus().inventoryObjId].nounIndex][0], + _vm->_arrayNouns[obj->nounIndex][0]); + } + + // No valid use of objects found, print failure string + if (!foundFl) { + // Deselect dragged icon if inventory not active + if (_vm->getGameStatus().inventoryState != I_ACTIVE) + _vm->getGameStatus().inventoryObjId = -1; + Utils::Box(BOX_ANY, "%s", _vm->_textData[use->dataIndex]); + return; + } + } + } + } + + if (_vm->getGameStatus().inventoryState == I_ACTIVE) // If inventory active, remove it + _vm->getGameStatus().inventoryState = I_UP; + _vm->getGameStatus().inventoryObjId = -1; // Deselect any dragged icon + _vm->_parser->lineHandler(); // and process command +} + +// Return object index of the topmost object under the cursor, or -1 if none +// Objects are filtered if not "useful" +int16 ObjectHandler::findObject(uint16 x, uint16 y) { + debugC(3, kDebugObject, "findObject(%d, %d)", x, y); + + int16 objIndex = -1; // Index of found object + uint16 y2Max = 0; // Greatest y2 + object_t *obj = _objects; + // Check objects on screen + for (int i = 0; i < _vm->_numObj; i++, obj++) { + // Object must be in current screen and "useful" + if (obj->screenIndex == *_vm->_screen_p && (obj->genericCmd || obj->objValue || obj->cmdIndex)) { + seq_t *curImage = obj->currImagePtr; + // Object must have a visible image... + if (curImage != 0 && obj->cycling != INVISIBLE) { + // If cursor inside object + if (x >= (uint16)obj->x && x <= obj->x + curImage->x2 && y >= (uint16)obj->y && y <= obj->y + curImage->y2) { + // If object is closest so far + if (obj->y + curImage->y2 > y2Max) { + y2Max = obj->y + curImage->y2; + objIndex = i; // Found an object! + } + } + } else { + // ...or a dummy object that has a hotspot rectangle + if (curImage == 0 && obj->vxPath != 0 && !obj->carriedFl) { + // If cursor inside special rectangle + if ((int16)x >= obj->oldx && (int16)x < obj->oldx + obj->vxPath && (int16)y >= obj->oldy && (int16)y < obj->oldy + obj->vyPath) { + // If object is closest so far + if (obj->oldy + obj->vyPath - 1 > (int16)y2Max) { + y2Max = obj->oldy + obj->vyPath - 1; + objIndex = i; // Found an object! + } + } + } + } + } + } + return objIndex; +} + +// Issue "Look at " command +// Note special case of swapped hero image +void ObjectHandler::lookObject(object_t *obj) { + debugC(1, kDebugObject, "lookObject"); + + if (obj == _vm->_hero) + // Hero swapped - look at other + obj = &_objects[_vm->_heroImage]; + + _vm->_parser->command("%s %s", _vm->_arrayVerbs[_vm->_look][0], _vm->_arrayNouns[obj->nounIndex][0]); +} + +// Free all object images +void ObjectHandler::freeObjects() { + debugC(1, kDebugObject, "freeObjects"); + + // Nothing to do if not allocated yet + if (_vm->_hero->seqList[0].seqPtr == 0) + return; + + // Free all sequence lists and image data + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; + for (int j = 0; j < obj->seqNumb; j++) { // for each sequence + seq_t *seq = obj->seqList[j].seqPtr; // Free image + if (seq == 0) // Failure during database load + break; + do { + free(seq->imagePtr); + seq = seq->nextSeqPtr; + } while (seq != obj->seqList[j].seqPtr); + free(seq); // Free sequence record + } + } +} + +// Compare function for the quicksort. The sort is to order the objects in +// increasing vertical position, using y+y2 as the baseline +// Returns -1 if ay2 < by2 else 1 if ay2 > by2 else 0 +int ObjectHandler::y2comp(const void *a, const void *b) { + debugC(6, kDebugObject, "y2comp"); + +// const object_t *p1 = &s_Engine->_objects[*(const byte *)a]; +// const object_t *p2 = &s_Engine->_objects[*(const byte *)b]; + const object_t *p1 = &HugoEngine::get()._object->_objects[*(const byte *)a]; + const object_t *p2 = &HugoEngine::get()._object->_objects[*(const byte *)b]; + + if (p1 == p2) + // Why does qsort try the same indexes? + return 0; + + if (p1->priority == BACKGROUND) + return -1; + + if (p2->priority == BACKGROUND) + return 1; + + if (p1->priority == FOREGROUND) + return 1; + + if (p2->priority == FOREGROUND) + return -1; + + int ay2 = p1->y + p1->currImagePtr->y2; + int by2 = p2->y + p2->currImagePtr->y2; + + return ay2 - by2; +} + +// Return TRUE if object being carried by hero +bool ObjectHandler::isCarrying(uint16 wordIndex) { + debugC(1, kDebugObject, "isCarrying(%d)", wordIndex); + + for (int i = 0; i < _vm->_numObj; i++) { + if ((wordIndex == _objects[i].nounIndex) && _objects[i].carriedFl) + return true; + } + return false; +} + +// Describe any takeable objects visible in this screen +void ObjectHandler::showTakeables() { + debugC(1, kDebugObject, "showTakeables"); + + for (int j = 0; j < _vm->_numObj; j++) { + object_t *obj = &_objects[j]; + if ((obj->cycling != INVISIBLE) && + (obj->screenIndex == *_vm->_screen_p) && + (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { + Utils::Box(BOX_ANY, "You can also see:\n%s.", _vm->_arrayNouns[obj->nounIndex][LOOK_NAME]); + } + } +} + +// Find a clear space around supplied object that hero can walk to +bool ObjectHandler::findObjectSpace(object_t *obj, int16 *destx, int16 *desty) { + debugC(1, kDebugObject, "findObjectSpace(obj, %d, %d)", *destx, *desty); + + seq_t *curImage = obj->currImagePtr; + int16 y = obj->y + curImage->y2 - 1; + + bool foundFl = true; + // Try left rear corner + for (int16 x = *destx = obj->x + curImage->x1; x < *destx + HERO_MAX_WIDTH; x++) { + if (BOUND(x, y)) + foundFl = false; + } + + if (!foundFl) { // Try right rear corner + foundFl = true; + for (int16 x = *destx = obj->x + curImage->x2 - HERO_MAX_WIDTH + 1; x <= obj->x + (int16)curImage->x2; x++) { + if (BOUND(x, y)) + foundFl = false; + } + } + + if (!foundFl) { // Try left front corner + foundFl = true; + y += 2; + for (int16 x = *destx = obj->x + curImage->x1; x < *destx + HERO_MAX_WIDTH; x++) { + if (BOUND(x, y)) + foundFl = false; + } + } + + if (!foundFl) { // Try right rear corner + foundFl = true; + for (int16 x = *destx = obj->x + curImage->x2 - HERO_MAX_WIDTH + 1; x <= obj->x + (int16)curImage->x2; x++) { + if (BOUND(x, y)) + foundFl = false; + } + } + + *desty = y; + return foundFl; +} + +void ObjectHandler::freeObjectArr() { + free(_objects); +} + +void ObjectHandler::loadObjectArr(Common::File &in) { + debugC(6, kDebugObject, "loadObject(&in)"); + +// TODO: For Hugo3, if not in story mode, set _objects[2].state to 3 + for (int varnt = 0; varnt < _vm->_numVariant; varnt++) { + uint16 numElem = in.readUint16BE(); + if (varnt == _vm->_gameVariant) { + _objCount = numElem; + _objects = (object_t *)malloc(sizeof(object_t) * numElem); + for (int i = 0; i < numElem; i++) { + _objects[i].nounIndex = in.readUint16BE(); + _objects[i].dataIndex = in.readUint16BE(); + uint16 numSubElem = in.readUint16BE(); + if (numSubElem == 0) + _objects[i].stateDataIndex = 0; + else + _objects[i].stateDataIndex = (uint16 *)malloc(sizeof(uint16) * numSubElem); + for (int j = 0; j < numSubElem; j++) + _objects[i].stateDataIndex[j] = in.readUint16BE(); + _objects[i].pathType = (path_t) in.readSint16BE(); + _objects[i].vxPath = in.readSint16BE(); + _objects[i].vyPath = in.readSint16BE(); + _objects[i].actIndex = in.readUint16BE(); + _objects[i].seqNumb = in.readByte(); + _objects[i].currImagePtr = 0; + if (_objects[i].seqNumb == 0) { + _objects[i].seqList[0].imageNbr = 0; + _objects[i].seqList[0].seqPtr = 0; + } + for (int j = 0; j < _objects[i].seqNumb; j++) { + _objects[i].seqList[j].imageNbr = in.readUint16BE(); + _objects[i].seqList[j].seqPtr = 0; + } + _objects[i].cycling = (cycle_t)in.readByte(); + _objects[i].cycleNumb = in.readByte(); + _objects[i].frameInterval = in.readByte(); + _objects[i].frameTimer = in.readByte(); + _objects[i].radius = in.readByte(); + _objects[i].screenIndex = in.readByte(); + _objects[i].x = in.readSint16BE(); + _objects[i].y = in.readSint16BE(); + _objects[i].oldx = in.readSint16BE(); + _objects[i].oldy = in.readSint16BE(); + _objects[i].vx = in.readByte(); + _objects[i].vy = in.readByte(); + _objects[i].objValue = in.readByte(); + _objects[i].genericCmd = in.readSint16BE(); + _objects[i].cmdIndex = in.readUint16BE(); + _objects[i].carriedFl = (in.readByte() != 0); + _objects[i].state = in.readByte(); + _objects[i].verbOnlyFl = (in.readByte() != 0); + _objects[i].priority = in.readByte(); + _objects[i].viewx = in.readSint16BE(); + _objects[i].viewy = in.readSint16BE(); + _objects[i].direction = in.readSint16BE(); + _objects[i].curSeqNum = in.readByte(); + _objects[i].curImageNum = in.readByte(); + _objects[i].oldvx = in.readByte(); + _objects[i].oldvy = in.readByte(); + } + } else { + for (int i = 0; i < numElem; i++) { + in.readUint16BE(); + in.readUint16BE(); + uint16 numSubElem = in.readUint16BE(); + for (int j = 0; j < numSubElem; j++) + in.readUint16BE(); + in.readSint16BE(); + in.readSint16BE(); + in.readSint16BE(); + in.readUint16BE(); + numSubElem = in.readByte(); + for (int j = 0; j < numSubElem; j++) + in.readUint16BE(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readSint16BE(); + in.readSint16BE(); + in.readSint16BE(); + in.readSint16BE(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readSint16BE(); + in.readUint16BE(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readSint16BE(); + in.readSint16BE(); + in.readUint16BE(); + in.readByte(); + in.readByte(); + in.readByte(); + in.readByte(); + } + } + } +} + +} // End of namespace Hugo diff --git a/engines/hugo/object.h b/engines/hugo/object.h new file mode 100644 index 00000000000..72b13caa8fd --- /dev/null +++ b/engines/hugo/object.h @@ -0,0 +1,131 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#ifndef HUGO_OBJECT_H +#define HUGO_OBJECT_H + +#include "common/file.h" + +#define MAXOBJECTS 128 // Used in Update_images() +#define BOUND(X, Y) ((_vm->getBoundaryOverlay()[Y * XBYTES + X / 8] & (0x80 >> X % 8)) != 0) // Boundary bit set + +namespace Hugo { + +class ObjectHandler { +public: + ObjectHandler(HugoEngine *vm); + virtual ~ObjectHandler(); + + object_t *_objects; + + virtual void moveObjects() = 0; + virtual void updateImages() = 0; + virtual void swapImages(int objNumb1, int objNumb2) = 0; + + bool isCarrying(uint16 wordIndex); + bool findObjectSpace(object_t *obj, int16 *destx, int16 *desty); + + int16 findObject(uint16 x, uint16 y); + void freeObjects(); + void loadObjectArr(Common::File &in); + void freeObjectArr(); + void lookObject(object_t *obj); + void restoreSeq(object_t *obj); + void saveSeq(object_t *obj); + void showTakeables(); + void useObject(int16 objId); + + static int y2comp(const void *a, const void *b); + + bool isCarried(int objIndex) { + return _objects[objIndex].carriedFl; + } + + void setCarry(int objIndex, bool val) { + _objects[objIndex].carriedFl = val; + } + + void setVelocity(int objIndex, int8 vx, int8 vy) { + _objects[objIndex].vx = vx; + _objects[objIndex].vy = vy; + } + + void setPath(int objIndex, path_t pathType, int16 vxPath, int16 vyPath) { + _objects[objIndex].pathType = pathType; + _objects[objIndex].vxPath = vxPath; + _objects[objIndex].vyPath = vyPath; + } +protected: + HugoEngine *_vm; + uint16 _objCount; +}; + +class ObjectHandler_v1d : public ObjectHandler { +public: + ObjectHandler_v1d(HugoEngine *vm); + virtual ~ObjectHandler_v1d(); + + void moveObjects(); + void updateImages(); + void swapImages(int objNumb1, int objNumb2); +}; + +class ObjectHandler_v1w : public ObjectHandler { +public: + ObjectHandler_v1w(HugoEngine *vm); + ~ObjectHandler_v1w(); + + void moveObjects(); + void updateImages(); + void swapImages(int objNumb1, int objNumb2); +}; + +class ObjectHandler_v2d : public ObjectHandler_v1d { +public: + ObjectHandler_v2d(HugoEngine *vm); + virtual ~ObjectHandler_v2d(); + + void moveObjects(); + void updateImages(); +}; + +class ObjectHandler_v3d : public ObjectHandler_v2d { +public: + ObjectHandler_v3d(HugoEngine *vm); + ~ObjectHandler_v3d(); + + void moveObjects(); + void swapImages(int objNumb1, int objNumb2); +}; + +} // End of namespace Hugo +#endif //HUGO_OBJECT_H diff --git a/engines/hugo/object_v1d.cpp b/engines/hugo/object_v1d.cpp new file mode 100644 index 00000000000..b2801d14c17 --- /dev/null +++ b/engines/hugo/object_v1d.cpp @@ -0,0 +1,358 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" +#include "common/random.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/object.h" +#include "hugo/global.h" +#include "hugo/display.h" +#include "hugo/file.h" +#include "hugo/route.h" +#include "hugo/util.h" +#include "hugo/parser.h" +#include "hugo/schedule.h" + +namespace Hugo { + +ObjectHandler_v1d::ObjectHandler_v1d(HugoEngine *vm) : ObjectHandler(vm) { +} + +ObjectHandler_v1d::~ObjectHandler_v1d() { +} + +// Draw all objects on screen as follows: +// 1. Sort 'FLOATING' objects in order of y2 (base of object) +// 2. Display new object frames/positions in dib +// Finally, cycle any animating objects to next frame +void ObjectHandler_v1d::updateImages() { + debugC(5, kDebugObject, "updateImages"); + + // Initialise the index array to visible objects in current screen + int num_objs = 0; + byte objindex[MAXOBJECTS]; // Array of indeces to objects + + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling >= ALMOST_INVISIBLE)) + objindex[num_objs++] = i; + } + + // Sort the objects into increasing y+y2 (painter's algorithm) + qsort(objindex, num_objs, sizeof(objindex[0]), y2comp); + + // Add each visible object to display list + for (int i = 0; i < num_objs; i++) { + object_t *obj = &_objects[objindex[i]]; + // Count down inter-frame timer + if (obj->frameTimer) + obj->frameTimer--; + + if (obj->cycling > ALMOST_INVISIBLE) { // Only if visible + switch (obj->cycling) { + case NOT_CYCLING: + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, false); + break; + case CYCLE_FORWARD: + if (obj->frameTimer) // Not time to see next frame yet + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, false); + else + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr->nextSeqPtr, false); + break; + case CYCLE_BACKWARD: { + seq_t *seqPtr = obj->currImagePtr; + if (!obj->frameTimer) { // Show next frame + while (seqPtr->nextSeqPtr != obj->currImagePtr) + seqPtr = seqPtr->nextSeqPtr; + } + _vm->_screen->displayFrame(obj->x, obj->y, seqPtr, false); + break; + } + default: + break; + } + } + } + + _vm->_scheduler->waitForRefresh(); + + // Cycle any animating objects + for (int i = 0; i < num_objs; i++) { + object_t *obj = &_objects[objindex[i]]; + if (obj->cycling != INVISIBLE) { + // Only if it's visible + if (obj->cycling == ALMOST_INVISIBLE) + obj->cycling = INVISIBLE; + + // Now Rotate to next picture in sequence + switch (obj->cycling) { + case NOT_CYCLING: + break; + case CYCLE_FORWARD: + if (!obj->frameTimer) { + // Time to step to next frame + obj->currImagePtr = obj->currImagePtr->nextSeqPtr; + // Find out if this is last frame of sequence + // If so, reset frame_timer and decrement n_cycle + if (obj->frameInterval || obj->cycleNumb) { + obj->frameTimer = obj->frameInterval; + for (int j = 0; j < obj->seqNumb; j++) { + if (obj->currImagePtr->nextSeqPtr == obj->seqList[j].seqPtr) { + if (obj->cycleNumb) { // Decr cycleNumb if Non-continous + if (!--obj->cycleNumb) + obj->cycling = NOT_CYCLING; + } + } + } + } + } + break; + case CYCLE_BACKWARD: { + if (!obj->frameTimer) { + // Time to step to prev frame + seq_t *seqPtr = obj->currImagePtr; + while (obj->currImagePtr->nextSeqPtr != seqPtr) + obj->currImagePtr = obj->currImagePtr->nextSeqPtr; + // Find out if this is first frame of sequence + // If so, reset frame_timer and decrement n_cycle + if (obj->frameInterval || obj->cycleNumb) { + obj->frameTimer = obj->frameInterval; + for (int j = 0; j < obj->seqNumb; j++) { + if (obj->currImagePtr == obj->seqList[j].seqPtr) { + if (obj->cycleNumb){ // Decr cycleNumb if Non-continous + if (!--obj->cycleNumb) + obj->cycling = NOT_CYCLING; + } + } + } + } + } + break; + } + default: + break; + } + obj->oldx = obj->x; + obj->oldy = obj->y; + } + } +} + +// Update all object positions. Process object 'local' events +// including boundary events and collisions +void ObjectHandler_v1d::moveObjects() { + debugC(4, kDebugObject, "moveObjects"); + + static int dxOld, dyOld; // previous directions for CHASEing + + // Added to DOS version in order to handle mouse properly + // If route mode enabled, do special route processing + if (_vm->getGameStatus().routeIndex >= 0) + _vm->_route->processRoute(); + + // Perform any adjustments to velocity based on special path types + // and store all (visible) object baselines into the boundary file. + // Don't store foreground or background objects + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if (obj->screenIndex == *_vm->_screen_p) { + switch (obj->pathType) { + case CHASE: { + // Allowable motion wrt boundary + int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - currImage->x1; + int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - currImage->y2 - 1; + if (abs(dx) <= 1) + obj->vx = 0; + else + obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath); + if (abs(dy) <= 1) + obj->vy = 0; + else + obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath); + + // Set first image in sequence (if multi-seq object) + if (obj->seqNumb == 4) { + if (!obj->vx) { // Got 4 directions + if (obj->vx != dxOld) { // vx just stopped + if (dy > 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != dxOld) { + if (dx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + } + + if (obj->vx || obj->vy) { + if (obj->seqNumb > 1) + obj->cycling = CYCLE_FORWARD; + } else { + obj->cycling = NOT_CYCLING; + _vm->boundaryCollision(obj); // Must have got hero! + } + dxOld = obj->vx; + dyOld = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + break; + } + case WANDER: + if (!_vm->_rnd->getRandomNumber(3 * NORMAL_TPS)) { // Kick on random interval + obj->vx = _vm->_rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath; + obj->vy = _vm->_rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath; + + // Set first image in sequence (if multi-seq object) + if (obj->seqNumb > 1) { + if (!obj->vx && (obj->seqNumb > 2)) { + if (obj->vx != dxOld) { // vx just stopped + if (obj->vy > 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != dxOld) { + if (obj->vx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + + if (obj->vx || obj->vy) + obj->cycling = CYCLE_FORWARD; + else + obj->cycling = NOT_CYCLING; + } + dxOld = obj->vx; + dyOld = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + } + break; + default: + ; // Really, nothing + } + // Store boundaries + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2); + } + } + + // Move objects, allowing for boundaries + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + if ((obj->screenIndex == *_vm->_screen_p) && (obj->vx || obj->vy)) { + // Only process if it's moving + + // Do object movement. Delta_x,y return allowed movement in x,y + // to move as close to a boundary as possible without crossing it. + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + // object coordinates + int x1 = obj->x + currImage->x1; // Left edge of object + int x2 = obj->x + currImage->x2; // Right edge + int y1 = obj->y + currImage->y1; // Top edge + int y2 = obj->y + currImage->y2; // Bottom edge + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(x1, x2, y2); // Clear our own boundary + + // Allowable motion wrt boundary + int dx = _vm->deltaX(x1, x2, obj->vx, y2); + if (dx != obj->vx) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vx = 0; + } + + int dy = _vm->deltaY(x1, x2, obj->vy, y2); + if (dy != obj->vy) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vy = 0; + } + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary + + obj->x += dx; // Update object position + obj->y += dy; + + // Don't let object go outside screen + if (x1 < EDGE) + obj->x = EDGE2; + if (x2 > (XPIX - EDGE)) + obj->x = XPIX - EDGE2 - (x2 - x1); + if (y1 < EDGE) + obj->y = EDGE2; + if (y2 > (YPIX - EDGE)) + obj->y = YPIX - EDGE2 - (y2 - y1); + + if ((obj->vx == 0) && (obj->vy == 0)) + obj->cycling = NOT_CYCLING; + } + } + + // Clear all object baselines from the boundary file. + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2); + } + + // If maze mode is enabled, do special maze processing + if (_maze.enabledFl) + _vm->processMaze(); +} + +void ObjectHandler_v1d::swapImages(int objNumb1, int objNumb2) { +// Swap all the images of one object with another. Set hero_image (we make +// the assumption for now that the first obj is always the HERO) to the object +// number of the swapped image + debugC(1, kDebugObject, "swapImages(%d, %d)", objNumb1, objNumb2); + + seqList_t tmpSeqList[MAX_SEQUENCES]; + int seqListSize = sizeof(seqList_t) * MAX_SEQUENCES; + + memcpy(tmpSeqList, _objects[objNumb1].seqList, seqListSize); + memcpy(_objects[objNumb1].seqList, _objects[objNumb2].seqList, seqListSize); + memcpy(_objects[objNumb2].seqList, tmpSeqList, seqListSize); + _objects[objNumb1].currImagePtr = _objects[objNumb1].seqList[0].seqPtr; + _objects[objNumb2].currImagePtr = _objects[objNumb2].seqList[0].seqPtr; + _vm->_heroImage = (_vm->_heroImage == HERO) ? objNumb2 : HERO; +} + +} // End of namespace Hugo diff --git a/engines/hugo/object_v1w.cpp b/engines/hugo/object_v1w.cpp new file mode 100644 index 00000000000..05fa4bd35c3 --- /dev/null +++ b/engines/hugo/object_v1w.cpp @@ -0,0 +1,370 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" +#include "common/random.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/object.h" +#include "hugo/global.h" +#include "hugo/display.h" +#include "hugo/file.h" +#include "hugo/route.h" +#include "hugo/util.h" +#include "hugo/parser.h" + +namespace Hugo { + +ObjectHandler_v1w::ObjectHandler_v1w(HugoEngine *vm) : ObjectHandler(vm) { +} + +ObjectHandler_v1w::~ObjectHandler_v1w() { +} + +// Draw all objects on screen as follows: +// 1. Sort 'FLOATING' objects in order of y2 (base of object) +// 2. Display new object frames/positions in dib +// Finally, cycle any animating objects to next frame +void ObjectHandler_v1w::updateImages() { + debugC(5, kDebugObject, "updateImages"); + + // Initialise the index array to visible objects in current screen + int num_objs = 0; + byte objindex[MAXOBJECTS]; // Array of indeces to objects + + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling >= ALMOST_INVISIBLE)) + objindex[num_objs++] = i; + } + + // Sort the objects into increasing y+y2 (painter's algorithm) + qsort(objindex, num_objs, sizeof(objindex[0]), y2comp); + + // Add each visible object to display list + for (int i = 0; i < num_objs; i++) { + object_t *obj = &_objects[objindex[i]]; + // Count down inter-frame timer + if (obj->frameTimer) + obj->frameTimer--; + + if (obj->cycling > ALMOST_INVISIBLE) { // Only if visible + switch (obj->cycling) { + case NOT_CYCLING: + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); + break; + case CYCLE_FORWARD: + if (obj->frameTimer) // Not time to see next frame yet + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); + else + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr->nextSeqPtr, obj->priority == OVEROVL); + break; + case CYCLE_BACKWARD: { + seq_t *seqPtr = obj->currImagePtr; + if (!obj->frameTimer) { // Show next frame + while (seqPtr->nextSeqPtr != obj->currImagePtr) + seqPtr = seqPtr->nextSeqPtr; + } + _vm->_screen->displayFrame(obj->x, obj->y, seqPtr, obj->priority == OVEROVL); + break; + } + default: + break; + } + } + } + + // Cycle any animating objects + for (int i = 0; i < num_objs; i++) { + object_t *obj = &_objects[objindex[i]]; + if (obj->cycling != INVISIBLE) { + // Only if it's visible + if (obj->cycling == ALMOST_INVISIBLE) + obj->cycling = INVISIBLE; + + // Now Rotate to next picture in sequence + switch (obj->cycling) { + case NOT_CYCLING: + break; + case CYCLE_FORWARD: + if (!obj->frameTimer) { + // Time to step to next frame + obj->currImagePtr = obj->currImagePtr->nextSeqPtr; + // Find out if this is last frame of sequence + // If so, reset frame_timer and decrement n_cycle + if (obj->frameInterval || obj->cycleNumb) { + obj->frameTimer = obj->frameInterval; + for (int j = 0; j < obj->seqNumb; j++) { + if (obj->currImagePtr->nextSeqPtr == obj->seqList[j].seqPtr) { + if (obj->cycleNumb) { // Decr cycleNumb if Non-continous + if (!--obj->cycleNumb) + obj->cycling = NOT_CYCLING; + } + } + } + } + } + break; + case CYCLE_BACKWARD: { + if (!obj->frameTimer) { + // Time to step to prev frame + seq_t *seqPtr = obj->currImagePtr; + while (obj->currImagePtr->nextSeqPtr != seqPtr) + obj->currImagePtr = obj->currImagePtr->nextSeqPtr; + // Find out if this is first frame of sequence + // If so, reset frame_timer and decrement n_cycle + if (obj->frameInterval || obj->cycleNumb) { + obj->frameTimer = obj->frameInterval; + for (int j = 0; j < obj->seqNumb; j++) { + if (obj->currImagePtr == obj->seqList[j].seqPtr) { + if (obj->cycleNumb){ // Decr cycleNumb if Non-continous + if (!--obj->cycleNumb) + obj->cycling = NOT_CYCLING; + } + } + } + } + } + break; + } + default: + break; + } + obj->oldx = obj->x; + obj->oldy = obj->y; + } + } +} + +// Update all object positions. Process object 'local' events +// including boundary events and collisions +void ObjectHandler_v1w::moveObjects() { + debugC(4, kDebugObject, "moveObjects"); + + // If route mode enabled, do special route processing + if (_vm->getGameStatus().routeIndex >= 0) + _vm->_route->processRoute(); + + // Perform any adjustments to velocity based on special path types + // and store all (visible) object baselines into the boundary file. + // Don't store foreground or background objects + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if (obj->screenIndex == *_vm->_screen_p) { + switch (obj->pathType) { + case CHASE: + case CHASE2: { + int8 radius = obj->radius; // Default to object's radius + if (radius < 0) // If radius infinity, use closer value + radius = DX; + + // Allowable motion wrt boundary + int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - currImage->x1; + int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - currImage->y2 - 1; + if (abs(dx) <= radius) + obj->vx = 0; + else + obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath); + if (abs(dy) <= radius) + obj->vy = 0; + else + obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath); + + // Set first image in sequence (if multi-seq object) + switch (obj->seqNumb) { + case 4: + if (!obj->vx) { // Got 4 directions + if (obj->vx != obj->oldvx) { // vx just stopped + if (dy >= 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != obj->oldvx) { + if (dx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + break; + case 3: + case 2: + if (obj->vx != obj->oldvx) { // vx just stopped + if (dx > 0) // Left & right only + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + break; + } + + if (obj->vx || obj->vy) { + obj->cycling = CYCLE_FORWARD; + } else { + obj->cycling = NOT_CYCLING; + _vm->boundaryCollision(obj); // Must have got hero! + } + obj->oldvx = obj->vx; + obj->oldvy = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + break; + } + case WANDER2: + case WANDER: + if (!_vm->_rnd->getRandomNumber(3 * NORMAL_TPS)) { // Kick on random interval + obj->vx = _vm->_rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath; + obj->vy = _vm->_rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath; + + // Set first image in sequence (if multi-seq object) + if (obj->seqNumb > 1) { + if (!obj->vx && (obj->seqNumb >= 4)) { + if (obj->vx != obj->oldvx) { // vx just stopped + if (obj->vy > 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != obj->oldvx) { + if (obj->vx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + } + obj->oldvx = obj->vx; + obj->oldvy = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + } + if (obj->vx || obj->vy) + obj->cycling = CYCLE_FORWARD; + break; + default: + ; // Really, nothing + } + // Store boundaries + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2); + } + } + + // Move objects, allowing for boundaries + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + if ((obj->screenIndex == *_vm->_screen_p) && (obj->vx || obj->vy)) { + // Only process if it's moving + + // Do object movement. Delta_x,y return allowed movement in x,y + // to move as close to a boundary as possible without crossing it. + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + // object coordinates + int x1 = obj->x + currImage->x1; // Left edge of object + int x2 = obj->x + currImage->x2; // Right edge + int y1 = obj->y + currImage->y1; // Top edge + int y2 = obj->y + currImage->y2; // Bottom edge + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(x1, x2, y2); // Clear our own boundary + + // Allowable motion wrt boundary + int dx = _vm->deltaX(x1, x2, obj->vx, y2); + if (dx != obj->vx) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vx = 0; + } + + int dy = _vm->deltaY(x1, x2, obj->vy, y2); + if (dy != obj->vy) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vy = 0; + } + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary + + obj->x += dx; // Update object position + obj->y += dy; + + // Don't let object go outside screen + if (x1 < EDGE) + obj->x = EDGE2; + if (x2 > (XPIX - EDGE)) + obj->x = XPIX - EDGE2 - (x2 - x1); + if (y1 < EDGE) + obj->y = EDGE2; + if (y2 > (YPIX - EDGE)) + obj->y = YPIX - EDGE2 - (y2 - y1); + + if ((obj->vx == 0) && (obj->vy == 0) && (obj->pathType != WANDER2) && (obj->pathType != CHASE2)) + obj->cycling = NOT_CYCLING; + } + } + + // Clear all object baselines from the boundary file. + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2); + } + + // If maze mode is enabled, do special maze processing + if (_maze.enabledFl) + _vm->processMaze(); +} + +void ObjectHandler_v1w::swapImages(int objNumb1, int objNumb2) { +// Swap all the images of one object with another. Set hero_image (we make +// the assumption for now that the first obj is always the HERO) to the object +// number of the swapped image + debugC(1, kDebugObject, "swapImages(%d, %d)", objNumb1, objNumb2); + + saveSeq(&_objects[objNumb1]); + + seqList_t tmpSeqList[MAX_SEQUENCES]; + int seqListSize = sizeof(seqList_t) * MAX_SEQUENCES; + + memcpy(tmpSeqList, _objects[objNumb1].seqList, seqListSize); + memcpy(_objects[objNumb1].seqList, _objects[objNumb2].seqList, seqListSize); + memcpy(_objects[objNumb2].seqList, tmpSeqList, seqListSize); + restoreSeq(&_objects[objNumb1]); + _objects[objNumb2].currImagePtr = _objects[objNumb2].seqList[0].seqPtr; + _vm->_heroImage = (_vm->_heroImage == HERO) ? objNumb2 : HERO; + + // Make sure baseline stays constant + _objects[objNumb1].y += _objects[objNumb2].currImagePtr->y2 - _objects[objNumb1].currImagePtr->y2; +} + +} // End of namespace Hugo diff --git a/engines/hugo/object_v2d.cpp b/engines/hugo/object_v2d.cpp new file mode 100644 index 00000000000..3a0e3672616 --- /dev/null +++ b/engines/hugo/object_v2d.cpp @@ -0,0 +1,352 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" +#include "common/random.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/object.h" +#include "hugo/global.h" +#include "hugo/display.h" +#include "hugo/file.h" +#include "hugo/route.h" +#include "hugo/util.h" +#include "hugo/parser.h" +#include "hugo/schedule.h" + +namespace Hugo { + +ObjectHandler_v2d::ObjectHandler_v2d(HugoEngine *vm) : ObjectHandler_v1d(vm) { +} + +ObjectHandler_v2d::~ObjectHandler_v2d() { +} + +// Draw all objects on screen as follows: +// 1. Sort 'FLOATING' objects in order of y2 (base of object) +// 2. Display new object frames/positions in dib +// Finally, cycle any animating objects to next frame +void ObjectHandler_v2d::updateImages() { + debugC(5, kDebugObject, "updateImages"); + + // Initialise the index array to visible objects in current screen + int num_objs = 0; + byte objindex[MAXOBJECTS]; // Array of indeces to objects + + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling >= ALMOST_INVISIBLE)) + objindex[num_objs++] = i; + } + + // Sort the objects into increasing y+y2 (painter's algorithm) + qsort(objindex, num_objs, sizeof(objindex[0]), y2comp); + + // Add each visible object to display list + for (int i = 0; i < num_objs; i++) { + object_t *obj = &_objects[objindex[i]]; + // Count down inter-frame timer + if (obj->frameTimer) + obj->frameTimer--; + + if (obj->cycling > ALMOST_INVISIBLE) { // Only if visible + switch (obj->cycling) { + case NOT_CYCLING: + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); + break; + case CYCLE_FORWARD: + if (obj->frameTimer) // Not time to see next frame yet + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr, obj->priority == OVEROVL); + else + _vm->_screen->displayFrame(obj->x, obj->y, obj->currImagePtr->nextSeqPtr, obj->priority == OVEROVL); + break; + case CYCLE_BACKWARD: { + seq_t *seqPtr = obj->currImagePtr; + if (!obj->frameTimer) { // Show next frame + while (seqPtr->nextSeqPtr != obj->currImagePtr) + seqPtr = seqPtr->nextSeqPtr; + } + _vm->_screen->displayFrame(obj->x, obj->y, seqPtr, obj->priority == OVEROVL); + break; + } + default: + break; + } + } + } + + _vm->_scheduler->waitForRefresh(); + + // Cycle any animating objects + for (int i = 0; i < num_objs; i++) { + object_t *obj = &_objects[objindex[i]]; + if (obj->cycling != INVISIBLE) { + // Only if it's visible + if (obj->cycling == ALMOST_INVISIBLE) + obj->cycling = INVISIBLE; + + // Now Rotate to next picture in sequence + switch (obj->cycling) { + case NOT_CYCLING: + break; + case CYCLE_FORWARD: + if (!obj->frameTimer) { + // Time to step to next frame + obj->currImagePtr = obj->currImagePtr->nextSeqPtr; + // Find out if this is last frame of sequence + // If so, reset frame_timer and decrement n_cycle + if (obj->frameInterval || obj->cycleNumb) { + obj->frameTimer = obj->frameInterval; + for (int j = 0; j < obj->seqNumb; j++) { + if (obj->currImagePtr->nextSeqPtr == obj->seqList[j].seqPtr) { + if (obj->cycleNumb) { // Decr cycleNumb if Non-continous + if (!--obj->cycleNumb) + obj->cycling = NOT_CYCLING; + } + } + } + } + } + break; + case CYCLE_BACKWARD: { + if (!obj->frameTimer) { + // Time to step to prev frame + seq_t *seqPtr = obj->currImagePtr; + while (obj->currImagePtr->nextSeqPtr != seqPtr) + obj->currImagePtr = obj->currImagePtr->nextSeqPtr; + // Find out if this is first frame of sequence + // If so, reset frame_timer and decrement n_cycle + if (obj->frameInterval || obj->cycleNumb) { + obj->frameTimer = obj->frameInterval; + for (int j = 0; j < obj->seqNumb; j++) { + if (obj->currImagePtr == obj->seqList[j].seqPtr) { + if (obj->cycleNumb){ // Decr cycleNumb if Non-continous + if (!--obj->cycleNumb) + obj->cycling = NOT_CYCLING; + } + } + } + } + } + break; + } + default: + break; + } + obj->oldx = obj->x; + obj->oldy = obj->y; + } + } +} + +// Update all object positions. Process object 'local' events +// including boundary events and collisions +void ObjectHandler_v2d::moveObjects() { + debugC(4, kDebugObject, "moveObjects"); + + // Added to DOS version in order to handle mouse properly + // If route mode enabled, do special route processing + if (_vm->getGameStatus().routeIndex >= 0) + _vm->_route->processRoute(); + + // Perform any adjustments to velocity based on special path types + // and store all (visible) object baselines into the boundary file. + // Don't store foreground or background objects + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if (obj->screenIndex == *_vm->_screen_p) { + switch (obj->pathType) { + case CHASE: + case CHASE2: { + int8 radius = obj->radius; // Default to object's radius + if (radius < 0) // If radius infinity, use closer value + radius = DX; + + // Allowable motion wrt boundary + int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - currImage->x1; + int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - currImage->y2 - 1; + if (abs(dx) <= radius) + obj->vx = 0; + else + obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath); + if (abs(dy) <= radius) + obj->vy = 0; + else + obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath); + + // Set first image in sequence (if multi-seq object) + switch (obj->seqNumb) { + case 4: + if (!obj->vx) { // Got 4 directions + if (obj->vx != obj->oldvx) { // vx just stopped + if (dy > 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != obj->oldvx) { + if (dx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + break; + case 3: + case 2: + if (obj->vx != obj->oldvx) { // vx just stopped + if (dx > 0) // Left & right only + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + break; + } + + if (obj->vx || obj->vy) { + obj->cycling = CYCLE_FORWARD; + } else { + obj->cycling = NOT_CYCLING; + _vm->boundaryCollision(obj); // Must have got hero! + } + obj->oldvx = obj->vx; + obj->oldvy = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + break; + } + case WANDER2: + case WANDER: + if (!_vm->_rnd->getRandomNumber(3 * NORMAL_TPS)) { // Kick on random interval + obj->vx = _vm->_rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath; + obj->vy = _vm->_rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath; + + // Set first image in sequence (if multi-seq object) + if (obj->seqNumb > 1) { + if (!obj->vx && (obj->seqNumb >= 4)) { + if (obj->vx != obj->oldvx) { // vx just stopped + if (obj->vy > 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != obj->oldvx) { + if (obj->vx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + } + obj->oldvx = obj->vx; + obj->oldvy = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + } + if (obj->vx || obj->vy) + obj->cycling = CYCLE_FORWARD; + break; + default: + ; // Really, nothing + } + // Store boundaries + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2); + } + } + + // Move objects, allowing for boundaries + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + if ((obj->screenIndex == *_vm->_screen_p) && (obj->vx || obj->vy)) { + // Only process if it's moving + + // Do object movement. Delta_x,y return allowed movement in x,y + // to move as close to a boundary as possible without crossing it. + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + // object coordinates + int x1 = obj->x + currImage->x1; // Left edge of object + int x2 = obj->x + currImage->x2; // Right edge + int y1 = obj->y + currImage->y1; // Top edge + int y2 = obj->y + currImage->y2; // Bottom edge + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(x1, x2, y2); // Clear our own boundary + + // Allowable motion wrt boundary + int dx = _vm->deltaX(x1, x2, obj->vx, y2); + if (dx != obj->vx) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vx = 0; + } + + int dy = _vm->deltaY(x1, x2, obj->vy, y2); + if (dy != obj->vy) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vy = 0; + } + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary + + obj->x += dx; // Update object position + obj->y += dy; + + // Don't let object go outside screen + if (x1 < EDGE) + obj->x = EDGE2; + if (x2 > (XPIX - EDGE)) + obj->x = XPIX - EDGE2 - (x2 - x1); + if (y1 < EDGE) + obj->y = EDGE2; + if (y2 > (YPIX - EDGE)) + obj->y = YPIX - EDGE2 - (y2 - y1); + + if ((obj->vx == 0) && (obj->vy == 0) && (obj->pathType != WANDER2) && (obj->pathType != CHASE2)) + obj->cycling = NOT_CYCLING; + } + } + + // Clear all object baselines from the boundary file. + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2); + } + + // If maze mode is enabled, do special maze processing + if (_maze.enabledFl) + _vm->processMaze(); +} + +} // End of namespace Hugo diff --git a/engines/hugo/object_v3d.cpp b/engines/hugo/object_v3d.cpp new file mode 100644 index 00000000000..42476ce3797 --- /dev/null +++ b/engines/hugo/object_v3d.cpp @@ -0,0 +1,253 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +#include "common/system.h" +#include "common/random.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/object.h" +#include "hugo/global.h" +#include "hugo/display.h" +#include "hugo/file.h" +#include "hugo/route.h" +#include "hugo/util.h" +#include "hugo/parser.h" + +namespace Hugo { + +ObjectHandler_v3d::ObjectHandler_v3d(HugoEngine *vm) : ObjectHandler_v2d(vm) { +} + +ObjectHandler_v3d::~ObjectHandler_v3d() { +} + +// Update all object positions. Process object 'local' events +// including boundary events and collisions +void ObjectHandler_v3d::moveObjects() { + debugC(4, kDebugObject, "moveObjects"); + + // Added to DOS version in order to handle mouse properly + // If route mode enabled, do special route processing + if (_vm->getGameStatus().routeIndex >= 0) + _vm->_route->processRoute(); + + // Perform any adjustments to velocity based on special path types + // and store all (visible) object baselines into the boundary file. + // Don't store foreground or background objects + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if (obj->screenIndex == *_vm->_screen_p) { + switch (obj->pathType) { + case CHASE: + case CHASE2: { + int8 radius = obj->radius; // Default to object's radius + if (radius < 0) // If radius infinity, use closer value + radius = DX; + + // Allowable motion wrt boundary + int dx = _vm->_hero->x + _vm->_hero->currImagePtr->x1 - obj->x - currImage->x1; + int dy = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - obj->y - currImage->y2 - 1; + if (abs(dx) <= radius) + obj->vx = 0; + else + obj->vx = (dx > 0) ? MIN(dx, obj->vxPath) : MAX(dx, -obj->vxPath); + if (abs(dy) <= radius) + obj->vy = 0; + else + obj->vy = (dy > 0) ? MIN(dy, obj->vyPath) : MAX(dy, -obj->vyPath); + + // Set first image in sequence (if multi-seq object) + switch (obj->seqNumb) { + case 4: + if (!obj->vx) { // Got 4 directions + if (obj->vx != obj->oldvx) { // vx just stopped + if (dy >= 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != obj->oldvx) { + if (dx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + break; + case 3: + case 2: + if (obj->vx != obj->oldvx) { // vx just stopped + if (dx > 0) // Left & right only + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + break; + } + + if (obj->vx || obj->vy) { + obj->cycling = CYCLE_FORWARD; + } else { + obj->cycling = NOT_CYCLING; + _vm->boundaryCollision(obj); // Must have got hero! + } + obj->oldvx = obj->vx; + obj->oldvy = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + break; + } + case WANDER2: + case WANDER: + if (!_vm->_rnd->getRandomNumber(3 * NORMAL_TPS)) { // Kick on random interval + obj->vx = _vm->_rnd->getRandomNumber(obj->vxPath << 1) - obj->vxPath; + obj->vy = _vm->_rnd->getRandomNumber(obj->vyPath << 1) - obj->vyPath; + + // Set first image in sequence (if multi-seq object) + if (obj->seqNumb > 1) { + if (!obj->vx && (obj->seqNumb >= 4)) { + if (obj->vx != obj->oldvx) { // vx just stopped + if (obj->vy > 0) + obj->currImagePtr = obj->seqList[DOWN].seqPtr; + else + obj->currImagePtr = obj->seqList[_UP].seqPtr; + } + } else if (obj->vx != obj->oldvx) { + if (obj->vx > 0) + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + else + obj->currImagePtr = obj->seqList[LEFT].seqPtr; + } + } + obj->oldvx = obj->vx; + obj->oldvy = obj->vy; + currImage = obj->currImagePtr; // Get (new) ptr to current image + } + if (obj->vx || obj->vy) + obj->cycling = CYCLE_FORWARD; + break; + default: + ; // Really, nothing + } + // Store boundaries + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(obj->x + currImage->x1, obj->x + currImage->x2, obj->y + currImage->y2); + } + } + + // Move objects, allowing for boundaries + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + if ((obj->screenIndex == *_vm->_screen_p) && (obj->vx || obj->vy)) { + // Only process if it's moving + + // Do object movement. Delta_x,y return allowed movement in x,y + // to move as close to a boundary as possible without crossing it. + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + // object coordinates + int x1 = obj->x + currImage->x1; // Left edge of object + int x2 = obj->x + currImage->x2; // Right edge + int y1 = obj->y + currImage->y1; // Top edge + int y2 = obj->y + currImage->y2; // Bottom edge + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(x1, x2, y2); // Clear our own boundary + + // Allowable motion wrt boundary + int dx = _vm->deltaX(x1, x2, obj->vx, y2); + if (dx != obj->vx) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vx = 0; + } + + int dy = _vm->deltaY(x1, x2, obj->vy, y2); + if (dy != obj->vy) { + // An object boundary collision! + _vm->boundaryCollision(obj); + obj->vy = 0; + } + + if ((obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(x1, x2, y2); // Re-store our own boundary + + obj->x += dx; // Update object position + obj->y += dy; + + // Don't let object go outside screen + if (x1 < EDGE) + obj->x = EDGE2; + if (x2 > (XPIX - EDGE)) + obj->x = XPIX - EDGE2 - (x2 - x1); + if (y1 < EDGE) + obj->y = EDGE2; + if (y2 > (YPIX - EDGE)) + obj->y = YPIX - EDGE2 - (y2 - y1); + + if ((obj->vx == 0) && (obj->vy == 0) && (obj->pathType != WANDER2) && (obj->pathType != CHASE2)) + obj->cycling = NOT_CYCLING; + } + } + + // Clear all object baselines from the boundary file. + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_objects[i]; // Get pointer to object + seq_t *currImage = obj->currImagePtr; // Get ptr to current image + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling > ALMOST_INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(obj->oldx + currImage->x1, obj->oldx + currImage->x2, obj->oldy + currImage->y2); + } + + // If maze mode is enabled, do special maze processing + if (_maze.enabledFl) + _vm->processMaze(); +} + +void ObjectHandler_v3d::swapImages(int objNumb1, int objNumb2) { +// Swap all the images of one object with another. Set hero_image (we make +// the assumption for now that the first obj is always the HERO) to the object +// number of the swapped image + debugC(1, kDebugObject, "swapImages(%d, %d)", objNumb1, objNumb2); + + saveSeq(&_objects[objNumb1]); + + seqList_t tmpSeqList[MAX_SEQUENCES]; + int seqListSize = sizeof(seqList_t) * MAX_SEQUENCES; + + memcpy(tmpSeqList, _objects[objNumb1].seqList, seqListSize); + memcpy(_objects[objNumb1].seqList, _objects[objNumb2].seqList, seqListSize); + memcpy(_objects[objNumb2].seqList, tmpSeqList, seqListSize); + restoreSeq(&_objects[objNumb1]); + _objects[objNumb2].currImagePtr = _objects[objNumb2].seqList[0].seqPtr; + _vm->_heroImage = (_vm->_heroImage == HERO) ? objNumb2 : HERO; +} + +} // End of namespace Hugo diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index 33fd0ddfef7..a1f493706e9 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -30,21 +30,16 @@ * */ -// parser.c - handles all keyboard/command input - #include "common/system.h" -#include "common/keyboard.h" -#include "hugo/game.h" #include "hugo/hugo.h" #include "hugo/parser.h" -#include "hugo/global.h" #include "hugo/file.h" -#include "hugo/schedule.h" #include "hugo/display.h" #include "hugo/route.h" #include "hugo/util.h" #include "hugo/sound.h" +#include "hugo/object.h" namespace Hugo { @@ -52,16 +47,19 @@ namespace Hugo { #define CX(X) LOWORD(X) #define CY(Y) HIWORD(Y) -Parser::Parser(HugoEngine &vm) : +Parser::Parser(HugoEngine *vm) : _vm(vm), _putIndex(0), _getIndex(0), _checkDoubleF1Fl(false) { } -void Parser::keyHandler(uint16 nChar, uint16 nFlags) { - status_t &gameStatus = _vm.getGameStatus(); - bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat +Parser::~Parser() { +} +void Parser::keyHandler(uint16 nChar, uint16 nFlags) { debugC(1, kDebugParser, "keyHandler(%d, %d)", nChar, nFlags); + status_t &gameStatus = _vm->getGameStatus(); + bool repeatedFl = (nFlags & 0x4000); // TRUE if key is a repeat + // Process key down event - called from OnKeyDown() switch (nChar) { // Set various toggle states case Common::KEYCODE_ESCAPE: // Escape key, may want to QUIT @@ -77,14 +75,14 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { case Common::KEYCODE_DOWN: if (!repeatedFl) { gameStatus.routeIndex = -1; // Stop any automatic route - _vm.route().setWalk(nChar); // Direction of hero travel + _vm->_route->setWalk(nChar); // Direction of hero travel } break; case Common::KEYCODE_F1: // User Help (DOS) if (_checkDoubleF1Fl) - _vm.file().instructions(); + _vm->_file->instructions(); else - _vm.screen().userHelp(); + _vm->_screen->userHelp(); _checkDoubleF1Fl = !_checkDoubleF1Fl; break; case Common::KEYCODE_F6: // Inventory @@ -94,14 +92,16 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { _config.turboFl = !_config.turboFl; break; case Common::KEYCODE_F2: // Toggle sound - _vm.sound().toggleSound(); - _vm.sound().toggleMusic(); + _vm->_sound->toggleSound(); + _vm->_sound->toggleMusic(); break; case Common::KEYCODE_F3: // Repeat last line + gameStatus.recallFl = true; + break; case Common::KEYCODE_F4: // Save game case Common::KEYCODE_F5: // Restore game case Common::KEYCODE_F9: // Boss button - warning("STUB: KeyHandler() - F3-F9 (DOS)"); + warning("STUB: KeyHandler() - F4-F5-F9 (DOS)"); break; default: // Any other key if (!gameStatus.storyModeFl) { // Keyboard disabled @@ -122,23 +122,19 @@ void Parser::keyHandler(uint16 nChar, uint16 nFlags) { } // Add any new chars to line buffer and display them. -// If CR pressed, pass line to Line_handler() +// If CR pressed, pass line to LineHandler() void Parser::charHandler() { + debugC(4, kDebugParser, "charHandler"); + static int16 lineIndex = 0; // Index into line static uint32 tick = 0; // For flashing cursor static char cursor = '_'; - char c; static command_t cmdLine; // Build command line - status_t &gameStatus = _vm.getGameStatus(); -// Strangerke : Useless ? -// bool updateFl = (_getIndex != _putIndex); // TRUE if any chars processed -// command_t status_line; // Includes prompt, cursor - - debugC(4, kDebugParser, "charHandler"); + status_t &gameStatus = _vm->getGameStatus(); // Check for one or more characters in ring buffer while (_getIndex != _putIndex) { - c = _ringBuffer[_getIndex++]; + char c = _ringBuffer[_getIndex++]; if (_getIndex >= sizeof(_ringBuffer)) _getIndex = 0; @@ -148,7 +144,7 @@ void Parser::charHandler() { cmdLine[--lineIndex] = '\0'; break; case Common::KEYCODE_RETURN: // EOL, pass line to line handler - if (lineIndex && (_vm._hero->pathType != QUIET)) { + if (lineIndex && (_vm->_hero->pathType != QUIET)) { // Remove inventory bar if active if (gameStatus.inventoryState == I_ACTIVE) gameStatus.inventoryState = I_UP; @@ -170,11 +166,8 @@ void Parser::charHandler() { } // See if time to blink cursor, set cursor character - if ((tick++ % (TPS / BLINKS)) == 0) { -// Strangerke : Useless ? -// updateFl = true; // Force an update + if ((tick++ % (TPS / BLINKS)) == 0) cursor = (cursor == '_') ? ' ' : '_'; - } // See if recall button pressed if (gameStatus.recallFl) { @@ -184,8 +177,8 @@ void Parser::charHandler() { lineIndex = strlen(cmdLine); } - sprintf(_statusLine, ">%s%c", cmdLine, cursor); - sprintf(_scoreLine, "F1-Help %s Score: %d of %d Sound %s", (_config.turboFl) ? "T" : " ", _vm.getScore(), _vm.getMaxScore(), (_config.soundFl) ? "On" : "Off"); + sprintf(_vm->_statusLine, ">%s%c", cmdLine, cursor); + sprintf(_vm->_scoreLine, "F1-Help %s Score: %d of %d Sound %s", (_config.turboFl) ? "T" : " ", _vm->getScore(), _vm->getMaxScore(), (_config.soundFl) ? "On" : "Off"); // See if "look" button pressed if (gameStatus.lookFl) { @@ -194,32 +187,12 @@ void Parser::charHandler() { } } -void Parser::drawStatusText() { - debugC(4, kDebugParser, "drawStatusText"); - - if (_vm.getPlatform() == Common::kPlatformWindows) - _vm.screen().loadFont(U_FONT8); - uint16 sdx = _vm.screen().stringLength(_statusLine); - uint16 sdy = _vm.screen().fontHeight() + 1; // + 1 for shadow - uint16 posX = 0; - uint16 posY = YPIX - sdy; - // Display the string and add rect to display list - _vm.screen().writeStr(posX, posY, _statusLine, _TLIGHTYELLOW); - _vm.screen().displayList(D_ADD, posX, posY, sdx, sdy); - - sdx = _vm.screen().stringLength(_scoreLine); - posY = 0; - _vm.screen().writeStr(posX, posY, _scoreLine, _TCYAN); - _vm.screen().displayList(D_ADD, posX, posY, sdx, sdy); -} - // Perform an immediate command. Takes parameters a la sprintf // Assumes final string will not overrun line[] length void Parser::command(const char *format, ...) { - va_list marker; - debugC(1, kDebugParser, "Command(%s, ...)", format); + va_list marker; va_start(marker, format); vsprintf(_line, format, marker); va_end(marker); @@ -227,492 +200,80 @@ void Parser::command(const char *format, ...) { lineHandler(); } -char *Parser::strlwr(char *buffer) { - char *result = buffer; - - debugC(1, kDebugParser, "strlwr(%s)", buffer); - - while (*buffer != '\0') { - if (isupper(*buffer)) - *buffer = tolower(*buffer); - buffer++; - } - - return result; -} - -// Parse the user's line of text input. Generate events as necessary -void Parser::lineHandler() { - char *noun, *verb; // ptrs to noun and verb strings -// int i; - object_t *obj; - char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby - char contextComment[XBYTES * 5] = ""; // Unused comment for context objects - status_t &gameStatus = _vm.getGameStatus(); - - - debugC(1, kDebugParser, "lineHandler"); - - // Toggle God Mode - if (!strncmp(_line, "PPG", 3)) { - _vm.sound().playSound(!_vm._soundTest, BOTH_CHANNELS, HIGH_PRI); - gameStatus.godModeFl ^= 1; - return; - } - - strlwr(_line); // Convert to lower case - - // God Mode cheat commands: - // goto Takes hero to named screen - // fetch Hero carries named object - // fetch all Hero carries all possible objects - // find Takes hero to screen containing named object - if (DEBUG || gameStatus.godModeFl) { - // Special code to allow me to go straight to any screen - if (strstr(_line, "goto")) - for (int i = 0; i < _vm._numScreens; i++) - if (!strcmp(&_line[strlen("goto") + 1], _vm._screenNames[i])) { - _vm.scheduler().newScreen(i); - return; - } - - // Special code to allow me to get objects from anywhere - if (strstr(_line, "fetch all")) { - for (int i = 0; i < _vm._numObj; i++) - if (_vm._objects[i].genericCmd & TAKE) - takeObject(&_vm._objects[i]); - return; - } - - if (strstr(_line, "fetch")) { - for (int i = 0; i < _vm._numObj; i++) - if (!strcmp(&_line[strlen("fetch") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { - takeObject(&_vm._objects[i]); - return; - } - } - - // Special code to allow me to goto objects - if (strstr(_line, "find")) - for (int i = 0; i < _vm._numObj; i++) - if (!strcmp(&_line[strlen("find") + 1], _vm._arrayNouns[_vm._objects[i].nounIndex][0])) { - _vm.scheduler().newScreen(_vm._objects[i].screenIndex); - return; - } - } - - // Special meta commands - // EXIT/QUIT - if (!strcmp("exit", _line) || strstr(_line, "quit")) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBExit]); - return; - } - - // SAVE/RESTORE - if (!strcmp("save", _line) && gameStatus.viewState == V_PLAY) { - _vm.file().saveGame(gameStatus.saveSlot, "Current game"); - return; - } - - if (!strcmp("restore", _line) && (gameStatus.viewState == V_PLAY || gameStatus.viewState == V_IDLE)) { - _vm.file().restoreGame(gameStatus.saveSlot); - _vm.scheduler().restoreScreen(*_vm._screen_p); - gameStatus.viewState = V_PLAY; - return; - } - - // Empty line - if (*_line == '\0') // Empty line - return; - if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! - return; - - if (gameStatus.gameOverFl) { - // No commands allowed! - Utils::gameOverMsg(); - return; - } - - // Test for nearby objects referenced explicitly - for (int i = 0; i < _vm._numObj; i++) { - obj = &_vm._objects[i]; - if (isWordPresent(_vm._arrayNouns[obj->nounIndex])) - if (isObjectVerb(obj, _line, farComment) || isGenericVerb(obj, _line, farComment)) - return; - } - - // Test for nearby objects that only require a verb - // Note comment is unused if not near. - for (int i = 0; i < _vm._numObj; i++) { - obj = &_vm._objects[i]; - if (obj->verbOnlyFl) - if (isObjectVerb(obj, _line, contextComment) || isGenericVerb(obj, _line, contextComment)) - return; - } - - // No objects match command line, try background and catchall commands - if (isBackgroundWord(_vm._backgroundObjects[*_vm._screen_p], _line)) - return; - if (isCatchallVerb(_vm._backgroundObjects[*_vm._screen_p], _line)) - return; - if (isBackgroundWord(_vm._catchallList, _line)) - return; - if (isCatchallVerb(_vm._catchallList, _line)) - return; - - // If a not-near comment was generated, print it - if (*farComment != '\0') { - Utils::Box(BOX_ANY, "%s", farComment); - return; - } - - // Nothing matches. Report recognition success to user. - verb = findVerb(_line); - noun = findNoun(_line); - if (verb == _vm._arrayVerbs[_vm._look][0] && _maze.enabledFl) { - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBMaze]); - showTakeables(); - } else if (verb && noun) // A combination I didn't think of - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoPoint]); - else if (noun) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoun]); - else if (verb) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBVerb]); - else - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBEh]); -} - -// Search for matching verb/noun pairs in background command list -// Print text for possible background object. Return TRUE if match found -bool Parser::isBackgroundWord(objectList_t obj, char *line) { - debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj, %s)", line); - - for (int i = 0; obj[i].verbIndex != 0; i++) - if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && - isWordPresent(_vm._arrayNouns[obj[i].nounIndex]) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - _vm.scheduler().processBonus(obj[i].bonusIndex); - return true; - } - return false; -} - -// Search for matching verbs in background command list. -// Noun is not required. Return TRUE if match found -// Note that if the background command list has match set TRUE then do not -// print text if there are any recognizable nouns in the command line -bool Parser::isCatchallVerb(objectList_t obj, char *line) { - debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj, %s)", line); - - for (int i = 0; obj[i].verbIndex != 0; i++) - if (isWordPresent(_vm._arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && - (!obj[i].matchFl || !findNoun(line)) && - ((obj[i].roomState == DONT_CARE) || - (obj[i].roomState == _vm._screenStates[*_vm._screen_p]))) { - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(obj[i].commentIndex)); - _vm.scheduler().processBonus(obj[i].bonusIndex); - - // If this is LOOK (without a noun), show any takeable objects - if (*(_vm._arrayVerbs[obj[i].verbIndex]) == _vm._arrayVerbs[_vm._look][0]) - showTakeables(); - - return(true); - } - return false; -} - -// Test whether hero is close to object. Return TRUE or FALSE -// If object not near, return suitable comment; may be another object close -// If radius is -1, treat radius as infinity -// Verb is included to determine correct comment if not near -bool Parser::isNear(object_t *obj, char *verb, char *comment) { - debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); - - if (obj->carriedFl) // Object is being carried - return(true); - - if (obj->screenIndex != *_vm._screen_p) { - // Not in same screen - if (obj->objValue) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtAny2]); - return(false); - } - - if (obj->cycling == INVISIBLE) { - if (obj->seqNumb) { - // There is an image - strcpy(comment, _vm._textParser[kCmtAny3]); - return(false); - } else - // No image, assume visible - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) - return(true); - else { - // User is not close enough - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - return(false); - } - } - - if ((obj->radius < 0) || - ((abs(obj->x - _vm._hero->x) <= obj->radius) && - (abs(obj->y + obj->currImagePtr->y2 - _vm._hero->y - _vm._hero->currImagePtr->y2) <= obj->radius))) - return(true); - else { - // User is not close enough - if (obj->objValue && (verb != _vm._arrayVerbs[_vm._take][0])) - strcpy(comment, _vm._textParser[kCmtAny1]); - else - strcpy(comment, _vm._textParser[kCmtClose]); - return(false); - } - return true; -} - // Locate any member of object name list appearing in command line bool Parser::isWordPresent(char **wordArr) { debugC(1, kDebugParser, "isWordPresent(%s)", wordArr[0]); - if (wordArr != NULL) { - for (int i = 0; strlen(wordArr[i]); i++) + if (wordArr != 0) { + for (int i = 0; strlen(wordArr[i]); i++) { if (strstr(_line, wordArr[i])) - return(true); + return true; + } } - return false; } // Locate word in list of nouns and return ptr to first string in noun list -char *Parser::findNoun(char *line) { - debugC(1, kDebugParser, "findNoun(%s)", line); +char *Parser::findNoun() { + debugC(1, kDebugParser, "findNoun()"); - for (int i = 0; _vm._arrayNouns[i]; i++) - for (int j = 0; strlen(_vm._arrayNouns[i][j]); j++) - if (strstr(line, _vm._arrayNouns[i][j])) - return(_vm._arrayNouns[i][0]); - return NULL; + for (int i = 0; _vm->_arrayNouns[i]; i++) { + for (int j = 0; strlen(_vm->_arrayNouns[i][j]); j++) { + if (strstr(_line, _vm->_arrayNouns[i][j])) + return _vm->_arrayNouns[i][0]; + } + } + return 0; } // Locate word in list of verbs and return ptr to first string in verb list -char *Parser::findVerb(char *line) { - debugC(1, kDebugParser, "findVerb(%s)", line); +char *Parser::findVerb() { + debugC(1, kDebugParser, "findVerb()"); - for (int i = 0; _vm._arrayVerbs[i]; i++) - for (int j = 0; strlen(_vm._arrayVerbs[i][j]); j++) - if (strstr(line, _vm._arrayVerbs[i][j])) - return(_vm._arrayVerbs[i][0]); - return NULL; -} - -// Describe any takeable objects visible in this screen -void Parser::showTakeables() { - object_t *obj; - - debugC(1, kDebugParser, "showTakeables"); - - for (int j = 0; j < _vm._numObj; j++) { - obj = &_vm._objects[j]; - if ((obj->cycling != INVISIBLE) && - (obj->screenIndex == *_vm._screen_p) && - (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { -// sprintf(_textBoxBuffer, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); - Utils::Box(BOX_ANY, "You can also see:\n%s.", _vm._arrayNouns[obj->nounIndex][LOOK_NAME]); + for (int i = 0; _vm->_arrayVerbs[i]; i++) { + for (int j = 0; strlen(_vm->_arrayVerbs[i][j]); j++) { + if (strstr(_line, _vm->_arrayVerbs[i][j])) + return _vm->_arrayVerbs[i][0]; } } + return 0; } -// Do all things necessary to carry an object -void Parser::takeObject(object_t *obj) { - debugC(1, kDebugParser, "takeObject(object_t *obj)"); - - obj->carriedFl = true; - if (obj->seqNumb) { // Don't change if no image to display - obj->cycling = INVISIBLE; - if (_vm.getPlatform() != Common::kPlatformWindows) - warning("takeObject : DOS version should use ALMOST_INVISIBLE"); - } - _vm.adjustScore(obj->objValue); - - if (obj->seqNumb > 0) // If object has an image, force walk to dropped - obj->viewx = -1; // (possibly moved) object next time taken! - Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[obj->nounIndex][TAKE_NAME]); -} - -// Do all necessary things to drop an object -void Parser::dropObject(object_t *obj) { - debugC(1, kDebugParser, "dropObject(object_t *obj)"); - - obj->carriedFl = false; - obj->screenIndex = *_vm._screen_p; - if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) - obj->cycling = CYCLE_FORWARD; - else - obj->cycling = NOT_CYCLING; - obj->x = _vm._hero->x - 1; - obj->y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; - obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; - _vm.adjustScore(-obj->objValue); - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBOk]); -} - -// Test whether command line contains one of the generic actions -bool Parser::isGenericVerb(object_t *obj, char *line, char *comment) { - debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s, %s)", line, comment); - - if (!obj->genericCmd) - return false; - - // Following is equivalent to switch, but couldn't do one - if (isWordPresent(_vm._arrayVerbs[_vm._look]) && isNear(obj, _vm._arrayVerbs[_vm._look][0], comment)) { - // Test state-dependent look before general look - if ((obj->genericCmd & LOOK_S) == LOOK_S) { - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->stateDataIndex[obj->state]]); - warning("isGenericVerb: use of state dependant look - To be validated"); - } else { - if ((LOOK & obj->genericCmd) == LOOK) - if (_vm._textData[obj->dataIndex]) - Utils::Box(BOX_ANY, "%s", _vm._textData[obj->dataIndex]); - else - return(false); - else - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBUnusual]); - } - } else if (isWordPresent(_vm._arrayVerbs[_vm._take]) && isNear(obj, _vm._arrayVerbs[_vm._take][0], comment)) { - if (obj->carriedFl) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBHave]); - else if ((TAKE & obj->genericCmd) == TAKE) - takeObject(obj); - else if (obj->cmdIndex != 0) // No comment if possible commands - return false; - else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNoUse]); - else - return false; - } else if (isWordPresent(_vm._arrayVerbs[_vm._drop])) { - if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBDontHave]); - else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - dropObject(obj); - else if (obj->cmdIndex == 0) - Utils::Box(BOX_ANY, "%s", _vm._textParser[kTBNeed]); - else - return false; - } else // It was not a generic cmd - return false; - - return true; -} - -// Return TRUE if object being carried by hero -bool Parser::isCarrying(uint16 wordIndex) { - debugC(1, kDebugParser, "isCarrying(%d)", wordIndex); - - for (int i = 0; i < _vm._numObj; i++) - if ((wordIndex == _vm._objects[i].nounIndex) && _vm._objects[i].carriedFl) - return true; - return false; -} - -// Test whether command line contains a verb allowed by this object. -// If it does, and the object is near and passes the tests in the command -// list then carry out the actions in the action list and return TRUE -bool Parser::isObjectVerb(object_t *obj, char *line, char *comment) { - int i; - cmd *cmnd; - char *verb; - uint16 *reqs; - uint16 cmdIndex; - - debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s, %s)", line, comment); - - // First, find matching verb in cmd list - cmdIndex = obj->cmdIndex; // ptr to list of commands - if (cmdIndex == 0) // No commands for this obj - return false; - - for (i = 0; _vm._cmdList[cmdIndex][i].verbIndex != 0; i++) // For each cmd - if (isWordPresent(_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex])) // Was this verb used? - break; - if (_vm._cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. - return false; - - // Verb match found. Check if object is Near - verb = *_vm._arrayVerbs[_vm._cmdList[cmdIndex][i].verbIndex]; - if (!isNear(obj, verb, comment)) - return(false); - - // Check all required objects are being carried - cmnd = &_vm._cmdList[cmdIndex][i]; // ptr to struct cmd - if (cmnd->reqIndex) { // At least 1 thing in list - reqs = _vm._arrayReqs[cmnd->reqIndex]; // ptr to list of required objects - for (i = 0; reqs[i]; i++) // for each obj - if (!isCarrying(reqs[i])) { - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataNoCarryIndex]); - return true; - } - } - - // Required objects are present, now check state is correct - if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataWrongIndex]); - return true; - } - - // Everything checked. Change the state and carry out any actions - if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care - obj->state = cmnd->newState; - Utils::Box(BOX_ANY, "%s", _vm._textData[cmnd->textDataDoneIndex]); - _vm.scheduler().insertActionList(cmnd->actIndex); - - // See if any additional generic actions - if ((verb == _vm._arrayVerbs[_vm._look][0]) || (verb == _vm._arrayVerbs[_vm._take][0]) || (verb == _vm._arrayVerbs[_vm._drop][0])) - isGenericVerb(obj, line, comment); - return true; -} - -void Parser::showDosInventory() { // Show user all objects being carried in a variable width 2 column format +void Parser::showDosInventory() { + debugC(1, kDebugParser, "showDosInventory()"); static const char *blanks = " "; - uint16 index, len, len1 = 0, len2 = 0; - char buffer[XBYTES *NUM_ROWS] = "\0"; + uint16 index = 0, len1 = 0, len2 = 0; - index = 0; - for (int i = 0; i < _vm._numObj; i++) /* Find widths of 2 columns */ - if (_vm._objects[i].carriedFl) { - len = strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1]); - if (index++ & 1) /* Right hand column */ + for (int i = 0; i < _vm->_numObj; i++) { // Find widths of 2 columns + if (_vm->_object->isCarried(i)) { + uint16 len = strlen(_vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][1]); + if (index++ & 1) // Right hand column len2 = (len > len2) ? len : len2; else len1 = (len > len1) ? len : len1; } - len1 += 1; /* For gap between columns */ + } + len1 += 1; // For gap between columns - if (len1 + len2 < (uint16)strlen(_vm._textParser[kTBOutro])) - len1 = strlen(_vm._textParser[kTBOutro]); + if (len1 + len2 < (uint16)strlen(_vm->_textParser[kTBOutro])) + len1 = strlen(_vm->_textParser[kTBOutro]); - strncat(buffer, blanks, (len1 + len2 - strlen(_vm._textParser[kTBIntro])) / 2); - strcat(strcat(buffer, _vm._textParser[kTBIntro]), "\n"); + char buffer[XBYTES *NUM_ROWS] = "\0"; + strncat(buffer, blanks, (len1 + len2 - strlen(_vm->_textParser[kTBIntro])) / 2); + strcat(strcat(buffer, _vm->_textParser[kTBIntro]), "\n"); index = 0; - for (int i = 0; i < _vm._numObj; i++) { /* Assign strings */ - if (_vm._objects[i].carriedFl) { + for (int i = 0; i < _vm->_numObj; i++) { // Assign strings + if (_vm->_object->isCarried(i)) { if (index++ & 1) - strcat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), "\n"); + strcat(strcat(buffer, _vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][1]), "\n"); else - strncat(strcat(buffer, _vm._arrayNouns[_vm._objects[i].nounIndex][1]), blanks, len1 - strlen(_vm._arrayNouns[_vm._objects[i].nounIndex][1])); + strncat(strcat(buffer, _vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][1]), blanks, len1 - strlen(_vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][1])); } } if (index & 1) strcat(buffer, "\n"); - strcat(buffer, _vm._textParser[kTBOutro]); + strcat(buffer, _vm->_textParser[kTBOutro]); Utils::Box(BOX_ANY, "%s", buffer); } diff --git a/engines/hugo/parser.h b/engines/hugo/parser.h index cc94ff7adcb..b98813c7bcf 100644 --- a/engines/hugo/parser.h +++ b/engines/hugo/parser.h @@ -35,50 +35,92 @@ namespace Hugo { enum seqTextParser { - kTBExit = 0, kTBMaze, kTBNoPoint, kTBNoun, kTBVerb, - kTBEh, kTBUnusual, kTBHave, kTBNoUse, kTBDontHave, - kTBNeed, kTBOk, kCmtAny1, kCmtAny2, kCmtAny3, - kCmtClose, kTBIntro, kTBOutro + kTBExit = 0, kTBMaze, kTBNoPoint, kTBNoun, kTBVerb, + kTBEh, kTBUnusual, kTBHave, kTBNoUse, kTBDontHave, + kTBNeed, kTBOk, kCmtAny1, kCmtAny2, kCmtAny3, + kCmtClose, kTBIntro, kTBOutro, kTBUnusual_1d, kCmtAny4, + kCmtAny5, kTBExit_1d, kTBEh_1d, kTBEh_2d, kTBNoUse_2d }; class Parser { public: - Parser(HugoEngine &vm); + Parser(HugoEngine *vm); + virtual ~Parser(); bool isWordPresent(char **wordArr); void charHandler(); void command(const char *format, ...); - void drawStatusText(); void keyHandler(uint16 nChar, uint16 nFlags); - void lineHandler(); + virtual void lineHandler() = 0; + +protected: + HugoEngine *_vm; + +protected: + char *findNoun(); + char *findVerb(); private: - HugoEngine &_vm; - char _ringBuffer[32]; // Ring buffer uint16 _putIndex; uint16 _getIndex; // Index into ring buffer bool _checkDoubleF1Fl; // Flag used to display user help or instructions - command_t _statusLine; - command_t _scoreLine; - - bool isBackgroundWord(objectList_t obj, char *line); - bool isCarrying(uint16 wordIndex); - bool isCatchallVerb(objectList_t obj, char *line); - bool isGenericVerb(object_t *obj, char *line, char *comment); - bool isNear(object_t *obj, char *verb, char *comment); - bool isObjectVerb(object_t *obj, char *line, char *comment); - - char *findNoun(char *line); - char *findVerb(char *line); - char *strlwr(char *buffer); - - void dropObject(object_t *obj); void showDosInventory(); - void showTakeables(); +}; + +class Parser_v1w : public Parser { +public: + Parser_v1w(HugoEngine *vm); + ~Parser_v1w(); + + virtual void lineHandler(); + +protected: + bool isBackgroundWord(objectList_t obj); + bool isCatchallVerb(objectList_t obj); + bool isGenericVerb(object_t *obj, char *comment); + bool isObjectVerb(object_t *obj, char *comment); void takeObject(object_t *obj); + +private: + bool isNear(object_t *obj, char *verb, char *comment); + void dropObject(object_t *obj); +}; + +class Parser_v1d : public Parser { +public: + Parser_v1d(HugoEngine *vm); + ~Parser_v1d(); + + virtual void lineHandler(); + +protected: + bool isNear(char *verb, char *noun, object_t *obj, char *comment); + bool isGenericVerb(char *word, object_t *obj); + bool isObjectVerb(char *word, object_t *obj); + bool isBackgroundWord(char *noun, char *verb, objectList_t obj); + bool isCatchallVerb(bool testNounFl, char *noun, char *verb, objectList_t obj); + char *findNextNoun(char *noun); + void dropObject(object_t *obj); + void takeObject(object_t *obj); +}; + +class Parser_v2d : public Parser_v1d { +public: + Parser_v2d(HugoEngine *vm); + ~Parser_v2d(); + + void lineHandler(); +}; + +class Parser_v3d : public Parser_v1w { +public: + Parser_v3d(HugoEngine *vm); + ~Parser_v3d(); + + void lineHandler(); }; } // End of namespace Hugo diff --git a/engines/hugo/parser_v1d.cpp b/engines/hugo/parser_v1d.cpp new file mode 100644 index 00000000000..dcdc2c74aca --- /dev/null +++ b/engines/hugo/parser_v1d.cpp @@ -0,0 +1,356 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// parser.c - handles all keyboard/command input + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/parser.h" +#include "hugo/file.h" +#include "hugo/schedule.h" +#include "hugo/util.h" +#include "hugo/object.h" + +namespace Hugo { + +Parser_v1d::Parser_v1d(HugoEngine *vm) : Parser(vm) { +} + +Parser_v1d::~Parser_v1d() { +} + +// Locate word in list of nouns and return ptr to string in noun list +// If n is NULL, start at beginning of list, else with n +char *Parser_v1d::findNextNoun(char *noun) { + debugC(1, kDebugParser, "findNextNoun(%s)", noun); + + int currNounIndex = -1; + if (noun) { // If noun not NULL, find index + for (currNounIndex = 0; _vm->_arrayNouns[currNounIndex]; currNounIndex++) { + if (noun == _vm->_arrayNouns[currNounIndex][0]) + break; + } + } + for (int i = currNounIndex + 1; _vm->_arrayNouns[i]; i++) { + for (int j = 0; strlen(_vm->_arrayNouns[i][j]); j++) { + if (strstr(_line, _vm->_arrayNouns[i][j])) + return _vm->_arrayNouns[i][0]; + } + } + return 0; +} + +// Test whether hero is close to object. Return TRUE or FALSE +// If no noun specified, check context flag in object before other tests. +// If object not near, return suitable string; may be similar object closer +// If radius is -1, treat radius as infinity +bool Parser_v1d::isNear(char *verb, char *noun, object_t *obj, char *comment) { + debugC(1, kDebugParser, "isNear(%s, %s, obj, %s)", verb, noun, comment); + + if (!noun && !obj->verbOnlyFl) { // No noun specified & object not context senesitive + return false; + } else if (noun && (noun != _vm->_arrayNouns[obj->nounIndex][0])) { // Noun specified & not same as object + return false; + } else if (obj->carriedFl) { // Object is being carried + return true; + } else if (obj->screenIndex != *_vm->_screen_p) { // Not in same screen + if (obj->objValue) + strcpy (comment, _vm->_textParser[kCmtAny4]); + return false; + } + + if (obj->cycling == INVISIBLE) { + if (obj->seqNumb) { // There is an image + strcpy(comment, _vm->_textParser[kCmtAny5]); + return false; + } else { // No image, assume visible + if ((obj->radius < 0) || + ((abs(obj->x - _vm->_hero->x) <= obj->radius) && + (abs(obj->y - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is either not close enough (stationary, valueless objects) + // or is not carrying it (small, portable objects of value) + if (noun) { // Don't say unless object specified + if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) + strcpy(comment, _vm->_textParser[kCmtAny4]); + else + strcpy(comment, _vm->_textParser[kCmtClose]); + } + return false; + } + } + } + + if ((obj->radius < 0) || + ((abs(obj->x - _vm->_hero->x) <= obj->radius) && + (abs(obj->y + obj->currImagePtr->y2 - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is either not close enough (stationary, valueless objects) + // or is not carrying it (small, portable objects of value) + if (noun) { // Don't say unless object specified + if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) + strcpy(comment, _vm->_textParser[kCmtAny4]); + else + strcpy(comment, _vm->_textParser[kCmtClose]); + } + return false; + } + + return true; +} + +// Test whether supplied verb is one of the common variety for this object +// say_ok needed for special case of take/drop which may be handled not only +// here but also in a cmd_list with a donestr string simultaneously +bool Parser_v1d::isGenericVerb(char *word, object_t *obj) { + debugC(1, kDebugParser, "isGenericVerb(%s, object_t *obj)", word); + + if (!obj->genericCmd) + return false; + + // Following is equivalent to switch, but couldn't do one + if (word == _vm->_arrayVerbs[_vm->_look][0]) { + if ((LOOK & obj->genericCmd) == LOOK) + Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->dataIndex]); + else + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBUnusual_1d]); + } else if (word == _vm->_arrayVerbs[_vm->_take][0]) { + if (obj->carriedFl) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBHave]); + else if ((TAKE & obj->genericCmd) == TAKE) + takeObject(obj); + else if (!obj->verbOnlyFl) // Make sure not taking object in context! + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoUse]); + else + return false; + } else if (word == _vm->_arrayVerbs[_vm->_drop][0]) { + if (!obj->carriedFl) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBDontHave]); + else if ((DROP & obj->genericCmd) == DROP) + dropObject(obj); + else + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNeed]); + } else { // It was not a generic cmd + return false; + } + + return true; +} + +// Test whether supplied verb is included in the list of allowed verbs for +// this object. If it is, then perform the tests on it from the cmd list +// and if it passes, perform the actions in the action list. If the verb +// is catered for, return TRUE +bool Parser_v1d::isObjectVerb(char *word, object_t *obj) { + debugC(1, kDebugParser, "isObjectVerb(%s, object_t *obj)", word); + + // First, find matching verb in cmd list + uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands + if (!cmdIndex) // No commands for this obj + return false; + + int i; + for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (!strcmp(word, _vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex][0])) // Is this verb catered for? + break; + } + + if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No + return false; + + // Verb match found, check all required objects are being carried + cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd + if (cmnd->reqIndex) { // At least 1 thing in list + uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + for (i = 0; reqs[i]; i++) { // for each obj + if (!_vm->_object->isCarrying(reqs[i])) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataNoCarryIndex]); + return true; + } + } + } + + // Required objects are present, now check state is correct + if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)){ + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataWrongIndex]); + return true; + } + + // Everything checked. Change the state and carry out any actions + if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care + obj->state = cmnd->newState; + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataDoneIndex]); + _vm->_scheduler->insertActionList(cmnd->actIndex); + // Special case if verb is Take or Drop. Assume additional generic actions + if ((word == _vm->_arrayVerbs[_vm->_take][0]) || (word == _vm->_arrayVerbs[_vm->_drop][0])) + isGenericVerb(word, obj); + return true; +} + +// Print text for possible background object. Return TRUE if match found +// Only match if both verb and noun found. Test_ca will match verb-only +bool Parser_v1d::isBackgroundWord(char *noun, char *verb, objectList_t obj) { + debugC(1, kDebugParser, "isBackgroundWord(%s, %s, object_list_t obj)", noun, verb); + + if (!noun) + return false; + + for (int i = 0; obj[i].verbIndex; i++) { + if ((verb == _vm->_arrayVerbs[obj[i].verbIndex][0]) && (noun == _vm->_arrayNouns[obj[i].nounIndex][0])) { + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + return true; + } + } + return false; +} + +// Do all things necessary to carry an object +void Parser_v1d::takeObject(object_t *obj) { + debugC(1, kDebugParser, "takeObject(object_t *obj)"); + + obj->carriedFl = true; + if (obj->seqNumb) // Don't change if no image to display + obj->cycling = ALMOST_INVISIBLE; + + _vm->adjustScore(obj->objValue); + + Utils::Box(BOX_ANY, TAKE_TEXT, _vm->_arrayNouns[obj->nounIndex][TAKE_NAME]); +} + +// Do all necessary things to drop an object +void Parser_v1d::dropObject(object_t *obj) { + debugC(1, kDebugParser, "dropObject(object_t *obj)"); + + obj->carriedFl = false; + obj->screenIndex = *_vm->_screen_p; + if (obj->seqNumb) // Don't change if no image to display + obj->cycling = NOT_CYCLING; + obj->x = _vm->_hero->x - 1; + obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + _vm->adjustScore(-obj->objValue); + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBOk]); +} + +// Print text for possible background object. Return TRUE if match found +// If test_noun TRUE, must have a noun given +bool Parser_v1d::isCatchallVerb(bool testNounFl, char *noun, char *verb, objectList_t obj) { + debugC(1, kDebugParser, "isCatchallVerb(%d, %s, %s, object_list_t obj)", (testNounFl) ? 1 : 0, noun, verb); + + if (testNounFl && !noun) + return false; + + for (int i = 0; obj[i].verbIndex; i++) { + if ((verb == _vm->_arrayVerbs[obj[i].verbIndex][0]) && ((noun == _vm->_arrayNouns[obj[i].nounIndex][0]) || (obj[i].nounIndex == 0))) { + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + return true; + } + } + return false; +} + +// Parse the user's line of text input. Generate events as necessary +void Parser_v1d::lineHandler() { + debugC(1, kDebugParser, "lineHandler()"); + + object_t *obj; + status_t &gameStatus = _vm->getGameStatus(); + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + +// Reset_prompt_line (); + Utils::strlwr(_line); // Convert to lower case + + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + if (Utils::Box(BOX_YESNO, "%s", _vm->_textParser[kTBExit_1d]) != 0) + _vm->endGame(); + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line)) { + if (gameStatus.gameOverFl) + Utils::gameOverMsg(); + else +// _vm->_file->saveOrRestore(true); + warning("STUB: saveOrRestore()"); + return; + } + + if (!strcmp("restore", _line)) { +// _vm->_file->saveOrRestore(false); + warning("STUB: saveOrRestore()"); + return; + } + + if (*_line == '\0') // Empty line + return; + + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { // No commands allowed! + Utils::gameOverMsg(); + return; + } + + // Find the first verb in the line + char *verb = findVerb(); + char *noun = 0; // Noun not found yet + + if (verb) { // OK, verb found. Try to match with object + do { + noun = findNextNoun(noun); // Find a noun in the line + // Must try at least once for objects allowing verb-context + for (int i = 0; i < _vm->_numObj; i++) { + obj = &_vm->_object->_objects[i]; + if (isNear(verb, noun, obj, farComment)) { + if (isObjectVerb(verb, obj) // Foreground object + || isGenericVerb(verb, obj)) // Common action type + return; + } + } + if ((*farComment == '\0') && isBackgroundWord(noun, verb, _vm->_backgroundObjects[*_vm->_screen_p])) + return; + } while (noun); + } + noun = findNextNoun(noun); + if (*farComment != '\0') // An object matched but not near enough + Utils::Box(BOX_ANY, "%s", farComment); + else if (!isCatchallVerb(true, noun, verb, _vm->_catchallList) && + !isCatchallVerb(false, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) && + !isCatchallVerb(false, noun, verb, _vm->_catchallList)) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBEh_1d]); +} + +} // End of namespace Hugo diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp new file mode 100644 index 00000000000..5021db4c6e7 --- /dev/null +++ b/engines/hugo/parser_v1w.cpp @@ -0,0 +1,435 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// parser.c - handles all keyboard/command input + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/parser.h" +#include "hugo/file.h" +#include "hugo/schedule.h" +#include "hugo/util.h" +#include "hugo/sound.h" +#include "hugo/object.h" + +namespace Hugo { +Parser_v1w::Parser_v1w(HugoEngine *vm) : Parser(vm) { +} + +Parser_v1w::~Parser_v1w() { +} + +// Test whether command line contains a verb allowed by this object. +// If it does, and the object is near and passes the tests in the command +// list then carry out the actions in the action list and return TRUE +bool Parser_v1w::isObjectVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isObjectVerb(object_t *obj, %s)", comment); + + // First, find matching verb in cmd list + uint16 cmdIndex = obj->cmdIndex; // ptr to list of commands + if (cmdIndex == 0) // No commands for this obj + return false; + + int i; + for (i = 0; _vm->_cmdList[cmdIndex][i].verbIndex != 0; i++) { // For each cmd + if (isWordPresent(_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex])) // Was this verb used? + break; + } + + if (_vm->_cmdList[cmdIndex][i].verbIndex == 0) // No verbs used. + return false; + + // Verb match found. Check if object is Near + char *verb = *_vm->_arrayVerbs[_vm->_cmdList[cmdIndex][i].verbIndex]; + if (!isNear(obj, verb, comment)) + return false; + + // Check all required objects are being carried + cmd *cmnd = &_vm->_cmdList[cmdIndex][i]; // ptr to struct cmd + if (cmnd->reqIndex) { // At least 1 thing in list + uint16 *reqs = _vm->_arrayReqs[cmnd->reqIndex]; // ptr to list of required objects + for (i = 0; reqs[i]; i++) { // for each obj + if (!_vm->_object->isCarrying(reqs[i])) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataNoCarryIndex]); + return true; + } + } + } + + // Required objects are present, now check state is correct + if ((obj->state != cmnd->reqState) && (cmnd->reqState != DONT_CARE)) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataWrongIndex]); + return true; + } + + // Everything checked. Change the state and carry out any actions + if (cmnd->reqState != DONT_CARE) // Don't change new state if required state didn't care + obj->state = cmnd->newState; + Utils::Box(BOX_ANY, "%s", _vm->_textData[cmnd->textDataDoneIndex]); + _vm->_scheduler->insertActionList(cmnd->actIndex); + + // See if any additional generic actions + if ((verb == _vm->_arrayVerbs[_vm->_look][0]) || (verb == _vm->_arrayVerbs[_vm->_take][0]) || (verb == _vm->_arrayVerbs[_vm->_drop][0])) + isGenericVerb(obj, comment); + return true; +} + +// Test whether command line contains one of the generic actions +bool Parser_v1w::isGenericVerb(object_t *obj, char *comment) { + debugC(1, kDebugParser, "isGenericVerb(object_t *obj, %s)", comment); + + if (!obj->genericCmd) + return false; + + // Following is equivalent to switch, but couldn't do one + if (isWordPresent(_vm->_arrayVerbs[_vm->_look]) && isNear(obj, _vm->_arrayVerbs[_vm->_look][0], comment)) { + // Test state-dependent look before general look + if ((obj->genericCmd & LOOK_S) == LOOK_S) { + Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->stateDataIndex[obj->state]]); + warning("isGenericVerb: use of state dependant look - To be validated"); + } else { + if ((LOOK & obj->genericCmd) == LOOK) { + if (_vm->_textData[obj->dataIndex]) + Utils::Box(BOX_ANY, "%s", _vm->_textData[obj->dataIndex]); + else + return false; + } else { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBUnusual]); + } + } + } else if (isWordPresent(_vm->_arrayVerbs[_vm->_take]) && isNear(obj, _vm->_arrayVerbs[_vm->_take][0], comment)) { + if (obj->carriedFl) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBHave]); + else if ((TAKE & obj->genericCmd) == TAKE) + takeObject(obj); + else if (obj->cmdIndex != 0) // No comment if possible commands + return false; + else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoUse]); + else + return false; + } else if (isWordPresent(_vm->_arrayVerbs[_vm->_drop])) { + if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBDontHave]); + else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) + dropObject(obj); + else if (obj->cmdIndex == 0) + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNeed]); + else + return false; + } else { // It was not a generic cmd + return false; + } + + return true; +} + +// Test whether hero is close to object. Return TRUE or FALSE +// If object not near, return suitable comment; may be another object close +// If radius is -1, treat radius as infinity +// Verb is included to determine correct comment if not near +bool Parser_v1w::isNear(object_t *obj, char *verb, char *comment) { + debugC(1, kDebugParser, "isNear(object_t *obj, %s, %s)", verb, comment); + + if (obj->carriedFl) // Object is being carried + return true; + + if (obj->screenIndex != *_vm->_screen_p) { + // Not in same screen + if (obj->objValue) + strcpy(comment, _vm->_textParser[kCmtAny1]); + else + strcpy(comment, _vm->_textParser[kCmtAny2]); + return false; + } + + if (obj->cycling == INVISIBLE) { + if (obj->seqNumb) { + // There is an image + strcpy(comment, _vm->_textParser[kCmtAny3]); + return false; + } else { + // No image, assume visible + if ((obj->radius < 0) || + ((abs(obj->x - _vm->_hero->x) <= obj->radius) && + (abs(obj->y - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is not close enough + if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) + strcpy(comment, _vm->_textParser[kCmtAny1]); + else + strcpy(comment, _vm->_textParser[kCmtClose]); + return false; + } + } + } + + if ((obj->radius < 0) || + ((abs(obj->x - _vm->_hero->x) <= obj->radius) && + (abs(obj->y + obj->currImagePtr->y2 - _vm->_hero->y - _vm->_hero->currImagePtr->y2) <= obj->radius))) { + return true; + } else { + // User is not close enough + if (obj->objValue && (verb != _vm->_arrayVerbs[_vm->_take][0])) + strcpy(comment, _vm->_textParser[kCmtAny1]); + else + strcpy(comment, _vm->_textParser[kCmtClose]); + return false; + } + return true; +} + +// Do all things necessary to carry an object +void Parser_v1w::takeObject(object_t *obj) { + debugC(1, kDebugParser, "takeObject(object_t *obj)"); + + obj->carriedFl = true; + if (obj->seqNumb) { // Don't change if no image to display + obj->cycling = INVISIBLE; + } + _vm->adjustScore(obj->objValue); + + if (obj->seqNumb > 0) // If object has an image, force walk to dropped + obj->viewx = -1; // (possibly moved) object next time taken! + Utils::Box(BOX_ANY, TAKE_TEXT, _vm->_arrayNouns[obj->nounIndex][TAKE_NAME]); +} + +// Do all necessary things to drop an object +void Parser_v1w::dropObject(object_t *obj) { + debugC(1, kDebugParser, "dropObject(object_t *obj)"); + + obj->carriedFl = false; + obj->screenIndex = *_vm->_screen_p; + if ((obj->seqNumb > 1) || (obj->seqList[0].imageNbr > 1)) + obj->cycling = CYCLE_FORWARD; + else + obj->cycling = NOT_CYCLING; + obj->x = _vm->_hero->x - 1; + obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + obj->y = (obj->y + obj->currImagePtr->y2 < YPIX) ? obj->y : YPIX - obj->currImagePtr->y2 - 10; + _vm->adjustScore(-obj->objValue); + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBOk]); +} + +// Search for matching verbs in background command list. +// Noun is not required. Return TRUE if match found +// Note that if the background command list has match set TRUE then do not +// print text if there are any recognizable nouns in the command line +bool Parser_v1w::isCatchallVerb(objectList_t obj) { + debugC(1, kDebugParser, "isCatchallVerb(object_list_t obj)"); + + for (int i = 0; obj[i].verbIndex != 0; i++) { + if (isWordPresent(_vm->_arrayVerbs[obj[i].verbIndex]) && obj[i].nounIndex == 0 && + (!obj[i].matchFl || !findNoun()) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + _vm->_scheduler->processBonus(obj[i].bonusIndex); + + // If this is LOOK (without a noun), show any takeable objects + if (*(_vm->_arrayVerbs[obj[i].verbIndex]) == _vm->_arrayVerbs[_vm->_look][0]) + _vm->_object->showTakeables(); + + return true; + } + } + return false; +} + +// Search for matching verb/noun pairs in background command list +// Print text for possible background object. Return TRUE if match found +bool Parser_v1w::isBackgroundWord(objectList_t obj) { + debugC(1, kDebugParser, "isBackgroundWord(object_list_t obj)"); + + for (int i = 0; obj[i].verbIndex != 0; i++) { + if (isWordPresent(_vm->_arrayVerbs[obj[i].verbIndex]) && + isWordPresent(_vm->_arrayNouns[obj[i].nounIndex]) && + ((obj[i].roomState == DONT_CARE) || + (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + _vm->_scheduler->processBonus(obj[i].bonusIndex); + return true; + } + } + return false; +} + +// Parse the user's line of text input. Generate events as necessary +void Parser_v1w::lineHandler() { + debugC(1, kDebugParser, "lineHandler()"); + + status_t &gameStatus = _vm->getGameStatus(); + + // Toggle God Mode + if (!strncmp(_line, "PPG", 3)) { + _vm->_sound->playSound(!_vm->_soundTest, BOTH_CHANNELS, HIGH_PRI); + gameStatus.godModeFl ^= 1; + return; + } + + Utils::strlwr(_line); // Convert to lower case + + // God Mode cheat commands: + // goto Takes hero to named screen + // fetch Hero carries named object + // fetch all Hero carries all possible objects + // find Takes hero to screen containing named object + if (gameStatus.godModeFl) { + // Special code to allow me to go straight to any screen + if (strstr(_line, "goto")) { + for (int i = 0; i < _vm->_numScreens; i++) { + if (!strcmp(&_line[strlen("goto") + 1], _vm->_screenNames[i])) { + _vm->_scheduler->newScreen(i); + return; + } + } + } + + // Special code to allow me to get objects from anywhere + if (strstr(_line, "fetch all")) { + for (int i = 0; i < _vm->_numObj; i++) { + if (_vm->_object->_objects[i].genericCmd & TAKE) + takeObject(&_vm->_object->_objects[i]); + } + return; + } + + if (strstr(_line, "fetch")) { + for (int i = 0; i < _vm->_numObj; i++) { + if (!strcmp(&_line[strlen("fetch") + 1], _vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][0])) { + takeObject(&_vm->_object->_objects[i]); + return; + } + } + } + + // Special code to allow me to goto objects + if (strstr(_line, "find")) { + for (int i = 0; i < _vm->_numObj; i++) { + if (!strcmp(&_line[strlen("find") + 1], _vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][0])) { + _vm->_scheduler->newScreen(_vm->_object->_objects[i].screenIndex); + return; + } + } + } + } + + // Special meta commands + // EXIT/QUIT + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBExit]); + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line) && gameStatus.viewState == V_PLAY) { + _vm->_file->saveGame(gameStatus.saveSlot, "Current game"); + return; + } + + if (!strcmp("restore", _line) && (gameStatus.viewState == V_PLAY || gameStatus.viewState == V_IDLE)) { + _vm->_file->restoreGame(gameStatus.saveSlot); + _vm->_scheduler->restoreScreen(*_vm->_screen_p); + gameStatus.viewState = V_PLAY; + return; + } + + // Empty line + if (*_line == '\0') // Empty line + return; + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { + // No commands allowed! + Utils::gameOverMsg(); + return; + } + + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + + // Test for nearby objects referenced explicitly + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_vm->_object->_objects[i]; + if (isWordPresent(_vm->_arrayNouns[obj->nounIndex])) { + if (isObjectVerb(obj, farComment) || isGenericVerb(obj, farComment)) + return; + } + } + + // Test for nearby objects that only require a verb + // Note comment is unused if not near. + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_vm->_object->_objects[i]; + if (obj->verbOnlyFl) { + char contextComment[XBYTES * 5] = ""; // Unused comment for context objects + if (isObjectVerb(obj, contextComment) || isGenericVerb(obj, contextComment)) + return; + } + } + + // No objects match command line, try background and catchall commands + if (isBackgroundWord(_vm->_backgroundObjects[*_vm->_screen_p])) + return; + if (isCatchallVerb(_vm->_backgroundObjects[*_vm->_screen_p])) + return; + if (isBackgroundWord(_vm->_catchallList)) + return; + if (isCatchallVerb(_vm->_catchallList)) + return; + + // If a not-near comment was generated, print it + if (*farComment != '\0') { + Utils::Box(BOX_ANY, "%s", farComment); + return; + } + + // Nothing matches. Report recognition success to user. + char *verb = findVerb(); + char *noun = findNoun(); + if (verb == _vm->_arrayVerbs[_vm->_look][0] && _maze.enabledFl) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBMaze]); + _vm->_object->showTakeables(); + } else if (verb && noun) { // A combination I didn't think of + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoPoint]); + } else if (noun) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoun]); + } else if (verb) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBVerb]); + } else { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBEh]); + } +} + +} // End of namespace Hugo diff --git a/engines/hugo/parser_v2d.cpp b/engines/hugo/parser_v2d.cpp new file mode 100644 index 00000000000..99fcf63a4e9 --- /dev/null +++ b/engines/hugo/parser_v2d.cpp @@ -0,0 +1,138 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// parser.c - handles all keyboard/command input + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/parser.h" +#include "hugo/util.h" +#include "hugo/object.h" + +namespace Hugo { + +Parser_v2d::Parser_v2d(HugoEngine *vm) : Parser_v1d(vm) { +} + +Parser_v2d::~Parser_v2d() { +} + +// Parse the user's line of text input. Generate events as necessary +void Parser_v2d::lineHandler() { + debugC(1, kDebugParser, "lineHandler()"); + + object_t *obj; + status_t &gameStatus = _vm->getGameStatus(); + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + +// Reset_prompt_line (); + Utils::strlwr(_line); // Convert to lower case + + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + if (Utils::Box(BOX_YESNO, "%s", _vm->_textParser[kTBExit_1d]) != 0) + _vm->endGame(); + else + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line)) { + _config.soundFl = false; + if (gameStatus.gameOverFl) + Utils::gameOverMsg(); + else +// _vm->_file->saveOrRestore(true); + warning("STUB: saveOrRestore()"); + return; + } + + if (!strcmp("restore", _line)) { + _config.soundFl = false; +// _vm->_file->saveOrRestore(false); + warning("STUB: saveOrRestore()"); + return; + } + + if (*_line == '\0') // Empty line + return; + + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { // No commands allowed! + Utils::gameOverMsg(); + return; + } + + // Find the first verb in the line + char *verb = findVerb(); + char *noun = 0; // Noun not found yet + + if (verb) { // OK, verb found. Try to match with object + do { + noun = findNextNoun(noun); // Find a noun in the line + // Must try at least once for objects allowing verb-context + for (int i = 0; i < _vm->_numObj; i++) { + obj = &_vm->_object->_objects[i]; + if (isNear(verb, noun, obj, farComment)) { + if (isObjectVerb(verb, obj) // Foreground object + || isGenericVerb(verb, obj)) // Common action type + return; + } + } + if ((*farComment != '\0') && isBackgroundWord(noun, verb, _vm->_backgroundObjects[*_vm->_screen_p])) + return; + } while (noun); + } + + noun = findNextNoun(noun); + if ( !isCatchallVerb(true, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) + && !isCatchallVerb(true, noun, verb, _vm->_catchallList) + && !isCatchallVerb(false, noun, verb, _vm->_backgroundObjects[*_vm->_screen_p]) + && !isCatchallVerb(false, noun, verb, _vm->_catchallList)) { + if (*farComment != '\0') { // An object matched but not near enough + Utils::Box(BOX_ANY, "%s", farComment); + } else if (_maze.enabledFl && (verb == _vm->_arrayVerbs[_vm->_look][0])) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBMaze]); + _vm->_object->showTakeables(); + } else if (verb && noun) { // A combination I didn't think of + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoUse_2d]); + } else if (verb || noun) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoun]); + } else { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBEh_2d]); + } + } +} + +} // End of namespace Hugo diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp new file mode 100644 index 00000000000..49c9ec2c08a --- /dev/null +++ b/engines/hugo/parser_v3d.cpp @@ -0,0 +1,204 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// parser.c - handles all keyboard/command input + +#include "common/system.h" + +#include "hugo/hugo.h" +#include "hugo/parser.h" +#include "hugo/schedule.h" +#include "hugo/util.h" +#include "hugo/sound.h" +#include "hugo/object.h" + +namespace Hugo { + +Parser_v3d::Parser_v3d(HugoEngine *vm) : Parser_v1w(vm) { +} + +Parser_v3d::~Parser_v3d() { +} + +// Parse the user's line of text input. Generate events as necessary +void Parser_v3d::lineHandler() { + debugC(1, kDebugParser, "lineHandler()"); + + status_t &gameStatus = _vm->getGameStatus(); + + // Toggle God Mode + if (!strncmp(_line, "PPG", 3)) { + _vm->_sound->playSound(!_vm->_soundTest, BOTH_CHANNELS, HIGH_PRI); + gameStatus.godModeFl ^= 1; + return; + } + + Utils::strlwr(_line); // Convert to lower case + + // God Mode cheat commands: + // goto Takes hero to named screen + // fetch Hero carries named object + // fetch all Hero carries all possible objects + // find Takes hero to screen containing named object + if (gameStatus.godModeFl) { + // Special code to allow me to go straight to any screen + if (strstr(_line, "goto")) { + for (int i = 0; i < _vm->_numScreens; i++) { + if (!strcmp(&_line[strlen("goto") + 1], _vm->_screenNames[i])) { + _vm->_scheduler->newScreen(i); + return; + } + } + } + + // Special code to allow me to get objects from anywhere + if (strstr(_line, "fetch all")) { + for (int i = 0; i < _vm->_numObj; i++) { + if (_vm->_object->_objects[i].genericCmd & TAKE) + takeObject(&_vm->_object->_objects[i]); + } + return; + } + + if (strstr(_line, "fetch")) { + for (int i = 0; i < _vm->_numObj; i++) { + if (!strcmp(&_line[strlen("fetch") + 1], _vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][0])) { + takeObject(&_vm->_object->_objects[i]); + return; + } + } + } + + // Special code to allow me to goto objects + if (strstr(_line, "find")) { + for (int i = 0; i < _vm->_numObj; i++) { + if (!strcmp(&_line[strlen("find") + 1], _vm->_arrayNouns[_vm->_object->_objects[i].nounIndex][0])) { + _vm->_scheduler->newScreen(_vm->_object->_objects[i].screenIndex); + return; + } + } + } + } + + // Special meta commands + // EXIT/QUIT + if (!strcmp("exit", _line) || strstr(_line, "quit")) { + if (Utils::Box(BOX_YESNO, "%s", _vm->_textParser[kTBExit_1d]) != 0) + _vm->endGame(); + else + return; + } + + // SAVE/RESTORE + if (!strcmp("save", _line)) { + _config.soundFl = false; + if (gameStatus.gameOverFl) + Utils::gameOverMsg(); + else +// _vm->_file->saveOrRestore(true); + warning("STUB: saveOrRestore()"); + return; + } + + if (!strcmp("restore", _line)) { + _config.soundFl = false; +// _vm->_file->saveOrRestore(false); + warning("STUB: saveOrRestore()"); + return; + } + + // Empty line + if (*_line == '\0') // Empty line + return; + if (strspn(_line, " ") == strlen(_line)) // Nothing but spaces! + return; + + if (gameStatus.gameOverFl) { + // No commands allowed! + Utils::gameOverMsg(); + return; + } + + char farComment[XBYTES * 5] = ""; // hold 5 line comment if object not nearby + + // Test for nearby objects referenced explicitly + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_vm->_object->_objects[i]; + if (isWordPresent(_vm->_arrayNouns[obj->nounIndex])) { + if (isObjectVerb(obj, farComment) || isGenericVerb(obj, farComment)) + return; + } + } + + // Test for nearby objects that only require a verb + // Note comment is unused if not near. + for (int i = 0; i < _vm->_numObj; i++) { + object_t *obj = &_vm->_object->_objects[i]; + if (obj->verbOnlyFl) { + char contextComment[XBYTES * 5] = ""; // Unused comment for context objects + if (isObjectVerb(obj, contextComment) || isGenericVerb(obj, contextComment)) + return; + } + } + + // No objects match command line, try background and catchall commands + if (isBackgroundWord(_vm->_backgroundObjects[*_vm->_screen_p])) + return; + if (isCatchallVerb(_vm->_backgroundObjects[*_vm->_screen_p])) + return; + if (isBackgroundWord(_vm->_catchallList)) + return; + if (isCatchallVerb(_vm->_catchallList)) + return; + + // If a not-near comment was generated, print it + if (*farComment != '\0') { + Utils::Box(BOX_ANY, "%s", farComment); + return; + } + + // Nothing matches. Report recognition success to user. + char *verb = findVerb(); + char *noun = findNoun(); + + if (verb && noun) { // A combination I didn't think of + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoPoint]); + } else if (noun) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBNoun]); + } else if (verb) { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBVerb]); + } else { + Utils::Box(BOX_ANY, "%s", _vm->_textParser[kTBEh]); + } +} + +} // End of namespace Hugo diff --git a/engines/hugo/route.cpp b/engines/hugo/route.cpp index deb4dc27d5d..9e068171a2b 100644 --- a/engines/hugo/route.cpp +++ b/engines/hugo/route.cpp @@ -38,17 +38,18 @@ #include "hugo/game.h" #include "hugo/route.h" #include "hugo/global.h" +#include "hugo/object.h" namespace Hugo { -Route::Route(HugoEngine &vm) : _vm(vm) { +Route::Route(HugoEngine *vm) : _vm(vm) { } // Face hero in new direction, based on cursor key input by user. void Route::setDirection(uint16 keyCode) { - object_t *obj = _vm._hero; // Pointer to hero object - debugC(1, kDebugRoute, "setDirection(%d)", keyCode); + object_t *obj = _vm->_hero; // Pointer to hero object + // Set first image in sequence switch (keyCode) { case Common::KEYCODE_UP: @@ -69,24 +70,24 @@ void Route::setDirection(uint16 keyCode) { case Common::KEYCODE_END: obj->currImagePtr = obj->seqList[LEFT].seqPtr; break; -// case Common::KEYCODE_PRIOR: -// obj->currImagePtr = obj->seqList[RIGHT].seqPtr; -// break; -// case Common::KEYCODE_NEXT: -// obj->currImagePtr = obj->seqList[RIGHT].seqPtr; -// break; + case Common::KEYCODE_PAGEUP: + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + break; + case Common::KEYCODE_PAGEDOWN: + obj->currImagePtr = obj->seqList[RIGHT].seqPtr; + break; } } // Set hero walking, based on cursor key input by user. // Hitting same key twice will stop hero. void Route::setWalk(uint16 direction) { - object_t *obj = _vm._hero; // Pointer to hero object - static uint16 oldDirection = 0; // Last direction char - debugC(1, kDebugRoute, "setWalk(%d)", direction); - if (_vm.getGameStatus().storyModeFl || obj->pathType != USER) // Make sure user has control + static uint16 oldDirection = 0; // Last direction char + object_t *obj = _vm->_hero; // Pointer to hero object + + if (_vm->getGameStatus().storyModeFl || obj->pathType != USER) // Make sure user has control return; if (!obj->vx && !obj->vy) @@ -111,20 +112,24 @@ void Route::setWalk(uint16 direction) { break; case Common::KEYCODE_HOME: obj->vx = -DX; + // Note: in v1 Dos and v2 Dos, obj->vy is set to DY obj->vy = -DY / 2; break; case Common::KEYCODE_END: obj->vx = -DX; + // Note: in v1 Dos and v2 Dos, obj->vy is set to -DY + obj->vy = DY / 2; + break; + case Common::KEYCODE_PAGEUP: + obj->vx = DX; + // Note: in v1 Dos and v2 Dos, obj->vy is set to -DY + obj->vy = -DY / 2; + break; + case Common::KEYCODE_PAGEDOWN: + obj->vx = DX; + // Note: in v1 Dos and v2 Dos, obj->vy is set to DY obj->vy = DY / 2; break; -// case Common::KEYCODE_PRIOR: -// obj->vx = DX; -// obj->vy = -DY / 2; -// break; -// case Common::KEYCODE_NEXT: -// obj->vx = DX; -// obj->vy = DY / 2; -// break; } oldDirection = direction; obj->cycling = CYCLE_FORWARD; @@ -148,13 +153,12 @@ void Route::setWalk(uint16 direction) { // around this, make sure any narrow gaps are 2 or more pixels high. // An example of this was the blocking guard in Hugo1/Dead-End. void Route::segment(int16 x, int16 y) { - int16 x1, x2; // Range of segment + debugC(1, kDebugRoute, "segment(%d, %d)", x, y); + // Note use of static - can't waste stack static image_pt p; // Ptr to _boundaryMap[y] static segment_t *seg_p; // Ptr to segment - debugC(1, kDebugRoute, "segment(%d, %d)", x, y); - // Bomb out if stack exhausted // Vinterstum: Is this just a safeguard, or actually used? //_fullStackFl = _stackavail () < 256; @@ -162,16 +166,21 @@ void Route::segment(int16 x, int16 y) { // Find and fill on either side of point p = _boundaryMap[y]; - for (x1 = x; x1 > 0; x1--) + int16 x1, x2; // Range of segment + for (x1 = x; x1 > 0; x1--) { if (p[x1] == 0) { p[x1] = kMapFill; - } else + } else { break; - for (x2 = x + 1; x2 < XPIX; x2++) + } + } + for (x2 = x + 1; x2 < XPIX; x2++) { if (p[x2] == 0) { p[x2] = kMapFill; - } else + } else { break; + } + } x1++; x2--; @@ -187,51 +196,62 @@ void Route::segment(int16 x, int16 y) { if (y <= 0 || y >= YPIX - 1) return; - if (_vm._hero->x < x1) { + if (_vm->_hero->x < x1) { // Hero x not in segment, search x1..x2 // Find all segments above current - for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) + for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) { if (_boundaryMap[y - 1][x] == 0) segment(x, y - 1); + } // Find all segments below current - for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) + for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) { if (_boundaryMap[y + 1][x] == 0) segment(x, y + 1); - } else if (_vm._hero->x + HERO_MAX_WIDTH > x2) { + } + } else if (_vm->_hero->x + HERO_MAX_WIDTH > x2) { // Hero x not in segment, search x1..x2 // Find all segments above current - for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--) + for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--) { if (_boundaryMap[y - 1][x] == 0) segment(x, y - 1); + } // Find all segments below current - for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--) + for (x = x2; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x >= x1; x--) { if (_boundaryMap[y + 1][x] == 0) segment(x, y + 1); + } } else { // Organize search around hero x position - this gives // better chance for more direct route. - for (x = _vm._hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) + for (x = _vm->_hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) { if (_boundaryMap[y - 1][x] == 0) segment(x, y - 1); - for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm._hero->x; x++) + } + + for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm->_hero->x; x++) { if (_boundaryMap[y - 1][x] == 0) segment(x, y - 1); - for (x = _vm._hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) + } + + for (x = _vm->_hero->x; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x <= x2; x++) { if (_boundaryMap[y + 1][x] == 0) segment(x, y + 1); - for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm._hero->x; x++) + } + + for (x = x1; !(_routeFoundFl | _fullStackFl | _fullSegmentFl) && x < _vm->_hero->x; x++) { if (_boundaryMap[y + 1][x] == 0) segment(x, y + 1); + } } // If found, surface, leaving trail back to hero if (_routeFoundFl) { // Bomb out if too many segments (leave one spare) - if (_segmentNumb >= kMaxSeg - 1) + if (_segmentNumb >= kMaxSeg - 1) { _fullSegmentFl = true; - else { + } else { // Create segment seg_p = &_segment[_segmentNumb]; seg_p->y = y; @@ -243,15 +263,15 @@ void Route::segment(int16 x, int16 y) { } // Create and return ptr to new node. Initialize with previous node. -// Returns NULL if MAX_NODES exceeded +// Returns 0 if MAX_NODES exceeded Point *Route::newNode() { debugC(1, kDebugRoute, "newNode"); if (_routeListIndex >= kMaxNodes) // Too many nodes - return(NULL); // Incomplete route - failure + return 0; // Incomplete route - failure _routeListIndex++; _route[_routeListIndex] = _route[_routeListIndex - 1]; // Initialize with previous node - return(&_route[_routeListIndex]); + return &_route[_routeListIndex]; } // Construct route to cx, cy. Return TRUE if successful. @@ -259,13 +279,6 @@ Point *Route::newNode() { // 2. Construct list of segments segment[] from hero to destination // 3. Compress to shortest route in route[] bool Route::findRoute(int16 cx, int16 cy) { - int16 i, j, x, y; // Loop on coordinates - int16 x1, x2, dx; // Overlap between segments - int16 herox1, herox2, heroy; // Current hero baseline - object_t *obj; // Ptr to object - segment_t *seg_p; // Ptr to segment - Point *routeNode; // Ptr to route node - debugC(1, kDebugRoute, "findRoute(%d, %d)", cx, cy); // Initialize for search @@ -276,32 +289,39 @@ bool Route::findRoute(int16 cx, int16 cy) { _heroWidth = HERO_MIN_WIDTH; // Minimum width of hero _destY = cy; // Destination coords _destX = cx; // Destination coords - herox1 = _vm._hero->x + _vm._hero->currImagePtr->x1; // Hero baseline - herox2 = _vm._hero->x + _vm._hero->currImagePtr->x2; // Hero baseline - heroy = _vm._hero->y + _vm._hero->currImagePtr->y2; // Hero baseline + + int16 herox1 = _vm->_hero->x + _vm->_hero->currImagePtr->x1; // Hero baseline + int16 herox2 = _vm->_hero->x + _vm->_hero->currImagePtr->x2; // Hero baseline + int16 heroy = _vm->_hero->y + _vm->_hero->currImagePtr->y2; // Hero baseline // Store all object baselines into objbound (except hero's = [0]) - for (i = 1, obj = &_vm._objects[i]; i < _vm._numObj; i++, obj++) - if ((obj->screenIndex == *_vm._screen_p) && (obj->cycling != INVISIBLE) && (obj->priority == FLOATING)) - _vm.storeBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2); + object_t *obj; // Ptr to object + int i; + for (i = 1, obj = &_vm->_object->_objects[i]; i < _vm->_numObj; i++, obj++) { + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling != INVISIBLE) && (obj->priority == FLOATING)) + _vm->storeBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2); + } // Combine objbound and boundary bitmaps to local byte map - for (y = 0; y < YPIX; y++) - for (x = 0; x < XBYTES; x++) + for (int16 y = 0; y < YPIX; y++) { + for (int16 x = 0; x < XBYTES; x++) { for (i = 0; i < 8; i++) - _boundaryMap[y][x * 8 + i] = ((_vm.getObjectBoundaryOverlay()[y * XBYTES + x] | _vm.getBoundaryOverlay()[y * XBYTES + x]) & (0x80 >> i)) ? kMapBound : 0; + _boundaryMap[y][x * 8 + i] = ((_vm->getObjectBoundaryOverlay()[y * XBYTES + x] | _vm->getBoundaryOverlay()[y * XBYTES + x]) & (0x80 >> i)) ? kMapBound : 0; + } + } // Clear all object baselines from objbound - for (i = 0, obj = _vm._objects; i < _vm._numObj; i++, obj++) - if ((obj->screenIndex == *_vm._screen_p) && (obj->cycling != INVISIBLE) && (obj->priority == FLOATING)) - _vm.clearBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2); + for (i = 0, obj = _vm->_object->_objects; i < _vm->_numObj; i++, obj++) { + if ((obj->screenIndex == *_vm->_screen_p) && (obj->cycling != INVISIBLE) && (obj->priority == FLOATING)) + _vm->clearBoundary(obj->oldx + obj->currImagePtr->x1, obj->oldx + obj->currImagePtr->x2, obj->oldy + obj->currImagePtr->y2); + } // Search from hero to destination segment(herox1, heroy); // Not found or not enough stack or MAX_SEG exceeded if (!_routeFoundFl || _fullStackFl || _fullSegmentFl) { - return(false); + return false; } // Now find the route of nodes from destination back to hero @@ -315,29 +335,30 @@ bool Route::findRoute(int16 cx, int16 cy) { _segment[_segmentNumb].x2 = herox2; _segmentNumb++; + Point *routeNode; // Ptr to route node // Look in segments[] for straight lines from destination to hero for (i = 0, _routeListIndex = 0; i < _segmentNumb - 1; i++) { - if ((routeNode = newNode()) == NULL) // New node for new segment - return(false); // Too many nodes + if ((routeNode = newNode()) == 0) // New node for new segment + return false; // Too many nodes routeNode->y = _segment[i].y; // Look ahead for furthest straight line - for (j = i + 1; j < _segmentNumb; j++) { - seg_p = &_segment[j]; + for (int16 j = i + 1; j < _segmentNumb; j++) { + segment_t *seg_p = &_segment[j]; // Can we get to this segment from previous node? - if (seg_p->x1 <= routeNode->x && seg_p->x2 >= routeNode->x + _heroWidth - 1) + if (seg_p->x1 <= routeNode->x && seg_p->x2 >= routeNode->x + _heroWidth - 1) { routeNode->y = seg_p->y; // Yes, keep updating node - else { + } else { // No, create another node on previous segment to reach it - if ((routeNode = newNode()) == NULL) // Add new route node - return (false); // Too many nodes + if ((routeNode = newNode()) == 0) // Add new route node + return false; // Too many nodes // Find overlap between old and new segments - x1 = MAX(_segment[j - 1].x1, seg_p->x1); - x2 = MIN(_segment[j - 1].x2, seg_p->x2); + int16 x1 = MAX(_segment[j - 1].x1, seg_p->x1); + int16 x2 = MIN(_segment[j - 1].x2, seg_p->x2); // If room, add a little offset to reduce staircase effect - dx = HERO_MAX_WIDTH >> 1; + int16 dx = HERO_MAX_WIDTH >> 1; if (x2 - x1 < _heroWidth + dx) dx = 0; @@ -364,51 +385,48 @@ bool Route::findRoute(int16 cx, int16 cy) { // Process hero in route mode - called from Move_objects() void Route::processRoute() { - int16 herox, heroy; // Hero position - Point *routeNode; // Ptr to current route node - static bool turnedFl = false; // Used to get extra cylce for turning - - status_t &gameStatus = _vm.getGameStatus(); - debugC(1, kDebugRoute, "processRoute"); + static bool turnedFl = false; // Used to get extra cylce for turning + // Current hero position - herox = _vm._hero->x + _vm._hero->currImagePtr->x1; - heroy = _vm._hero->y + _vm._hero->currImagePtr->y2; - routeNode = &_route[gameStatus.routeIndex]; + int16 herox = _vm->_hero->x + _vm->_hero->currImagePtr->x1; + int16 heroy = _vm->_hero->y + _vm->_hero->currImagePtr->y2; + status_t &gameStatus = _vm->getGameStatus(); + Point *routeNode = &_route[gameStatus.routeIndex]; // Arrived at node? if (abs(herox - routeNode->x) < DX + 1 && abs(heroy - routeNode->y) < DY) { // DX too low // Close enough - position hero exactly - _vm._hero->x = _vm._hero->oldx = routeNode->x - _vm._hero->currImagePtr->x1; - _vm._hero->y = _vm._hero->oldy = routeNode->y - _vm._hero->currImagePtr->y2; - _vm._hero->vx = _vm._hero->vy = 0; - _vm._hero->cycling = NOT_CYCLING; + _vm->_hero->x = _vm->_hero->oldx = routeNode->x - _vm->_hero->currImagePtr->x1; + _vm->_hero->y = _vm->_hero->oldy = routeNode->y - _vm->_hero->currImagePtr->y2; + _vm->_hero->vx = _vm->_hero->vy = 0; + _vm->_hero->cycling = NOT_CYCLING; // Arrived at final node? if (--gameStatus.routeIndex < 0) { // See why we walked here switch (gameStatus.go_for) { case GO_EXIT: // Walked to an exit, proceed into it - setWalk(_vm._hotspots[gameStatus.go_id].direction); + setWalk(_vm->_hotspots[gameStatus.go_id].direction); break; case GO_LOOK: // Look at an object if (turnedFl) { - _vm.lookObject(&_vm._objects[gameStatus.go_id]); + _vm->_object->lookObject(&_vm->_object->_objects[gameStatus.go_id]); turnedFl = false; } else { - setDirection(_vm._objects[gameStatus.go_id].direction); + setDirection(_vm->_object->_objects[gameStatus.go_id].direction); gameStatus.routeIndex++; // Come round again turnedFl = true; } break; case GO_GET: // Get (or use) an object if (turnedFl) { - _vm.useObject(gameStatus.go_id); + _vm->_object->useObject(gameStatus.go_id); turnedFl = false; } else { - setDirection(_vm._objects[gameStatus.go_id].direction); + setDirection(_vm->_object->_objects[gameStatus.go_id].direction); gameStatus.routeIndex++; // Come round again turnedFl = true; } @@ -418,20 +436,20 @@ void Route::processRoute() { break; } } - } else if (_vm._hero->vx == 0 && _vm._hero->vy == 0) { + } else if (_vm->_hero->vx == 0 && _vm->_hero->vy == 0) { // Set direction of travel if at a node // Note realignment when changing to (thinner) up/down sprite, // otherwise hero could bump into boundaries along route. - if (herox < routeNode->x) + if (herox < routeNode->x) { setWalk(Common::KEYCODE_RIGHT); - else if (herox > routeNode->x) + } else if (herox > routeNode->x) { setWalk(Common::KEYCODE_LEFT); - else if (heroy < routeNode->y) { + } else if (heroy < routeNode->y) { setWalk(Common::KEYCODE_DOWN); - _vm._hero->x = _vm._hero->oldx = routeNode->x - _vm._hero->currImagePtr->x1; + _vm->_hero->x = _vm->_hero->oldx = routeNode->x - _vm->_hero->currImagePtr->x1; } else if (heroy > routeNode->y) { setWalk(Common::KEYCODE_UP); - _vm._hero->x = _vm._hero->oldx = routeNode->x - _vm._hero->currImagePtr->x1; + _vm->_hero->x = _vm->_hero->oldx = routeNode->x - _vm->_hero->currImagePtr->x1; } } } @@ -440,16 +458,13 @@ void Route::processRoute() { // go_for is the purpose, id indexes the exit or object to walk to // Returns FALSE if route not found bool Route::startRoute(go_t go_for, int16 id, int16 cx, int16 cy) { - bool foundFl = false; // TRUE if route found ok - - status_t &gameStatus = _vm.getGameStatus(); - debugC(1, kDebugRoute, "startRoute(%d, %d, %d, %d)", go_for, id, cx, cy); // Don't attempt to walk if user does not have control - if (_vm._hero->pathType != USER) + if (_vm->_hero->pathType != USER) return false; + status_t &gameStatus = _vm->getGameStatus(); // if inventory showing, make it go away if (gameStatus.inventoryState != I_OFF) gameStatus.inventoryState = I_UP; @@ -461,9 +476,10 @@ bool Route::startRoute(go_t go_for, int16 id, int16 cx, int16 cy) { if (gameStatus.go_for == GO_SPACE) cx -= HERO_MIN_WIDTH / 2; + bool foundFl = false; // TRUE if route found ok if ((foundFl = findRoute(cx, cy))) { // Found a route? gameStatus.routeIndex = _routeListIndex; // Node index - _vm._hero->vx = _vm._hero->vy = 0; // Stop manual motion + _vm->_hero->vx = _vm->_hero->vy = 0; // Stop manual motion } return foundFl; diff --git a/engines/hugo/route.h b/engines/hugo/route.h index 09b4575fcd4..b2185a4bb7d 100644 --- a/engines/hugo/route.h +++ b/engines/hugo/route.h @@ -53,7 +53,7 @@ struct segment_t { // Search segment class Route { public: - Route(HugoEngine &vm); + Route(HugoEngine *vm); void processRoute(); bool startRoute(go_t go_for, short id, short cx, short cy); @@ -61,7 +61,7 @@ public: void setWalk(uint16 direction); private: - HugoEngine &_vm; + HugoEngine *_vm; byte _boundaryMap[YPIX][XPIX]; // Boundary byte map segment_t _segment[kMaxSeg]; // List of points in fill-path diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp index 41d194120f8..a72b337ffef 100644 --- a/engines/hugo/schedule.cpp +++ b/engines/hugo/schedule.cpp @@ -33,23 +33,16 @@ // This module contains all the scheduling and timing stuff #include "common/system.h" -#include "common/stream.h" -#include "hugo/game.h" #include "hugo/hugo.h" #include "hugo/schedule.h" -#include "hugo/global.h" #include "hugo/file.h" #include "hugo/display.h" -#include "hugo/parser.h" #include "hugo/util.h" -#include "hugo/sound.h" namespace Hugo { -#define SIGN(X) ((X < 0) ? -1 : 1) - -Scheduler::Scheduler(HugoEngine &vm) : _vm(vm) { +Scheduler::Scheduler(HugoEngine *vm) : _vm(vm) { } Scheduler::~Scheduler() { @@ -76,453 +69,77 @@ void Scheduler::initEventQueue() { // Return a ptr to an event structure from the free list event_t *Scheduler::getQueue() { debugC(4, kDebugSchedule, "getQueue"); - event_t *resEvent; if (!_freeEvent) // Error: no more events available Utils::Error(EVNT_ERR, "%s", "getQueue"); - resEvent = _freeEvent; + event_t *resEvent = _freeEvent; _freeEvent = _freeEvent->nextEvent; resEvent->nextEvent = 0; return resEvent; } -// Delete an event structure (i.e. return it to the free list) -// Historical note: Originally event p was assumed to be at head of queue -// (i.e. earliest) since all events were deleted in order when proceeding to -// a new screen. To delete an event from the middle of the queue, the action -// was overwritten to be ANULL. With the advent of GLOBAL events, Del_queue -// was modified to allow deletes anywhere in the list, and the DEL_EVENT -// action was modified to perform the actual delete. -void Scheduler::delQueue(event_t *curEvent) { - debugC(4, kDebugSchedule, "delQueue"); - if (curEvent == _headEvent) // If p was the head ptr - _headEvent = curEvent->nextEvent; // then make new head_p - else { // Unlink p - curEvent->prevEvent->nextEvent = curEvent->nextEvent; - if (curEvent->nextEvent) - curEvent->nextEvent->prevEvent = curEvent->prevEvent; - else - _tailEvent = curEvent->prevEvent; - } - - if (_headEvent) - _headEvent->prevEvent = 0; // Mark end of list - else - _tailEvent = 0; // Empty queue - - curEvent->nextEvent = _freeEvent; // Return p to free list - if (_freeEvent) // Special case, if free list was empty - _freeEvent->prevEvent = curEvent; - _freeEvent = curEvent; -} - -// Insert the action pointed to by p into the timer event queue -// The queue goes from head (earliest) to tail (latest) timewise -void Scheduler::insertAction(act *action) { - debugC(1, kDebugSchedule, "insertAction - Action type A%d", action->a0.actType); - - // First, get and initialise the event structure - event_t *curEvent = getQueue(); - curEvent->action = action; - switch (action->a0.actType) { // Assign whether local or global - case AGSCHEDULE: - curEvent->localActionFl = false; // Lasts over a new screen - break; - default: - curEvent->localActionFl = true; // Rest are for current screen only - break; - } - - curEvent->time = action->a0.timer + getTicks(); // Convert rel to abs time - - // Now find the place to insert the event - if (!_tailEvent) { // Empty queue - _tailEvent = _headEvent = curEvent; - curEvent->nextEvent = curEvent->prevEvent = NULL; - } else { - event_t *wrkEvent = _tailEvent; // Search from latest time back - bool found = false; - - while (wrkEvent && !found) { - if (wrkEvent->time <= curEvent->time) { // Found if new event later - found = true; - if (wrkEvent == _tailEvent) // New latest in list - _tailEvent = curEvent; - else - wrkEvent->nextEvent->prevEvent = curEvent; - curEvent->nextEvent = wrkEvent->nextEvent; - wrkEvent->nextEvent = curEvent; - curEvent->prevEvent = wrkEvent; - } - wrkEvent = wrkEvent->prevEvent; - } - - if (!found) { // Must be earliest in list - _headEvent->prevEvent = curEvent; // So insert as new head - curEvent->nextEvent = _headEvent; - curEvent->prevEvent = NULL; - _headEvent = curEvent; - } - } -} - -void Scheduler::insertActionList(uint16 actIndex) { // Call Insert_action for each action in the list supplied +void Scheduler::insertActionList(uint16 actIndex) { debugC(1, kDebugSchedule, "insertActionList(%d)", actIndex); - if (_vm._actListArr[actIndex]) - for (int i = 0; _vm._actListArr[actIndex][i].a0.actType != ANULL; i++) - insertAction(&_vm._actListArr[actIndex][i]); + if (_vm->_actListArr[actIndex]) { + for (int i = 0; _vm->_actListArr[actIndex][i].a0.actType != ANULL; i++) + insertAction(&_vm->_actListArr[actIndex][i]); + } } -void Scheduler::decodeString(char *line) { // Decode a string +void Scheduler::decodeString(char *line) { debugC(1, kDebugSchedule, "decodeString(%s)", line); - const char *cypher = getCypher(); + static const char *cypher = getCypher(); for (uint16 i = 0; i < strlen(line); i++) line[i] -= cypher[i % strlen(cypher)]; debugC(1, kDebugSchedule, "result : %s", line); } -event_t *Scheduler::doAction(event_t *curEvent) { -// This function performs the action in the event structure pointed to by p -// It dequeues the event and returns it to the free list. It returns a ptr -// to the next action in the list, except special case of NEW_SCREEN - event_t *wrkEvent; // Save ev_p->next_p for return - event_t *saveEvent; // Used in DEL_EVENTS - char *response; // User's response string - object_t *obj1; - object_t *obj2; - int dx, dy; - act *action; // Ptr to action structure - - status_t &gameStatus = _vm.getGameStatus(); - - action = curEvent->action; - debugC(1, kDebugSchedule, "doAction - Event action type : %d", action->a0.actType); - - switch (action->a0.actType) { - case ANULL: // Big NOP from DEL_EVENTS - break; - case ASCHEDULE: // act0: Schedule an action list - insertActionList(action->a0.actIndex); - break; - case START_OBJ: // act1: Start an object cycling - _vm._objects[action->a1.objNumb].cycleNumb = action->a1.cycleNumb; - _vm._objects[action->a1.objNumb].cycling = action->a1.cycle; - break; - case INIT_OBJXY: // act2: Initialise an object - _vm._objects[action->a2.objNumb].x = action->a2.x; // Coordinates - _vm._objects[action->a2.objNumb].y = action->a2.y; - break; - case PROMPT: // act3: Prompt user for key phrase -// TODO : Add specific code for Hugo 1 DOS, which is handled differently, - response = Utils::Box(BOX_PROMPT, "%s", _vm.file().fetchString(action->a3.promptIndex)); - - warning("STUB: doAction(act3), expecting answer %s", response); - -// TODO : The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block -#if 0 - bool found; - char *tmpStr; // General purpose string ptr - - for (found = false, dx = 0; !found && (action->a3.responsePtr[dx] != -1); dx++) { - tmpStr = _vm.file().Fetch_string(action->a3.responsePtr[dx]); - if (strstr(_vm.parser().strlwr(response) , tmpStr)) - found = true; - } - - if (found) - insertActionList(action->a3.actPassIndex); - else - insertActionList(action->a3.actFailIndex); -#endif - -//HACK: As the answer is not read, currently it's always considered correct - insertActionList(action->a3.actPassIndex); - break; - case BKGD_COLOR: // act4: Set new background color - _vm.screen().setBackgroundColor(action->a4.newBackgroundColor); - break; - case INIT_OBJVXY: // act5: Initialise an object - _vm._objects[action->a5.objNumb].vx = action->a5.vx; // velocities - _vm._objects[action->a5.objNumb].vy = action->a5.vy; - break; - case INIT_CARRY: // act6: Initialise an object - _vm._objects[action->a6.objNumb].carriedFl = action->a6.carriedFl; // carried status - break; - case INIT_HF_COORD: // act7: Initialise an object to hero's "feet" coords - _vm._objects[action->a7.objNumb].x = _vm._hero->x - 1; - _vm._objects[action->a7.objNumb].y = _vm._hero->y + _vm._hero->currImagePtr->y2 - 1; - _vm._objects[action->a7.objNumb].screenIndex = *_vm._screen_p; // Don't forget screen! - break; - case NEW_SCREEN: // act8: Start new screen - newScreen(action->a8.screenIndex); - break; - case INIT_OBJSTATE: // act9: Initialise an object state - _vm._objects[action->a9.objNumb].state = action->a9.newState; - break; - case INIT_PATH: // act10: Initialise an object path and velocity - _vm._objects[action->a10.objNumb].pathType = (path_t) action->a10.newPathType; - _vm._objects[action->a10.objNumb].vxPath = action->a10.vxPath; - _vm._objects[action->a10.objNumb].vyPath = action->a10.vyPath; - break; - case COND_R: // act11: action lists conditional on object state - if (_vm._objects[action->a11.objNumb].state == action->a11.stateReq) - insertActionList(action->a11.actPassIndex); - else - insertActionList(action->a11.actFailIndex); - break; - case TEXT: // act12: Text box (CF WARN) - Utils::Box(BOX_ANY, "%s", _vm.file().fetchString(action->a12.stringIndex)); // Fetch string from file - break; - case SWAP_IMAGES: // act13: Swap 2 object images - swapImages(action->a13.obj1, action->a13.obj2); - break; - case COND_SCR: // act14: Conditional on current screen - if (_vm._objects[action->a14.objNumb].screenIndex == action->a14.screenReq) - insertActionList(action->a14.actPassIndex); - else - insertActionList(action->a14.actFailIndex); - break; - case AUTOPILOT: // act15: Home in on a (stationary) object - // object p1 will home in on object p2 - obj1 = &_vm._objects[action->a15.obj1]; - obj2 = &_vm._objects[action->a15.obj2]; - obj1->pathType = AUTO; - dx = obj1->x + obj1->currImagePtr->x1 - obj2->x - obj2->currImagePtr->x1; - dy = obj1->y + obj1->currImagePtr->y1 - obj2->y - obj2->currImagePtr->y1; - - if (dx == 0) // Don't EVER divide by zero! - dx = 1; - if (dy == 0) - dy = 1; - - if (abs(dx) > abs(dy)) { - obj1->vx = action->a15.dx * -SIGN(dx); - obj1->vy = abs((action->a15.dy * dy) / dx) * -SIGN(dy); - } else { - obj1->vy = action->a15.dy * -SIGN(dy); - obj1->vx = abs((action->a15.dx * dx) / dy) * -SIGN(dx); - } - break; - case INIT_OBJ_SEQ: // act16: Set sequence number to use - // Note: Don't set a sequence at time 0 of a new screen, it causes - // problems clearing the boundary bits of the object! t>0 is safe - _vm._objects[action->a16.objNumb].currImagePtr = _vm._objects[action->a16.objNumb].seqList[action->a16.seqIndex].seqPtr; - break; - case SET_STATE_BITS: // act17: OR mask with curr obj state - _vm._objects[action->a17.objNumb].state |= action->a17.stateMask; - break; - case CLEAR_STATE_BITS: // act18: AND ~mask with curr obj state - _vm._objects[action->a18.objNumb].state &= ~action->a18.stateMask; - break; - case TEST_STATE_BITS: // act19: If all bits set, do apass else afail - if ((_vm._objects[action->a19.objNumb].state & action->a19.stateMask) == action->a19.stateMask) - insertActionList(action->a19.actPassIndex); - else - insertActionList(action->a19.actFailIndex); - break; - case DEL_EVENTS: // act20: Remove all events of this action type - // Note: actions are not deleted here, simply turned into NOPs! - wrkEvent = _headEvent; // The earliest event - while (wrkEvent) { // While events found in list - saveEvent = wrkEvent->nextEvent; - if (wrkEvent->action->a20.actType == action->a20.actTypeDel) - delQueue(wrkEvent); - wrkEvent = saveEvent; - } - break; - case GAMEOVER: // act21: Game over! - // NOTE: Must wait at least 1 tick before issuing this action if - // any objects are to be made invisible! - gameStatus.gameOverFl = true; - break; - case INIT_HH_COORD: // act22: Initialise an object to hero's actual coords - _vm._objects[action->a22.objNumb].x = _vm._hero->x; - _vm._objects[action->a22.objNumb].y = _vm._hero->y; - _vm._objects[action->a22.objNumb].screenIndex = *_vm._screen_p;// Don't forget screen! - break; - case EXIT: // act23: Exit game back to DOS - _vm.endGame(); - break; - case BONUS: // act24: Get bonus score for action - processBonus(action->a24.pointIndex); - break; - case COND_BOX: // act25: Conditional on bounding box - obj1 = &_vm._objects[action->a25.objNumb]; - dx = obj1->x + obj1->currImagePtr->x1; - dy = obj1->y + obj1->currImagePtr->y2; - if ((dx >= action->a25.x1) && (dx <= action->a25.x2) && - (dy >= action->a25.y1) && (dy <= action->a25.y2)) - insertActionList(action->a25.actPassIndex); - else - insertActionList(action->a25.actFailIndex); - break; - case SOUND: // act26: Play a sound (or tune) - if (action->a26.soundIndex < _vm._tunesNbr) - _vm.sound().playMusic(action->a26.soundIndex); - else - _vm.sound().playSound(action->a26.soundIndex, BOTH_CHANNELS, MED_PRI); - break; - case ADD_SCORE: // act27: Add object's value to score - _vm.adjustScore(_vm._objects[action->a27.objNumb].objValue); - break; - case SUB_SCORE: // act28: Subtract object's value from score - _vm.adjustScore(-_vm._objects[action->a28.objNumb].objValue); - break; - case COND_CARRY: // act29: Conditional on object being carried - if (_vm._objects[action->a29.objNumb].carriedFl) - insertActionList(action->a29.actPassIndex); - else - insertActionList(action->a29.actFailIndex); - break; - case INIT_MAZE: // act30: Enable and init maze structure - _maze.enabledFl = true; - _maze.size = action->a30.mazeSize; - _maze.x1 = action->a30.x1; - _maze.y1 = action->a30.y1; - _maze.x2 = action->a30.x2; - _maze.y2 = action->a30.y2; - _maze.x3 = action->a30.x3; - _maze.x4 = action->a30.x4; - _maze.firstScreenIndex = action->a30.firstScreenIndex; - break; - case EXIT_MAZE: // act31: Disable maze mode - _maze.enabledFl = false; - break; - case INIT_PRIORITY: - _vm._objects[action->a32.objNumb].priority = action->a32.priority; - break; - case INIT_SCREEN: - _vm._objects[action->a33.objNumb].screenIndex = action->a33.screenIndex; - break; - case AGSCHEDULE: // act34: Schedule a (global) action list - insertActionList(action->a34.actIndex); - break; - case REMAPPAL: // act35: Remap a palette color - _vm.screen().remapPal(action->a35.oldColorIndex, action->a35.newColorIndex); - break; - case COND_NOUN: // act36: Conditional on noun mentioned - if (_vm.parser().isWordPresent(_vm._arrayNouns[action->a36.nounIndex])) - insertActionList(action->a36.actPassIndex); - else - insertActionList(action->a36.actFailIndex); - break; - case SCREEN_STATE: // act37: Set new screen state - _vm._screenStates[action->a37.screenIndex] = action->a37.newState; - break; - case INIT_LIPS: // act38: Position lips on object - _vm._objects[action->a38.lipsObjNumb].x = _vm._objects[action->a38.objNumb].x + action->a38.dxLips; - _vm._objects[action->a38.lipsObjNumb].y = _vm._objects[action->a38.objNumb].y + action->a38.dyLips; - _vm._objects[action->a38.lipsObjNumb].screenIndex = *_vm._screen_p; // Don't forget screen! - _vm._objects[action->a38.lipsObjNumb].cycling = CYCLE_FORWARD; - break; - case INIT_STORY_MODE: // act39: Init story_mode flag - // This is similar to the QUIET path mode, except that it is - // independant of it and it additionally disables the ">" prompt - gameStatus.storyModeFl = action->a39.storyModeFl; - - // End the game after story if this is special vendor demo mode - if (gameStatus.demoFl && action->a39.storyModeFl == false) - _vm.endGame(); - break; - case WARN: // act40: Text box (CF TEXT) - Utils::Box(BOX_OK, "%s", _vm.file().fetchString(action->a40.stringIndex)); - break; - case COND_BONUS: // act41: Perform action if got bonus - if (_vm._points[action->a41.BonusIndex].scoredFl) - insertActionList(action->a41.actPassIndex); - else - insertActionList(action->a41.actFailIndex); - break; - case TEXT_TAKE: // act42: Text box with "take" message - Utils::Box(BOX_ANY, TAKE_TEXT, _vm._arrayNouns[_vm._objects[action->a42.objNumb].nounIndex][TAKE_NAME]); - break; - case YESNO: // act43: Prompt user for Yes or No - warning("doAction(act43) - Yes/No Box"); - if (Utils::Box(BOX_YESNO, "%s", _vm.file().fetchString(action->a43.promptIndex)) != NULL) - insertActionList(action->a43.actYesIndex); - else - insertActionList(action->a43.actNoIndex); - break; - case STOP_ROUTE: // act44: Stop any route in progress - gameStatus.routeIndex = -1; - break; - case COND_ROUTE: // act45: Conditional on route in progress - if (gameStatus.routeIndex >= action->a45.routeIndex) - insertActionList(action->a45.actPassIndex); - else - insertActionList(action->a45.actFailIndex); - break; - case INIT_JUMPEXIT: // act46: Init status.jumpexit flag - // This is to allow left click on exit to get there immediately - // For example the plane crash in Hugo2 where hero is invisible - // Couldn't use INVISIBLE flag since conflicts with boat in Hugo1 - gameStatus.jumpExitFl = action->a46.jumpExitFl; - break; - case INIT_VIEW: // act47: Init object.viewx, viewy, dir - _vm._objects[action->a47.objNumb].viewx = action->a47.viewx; - _vm._objects[action->a47.objNumb].viewy = action->a47.viewy; - _vm._objects[action->a47.objNumb].direction = action->a47.direction; - break; - case INIT_OBJ_FRAME: // act48: Set seq,frame number to use - // Note: Don't set a sequence at time 0 of a new screen, it causes - // problems clearing the boundary bits of the object! t>0 is safe - _vm._objects[action->a48.objNumb].currImagePtr = _vm._objects[action->a48.objNumb].seqList[action->a48.seqIndex].seqPtr; - for (dx = 0; dx < action->a48.frameIndex; dx++) - _vm._objects[action->a48.objNumb].currImagePtr = _vm._objects[action->a48.objNumb].currImagePtr->nextSeqPtr; - break; - case OLD_SONG: - //TODO For Hugo 1 and Hugo2 DOS: The songs were not stored in a DAT file, but directly as - //strings. the current play_music should be modified to use a strings instead of reading - //the file, in those cases. This replaces, for those DOS versions, act26. - warning("STUB: doAction(act49)"); - break; - default: - Utils::Error(EVNT_ERR, "%s", "doAction"); - break; - } - - if (action->a0.actType == NEW_SCREEN) // New_screen() deletes entire list - return (NULL); // next_p = NULL since list now empty - else { - wrkEvent = curEvent->nextEvent; - delQueue(curEvent); // Return event to free list - return(wrkEvent); // Return next event ptr - } -} - -// This is the scheduler which runs every tick. It examines the event queue -// for any events whose time has come. It dequeues these events and performs -// the action associated with the event, returning it to the free queue -void Scheduler::runScheduler() { - debugC(6, kDebugSchedule, "runScheduler"); - - status_t &gameStatus = _vm.getGameStatus(); - - event_t *curEvent = _headEvent; // The earliest event - while (curEvent && curEvent->time <= gameStatus.tick) // While mature events found - curEvent = doAction(curEvent); // Perform the action (returns next_p) - gameStatus.tick++; // Accessed elsewhere via getTicks() -} - -uint32 Scheduler::getTicks() { // Return system time in ticks. A tick is 1/TICKS_PER_SEC mS +uint32 Scheduler::getWinTicks() { debugC(3, kDebugSchedule, "getTicks"); - return _vm.getGameStatus().tick; + return _vm->getGameStatus().tick; +} + +// Return system time in ticks. A tick is 1/TICKS_PER_SEC mS +// If update FALSE, simply return last known time +// Note that this is real time unless a processing cycle takes longer than +// a real tick, in which case the system tick is simply incremented +uint32 Scheduler::getDosTicks(bool updateFl) { + debugC(5, kDebugSchedule, "getTicks"); + + static uint32 tick = 0; // Current system time in ticks + static uint32 t_old = 0; // The previous wall time in ticks + + uint32 t_now; // Current wall time in ticks + + if (!updateFl) + return(tick); + + if (t_old == 0) + t_old = (uint32) floor((double) (g_system->getMillis() * TPS / 1000)); + /* Calculate current wall time in ticks */ + t_now = g_system->getMillis() * TPS / 1000 ; + + if ((t_now - t_old) > 0) { + t_old = t_now; + tick++; + } + return(tick); } -void Scheduler::processBonus(int bonusIndex) { // Add indecated bonus to score if not added already +void Scheduler::processBonus(int bonusIndex) { debugC(1, kDebugSchedule, "processBonus(%d)", bonusIndex); - if (!_vm._points[bonusIndex].scoredFl) { - _vm.adjustScore(_vm._points[bonusIndex].score); - _vm._points[bonusIndex].scoredFl = true; + if (!_vm->_points[bonusIndex].scoredFl) { + _vm->adjustScore(_vm->_points[bonusIndex].score); + _vm->_points[bonusIndex].scoredFl = true; } } @@ -536,11 +153,11 @@ void Scheduler::newScreen(int screenIndex) { debugC(1, kDebugSchedule, "newScreen(%d)", screenIndex); // Make sure the background file exists! - if (!_vm.isPacked()) { + if (!_vm->isPacked()) { char line[32]; - if (!_vm.file().fileExists(strcat(strncat(strcpy(line, _vm._picDir), _vm._screenNames[screenIndex], NAME_LEN), BKGEXT)) && - !_vm.file().fileExists(strcat(strcpy(line, _vm._screenNames[screenIndex]), ".ART"))) { - Utils::Box(BOX_ANY, "%s", _vm._textSchedule[kSsNoBackground]); + if (!_vm->_file->fileExists(strcat(strncat(strcpy(line, _vm->_picDir), _vm->_screenNames[screenIndex], NAME_LEN), BKGEXT)) && + !_vm->_file->fileExists(strcat(strcpy(line, _vm->_screenNames[screenIndex]), ".ART"))) { + Utils::Box(BOX_ANY, "%s", _vm->_textSchedule[kSsNoBackground]); return; } } @@ -556,145 +173,51 @@ void Scheduler::newScreen(int screenIndex) { } // 2. Set the new screen in the hero object and any being carried - _vm.setNewScreen(screenIndex); + _vm->setNewScreen(screenIndex); // 3. Read in new screen files - _vm.readScreenFiles(screenIndex); + _vm->readScreenFiles(screenIndex); // 4. Schedule action list for this screen - _vm.screenActions(screenIndex); + _vm->screenActions(screenIndex); // 5. Initialise prompt line and status line - _vm.initNewScreenDisplay(); + _vm->_screen->initNewScreenDisplay(); } -// Write the event queue to the file with handle f -// Note that we convert all the event structure ptrs to indexes -// using -1 for NULL. We can't convert the action ptrs to indexes -// so we save address of first dummy action ptr to compare on restore. -void Scheduler::saveEvents(Common::WriteStream *f) { - uint32 curTime; - event_t saveEvents_[kMaxEvents]; // Convert event ptrs to indexes - event_t *wrkEvent; // Event ptr - int16 freeIndex; // Free list index - int16 headIndex; // Head of list index - int16 tailIndex; // Tail of list index - - debugC(1, kDebugSchedule, "saveEvents"); - - curTime = getTicks(); - - // Convert event ptrs to indexes - for (int16 i = 0; i < kMaxEvents; i++) { - wrkEvent = &_events[i]; - saveEvents_[i] = *wrkEvent; - saveEvents_[i].prevEvent = (wrkEvent->prevEvent == NULL) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events); - saveEvents_[i].nextEvent = (wrkEvent->nextEvent == NULL) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events); - } - freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events; - headIndex = (_headEvent == 0) ? -1 : _headEvent - _events; - tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events; - - f->write(&curTime, sizeof(curTime)); - f->write(&freeIndex, sizeof(freeIndex)); - f->write(&headIndex, sizeof(headIndex)); - f->write(&tailIndex, sizeof(tailIndex)); - f->write(saveEvents_, sizeof(saveEvents_)); -} - -// Restore the event list from file with handle f -void Scheduler::restoreEvents(Common::SeekableReadStream *f) { - uint32 curTime, saveTime; - event_t *wrkEvent; // Event ptr - event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes - int16 freeIndex; // Free list index - int16 headIndex; // Head of list index - int16 tailIndex; // Tail of list index - - debugC(1, kDebugSchedule, "restoreEvents"); - - f->read(&saveTime, sizeof(saveTime)); // time of save - f->read(&freeIndex, sizeof(freeIndex)); - f->read(&headIndex, sizeof(headIndex)); - f->read(&tailIndex, sizeof(tailIndex)); - f->read(savedEvents, sizeof(savedEvents)); - - // Restore events indexes to pointers - for (int i = 0; i < kMaxEvents; i++) { - wrkEvent = &savedEvents[i]; - _events[i] = *wrkEvent; - _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ]; - _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ]; - } - _freeEvent = (freeIndex == -1) ? NULL : &_events[freeIndex]; - _headEvent = (headIndex == -1) ? NULL : &_events[headIndex]; - _tailEvent = (tailIndex == -1) ? NULL : &_events[tailIndex]; - - // Adjust times to fit our time - curTime = getTicks(); - wrkEvent = _headEvent; // The earliest event - while (wrkEvent) { // While mature events found - wrkEvent->time = wrkEvent->time - saveTime + curTime; - wrkEvent = wrkEvent->nextEvent; - } -} - -void Scheduler::restoreScreen(int screenIndex) { // Transition to a new screen as follows: // 1. Set the new screen (in the hero object and any carried objects) // 2. Read in the screen files for the new screen // 3. Initialise prompt line and status line - +void Scheduler::restoreScreen(int screenIndex) { debugC(1, kDebugSchedule, "restoreScreen(%d)", screenIndex); // 1. Set the new screen in the hero object and any being carried - _vm.setNewScreen(screenIndex); + _vm->setNewScreen(screenIndex); // 2. Read in new screen files - _vm.readScreenFiles(screenIndex); + _vm->readScreenFiles(screenIndex); // 3. Initialise prompt line and status line - _vm.initNewScreenDisplay(); + _vm->_screen->initNewScreenDisplay(); } -void Scheduler::swapImages(int objNumb1, int objNumb2) { -// Swap all the images of one object with another. Set hero_image (we make -// the assumption for now that the first obj is always the HERO) to the object -// number of the swapped image - seqList_t tmpSeqList[MAX_SEQUENCES]; - int seqListSize = sizeof(seqList_t) * MAX_SEQUENCES; +// Wait (if necessary) for next synchronizing tick +// Slow machines won't make it by the end of tick, so will just plod on +// at their own speed, not waiting here, but free running. +// Note: DOS Versions only +void Scheduler::waitForRefresh(void) { + debugC(1, kDebugSchedule, "waitForRefresh()"); - debugC(1, kDebugSchedule, "swapImages(%d, %d)", objNumb1, objNumb2); + static uint32 timeout = 0; + uint32 t; - _vm.file().saveSeq(&_vm._objects[objNumb1]); - memcpy(tmpSeqList, _vm._objects[objNumb1].seqList, seqListSize); - memcpy(_vm._objects[objNumb1].seqList, _vm._objects[objNumb2].seqList, seqListSize); - memcpy(_vm._objects[objNumb2].seqList, tmpSeqList, seqListSize); - _vm.file().restoreSeq(&_vm._objects[objNumb1]); - _vm._objects[objNumb2].currImagePtr = _vm._objects[objNumb2].seqList[0].seqPtr; - _vm._heroImage = (_vm._heroImage == HERO) ? objNumb2 : HERO; + if (timeout == 0) + timeout = getDosTicks(true); - // Make sure baseline stays constant - _vm._objects[objNumb1].y += _vm._objects[objNumb2].currImagePtr->y2 - _vm._objects[objNumb1].currImagePtr->y2; + while ((t = getDosTicks(true)) < timeout) + ; + timeout = ++t; } -Scheduler_v1::Scheduler_v1(HugoEngine &vm) : Scheduler(vm) { -} - -Scheduler_v1::~Scheduler_v1() { -} - -const char *Scheduler_v1::getCypher() { - return "Copyright 1991, Gray Design Associates"; -} - -Scheduler_v2::Scheduler_v2(HugoEngine &vm) : Scheduler(vm) { -} - -Scheduler_v2::~Scheduler_v2() { -} - -const char *Scheduler_v2::getCypher() { - return "Copyright 1992, Gray Design Associates"; -} } // End of namespace Hugo diff --git a/engines/hugo/schedule.h b/engines/hugo/schedule.h index 285f7bd6639..e6eb5d79476 100644 --- a/engines/hugo/schedule.h +++ b/engines/hugo/schedule.h @@ -35,71 +35,104 @@ namespace Hugo { -#define kMaxEvents 50 /* Max events in event queue */ +#define SIGN(X) ((X < 0) ? -1 : 1) +#define kMaxEvents 50 // Max events in event queue struct event_t { - act *action; /* Ptr to action to perform */ - bool localActionFl; /* TRUE if action is only for this screen */ - uint32 time; /* (absolute) time to perform action */ - struct event_t *prevEvent; /* Chain to previous event */ - struct event_t *nextEvent; /* Chain to next event */ + act *action; // Ptr to action to perform + bool localActionFl; // true if action is only for this screen + uint32 time; // (absolute) time to perform action + struct event_t *prevEvent; // Chain to previous event + struct event_t *nextEvent; // Chain to next event }; class Scheduler { public: - Scheduler(HugoEngine &vm); + Scheduler(HugoEngine *vm); virtual ~Scheduler(); + virtual void insertAction(act *action) = 0; + virtual void restoreEvents(Common::SeekableReadStream *f) = 0; + virtual void runScheduler() = 0; + virtual void saveEvents(Common::WriteStream *f) = 0; + void initEventQueue(); - void insertAction(act *action); void insertActionList(uint16 actIndex); void decodeString(char *line); - void runScheduler(); - uint32 getTicks(); + uint32 getWinTicks(); + uint32 getDosTicks(bool updateFl); + void waitForRefresh(void); void processBonus(int bonusIndex); void newScreen(int screenIndex); - void restoreEvents(Common::SeekableReadStream *f); - void saveEvents(Common::WriteStream *f); void restoreScreen(int screenIndex); - void swapImages(int objNumb1, int objNumb2); -private: +protected: + HugoEngine *_vm; + enum seqTextSchedule { kSsNoBackground = 0, kSsBadSaveGame = 1 }; - HugoEngine &_vm; + event_t *_freeEvent; // Free list of event structures + event_t *_headEvent; // Head of list (earliest time) + event_t *_tailEvent; // Tail of list (latest time) + event_t _events[kMaxEvents]; // Statically declare event structures - event_t _events[kMaxEvents]; /* Statically declare event structures */ - - event_t *_freeEvent; /* Free list of event structures */ - event_t *_headEvent; /* Head of list (earliest time) */ - event_t *_tailEvent; /* Tail of list (latest time) */ + virtual const char *getCypher() = 0; + virtual void delQueue(event_t *curEvent) = 0; + virtual event_t *doAction(event_t *curEvent) = 0; event_t *getQueue(); - void delQueue(event_t *curEvent); - event_t *doAction(event_t *curEvent); - - virtual const char *getCypher() = 0; }; -class Scheduler_v1 : public Scheduler { +class Scheduler_v1d : public Scheduler { public: - Scheduler_v1(HugoEngine &vm); - ~Scheduler_v1(); + Scheduler_v1d(HugoEngine *vm); + ~Scheduler_v1d(); + + virtual const char *getCypher(); + virtual void insertAction(act *action); + virtual void restoreEvents(Common::SeekableReadStream *f); + virtual void saveEvents(Common::WriteStream *f); + virtual void runScheduler(); +protected: + virtual void delQueue(event_t *curEvent); + virtual event_t *doAction(event_t *curEvent); +}; + +class Scheduler_v2d : public Scheduler_v1d { +public: + Scheduler_v2d(HugoEngine *vm); + virtual ~Scheduler_v2d(); + + virtual void insertAction(act *action); +protected: + virtual void delQueue(event_t *curEvent); + virtual event_t *doAction(event_t *curEvent); +}; + +class Scheduler_v3d : public Scheduler_v2d { +public: + Scheduler_v3d(HugoEngine *vm); + ~Scheduler_v3d(); const char *getCypher(); +protected: + virtual event_t *doAction(event_t *curEvent); + }; -class Scheduler_v2 : public Scheduler { +class Scheduler_v1w : public Scheduler_v3d { public: - Scheduler_v2(HugoEngine &vm); - ~Scheduler_v2(); + Scheduler_v1w(HugoEngine *vm); + ~Scheduler_v1w(); - const char *getCypher(); + virtual event_t *doAction(event_t *curEvent); + void insertAction(act *action); + void restoreEvents(Common::SeekableReadStream *f); + void runScheduler(); + void saveEvents(Common::WriteStream *f); }; - } // End of namespace Hugo - #endif //HUGO_SCHEDULE_H diff --git a/engines/hugo/schedule_v1d.cpp b/engines/hugo/schedule_v1d.cpp new file mode 100644 index 00000000000..09bfc2294ba --- /dev/null +++ b/engines/hugo/schedule_v1d.cpp @@ -0,0 +1,406 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// This module contains all the scheduling and timing stuff + +#include "common/system.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/schedule.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/parser.h" +#include "hugo/util.h" +#include "hugo/sound.h" +#include "hugo/object.h" + +namespace Hugo { + +Scheduler_v1d::Scheduler_v1d(HugoEngine *vm) : Scheduler(vm) { +} + +Scheduler_v1d::~Scheduler_v1d() { +} + +const char *Scheduler_v1d::getCypher() { + return "Copyright 1991, Gray Design Associates"; +} + +// Delete an event structure (i.e. return it to the free list) +// Note that event is assumed at head of queue (i.e. earliest). To delete +// an event from the middle of the queue, merely overwrite its action type +// to be ANULL +void Scheduler_v1d::delQueue(event_t *curEvent) { + debugC(4, kDebugSchedule, "delQueue()"); + + if (curEvent == _headEvent) // If p was the head ptr + _headEvent = curEvent->nextEvent; // then make new head_p + + if (_headEvent) + _headEvent->prevEvent = 0; // Mark end of list + else + _tailEvent = 0; // Empty queue + + curEvent->nextEvent = _freeEvent; // Return p to free list + if (_freeEvent) // Special case, if free list was empty + _freeEvent->prevEvent = curEvent; + _freeEvent = curEvent; +} + +// Insert the action pointed to by p into the timer event queue +// The queue goes from head (earliest) to tail (latest) timewise +void Scheduler_v1d::insertAction(act *action) { + debugC(1, kDebugSchedule, "insertAction() - Action type A%d", action->a0.actType); + + // First, get and initialise the event structure + event_t *curEvent = getQueue(); + curEvent->action = action; + + curEvent->localActionFl = true; // Rest are for current screen only + + curEvent->time = action->a0.timer + getDosTicks(false); // Convert rel to abs time + + // Now find the place to insert the event + if (!_tailEvent) { // Empty queue + _tailEvent = _headEvent = curEvent; + curEvent->nextEvent = curEvent->prevEvent = 0; + } else { + event_t *wrkEvent = _tailEvent; // Search from latest time back + bool found = false; + + while (wrkEvent && !found) { + if (wrkEvent->time <= curEvent->time) { // Found if new event later + found = true; + if (wrkEvent == _tailEvent) // New latest in list + _tailEvent = curEvent; + else + wrkEvent->nextEvent->prevEvent = curEvent; + curEvent->nextEvent = wrkEvent->nextEvent; + wrkEvent->nextEvent = curEvent; + curEvent->prevEvent = wrkEvent; + } + wrkEvent = wrkEvent->prevEvent; + } + + if (!found) { // Must be earliest in list + _headEvent->prevEvent = curEvent; // So insert as new head + curEvent->nextEvent = _headEvent; + curEvent->prevEvent = 0; + _headEvent = curEvent; + } + } +} + +event_t *Scheduler_v1d::doAction(event_t *curEvent) { +// This function performs the action in the event structure pointed to by p +// It dequeues the event and returns it to the free list. It returns a ptr +// to the next action in the list, except special case of NEW_SCREEN + debugC(1, kDebugSchedule, "doAction - Event action type : %d", curEvent->action->a0.actType); + + status_t &gameStatus = _vm->getGameStatus(); + act *action = curEvent->action; + char *response; // User's response string + object_t *obj1; + object_t *obj2; + int dx, dy; + event_t *wrkEvent; // Save ev_p->next_p for return +// event_t *saveEvent; // Used in DEL_EVENTS + + switch (action->a0.actType) { + case ANULL: // Big NOP from DEL_EVENTS + break; + case ASCHEDULE: // act0: Schedule an action list + insertActionList(action->a0.actIndex); + break; + case START_OBJ: // act1: Start an object cycling + _vm->_object->_objects[action->a1.objNumb].cycleNumb = action->a1.cycleNumb; + _vm->_object->_objects[action->a1.objNumb].cycling = action->a1.cycle; + break; + case INIT_OBJXY: // act2: Initialise an object + _vm->_object->_objects[action->a2.objNumb].x = action->a2.x; // Coordinates + _vm->_object->_objects[action->a2.objNumb].y = action->a2.y; + break; + case PROMPT: { // act3: Prompt user for key phrase + response = Utils::Box(BOX_PROMPT, "%s", _vm->_file->fetchString(action->a3.promptIndex)); + if (action->a3.encodedFl) + decodeString(response); + + warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0])); + + // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block +#if 0 + if (strstr (response, action->a3.response)) + insertActionList(action->a3.actPassIndex); + else + insertActionList(action->a3.actFailIndex); +#endif + + // HACK: As the answer is not read, currently it's always considered correct + insertActionList(action->a3.actPassIndex); + break; + } + case BKGD_COLOR: // act4: Set new background color + _vm->_screen->setBackgroundColor(action->a4.newBackgroundColor); + break; + case INIT_OBJVXY: // act5: Initialise an object velocity + _vm->_object->setVelocity(action->a5.objNumb, action->a5.vx, action->a5.vy); + break; + case INIT_CARRY: // act6: Initialise an object + _vm->_object->setCarry(action->a6.objNumb, action->a6.carriedFl); // carried status + break; + case INIT_HF_COORD: // act7: Initialise an object to hero's "feet" coords + _vm->_object->_objects[action->a7.objNumb].x = _vm->_hero->x - 1; + _vm->_object->_objects[action->a7.objNumb].y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + _vm->_object->_objects[action->a7.objNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + break; + case NEW_SCREEN: // act8: Start new screen + newScreen(action->a8.screenIndex); + break; + case INIT_OBJSTATE: // act9: Initialise an object state + _vm->_object->_objects[action->a9.objNumb].state = action->a9.newState; + break; + case INIT_PATH: // act10: Initialise an object path and velocity + _vm->_object->setPath(action->a10.objNumb, (path_t) action->a10.newPathType, action->a10.vxPath, action->a10.vyPath); + break; + case COND_R: // act11: action lists conditional on object state + if (_vm->_object->_objects[action->a11.objNumb].state == action->a11.stateReq) + insertActionList(action->a11.actPassIndex); + else + insertActionList(action->a11.actFailIndex); + break; + case TEXT: // act12: Text box (CF WARN) + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file + break; + case SWAP_IMAGES: // act13: Swap 2 object images + _vm->_object->swapImages(action->a13.obj1, action->a13.obj2); + break; + case COND_SCR: // act14: Conditional on current screen + if (_vm->_object->_objects[action->a14.objNumb].screenIndex == action->a14.screenReq) + insertActionList(action->a14.actPassIndex); + else + insertActionList(action->a14.actFailIndex); + break; + case AUTOPILOT: // act15: Home in on a (stationary) object + // object p1 will home in on object p2 + obj1 = &_vm->_object->_objects[action->a15.obj1]; + obj2 = &_vm->_object->_objects[action->a15.obj2]; + obj1->pathType = AUTO; + dx = obj1->x + obj1->currImagePtr->x1 - obj2->x - obj2->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y1 - obj2->y - obj2->currImagePtr->y1; + + if (dx == 0) // Don't EVER divide by zero! + dx = 1; + if (dy == 0) + dy = 1; + + if (abs(dx) > abs(dy)) { + obj1->vx = action->a15.dx * -SIGN(dx); + obj1->vy = abs((action->a15.dy * dy) / dx) * -SIGN(dy); + } else { + obj1->vy = action->a15.dy * SIGN(dy); + obj1->vx = abs((action->a15.dx * dx) / dy) * SIGN(dx); + } + break; + case INIT_OBJ_SEQ: // act16: Set sequence number to use + // Note: Don't set a sequence at time 0 of a new screen, it causes + // problems clearing the boundary bits of the object! t>0 is safe + _vm->_object->_objects[action->a16.objNumb].currImagePtr = _vm->_object->_objects[action->a16.objNumb].seqList[action->a16.seqIndex].seqPtr; + break; + case SET_STATE_BITS: // act17: OR mask with curr obj state + _vm->_object->_objects[action->a17.objNumb].state |= action->a17.stateMask; + break; + case CLEAR_STATE_BITS: // act18: AND ~mask with curr obj state + _vm->_object->_objects[action->a18.objNumb].state &= ~action->a18.stateMask; + break; + case TEST_STATE_BITS: // act19: If all bits set, do apass else afail + if ((_vm->_object->_objects[action->a19.objNumb].state & action->a19.stateMask) == action->a19.stateMask) + insertActionList(action->a19.actPassIndex); + else + insertActionList(action->a19.actFailIndex); + break; + case DEL_EVENTS: // act20: Remove all events of this action type + // Note: actions are not deleted here, simply turned into NOPs! + wrkEvent = _headEvent; // The earliest event + while (wrkEvent) { // While events found in list + if (wrkEvent->action->a20.actType == action->a20.actTypeDel) + wrkEvent->action->a20.actType = ANULL; + wrkEvent = wrkEvent->nextEvent; + } + break; + case GAMEOVER: // act21: Game over! + // NOTE: Must wait at least 1 tick before issuing this action if + // any objects are to be made invisible! + gameStatus.gameOverFl = true; + break; + case INIT_HH_COORD: // act22: Initialise an object to hero's actual coords + _vm->_object->_objects[action->a22.objNumb].x = _vm->_hero->x; + _vm->_object->_objects[action->a22.objNumb].y = _vm->_hero->y; + _vm->_object->_objects[action->a22.objNumb].screenIndex = *_vm->_screen_p;// Don't forget screen! + break; + case EXIT: // act23: Exit game back to DOS + _vm->endGame(); + break; + case BONUS: // act24: Get bonus score for action + processBonus(action->a24.pointIndex); + break; + case COND_BOX: // act25: Conditional on bounding box + obj1 = &_vm->_object->_objects[action->a25.objNumb]; + dx = obj1->x + obj1->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y2; + if ((dx >= action->a25.x1) && (dx <= action->a25.x2) && + (dy >= action->a25.y1) && (dy <= action->a25.y2)) + insertActionList(action->a25.actPassIndex); + else + insertActionList(action->a25.actFailIndex); + break; +// case SOUND: // act26: Play a sound (or tune) +// if (action->a26.soundIndex < _vm->_tunesNbr) +// _vm->_sound->playMusic(action->a26.soundIndex); +// else +// _vm->_sound->playSound(action->a26.soundIndex, BOTH_CHANNELS, MED_PRI); +// break; + case ADD_SCORE: // act27: Add object's value to score + _vm->adjustScore(_vm->_object->_objects[action->a27.objNumb].objValue); + break; + case SUB_SCORE: // act28: Subtract object's value from score + _vm->adjustScore(-_vm->_object->_objects[action->a28.objNumb].objValue); + break; + case COND_CARRY: // act29: Conditional on object being carried + if (_vm->_object->isCarried(action->a29.objNumb)) + insertActionList(action->a29.actPassIndex); + else + insertActionList(action->a29.actFailIndex); + break; + case OLD_SONG: + //TODO For Hugo 1 and Hugo2 DOS: The songs were not stored in a DAT file, but directly as + //strings. the current play_music should be modified to use a strings instead of reading + //the file, in those cases. This replaces, for those DOS versions, act26. + warning("STUB: doAction(act49)"); + break; + default: + Utils::Error(EVNT_ERR, "%s", "doAction"); + break; + } + + if (action->a0.actType == NEW_SCREEN) { // New_screen() deletes entire list + return 0; // next_p = 0 since list now empty + } else { + wrkEvent = curEvent->nextEvent; + delQueue(curEvent); // Return event to free list + return wrkEvent; // Return next event ptr + } +} + +// Write the event queue to the file with handle f +// Note that we convert all the event structure ptrs to indexes +// using -1 for NULL. We can't convert the action ptrs to indexes +// so we save address of first dummy action ptr to compare on restore. +void Scheduler_v1d::saveEvents(Common::WriteStream *f) { + debugC(1, kDebugSchedule, "saveEvents()"); + + uint32 curTime = getDosTicks(false); + event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes + + // Convert event ptrs to indexes + for (int16 i = 0; i < kMaxEvents; i++) { + event_t *wrkEvent = &_events[i]; + saveEventArr[i] = *wrkEvent; + saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events); + saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events); + } + + int16 freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events; + int16 headIndex = (_headEvent == 0) ? -1 : _headEvent - _events; + int16 tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events; + + f->write(&curTime, sizeof(curTime)); + f->write(&freeIndex, sizeof(freeIndex)); + f->write(&headIndex, sizeof(headIndex)); + f->write(&tailIndex, sizeof(tailIndex)); + f->write(saveEventArr, sizeof(saveEventArr)); +} + +// Restore the event list from file with handle f +void Scheduler_v1d::restoreEvents(Common::SeekableReadStream *f) { + debugC(1, kDebugSchedule, "restoreEvents"); + + uint32 saveTime; + int16 freeIndex; // Free list index + int16 headIndex; // Head of list index + int16 tailIndex; // Tail of list index + event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes + + f->read(&saveTime, sizeof(saveTime)); // time of save + f->read(&freeIndex, sizeof(freeIndex)); + f->read(&headIndex, sizeof(headIndex)); + f->read(&tailIndex, sizeof(tailIndex)); + f->read(savedEvents, sizeof(savedEvents)); + + event_t *wrkEvent; + // Restore events indexes to pointers + for (int i = 0; i < kMaxEvents; i++) { + wrkEvent = &savedEvents[i]; + _events[i] = *wrkEvent; + _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ]; + _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ]; + } + _freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex]; + _headEvent = (headIndex == -1) ? 0 : &_events[headIndex]; + _tailEvent = (tailIndex == -1) ? 0 : &_events[tailIndex]; + + // Adjust times to fit our time + uint32 curTime = getDosTicks(false); + wrkEvent = _headEvent; // The earliest event + while (wrkEvent) { // While mature events found + wrkEvent->time = wrkEvent->time - saveTime + curTime; + wrkEvent = wrkEvent->nextEvent; + } +} + +// This is the scheduler which runs every tick. It examines the event queue +// for any events whose time has come. It dequeues these events and performs +// the action associated with the event, returning it to the free queue +void Scheduler_v1d::runScheduler() { + debugC(6, kDebugSchedule, "runScheduler"); + + uint32 ticker; // The time now, in ticks + event_t *curEvent; // Event ptr + + ticker = getDosTicks(false); + + curEvent = _headEvent; // The earliest event + while (curEvent && curEvent->time <= ticker) // While mature events found + curEvent = doAction(curEvent); // Perform the action (returns next_p) +} + +} // End of namespace Hugo diff --git a/engines/hugo/schedule_v1w.cpp b/engines/hugo/schedule_v1w.cpp new file mode 100644 index 00000000000..34eff0447f8 --- /dev/null +++ b/engines/hugo/schedule_v1w.cpp @@ -0,0 +1,481 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// This module contains all the scheduling and timing stuff + +#include "common/system.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/schedule.h" +#include "hugo/global.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/parser.h" +#include "hugo/util.h" +#include "hugo/sound.h" +#include "hugo/object.h" + +namespace Hugo { + +Scheduler_v1w::Scheduler_v1w(HugoEngine *vm) : Scheduler_v3d(vm) { +} + +Scheduler_v1w::~Scheduler_v1w() { +} + +event_t *Scheduler_v1w::doAction(event_t *curEvent) { +// This function performs the action in the event structure pointed to by p +// It dequeues the event and returns it to the free list. It returns a ptr +// to the next action in the list, except special case of NEW_SCREEN + debugC(1, kDebugSchedule, "doAction - Event action type : %d", curEvent->action->a0.actType); + + status_t &gameStatus = _vm->getGameStatus(); + act *action = curEvent->action; + char *response; // User's response string + object_t *obj1; + object_t *obj2; + int dx, dy; + event_t *wrkEvent; // Save ev_p->next_p for return + event_t *saveEvent; // Used in DEL_EVENTS + + switch (action->a0.actType) { + case ANULL: // Big NOP from DEL_EVENTS + break; + case ASCHEDULE: // act0: Schedule an action list + insertActionList(action->a0.actIndex); + break; + case START_OBJ: // act1: Start an object cycling + _vm->_object->_objects[action->a1.objNumb].cycleNumb = action->a1.cycleNumb; + _vm->_object->_objects[action->a1.objNumb].cycling = action->a1.cycle; + break; + case INIT_OBJXY: // act2: Initialise an object + _vm->_object->_objects[action->a2.objNumb].x = action->a2.x; // Coordinates + _vm->_object->_objects[action->a2.objNumb].y = action->a2.y; + break; + case PROMPT: { // act3: Prompt user for key phrase + response = Utils::Box(BOX_PROMPT, "%s", _vm->_file->fetchString(action->a3.promptIndex)); + + warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0])); + + // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block +#if 0 + bool found; + char *tmpStr; // General purpose string ptr + + for (found = false, dx = 0; !found && (action->a3.responsePtr[dx] != -1); dx++) { + tmpStr = _vm->_file->fetchString(action->a3.responsePtr[dx]); + if (strstr(Utils::strlwr(response) , tmpStr)) + found = true; + } + + if (found) + insertActionList(action->a3.actPassIndex); + else + insertActionList(action->a3.actFailIndex); +#endif + + // HACK: As the answer is not read, currently it's always considered correct + insertActionList(action->a3.actPassIndex); + break; + } + case BKGD_COLOR: // act4: Set new background color + _vm->_screen->setBackgroundColor(action->a4.newBackgroundColor); + break; + case INIT_OBJVXY: // act5: Initialise an object velocity + _vm->_object->setVelocity(action->a5.objNumb, action->a5.vx, action->a5.vy); + break; + case INIT_CARRY: // act6: Initialise an object + _vm->_object->setCarry(action->a6.objNumb, action->a6.carriedFl); // carried status + break; + case INIT_HF_COORD: // act7: Initialise an object to hero's "feet" coords + _vm->_object->_objects[action->a7.objNumb].x = _vm->_hero->x - 1; + _vm->_object->_objects[action->a7.objNumb].y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + _vm->_object->_objects[action->a7.objNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + break; + case NEW_SCREEN: // act8: Start new screen + newScreen(action->a8.screenIndex); + break; + case INIT_OBJSTATE: // act9: Initialise an object state + _vm->_object->_objects[action->a9.objNumb].state = action->a9.newState; + break; + case INIT_PATH: // act10: Initialise an object path and velocity + _vm->_object->setPath(action->a10.objNumb, (path_t) action->a10.newPathType, action->a10.vxPath, action->a10.vyPath); + break; + case COND_R: // act11: action lists conditional on object state + if (_vm->_object->_objects[action->a11.objNumb].state == action->a11.stateReq) + insertActionList(action->a11.actPassIndex); + else + insertActionList(action->a11.actFailIndex); + break; + case TEXT: // act12: Text box (CF WARN) + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file + break; + case SWAP_IMAGES: // act13: Swap 2 object images + _vm->_object->swapImages(action->a13.obj1, action->a13.obj2); + break; + case COND_SCR: // act14: Conditional on current screen + if (_vm->_object->_objects[action->a14.objNumb].screenIndex == action->a14.screenReq) + insertActionList(action->a14.actPassIndex); + else + insertActionList(action->a14.actFailIndex); + break; + case AUTOPILOT: // act15: Home in on a (stationary) object + // object p1 will home in on object p2 + obj1 = &_vm->_object->_objects[action->a15.obj1]; + obj2 = &_vm->_object->_objects[action->a15.obj2]; + obj1->pathType = AUTO; + dx = obj1->x + obj1->currImagePtr->x1 - obj2->x - obj2->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y1 - obj2->y - obj2->currImagePtr->y1; + + if (dx == 0) // Don't EVER divide by zero! + dx = 1; + if (dy == 0) + dy = 1; + + if (abs(dx) > abs(dy)) { + obj1->vx = action->a15.dx * -SIGN(dx); + obj1->vy = abs((action->a15.dy * dy) / dx) * -SIGN(dy); + } else { + obj1->vy = action->a15.dy * -SIGN(dy); + obj1->vx = abs((action->a15.dx * dx) / dy) * -SIGN(dx); + } + break; + case INIT_OBJ_SEQ: // act16: Set sequence number to use + // Note: Don't set a sequence at time 0 of a new screen, it causes + // problems clearing the boundary bits of the object! t>0 is safe + _vm->_object->_objects[action->a16.objNumb].currImagePtr = _vm->_object->_objects[action->a16.objNumb].seqList[action->a16.seqIndex].seqPtr; + break; + case SET_STATE_BITS: // act17: OR mask with curr obj state + _vm->_object->_objects[action->a17.objNumb].state |= action->a17.stateMask; + break; + case CLEAR_STATE_BITS: // act18: AND ~mask with curr obj state + _vm->_object->_objects[action->a18.objNumb].state &= ~action->a18.stateMask; + break; + case TEST_STATE_BITS: // act19: If all bits set, do apass else afail + if ((_vm->_object->_objects[action->a19.objNumb].state & action->a19.stateMask) == action->a19.stateMask) + insertActionList(action->a19.actPassIndex); + else + insertActionList(action->a19.actFailIndex); + break; + case DEL_EVENTS: // act20: Remove all events of this action type + // Note: actions are not deleted here, simply turned into NOPs! + wrkEvent = _headEvent; // The earliest event + while (wrkEvent) { // While events found in list + saveEvent = wrkEvent->nextEvent; + if (wrkEvent->action->a20.actType == action->a20.actTypeDel) + delQueue(wrkEvent); + wrkEvent = saveEvent; + } + break; + case GAMEOVER: // act21: Game over! + // NOTE: Must wait at least 1 tick before issuing this action if + // any objects are to be made invisible! + gameStatus.gameOverFl = true; + break; + case INIT_HH_COORD: // act22: Initialise an object to hero's actual coords + _vm->_object->_objects[action->a22.objNumb].x = _vm->_hero->x; + _vm->_object->_objects[action->a22.objNumb].y = _vm->_hero->y; + _vm->_object->_objects[action->a22.objNumb].screenIndex = *_vm->_screen_p;// Don't forget screen! + break; + case EXIT: // act23: Exit game back to DOS + _vm->endGame(); + break; + case BONUS: // act24: Get bonus score for action + processBonus(action->a24.pointIndex); + break; + case COND_BOX: // act25: Conditional on bounding box + obj1 = &_vm->_object->_objects[action->a25.objNumb]; + dx = obj1->x + obj1->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y2; + if ((dx >= action->a25.x1) && (dx <= action->a25.x2) && + (dy >= action->a25.y1) && (dy <= action->a25.y2)) + insertActionList(action->a25.actPassIndex); + else + insertActionList(action->a25.actFailIndex); + break; + case SOUND: // act26: Play a sound (or tune) + if (action->a26.soundIndex < _vm->_tunesNbr) + _vm->_sound->playMusic(action->a26.soundIndex); + else + _vm->_sound->playSound(action->a26.soundIndex, BOTH_CHANNELS, MED_PRI); + break; + case ADD_SCORE: // act27: Add object's value to score + _vm->adjustScore(_vm->_object->_objects[action->a27.objNumb].objValue); + break; + case SUB_SCORE: // act28: Subtract object's value from score + _vm->adjustScore(-_vm->_object->_objects[action->a28.objNumb].objValue); + break; + case COND_CARRY: // act29: Conditional on object being carried + if (_vm->_object->isCarried(action->a29.objNumb)) + insertActionList(action->a29.actPassIndex); + else + insertActionList(action->a29.actFailIndex); + break; + case INIT_MAZE: // act30: Enable and init maze structure + _maze.enabledFl = true; + _maze.size = action->a30.mazeSize; + _maze.x1 = action->a30.x1; + _maze.y1 = action->a30.y1; + _maze.x2 = action->a30.x2; + _maze.y2 = action->a30.y2; + _maze.x3 = action->a30.x3; + _maze.x4 = action->a30.x4; + _maze.firstScreenIndex = action->a30.firstScreenIndex; + break; + case EXIT_MAZE: // act31: Disable maze mode + _maze.enabledFl = false; + break; + case INIT_PRIORITY: + _vm->_object->_objects[action->a32.objNumb].priority = action->a32.priority; + break; + case INIT_SCREEN: + _vm->_object->_objects[action->a33.objNumb].screenIndex = action->a33.screenIndex; + break; + case AGSCHEDULE: // act34: Schedule a (global) action list + insertActionList(action->a34.actIndex); + break; + case REMAPPAL: // act35: Remap a palette color + _vm->_screen->remapPal(action->a35.oldColorIndex, action->a35.newColorIndex); + break; + case COND_NOUN: // act36: Conditional on noun mentioned + if (_vm->_parser->isWordPresent(_vm->_arrayNouns[action->a36.nounIndex])) + insertActionList(action->a36.actPassIndex); + else + insertActionList(action->a36.actFailIndex); + break; + case SCREEN_STATE: // act37: Set new screen state + _vm->_screenStates[action->a37.screenIndex] = action->a37.newState; + break; + case INIT_LIPS: // act38: Position lips on object + _vm->_object->_objects[action->a38.lipsObjNumb].x = _vm->_object->_objects[action->a38.objNumb].x + action->a38.dxLips; + _vm->_object->_objects[action->a38.lipsObjNumb].y = _vm->_object->_objects[action->a38.objNumb].y + action->a38.dyLips; + _vm->_object->_objects[action->a38.lipsObjNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + _vm->_object->_objects[action->a38.lipsObjNumb].cycling = CYCLE_FORWARD; + break; + case INIT_STORY_MODE: // act39: Init story_mode flag + // This is similar to the QUIET path mode, except that it is + // independant of it and it additionally disables the ">" prompt + gameStatus.storyModeFl = action->a39.storyModeFl; + + // End the game after story if this is special vendor demo mode + if (gameStatus.demoFl && action->a39.storyModeFl == false) + _vm->endGame(); + break; + case WARN: // act40: Text box (CF TEXT) + Utils::Box(BOX_OK, "%s", _vm->_file->fetchString(action->a40.stringIndex)); + break; + case COND_BONUS: // act41: Perform action if got bonus + if (_vm->_points[action->a41.BonusIndex].scoredFl) + insertActionList(action->a41.actPassIndex); + else + insertActionList(action->a41.actFailIndex); + break; + case TEXT_TAKE: // act42: Text box with "take" message + Utils::Box(BOX_ANY, TAKE_TEXT, _vm->_arrayNouns[_vm->_object->_objects[action->a42.objNumb].nounIndex][TAKE_NAME]); + break; + case YESNO: // act43: Prompt user for Yes or No + warning("doAction(act43) - Yes/No Box"); + if (Utils::Box(BOX_YESNO, "%s", _vm->_file->fetchString(action->a43.promptIndex)) != 0) + insertActionList(action->a43.actYesIndex); + else + insertActionList(action->a43.actNoIndex); + break; + case STOP_ROUTE: // act44: Stop any route in progress + gameStatus.routeIndex = -1; + break; + case COND_ROUTE: // act45: Conditional on route in progress + if (gameStatus.routeIndex >= action->a45.routeIndex) + insertActionList(action->a45.actPassIndex); + else + insertActionList(action->a45.actFailIndex); + break; + case INIT_JUMPEXIT: // act46: Init status.jumpexit flag + // This is to allow left click on exit to get there immediately + // For example the plane crash in Hugo2 where hero is invisible + // Couldn't use INVISIBLE flag since conflicts with boat in Hugo1 + gameStatus.jumpExitFl = action->a46.jumpExitFl; + break; + case INIT_VIEW: // act47: Init object.viewx, viewy, dir + _vm->_object->_objects[action->a47.objNumb].viewx = action->a47.viewx; + _vm->_object->_objects[action->a47.objNumb].viewy = action->a47.viewy; + _vm->_object->_objects[action->a47.objNumb].direction = action->a47.direction; + break; + case INIT_OBJ_FRAME: // act48: Set seq,frame number to use + // Note: Don't set a sequence at time 0 of a new screen, it causes + // problems clearing the boundary bits of the object! t>0 is safe + _vm->_object->_objects[action->a48.objNumb].currImagePtr = _vm->_object->_objects[action->a48.objNumb].seqList[action->a48.seqIndex].seqPtr; + for (dx = 0; dx < action->a48.frameIndex; dx++) + _vm->_object->_objects[action->a48.objNumb].currImagePtr = _vm->_object->_objects[action->a48.objNumb].currImagePtr->nextSeqPtr; + break; + default: + Utils::Error(EVNT_ERR, "%s", "doAction"); + break; + } + + if (action->a0.actType == NEW_SCREEN) { // New_screen() deletes entire list + return 0; // next_p = 0 since list now empty + } else { + wrkEvent = curEvent->nextEvent; + delQueue(curEvent); // Return event to free list + return wrkEvent; // Return next event ptr + } +} + +// Write the event queue to the file with handle f +// Note that we convert all the event structure ptrs to indexes +// using -1 for NULL. We can't convert the action ptrs to indexes +// so we save address of first dummy action ptr to compare on restore. +void Scheduler_v1w::saveEvents(Common::WriteStream *f) { + debugC(1, kDebugSchedule, "saveEvents()"); + + uint32 curTime = getWinTicks(); + event_t saveEventArr[kMaxEvents]; // Convert event ptrs to indexes + + // Convert event ptrs to indexes + for (int16 i = 0; i < kMaxEvents; i++) { + event_t *wrkEvent = &_events[i]; + saveEventArr[i] = *wrkEvent; + saveEventArr[i].prevEvent = (wrkEvent->prevEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->prevEvent - _events); + saveEventArr[i].nextEvent = (wrkEvent->nextEvent == 0) ? (event_t *) - 1 : (event_t *)(wrkEvent->nextEvent - _events); + } + + int16 freeIndex = (_freeEvent == 0) ? -1 : _freeEvent - _events; + int16 headIndex = (_headEvent == 0) ? -1 : _headEvent - _events; + int16 tailIndex = (_tailEvent == 0) ? -1 : _tailEvent - _events; + + f->write(&curTime, sizeof(curTime)); + f->write(&freeIndex, sizeof(freeIndex)); + f->write(&headIndex, sizeof(headIndex)); + f->write(&tailIndex, sizeof(tailIndex)); + f->write(saveEventArr, sizeof(saveEventArr)); +} + +// Restore the event list from file with handle f +void Scheduler_v1w::restoreEvents(Common::SeekableReadStream *f) { + debugC(1, kDebugSchedule, "restoreEvents"); + + uint32 saveTime; + int16 freeIndex; // Free list index + int16 headIndex; // Head of list index + int16 tailIndex; // Tail of list index + event_t savedEvents[kMaxEvents]; // Convert event ptrs to indexes + + f->read(&saveTime, sizeof(saveTime)); // time of save + f->read(&freeIndex, sizeof(freeIndex)); + f->read(&headIndex, sizeof(headIndex)); + f->read(&tailIndex, sizeof(tailIndex)); + f->read(savedEvents, sizeof(savedEvents)); + + event_t *wrkEvent; + // Restore events indexes to pointers + for (int i = 0; i < kMaxEvents; i++) { + wrkEvent = &savedEvents[i]; + _events[i] = *wrkEvent; + _events[i].prevEvent = (wrkEvent->prevEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->prevEvent ]; + _events[i].nextEvent = (wrkEvent->nextEvent == (event_t *) - 1) ? (event_t *)0 : &_events[(size_t)wrkEvent->nextEvent ]; + } + _freeEvent = (freeIndex == -1) ? 0 : &_events[freeIndex]; + _headEvent = (headIndex == -1) ? 0 : &_events[headIndex]; + _tailEvent = (tailIndex == -1) ? 0 : &_events[tailIndex]; + + // Adjust times to fit our time + uint32 curTime = getWinTicks(); + wrkEvent = _headEvent; // The earliest event + while (wrkEvent) { // While mature events found + wrkEvent->time = wrkEvent->time - saveTime + curTime; + wrkEvent = wrkEvent->nextEvent; + } +} + +void Scheduler_v1w::insertAction(act *action) { + debugC(1, kDebugSchedule, "insertAction() - Action type A%d", action->a0.actType); + + // First, get and initialise the event structure + event_t *curEvent = getQueue(); + curEvent->action = action; + switch (action->a0.actType) { // Assign whether local or global + case AGSCHEDULE: + curEvent->localActionFl = false; // Lasts over a new screen + break; + default: + curEvent->localActionFl = true; // Rest are for current screen only + break; + } + + curEvent->time = action->a0.timer + getWinTicks(); // Convert rel to abs time + + // Now find the place to insert the event + if (!_tailEvent) { // Empty queue + _tailEvent = _headEvent = curEvent; + curEvent->nextEvent = curEvent->prevEvent = 0; + } else { + event_t *wrkEvent = _tailEvent; // Search from latest time back + bool found = false; + + while (wrkEvent && !found) { + if (wrkEvent->time <= curEvent->time) { // Found if new event later + found = true; + if (wrkEvent == _tailEvent) // New latest in list + _tailEvent = curEvent; + else + wrkEvent->nextEvent->prevEvent = curEvent; + curEvent->nextEvent = wrkEvent->nextEvent; + wrkEvent->nextEvent = curEvent; + curEvent->prevEvent = wrkEvent; + } + wrkEvent = wrkEvent->prevEvent; + } + + if (!found) { // Must be earliest in list + _headEvent->prevEvent = curEvent; // So insert as new head + curEvent->nextEvent = _headEvent; + curEvent->prevEvent = 0; + _headEvent = curEvent; + } + } +} + +// This is the scheduler which runs every tick. It examines the event queue +// for any events whose time has come. It dequeues these events and performs +// the action associated with the event, returning it to the free queue +void Scheduler_v1w::runScheduler() { + debugC(6, kDebugSchedule, "runScheduler"); + + status_t &gameStatus = _vm->getGameStatus(); + event_t *curEvent = _headEvent; // The earliest event + + while (curEvent && curEvent->time <= gameStatus.tick) // While mature events found + curEvent = doAction(curEvent); // Perform the action (returns next_p) + gameStatus.tick++; // Accessed elsewhere via getTicks() +} +} // End of namespace Hugo diff --git a/engines/hugo/schedule_v2d.cpp b/engines/hugo/schedule_v2d.cpp new file mode 100644 index 00000000000..2735bc4cf4a --- /dev/null +++ b/engines/hugo/schedule_v2d.cpp @@ -0,0 +1,385 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// This module contains all the scheduling and timing stuff + +#include "common/system.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/schedule.h" +#include "hugo/global.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/parser.h" +#include "hugo/util.h" +#include "hugo/sound.h" +#include "hugo/object.h" + +namespace Hugo { + +Scheduler_v2d::Scheduler_v2d(HugoEngine *vm) : Scheduler_v1d(vm) { +} + +Scheduler_v2d::~Scheduler_v2d() { +} + +// Delete an event structure (i.e. return it to the free list) +// Historical note: Originally event p was assumed to be at head of queue +// (i.e. earliest) since all events were deleted in order when proceeding to +// a new screen. To delete an event from the middle of the queue, the action +// was overwritten to be ANULL. With the advent of GLOBAL events, delQueue +// was modified to allow deletes anywhere in the list, and the DEL_EVENT +// action was modified to perform the actual delete. +void Scheduler_v2d::delQueue(event_t *curEvent) { + debugC(4, kDebugSchedule, "delQueue()"); + + if (curEvent == _headEvent) { // If p was the head ptr + _headEvent = curEvent->nextEvent; // then make new head_p + } else { // Unlink p + curEvent->prevEvent->nextEvent = curEvent->nextEvent; + if (curEvent->nextEvent) + curEvent->nextEvent->prevEvent = curEvent->prevEvent; + else + _tailEvent = curEvent->prevEvent; + } + + if (_headEvent) + _headEvent->prevEvent = 0; // Mark end of list + else + _tailEvent = 0; // Empty queue + + curEvent->nextEvent = _freeEvent; // Return p to free list + if (_freeEvent) // Special case, if free list was empty + _freeEvent->prevEvent = curEvent; + _freeEvent = curEvent; +} + +// Insert the action pointed to by p into the timer event queue +// The queue goes from head (earliest) to tail (latest) timewise +void Scheduler_v2d::insertAction(act *action) { + debugC(1, kDebugSchedule, "insertAction() - Action type A%d", action->a0.actType); + + // First, get and initialise the event structure + event_t *curEvent = getQueue(); + curEvent->action = action; + switch (action->a0.actType) { // Assign whether local or global + case AGSCHEDULE: + curEvent->localActionFl = false; // Lasts over a new screen + break; + default: + curEvent->localActionFl = true; // Rest are for current screen only + break; + } + + curEvent->time = action->a0.timer + getDosTicks(false); // Convert rel to abs time + + // Now find the place to insert the event + if (!_tailEvent) { // Empty queue + _tailEvent = _headEvent = curEvent; + curEvent->nextEvent = curEvent->prevEvent = 0; + } else { + event_t *wrkEvent = _tailEvent; // Search from latest time back + bool found = false; + + while (wrkEvent && !found) { + if (wrkEvent->time <= curEvent->time) { // Found if new event later + found = true; + if (wrkEvent == _tailEvent) // New latest in list + _tailEvent = curEvent; + else + wrkEvent->nextEvent->prevEvent = curEvent; + curEvent->nextEvent = wrkEvent->nextEvent; + wrkEvent->nextEvent = curEvent; + curEvent->prevEvent = wrkEvent; + } + wrkEvent = wrkEvent->prevEvent; + } + + if (!found) { // Must be earliest in list + _headEvent->prevEvent = curEvent; // So insert as new head + curEvent->nextEvent = _headEvent; + curEvent->prevEvent = 0; + _headEvent = curEvent; + } + } +} + +// This function performs the action in the event structure pointed to by p +// It dequeues the event and returns it to the free list. It returns a ptr +// to the next action in the list, except special case of NEW_SCREEN +event_t *Scheduler_v2d::doAction(event_t *curEvent) { + debugC(1, kDebugSchedule, "doAction - Event action type : %d", curEvent->action->a0.actType); + + status_t &gameStatus = _vm->getGameStatus(); + act *action = curEvent->action; + char *response; // User's response string + object_t *obj1; + object_t *obj2; + int dx, dy; + event_t *wrkEvent; // Save ev_p->next_p for return + event_t *saveEvent; // Used in DEL_EVENTS + + switch (action->a0.actType) { + case ANULL: // Big NOP from DEL_EVENTS + break; + case ASCHEDULE: // act0: Schedule an action list + insertActionList(action->a0.actIndex); + break; + case START_OBJ: // act1: Start an object cycling + _vm->_object->_objects[action->a1.objNumb].cycleNumb = action->a1.cycleNumb; + _vm->_object->_objects[action->a1.objNumb].cycling = action->a1.cycle; + break; + case INIT_OBJXY: // act2: Initialise an object + _vm->_object->_objects[action->a2.objNumb].x = action->a2.x; // Coordinates + _vm->_object->_objects[action->a2.objNumb].y = action->a2.y; + break; + case PROMPT: { // act3: Prompt user for key phrase + response = Utils::Box(BOX_PROMPT, "%s", _vm->_file->fetchString(action->a3.promptIndex)); + + warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0])); + + // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block +#if 0 + bool found; + char *tmpStr; // General purpose string ptr + + for (found = false, dx = 0; !found && (action->a3.responsePtr[dx] != -1); dx++) { + tmpStr = _vm->_file->fetchString(action->a3.responsePtr[dx]); + if (strstr(Utils::strlwr(response) , tmpStr)) + found = true; + } + + if (found) + insertActionList(action->a3.actPassIndex); + else + insertActionList(action->a3.actFailIndex); +#endif + + // HACK: As the answer is not read, currently it's always considered correct + insertActionList(action->a3.actPassIndex); + break; + } + case BKGD_COLOR: // act4: Set new background color + _vm->_screen->setBackgroundColor(action->a4.newBackgroundColor); + break; + case INIT_OBJVXY: // act5: Initialise an object velocity + _vm->_object->setVelocity(action->a5.objNumb, action->a5.vx, action->a5.vy); + break; + case INIT_CARRY: // act6: Initialise an object + _vm->_object->setCarry(action->a6.objNumb, action->a6.carriedFl); // carried status + break; + case INIT_HF_COORD: // act7: Initialise an object to hero's "feet" coords + _vm->_object->_objects[action->a7.objNumb].x = _vm->_hero->x - 1; + _vm->_object->_objects[action->a7.objNumb].y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + _vm->_object->_objects[action->a7.objNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + break; + case NEW_SCREEN: // act8: Start new screen + newScreen(action->a8.screenIndex); + break; + case INIT_OBJSTATE: // act9: Initialise an object state + _vm->_object->_objects[action->a9.objNumb].state = action->a9.newState; + break; + case INIT_PATH: // act10: Initialise an object path and velocity + _vm->_object->setPath(action->a10.objNumb, (path_t) action->a10.newPathType, action->a10.vxPath, action->a10.vyPath); + break; + case COND_R: // act11: action lists conditional on object state + if (_vm->_object->_objects[action->a11.objNumb].state == action->a11.stateReq) + insertActionList(action->a11.actPassIndex); + else + insertActionList(action->a11.actFailIndex); + break; + case TEXT: // act12: Text box (CF WARN) + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file + break; + case SWAP_IMAGES: // act13: Swap 2 object images + _vm->_object->swapImages(action->a13.obj1, action->a13.obj2); + break; + case COND_SCR: // act14: Conditional on current screen + if (_vm->_object->_objects[action->a14.objNumb].screenIndex == action->a14.screenReq) + insertActionList(action->a14.actPassIndex); + else + insertActionList(action->a14.actFailIndex); + break; + case AUTOPILOT: // act15: Home in on a (stationary) object + // object p1 will home in on object p2 + obj1 = &_vm->_object->_objects[action->a15.obj1]; + obj2 = &_vm->_object->_objects[action->a15.obj2]; + obj1->pathType = AUTO; + dx = obj1->x + obj1->currImagePtr->x1 - obj2->x - obj2->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y1 - obj2->y - obj2->currImagePtr->y1; + + if (dx == 0) // Don't EVER divide by zero! + dx = 1; + if (dy == 0) + dy = 1; + + if (abs(dx) > abs(dy)) { + obj1->vx = action->a15.dx * -SIGN(dx); + obj1->vy = abs((action->a15.dy * dy) / dx) * -SIGN(dy); + } else { + obj1->vy = action->a15.dy * -SIGN(dy); + obj1->vx = abs((action->a15.dx * dx) / dy) * -SIGN(dx); + } + break; + case INIT_OBJ_SEQ: // act16: Set sequence number to use + // Note: Don't set a sequence at time 0 of a new screen, it causes + // problems clearing the boundary bits of the object! t>0 is safe + _vm->_object->_objects[action->a16.objNumb].currImagePtr = _vm->_object->_objects[action->a16.objNumb].seqList[action->a16.seqIndex].seqPtr; + break; + case SET_STATE_BITS: // act17: OR mask with curr obj state + _vm->_object->_objects[action->a17.objNumb].state |= action->a17.stateMask; + break; + case CLEAR_STATE_BITS: // act18: AND ~mask with curr obj state + _vm->_object->_objects[action->a18.objNumb].state &= ~action->a18.stateMask; + break; + case TEST_STATE_BITS: // act19: If all bits set, do apass else afail + if ((_vm->_object->_objects[action->a19.objNumb].state & action->a19.stateMask) == action->a19.stateMask) + insertActionList(action->a19.actPassIndex); + else + insertActionList(action->a19.actFailIndex); + break; + case DEL_EVENTS: // act20: Remove all events of this action type + // Note: actions are not deleted here, simply turned into NOPs! + wrkEvent = _headEvent; // The earliest event + while (wrkEvent) { // While events found in list + saveEvent = wrkEvent->nextEvent; + if (wrkEvent->action->a20.actType == action->a20.actTypeDel) + delQueue(wrkEvent); + wrkEvent = saveEvent; + } + break; + case GAMEOVER: // act21: Game over! + // NOTE: Must wait at least 1 tick before issuing this action if + // any objects are to be made invisible! + gameStatus.gameOverFl = true; + break; + case INIT_HH_COORD: // act22: Initialise an object to hero's actual coords + _vm->_object->_objects[action->a22.objNumb].x = _vm->_hero->x; + _vm->_object->_objects[action->a22.objNumb].y = _vm->_hero->y; + _vm->_object->_objects[action->a22.objNumb].screenIndex = *_vm->_screen_p;// Don't forget screen! + break; + case EXIT: // act23: Exit game back to DOS + _vm->endGame(); + break; + case BONUS: // act24: Get bonus score for action + processBonus(action->a24.pointIndex); + break; + case COND_BOX: // act25: Conditional on bounding box + obj1 = &_vm->_object->_objects[action->a25.objNumb]; + dx = obj1->x + obj1->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y2; + if ((dx >= action->a25.x1) && (dx <= action->a25.x2) && + (dy >= action->a25.y1) && (dy <= action->a25.y2)) + insertActionList(action->a25.actPassIndex); + else + insertActionList(action->a25.actFailIndex); + break; +// case SOUND: // act26: Play a sound (or tune) +// if (action->a26.soundIndex < _vm->_tunesNbr) +// _vm->_sound->playMusic(action->a26.soundIndex); +// else +// _vm->_sound->playSound(action->a26.soundIndex, BOTH_CHANNELS, MED_PRI); +// break; + case ADD_SCORE: // act27: Add object's value to score + _vm->adjustScore(_vm->_object->_objects[action->a27.objNumb].objValue); + break; + case SUB_SCORE: // act28: Subtract object's value from score + _vm->adjustScore(-_vm->_object->_objects[action->a28.objNumb].objValue); + break; + case COND_CARRY: // act29: Conditional on object being carried + if (_vm->_object->isCarried(action->a29.objNumb)) + insertActionList(action->a29.actPassIndex); + else + insertActionList(action->a29.actFailIndex); + break; + case INIT_MAZE: // act30: Enable and init maze structure + _maze.enabledFl = true; + _maze.size = action->a30.mazeSize; + _maze.x1 = action->a30.x1; + _maze.y1 = action->a30.y1; + _maze.x2 = action->a30.x2; + _maze.y2 = action->a30.y2; + _maze.x3 = action->a30.x3; + _maze.x4 = action->a30.x4; + _maze.firstScreenIndex = action->a30.firstScreenIndex; + break; + case EXIT_MAZE: // act31: Disable maze mode + _maze.enabledFl = false; + break; + case INIT_PRIORITY: + _vm->_object->_objects[action->a32.objNumb].priority = action->a32.priority; + break; + case INIT_SCREEN: + _vm->_object->_objects[action->a33.objNumb].screenIndex = action->a33.screenIndex; + break; + case AGSCHEDULE: // act34: Schedule a (global) action list + insertActionList(action->a34.actIndex); + break; + case REMAPPAL: // act35: Remap a palette color + _vm->_screen->remapPal(action->a35.oldColorIndex, action->a35.newColorIndex); + break; + case COND_NOUN: // act36: Conditional on noun mentioned + if (_vm->_parser->isWordPresent(_vm->_arrayNouns[action->a36.nounIndex])) + insertActionList(action->a36.actPassIndex); + else + insertActionList(action->a36.actFailIndex); + break; + case SCREEN_STATE: // act37: Set new screen state + _vm->_screenStates[action->a37.screenIndex] = action->a37.newState; + break; + case INIT_LIPS: // act38: Position lips on object + _vm->_object->_objects[action->a38.lipsObjNumb].x = _vm->_object->_objects[action->a38.objNumb].x + action->a38.dxLips; + _vm->_object->_objects[action->a38.lipsObjNumb].y = _vm->_object->_objects[action->a38.objNumb].y + action->a38.dyLips; + _vm->_object->_objects[action->a38.lipsObjNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + _vm->_object->_objects[action->a38.lipsObjNumb].cycling = CYCLE_FORWARD; + break; + case OLD_SONG: + //TODO For Hugo 1 and Hugo2 DOS: The songs were not stored in a DAT file, but directly as + //strings. the current play_music should be modified to use a strings instead of reading + //the file, in those cases. This replaces, for those DOS versions, act26. + warning("STUB: doAction(act49)"); + break; + default: + Utils::Error(EVNT_ERR, "%s", "doAction"); + break; + } + + if (action->a0.actType == NEW_SCREEN) { // New_screen() deletes entire list + return 0; // next_p = 0 since list now empty + } else { + wrkEvent = curEvent->nextEvent; + delQueue(curEvent); // Return event to free list + return wrkEvent; // Return next event ptr + } +} +} // End of namespace Hugo diff --git a/engines/hugo/schedule_v3d.cpp b/engines/hugo/schedule_v3d.cpp new file mode 100644 index 00000000000..cc449ba8c4c --- /dev/null +++ b/engines/hugo/schedule_v3d.cpp @@ -0,0 +1,326 @@ +/* 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$ + * + */ + +/* + * This code is based on original Hugo Trilogy source code + * + * Copyright (c) 1989-1995 David P. Gray + * + */ + +// This module contains all the scheduling and timing stuff + +#include "common/system.h" + +#include "hugo/game.h" +#include "hugo/hugo.h" +#include "hugo/schedule.h" +#include "hugo/global.h" +#include "hugo/file.h" +#include "hugo/display.h" +#include "hugo/parser.h" +#include "hugo/util.h" +#include "hugo/sound.h" +#include "hugo/object.h" + +namespace Hugo { + +Scheduler_v3d::Scheduler_v3d(HugoEngine *vm) : Scheduler_v2d(vm) { +} + +Scheduler_v3d::~Scheduler_v3d() { +} + +const char *Scheduler_v3d::getCypher() { + return "Copyright 1992, Gray Design Associates"; +} + +// This function performs the action in the event structure pointed to by p +// It dequeues the event and returns it to the free list. It returns a ptr +// to the next action in the list, except special case of NEW_SCREEN +event_t *Scheduler_v3d::doAction(event_t *curEvent) { + debugC(1, kDebugSchedule, "doAction - Event action type : %d", curEvent->action->a0.actType); + + status_t &gameStatus = _vm->getGameStatus(); + act *action = curEvent->action; + char *response; // User's response string + object_t *obj1; + object_t *obj2; + int dx, dy; + event_t *wrkEvent; // Save ev_p->next_p for return + event_t *saveEvent; // Used in DEL_EVENTS + + switch (action->a0.actType) { + case ANULL: // Big NOP from DEL_EVENTS + break; + case ASCHEDULE: // act0: Schedule an action list + insertActionList(action->a0.actIndex); + break; + case START_OBJ: // act1: Start an object cycling + _vm->_object->_objects[action->a1.objNumb].cycleNumb = action->a1.cycleNumb; + _vm->_object->_objects[action->a1.objNumb].cycling = action->a1.cycle; + break; + case INIT_OBJXY: // act2: Initialise an object + _vm->_object->_objects[action->a2.objNumb].x = action->a2.x; // Coordinates + _vm->_object->_objects[action->a2.objNumb].y = action->a2.y; + break; + case PROMPT: { // act3: Prompt user for key phrase + response = Utils::Box(BOX_PROMPT, "%s", _vm->_file->fetchString(action->a3.promptIndex)); + + warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0])); + + // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block +#if 0 + bool found; + char *tmpStr; // General purpose string ptr + + for (found = false, dx = 0; !found && (action->a3.responsePtr[dx] != -1); dx++) { + tmpStr = _vm->_file->fetchString(action->a3.responsePtr[dx]); + if (strstr(Utils::strlwr(response) , tmpStr)) + found = true; + } + + if (found) + insertActionList(action->a3.actPassIndex); + else + insertActionList(action->a3.actFailIndex); +#endif + + // HACK: As the answer is not read, currently it's always considered correct + insertActionList(action->a3.actPassIndex); + break; + } + case BKGD_COLOR: // act4: Set new background color + _vm->_screen->setBackgroundColor(action->a4.newBackgroundColor); + break; + case INIT_OBJVXY: // act5: Initialise an object velocity + _vm->_object->setVelocity(action->a5.objNumb, action->a5.vx, action->a5.vy); + break; + case INIT_CARRY: // act6: Initialise an object + _vm->_object->setCarry(action->a6.objNumb, action->a6.carriedFl); // carried status + break; + case INIT_HF_COORD: // act7: Initialise an object to hero's "feet" coords + _vm->_object->_objects[action->a7.objNumb].x = _vm->_hero->x - 1; + _vm->_object->_objects[action->a7.objNumb].y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; + _vm->_object->_objects[action->a7.objNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + break; + case NEW_SCREEN: // act8: Start new screen + newScreen(action->a8.screenIndex); + break; + case INIT_OBJSTATE: // act9: Initialise an object state + _vm->_object->_objects[action->a9.objNumb].state = action->a9.newState; + break; + case INIT_PATH: // act10: Initialise an object path and velocity + _vm->_object->setPath(action->a10.objNumb, (path_t) action->a10.newPathType, action->a10.vxPath, action->a10.vyPath); + break; + case COND_R: // act11: action lists conditional on object state + if (_vm->_object->_objects[action->a11.objNumb].state == action->a11.stateReq) + insertActionList(action->a11.actPassIndex); + else + insertActionList(action->a11.actFailIndex); + break; + case TEXT: // act12: Text box (CF WARN) + Utils::Box(BOX_ANY, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file + break; + case SWAP_IMAGES: // act13: Swap 2 object images + _vm->_object->swapImages(action->a13.obj1, action->a13.obj2); + break; + case COND_SCR: // act14: Conditional on current screen + if (_vm->_object->_objects[action->a14.objNumb].screenIndex == action->a14.screenReq) + insertActionList(action->a14.actPassIndex); + else + insertActionList(action->a14.actFailIndex); + break; + case AUTOPILOT: // act15: Home in on a (stationary) object + // object p1 will home in on object p2 + obj1 = &_vm->_object->_objects[action->a15.obj1]; + obj2 = &_vm->_object->_objects[action->a15.obj2]; + obj1->pathType = AUTO; + dx = obj1->x + obj1->currImagePtr->x1 - obj2->x - obj2->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y1 - obj2->y - obj2->currImagePtr->y1; + + if (dx == 0) // Don't EVER divide by zero! + dx = 1; + if (dy == 0) + dy = 1; + + if (abs(dx) > abs(dy)) { + obj1->vx = action->a15.dx * -SIGN(dx); + obj1->vy = abs((action->a15.dy * dy) / dx) * -SIGN(dy); + } else { + obj1->vy = action->a15.dy * -SIGN(dy); + obj1->vx = abs((action->a15.dx * dx) / dy) * -SIGN(dx); + } + break; + case INIT_OBJ_SEQ: // act16: Set sequence number to use + // Note: Don't set a sequence at time 0 of a new screen, it causes + // problems clearing the boundary bits of the object! t>0 is safe + _vm->_object->_objects[action->a16.objNumb].currImagePtr = _vm->_object->_objects[action->a16.objNumb].seqList[action->a16.seqIndex].seqPtr; + break; + case SET_STATE_BITS: // act17: OR mask with curr obj state + _vm->_object->_objects[action->a17.objNumb].state |= action->a17.stateMask; + break; + case CLEAR_STATE_BITS: // act18: AND ~mask with curr obj state + _vm->_object->_objects[action->a18.objNumb].state &= ~action->a18.stateMask; + break; + case TEST_STATE_BITS: // act19: If all bits set, do apass else afail + if ((_vm->_object->_objects[action->a19.objNumb].state & action->a19.stateMask) == action->a19.stateMask) + insertActionList(action->a19.actPassIndex); + else + insertActionList(action->a19.actFailIndex); + break; + case DEL_EVENTS: // act20: Remove all events of this action type + // Note: actions are not deleted here, simply turned into NOPs! + wrkEvent = _headEvent; // The earliest event + while (wrkEvent) { // While events found in list + saveEvent = wrkEvent->nextEvent; + if (wrkEvent->action->a20.actType == action->a20.actTypeDel) + delQueue(wrkEvent); + wrkEvent = saveEvent; + } + break; + case GAMEOVER: // act21: Game over! + // NOTE: Must wait at least 1 tick before issuing this action if + // any objects are to be made invisible! + gameStatus.gameOverFl = true; + break; + case INIT_HH_COORD: // act22: Initialise an object to hero's actual coords + _vm->_object->_objects[action->a22.objNumb].x = _vm->_hero->x; + _vm->_object->_objects[action->a22.objNumb].y = _vm->_hero->y; + _vm->_object->_objects[action->a22.objNumb].screenIndex = *_vm->_screen_p;// Don't forget screen! + break; + case EXIT: // act23: Exit game back to DOS + _vm->endGame(); + break; + case BONUS: // act24: Get bonus score for action + processBonus(action->a24.pointIndex); + break; + case COND_BOX: // act25: Conditional on bounding box + obj1 = &_vm->_object->_objects[action->a25.objNumb]; + dx = obj1->x + obj1->currImagePtr->x1; + dy = obj1->y + obj1->currImagePtr->y2; + if ((dx >= action->a25.x1) && (dx <= action->a25.x2) && + (dy >= action->a25.y1) && (dy <= action->a25.y2)) + insertActionList(action->a25.actPassIndex); + else + insertActionList(action->a25.actFailIndex); + break; +// case SOUND: // act26: Play a sound (or tune) +// if (action->a26.soundIndex < _vm->_tunesNbr) +// _vm->_sound->playMusic(action->a26.soundIndex); +// else +// _vm->_sound->playSound(action->a26.soundIndex, BOTH_CHANNELS, MED_PRI); +// break; + case ADD_SCORE: // act27: Add object's value to score + _vm->adjustScore(_vm->_object->_objects[action->a27.objNumb].objValue); + break; + case SUB_SCORE: // act28: Subtract object's value from score + _vm->adjustScore(-_vm->_object->_objects[action->a28.objNumb].objValue); + break; + case COND_CARRY: // act29: Conditional on object being carried + if (_vm->_object->isCarried(action->a29.objNumb)) + insertActionList(action->a29.actPassIndex); + else + insertActionList(action->a29.actFailIndex); + break; + case INIT_MAZE: // act30: Enable and init maze structure + _maze.enabledFl = true; + _maze.size = action->a30.mazeSize; + _maze.x1 = action->a30.x1; + _maze.y1 = action->a30.y1; + _maze.x2 = action->a30.x2; + _maze.y2 = action->a30.y2; + _maze.x3 = action->a30.x3; + _maze.x4 = action->a30.x4; + _maze.firstScreenIndex = action->a30.firstScreenIndex; + break; + case EXIT_MAZE: // act31: Disable maze mode + _maze.enabledFl = false; + break; + case INIT_PRIORITY: + _vm->_object->_objects[action->a32.objNumb].priority = action->a32.priority; + break; + case INIT_SCREEN: + _vm->_object->_objects[action->a33.objNumb].screenIndex = action->a33.screenIndex; + break; + case AGSCHEDULE: // act34: Schedule a (global) action list + insertActionList(action->a34.actIndex); + break; + case REMAPPAL: // act35: Remap a palette color + _vm->_screen->remapPal(action->a35.oldColorIndex, action->a35.newColorIndex); + break; + case COND_NOUN: // act36: Conditional on noun mentioned + if (_vm->_parser->isWordPresent(_vm->_arrayNouns[action->a36.nounIndex])) + insertActionList(action->a36.actPassIndex); + else + insertActionList(action->a36.actFailIndex); + break; + case SCREEN_STATE: // act37: Set new screen state + _vm->_screenStates[action->a37.screenIndex] = action->a37.newState; + break; + case INIT_LIPS: // act38: Position lips on object + _vm->_object->_objects[action->a38.lipsObjNumb].x = _vm->_object->_objects[action->a38.objNumb].x + action->a38.dxLips; + _vm->_object->_objects[action->a38.lipsObjNumb].y = _vm->_object->_objects[action->a38.objNumb].y + action->a38.dyLips; + _vm->_object->_objects[action->a38.lipsObjNumb].screenIndex = *_vm->_screen_p; // Don't forget screen! + _vm->_object->_objects[action->a38.lipsObjNumb].cycling = CYCLE_FORWARD; + break; + case INIT_STORY_MODE: // act39: Init story_mode flag + // This is similar to the QUIET path mode, except that it is + // independant of it and it additionally disables the ">" prompt + gameStatus.storyModeFl = action->a39.storyModeFl; + + // End the game after story if this is special vendor demo mode + if (gameStatus.demoFl && action->a39.storyModeFl == false) + _vm->endGame(); + break; + case WARN: // act40: Text box (CF TEXT) + Utils::Box(BOX_OK, "%s", _vm->_file->fetchString(action->a40.stringIndex)); + break; + case COND_BONUS: // act41: Perform action if got bonus + if (_vm->_points[action->a41.BonusIndex].scoredFl) + insertActionList(action->a41.actPassIndex); + else + insertActionList(action->a41.actFailIndex); + break; + case OLD_SONG: + //TODO For Hugo 1 and Hugo2 DOS: The songs were not stored in a DAT file, but directly as + //strings. the current play_music should be modified to use a strings instead of reading + //the file, in those cases. This replaces, for those DOS versions, act26. + warning("STUB: doAction(act49)"); + break; + default: + Utils::Error(EVNT_ERR, "%s", "doAction"); + break; + } + + if (action->a0.actType == NEW_SCREEN) { // New_screen() deletes entire list + return 0; // next_p = 0 since list now empty + } else { + wrkEvent = curEvent->nextEvent; + delQueue(curEvent); // Return event to free list + return wrkEvent; // Return next event ptr + } +} +} // End of namespace Hugo diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp index 7b6ae2ec242..b8a5a3297ec 100644 --- a/engines/hugo/sound.cpp +++ b/engines/hugo/sound.cpp @@ -184,11 +184,11 @@ int MidiPlayer::open() { void MidiPlayer::close() { stop(); _mutex.lock(); - _driver->setTimerCallback(NULL, NULL); + _driver->setTimerCallback(0, 0); _driver->close(); delete _driver; _driver = 0; - _parser->setMidiDriver(NULL); + _parser->setMidiDriver(0); delete _parser; _mutex.unlock(); } @@ -239,7 +239,7 @@ void MidiPlayer::timerCallback(void *p) { player->updateTimer(); } -SoundHandler::SoundHandler(HugoEngine &vm) : _vm(vm) { +SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) { MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); MidiDriver *driver = MidiDriver::createMidi(dev); @@ -248,13 +248,13 @@ SoundHandler::SoundHandler(HugoEngine &vm) : _vm(vm) { void SoundHandler::setMusicVolume() { /* Set the FM music volume from config.mvolume (0..100%) */ - + _midiPlayer->setVolume(_config.musicVolume * 255 / 100); } void SoundHandler::stopSound() { /* Stop any sound that might be playing */ - _vm._mixer->stopAll(); + _vm->_mixer->stopAll(); } void SoundHandler::stopMusic() { @@ -265,7 +265,7 @@ void SoundHandler::stopMusic() { void SoundHandler::toggleMusic() { // Turn music on and off _config.musicFl = !_config.musicFl; - + _midiPlayer->pause(_config.musicFl); } @@ -285,8 +285,8 @@ void SoundHandler::playMusic(int16 tune) { uint16 size; // Size of sequence data if (_config.musicFl) { - _vm.getGameStatus().song = tune; - seqPtr = _vm.file().getSound(tune, &size); + _vm->getGameStatus().song = tune; + seqPtr = _vm->_file->getSound(tune, &size); playMIDI(seqPtr, size); } } @@ -302,7 +302,7 @@ void SoundHandler::playSound(int16 sound, stereo_t channel, byte priority) { static byte curPriority = 0; // Priority of currently playing sound // /* Sound disabled */ - if (!_config.soundFl || !_vm._mixer->isReady()) + if (!_config.soundFl || !_vm->_mixer->isReady()) return; // // // See if last wave still playing - if so, check priority @@ -314,11 +314,11 @@ void SoundHandler::playSound(int16 sound, stereo_t channel, byte priority) { curPriority = priority; // /* Get sound data */ - if ((sound_p = _vm.file().getSound(sound, &size)) == NULL) + if ((sound_p = _vm->_file->getSound(sound, &size)) == 0) return; Audio::AudioStream *stream = Audio::makeRawStream(sound_p, size, 11025, Audio::FLAG_UNSIGNED); - _vm._mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, stream); + _vm->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, stream); } diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h index 53a5912a929..ff38a7f70a7 100644 --- a/engines/hugo/sound.h +++ b/engines/hugo/sound.h @@ -38,10 +38,10 @@ namespace Hugo { class MidiPlayer; - + class SoundHandler { public: - SoundHandler(HugoEngine &vm); + SoundHandler(HugoEngine *vm); void toggleMusic(); void toggleSound(); @@ -51,7 +51,7 @@ public: void initSound(); private: - HugoEngine &_vm; + HugoEngine *_vm; Audio::SoundHandle _soundHandle; MidiPlayer *_midiPlayer; diff --git a/engines/hugo/util.cpp b/engines/hugo/util.cpp index 8c63bedc042..2def4a4dba5 100644 --- a/engines/hugo/util.cpp +++ b/engines/hugo/util.cpp @@ -41,95 +41,108 @@ namespace Hugo { int Utils::firstBit(byte data) { - /* Returns index (0 to 7) of first 1 in supplied byte, or 8 if not found */ - int i; - +// Returns index (0 to 7) of first 1 in supplied byte, or 8 if not found if (!data) - return(8); + return 8; + int i; for (i = 0; i < 8; i++) { if ((data << i) & 0x80) break; } - return(i); + return i; } int Utils::lastBit(byte data) { - /* Returns index (0 to 7) of last 1 in supplied byte, or 8 if not found */ - int i; +// Returns index (0 to 7) of last 1 in supplied byte, or 8 if not found if (!data) - return(8); + return 8; + int i; for (i = 7; i >= 0; i--) { if ((data << i) & 0x80) break; } - return(i); + return i; } void Utils::reverseByte(byte *data) { - /* Reverse the bit order in supplied byte */ +// Reverse the bit order in supplied byte byte maskIn = 0x80; byte maskOut = 0x01; byte result = 0; - for (byte i = 0; i < 8; i++, maskIn >>= 1, maskOut <<= 1) + for (byte i = 0; i < 8; i++, maskIn >>= 1, maskOut <<= 1) { if (*data & maskIn) result |= maskOut; + } *data = result; } char *Utils::Box(box_t dismiss, const char *s, ...) { static char buffer[MAX_STRLEN + 1]; // Format text into this - va_list marker; - if (!s) return(NULL); // NULL strings catered for + if (!s) + return 0; // NULL strings catered for if (s[0] == '\0') - return(NULL); + return 0; if (strlen(s) > MAX_STRLEN - 100) { // Test length - Warn(false, "String too big:\n%s", s); - return(NULL); + Warn("String too big:\n%s", s); + return 0; } + va_list marker; va_start(marker, s); vsprintf(buffer, s, marker); // Format string into buffer va_end(marker); - //Warn(false, "BOX: %s", buffer); - int boxTime = strlen(buffer) * 30; - GUI::TimedMessageDialog dialog(buffer, MAX(1500, boxTime)); - dialog.runModal(); + if (buffer[0] == '\0') + return 0; + switch(dismiss) { + case BOX_ANY: + case BOX_OK: { + GUI::MessageDialog dialog(buffer, "OK"); + dialog.runModal(); + break; + } + case BOX_YESNO: { + GUI::MessageDialog dialog(buffer, "YES", "NO"); + if (dialog.runModal() == GUI::kMessageOK) + return buffer; + return 0; + break; + } + case BOX_PROMPT: + warning("Box: unhandled BOX_PROMPT"); + int boxTime = strlen(buffer) * 30; + GUI::TimedMessageDialog dialog(buffer, MAX(1500, boxTime)); + dialog.runModal(); // TODO: Some boxes (i.e. the combination code for the shed), needs to return an input. + } + return buffer; } -void Utils::Warn(bool technote, const char *format, ...) { - /* Warning handler. Print supplied message and continue */ - /* Arguments are same as printf */ - /* technote TRUE if we are to refer user to technote file */ +void Utils::Warn(const char *format, ...) { +// Warning handler. Print supplied message and continue +// Arguments are same as printf char buffer[WARNLEN]; va_list marker; - va_start(marker, format); vsnprintf(buffer, WARNLEN, format, marker); va_end(marker); -//// if (technote) -//// strcat (buffer, sTech); - //MessageBeep(MB_ICONEXCLAMATION); - //MessageBox(hwnd, buffer, "HugoWin Warning", MB_OK | MB_ICONEXCLAMATION); warning("Hugo warning: %s", buffer); } void Utils::Error(int error_type, const char *format, ...) { - /* Fatal error handler. Reset environment, print error and exit */ - /* Arguments are same as printf */ - va_list marker; +// Fatal error handler. Reset environment, print error and exit +// Arguments are same as printf char buffer[ERRLEN + 1]; bool fatal = true; // Fatal error, else continue @@ -158,6 +171,7 @@ void Utils::Error(int error_type, const char *format, ...) { if (fatal) HugoEngine::get().shutdown(); // Restore any devices before exit + va_list marker; va_start(marker, format); vsnprintf(&buffer[strlen(buffer)], ERRLEN - strlen(buffer), format, marker); va_end(marker); @@ -175,4 +189,17 @@ void Utils::gameOverMsg(void) { warning("STUB: Gameover_msg(): %s", HugoEngine::get()._textUtil[kGameOver]); } +char *Utils::strlwr(char *buffer) { + char *result = buffer; + + while (*buffer != '\0') { + if (isupper(*buffer)) + *buffer = tolower(*buffer); + buffer++; + } + + return result; +} + + } // End of namespace Hugo diff --git a/engines/hugo/util.h b/engines/hugo/util.h index f944baa3245..69428fb3bb6 100644 --- a/engines/hugo/util.h +++ b/engines/hugo/util.h @@ -51,11 +51,14 @@ enum seqTextUtil { namespace Utils { int firstBit(byte data); int lastBit(byte data); -void reverseByte(byte *data); -void Warn(bool technote, const char *format, ...) GCC_PRINTF(2, 3); -void Error(int code, const char *format, ...) GCC_PRINTF(2, 3); + void gameOverMsg(); +void reverseByte(byte *data); +void Error(int code, const char *format, ...) GCC_PRINTF(2, 3); +void Warn(const char *format, ...) GCC_PRINTF(1, 2); + char *Box(box_t, const char *, ...) GCC_PRINTF(2, 3); +char *strlwr(char *buffer); } } // End of namespace Hugo diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp index 6c4fafa674c..b06dffd36fd 100644 --- a/engines/kyra/animator_v2.cpp +++ b/engines/kyra/animator_v2.cpp @@ -141,7 +141,7 @@ void KyraEngine_v2::flagAnimObjsSpecialRefresh() { } void KyraEngine_v2::addItemToAnimList(int item) { - assert(item < _itemListSize); + assert(item >= 0 && item < _itemListSize); restorePage3(); diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h index 2e1d5afc170..5c97df88956 100644 --- a/engines/kyra/detection_tables.h +++ b/engines/kyra/detection_tables.h @@ -1075,6 +1075,22 @@ const KYRAGameDescription adGameDescs[] = { LOL_FLOPPY_CMP_FLAGS }, + { + { + "lol", + 0, + { + { "WESTWOOD.1", 0, "320b2828be595c491903f467094f05eb", -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", @@ -1125,6 +1141,23 @@ const KYRAGameDescription adGameDescs[] = { LOL_FLOPPY_FLAGS }, + { + { + "lol", + "Extracted", + { + { "GENERAL.PAK", 0, "d119e3b57f8e5edcbb90980ca6f4215a", -1 }, + { "CHAPTER7.PAK", 0, "71a3d3cb1554294646a389e5c345cf28", -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", diff --git a/engines/kyra/gui_hof.cpp b/engines/kyra/gui_hof.cpp index 621b3199c51..56971e563c4 100644 --- a/engines/kyra/gui_hof.cpp +++ b/engines/kyra/gui_hof.cpp @@ -122,9 +122,9 @@ int KyraEngine_HoF::buttonInventory(Button *button) { int inventorySlot = button->index - 6; - uint16 item = _mainCharacter.inventory[inventorySlot]; - if (_itemInHand == -1) { - if (item == 0xFFFF) + Item item = _mainCharacter.inventory[inventorySlot]; + if (_itemInHand == kItemNone) { + if (item == kItemNone) return 0; _screen->hideMouse(); clearInventorySlot(inventorySlot, 0); @@ -134,9 +134,9 @@ int KyraEngine_HoF::buttonInventory(Button *button) { updateCommandLineEx(item+54, string, 0xD6); _itemInHand = (int16)item; _screen->showMouse(); - _mainCharacter.inventory[inventorySlot] = 0xFFFF; + _mainCharacter.inventory[inventorySlot] = kItemNone; } else { - if (_mainCharacter.inventory[inventorySlot] != 0xFFFF) { + if (_mainCharacter.inventory[inventorySlot] != kItemNone) { if (checkInventoryItemExchange(_itemInHand, inventorySlot)) return 0; @@ -160,7 +160,7 @@ int KyraEngine_HoF::buttonInventory(Button *button) { updateCommandLineEx(_itemInHand+54, string, 0xD6); _screen->showMouse(); _mainCharacter.inventory[inventorySlot] = _itemInHand; - _itemInHand = -1; + _itemInHand = kItemNone; } } @@ -168,15 +168,15 @@ int KyraEngine_HoF::buttonInventory(Button *button) { } int KyraEngine_HoF::scrollInventory(Button *button) { - uint16 *src = _mainCharacter.inventory; - uint16 *dst = &_mainCharacter.inventory[10]; - uint16 temp[5]; + Item *src = _mainCharacter.inventory; + Item *dst = &_mainCharacter.inventory[10]; + Item temp[5]; - memcpy(temp, src, sizeof(uint16)*5); - memcpy(src, src+5, sizeof(uint16)*5); - memcpy(src+5, dst, sizeof(uint16)*5); - memcpy(dst, dst+5, sizeof(uint16)*5); - memcpy(dst+5, temp, sizeof(uint16)*5); + memcpy(temp, src, sizeof(Item)*5); + memcpy(src, src+5, sizeof(Item)*5); + memcpy(src+5, dst, sizeof(Item)*5); + memcpy(dst, dst+5, sizeof(Item)*5); + memcpy(dst+5, temp, sizeof(Item)*5); _screen->hideMouse(); _screen->copyRegion(0x46, 0x90, 0x46, 0x90, 0x71, 0x2E, 0, 2); _screen->showMouse(); @@ -185,7 +185,7 @@ int KyraEngine_HoF::scrollInventory(Button *button) { return 0; } -int KyraEngine_HoF::getInventoryItemSlot(uint16 item) { +int KyraEngine_HoF::getInventoryItemSlot(Item item) { for (int i = 0; i < 20; ++i) { if (_mainCharacter.inventory[i] == item) return i; @@ -195,14 +195,14 @@ int KyraEngine_HoF::getInventoryItemSlot(uint16 item) { int KyraEngine_HoF::findFreeVisibleInventorySlot() { for (int i = 0; i < 10; ++i) { - if (_mainCharacter.inventory[i] == 0xFFFF) + if (_mainCharacter.inventory[i] == kItemNone) return i; } return -1; } void KyraEngine_HoF::removeSlotFromInventory(int slot) { - _mainCharacter.inventory[slot] = 0xFFFF; + _mainCharacter.inventory[slot] = kItemNone; if (slot < 10) { _screen->hideMouse(); clearInventorySlot(slot, 0); @@ -210,21 +210,21 @@ void KyraEngine_HoF::removeSlotFromInventory(int slot) { } } -bool KyraEngine_HoF::checkInventoryItemExchange(uint16 handItem, int slot) { +bool KyraEngine_HoF::checkInventoryItemExchange(Item handItem, int slot) { bool removeItem = false; - uint16 newItem = 0xFFFF; + Item newItem = kItemNone; - uint16 invItem = _mainCharacter.inventory[slot]; + Item invItem = _mainCharacter.inventory[slot]; for (const uint16 *table = _itemMagicTable; *table != 0xFFFF; table += 4) { - if (table[0] != handItem || table[1] != invItem) + if (table[0] != handItem || table[1] != (uint16)invItem) continue; if (table[3] == 0xFFFF) continue; removeItem = (table[3] == 1); - newItem = table[2]; + newItem = (Item)table[2]; snd_playSoundEffect(0x68); _mainCharacter.inventory[slot] = newItem; @@ -246,7 +246,7 @@ bool KyraEngine_HoF::checkInventoryItemExchange(uint16 handItem, int slot) { return false; } -void KyraEngine_HoF::drawInventoryShape(int page, uint16 item, int slot) { +void KyraEngine_HoF::drawInventoryShape(int page, Item item, int slot) { _screen->drawShape(page, getShapePtr(item+64), _inventoryX[slot], _inventoryY[slot], 0, 0); _screen->updateScreen(); } @@ -260,11 +260,11 @@ void KyraEngine_HoF::redrawInventory(int page) { int pageBackUp = _screen->_curPage; _screen->_curPage = page; - const uint16 *inventory = _mainCharacter.inventory; + const Item *inventory = _mainCharacter.inventory; _screen->hideMouse(); for (int i = 0; i < 10; ++i) { clearInventorySlot(i, page); - if (inventory[i] != 0xFFFF) { + if (inventory[i] != kItemNone) { _screen->drawShape(page, getShapePtr(inventory[i]+64), _inventoryX[i], _inventoryY[i], 0, 0); drawInventoryShape(page, inventory[i], i); } @@ -734,7 +734,7 @@ int GUI_HoF::optionsButton(Button *button) { if (_loadedSave) { if (_restartGame) - _vm->_itemInHand = -1; + _vm->_itemInHand = kItemNone; } else { restorePage1(_vm->_screenBuffer); restorePalette(); @@ -820,7 +820,7 @@ void GUI_HoF::resetState(int item) { _vm->setNextIdleAnimTimer(); _isDeathMenu = false; if (!_loadedSave) { - _vm->_itemInHand = -1; + _vm->_itemInHand = kItemNone; _vm->setHandItem(item); } else { _vm->setHandItem(_vm->_itemInHand); @@ -998,7 +998,7 @@ int GUI_HoF::gameOptionsTalkie(Button *caller) { Graphics::Surface thumb; createScreenThumbnail(thumb); - _vm->saveGameState(999, "Autosave", &thumb); + _vm->saveGameStateIntern(999, "Autosave", &thumb); thumb.free(); _vm->_lastAutosave = _vm->_system->getMillis(); diff --git a/engines/kyra/gui_lok.cpp b/engines/kyra/gui_lok.cpp index 9a1d7503919..b7952eb81e1 100644 --- a/engines/kyra/gui_lok.cpp +++ b/engines/kyra/gui_lok.cpp @@ -32,6 +32,7 @@ #include "kyra/gui_lok.h" #include "kyra/timer.h" #include "kyra/util.h" +#include "kyra/item.h" #include "common/config-manager.h" #include "common/savefile.h" @@ -49,9 +50,9 @@ void KyraEngine_LoK::initMainButtonList() { int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { int itemOffset = caller->index - 2; - uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset]; - if (_itemInHand == -1) { - if (inventoryItem == 0xFF) { + Item inventoryItem = (int8)_currentCharacter->inventoryItems[itemOffset]; + if (_itemInHand == kItemNone) { + if (inventoryItem == kItemNone) { snd_playSoundEffect(0x36); return 0; } else { @@ -62,10 +63,10 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { updateSentenceCommand(_itemList[getItemListIndex(inventoryItem)], _takenList[0], 179); _itemInHand = inventoryItem; _screen->showMouse(); - _currentCharacter->inventoryItems[itemOffset] = 0xFF; + _currentCharacter->inventoryItems[itemOffset] = kItemNone; } } else { - if (inventoryItem != 0xFF) { + if (inventoryItem != kItemNone) { snd_playSoundEffect(0x35); _screen->hideMouse(); _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12); @@ -87,7 +88,7 @@ int KyraEngine_LoK::buttonInventoryCallback(Button *caller) { updateSentenceCommand(_itemList[getItemListIndex(_itemInHand)], _placedList[0], 179); _screen->showMouse(); _currentCharacter->inventoryItems[itemOffset] = _itemInHand; - _itemInHand = -1; + _itemInHand = kItemNone; } } _screen->updateScreen(); @@ -104,7 +105,7 @@ int KyraEngine_LoK::buttonAmuletCallback(Button *caller) { } if (!queryGameFlag(0x2D)) return 1; - if (_itemInHand != -1) { + if (_itemInHand != kItemNone) { assert(_putDownFirst); characterSays(2000, _putDownFirst[0], 0, -2); return 1; @@ -777,7 +778,7 @@ int GUI_LoK::saveGame(Button *button) { Graphics::Surface thumb; createScreenThumbnail(thumb); - _vm->saveGameState(_vm->_gameToLoad, _savegameName, &thumb); + _vm->saveGameStateIntern(_vm->_gameToLoad, _savegameName, &thumb); thumb.free(); } } diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index 2c860738920..07fbf1664d4 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -2906,7 +2906,7 @@ int GUI_LoL::clickedSavenameMenu(Button *button) { int slot = _menuResult == -2 ? getNextSavegameSlot() : _menuResult - 1; Graphics::Surface thumb; createScreenThumbnail(thumb); - _vm->saveGameState(slot, _saveDescription, &thumb); + _vm->saveGameStateIntern(slot, _saveDescription, &thumb); thumb.free(); _displayMenu = false; diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index bcc74f5a073..a04ec493249 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -130,7 +130,7 @@ void KyraEngine_MR::showMessageFromCCode(int string, uint8 c0, int) { showMessage((const char *)getTableEntry(_cCodeFile, string), c0, 0xF0); } -void KyraEngine_MR::updateItemCommand(int item, int str, uint8 c0) { +void KyraEngine_MR::updateItemCommand(Item item, int str, uint8 c0) { char buffer[100]; char *src = (char *)getTableEntry(_itemFile, item); @@ -449,7 +449,7 @@ void KyraEngine_MR::redrawInventory(int page) { for (int i = 0; i < 10; ++i) { clearInventorySlot(i, page); - if (_mainCharacter.inventory[i] != 0xFFFF) { + if (_mainCharacter.inventory[i] != kItemNone) { _screen->drawShape(page, getShapePtr(_mainCharacter.inventory[i]+248), _inventoryX[i], _inventoryY[i] + yOffset, 0, 0); drawInventorySlot(page, _mainCharacter.inventory[i], i); } @@ -472,7 +472,7 @@ void KyraEngine_MR::clearInventorySlot(int slot, int page) { _screen->drawShape(page, getShapePtr(slot+422), _inventoryX[slot], _inventoryY[slot] + yOffset, 0, 0); } -void KyraEngine_MR::drawInventorySlot(int page, int item, int slot) { +void KyraEngine_MR::drawInventorySlot(int page, Item item, int slot) { int yOffset = 0; if (page == 30) { page = 2; @@ -488,9 +488,9 @@ int KyraEngine_MR::buttonInventory(Button *button) { return 0; const int slot = button->index - 5; - const int16 slotItem = (int16)_mainCharacter.inventory[slot]; - if (_itemInHand == -1) { - if (slotItem == -1) + const Item slotItem = _mainCharacter.inventory[slot]; + if (_itemInHand == kItemNone) { + if (slotItem == kItemNone) return 0; _screen->hideMouse(); @@ -499,7 +499,7 @@ int KyraEngine_MR::buttonInventory(Button *button) { setMouseCursor(slotItem); updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF); _itemInHand = slotItem; - _mainCharacter.inventory[slot] = 0xFFFF; + _mainCharacter.inventory[slot] = kItemNone; _screen->showMouse(); } else if (_itemInHand == 27) { if (_chatText) @@ -528,7 +528,7 @@ int KyraEngine_MR::buttonInventory(Button *button) { updateItemCommand(_itemInHand, (_lang == 1) ? getItemCommandStringInv(_itemInHand) : 2, 0xFF); _screen->showMouse(); _mainCharacter.inventory[slot] = _itemInHand; - _itemInHand = -1; + _itemInHand = kItemNone; } } @@ -635,7 +635,7 @@ int KyraEngine_MR::buttonJesterStaff(Button *button) { updateItemCommand(27, 2, 0xFF); setGameFlag(0x97); _screen->showMouse(); - } else if (_itemInHand == -1) { + } else if (_itemInHand == kItemNone) { if (queryGameFlag(0x97)) { _screen->hideMouse(); snd_playSoundEffect(0x0B, 0xC8); @@ -1141,7 +1141,7 @@ void GUI_MR::resetState(int item) { _vm->setNextIdleAnimTimer(); _isDeathMenu = false; if (!_loadedSave) { - _vm->_itemInHand = -1; + _vm->_itemInHand = kItemNone; _vm->setHandItem(item); } else { _vm->setHandItem(_vm->_itemInHand); @@ -1239,7 +1239,7 @@ int GUI_MR::optionsButton(Button *button) { if (_loadedSave) { if (_restartGame) - _vm->_itemInHand = -1; + _vm->_itemInHand = kItemNone; } else { restorePage1(_vm->_screenBuffer); } @@ -1380,7 +1380,7 @@ int GUI_MR::gameOptions(Button *caller) { Graphics::Surface thumb; createScreenThumbnail(thumb); - _vm->saveGameState(999, "Autosave", &thumb); + _vm->saveGameStateIntern(999, "Autosave", &thumb); thumb.free(); _vm->_lastAutosave = _vm->_system->getMillis(); diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp index fe4b54d09b2..2247a0ca2e3 100644 --- a/engines/kyra/gui_v2.cpp +++ b/engines/kyra/gui_v2.cpp @@ -625,7 +625,7 @@ int GUI_v2::saveMenu(Button *caller) { Graphics::Surface thumb; createScreenThumbnail(thumb); Util::convertDOSToISO(_saveDescription); - _vm->saveGameState(_saveSlot, _saveDescription, &thumb); + _vm->saveGameStateIntern(_saveSlot, _saveDescription, &thumb); thumb.free(); _displayMenu = false; diff --git a/engines/hugo/engine.h b/engines/kyra/item.h similarity index 76% rename from engines/hugo/engine.h rename to engines/kyra/item.h index 0d14d244b53..2088f4bd8bc 100644 --- a/engines/hugo/engine.h +++ b/engines/kyra/item.h @@ -23,22 +23,23 @@ * */ -/* - * This code is based on original Hugo 1-3 Trilogy source code - * - * Copyright (c) 1989-1995 David P. Gray - * - */ +#ifndef KYRA_ITEM_H +#define KYRA_ITEM_H -#ifndef HUGO_ENGINE_H -#define HUGO_ENGINE_H -namespace Hugo { +#include "common/scummsys.h" -enum seqTextEngine { - // Strings used by the engine - kEsAdvertise = 0 +namespace Kyra { + +typedef int16 Item; + +enum { + /** + * Constant for invalid item. + */ + kItemNone = -1 }; -} // End of namespace Hugo +} // End of namespace Kyra + +#endif -#endif // HUGO_ENGINE_H diff --git a/engines/kyra/items_hof.cpp b/engines/kyra/items_hof.cpp index 876db587161..6a78a77c23f 100644 --- a/engines/kyra/items_hof.cpp +++ b/engines/kyra/items_hof.cpp @@ -31,9 +31,9 @@ int KyraEngine_HoF::checkItemCollision(int x, int y) { int itemPos = -1, yPos = -1; for (int i = 0; i < 30; ++i) { - const Item &curItem = _itemList[i]; + const ItemDefinition &curItem = _itemList[i]; - if (curItem.id == 0xFFFF || curItem.sceneId != _mainCharacter.sceneId) + if (curItem.id == kItemNone || curItem.sceneId != _mainCharacter.sceneId) continue; int itemX1 = curItem.x - 8 - 3; @@ -79,7 +79,7 @@ void KyraEngine_HoF::updateWaterFlasks() { } } -bool KyraEngine_HoF::dropItem(int unk1, uint16 item, int x, int y, int unk2) { +bool KyraEngine_HoF::dropItem(int unk1, Item item, int x, int y, int unk2) { if (_mouseState <= -1) return false; @@ -93,7 +93,7 @@ bool KyraEngine_HoF::dropItem(int unk1, uint16 item, int x, int y, int unk2) { return success; } -bool KyraEngine_HoF::processItemDrop(uint16 sceneId, uint16 item, int x, int y, int unk1, int unk2) { +bool KyraEngine_HoF::processItemDrop(uint16 sceneId, Item item, int x, int y, int unk1, int unk2) { int itemPos = checkItemCollision(x, y); if (unk1) @@ -108,7 +108,7 @@ bool KyraEngine_HoF::processItemDrop(uint16 sceneId, uint16 item, int x, int y, if (unk1 != 3) { for (int i = 0; i < 30; ++i) { - if (_itemList[i].id == 0xFFFF) { + if (_itemList[i].id == kItemNone) { freeItemSlot = i; break; } @@ -200,7 +200,7 @@ bool KyraEngine_HoF::processItemDrop(uint16 sceneId, uint16 item, int x, int y, return true; } -void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, uint16 item) { +void KyraEngine_HoF::itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, Item item) { uint8 *itemShape = getShapePtr(item + 64); if (startX == dstX && startY == dstY) { @@ -335,7 +335,7 @@ bool KyraEngine_HoF::pickUpItem(int x, int y) { _screen->hideMouse(); deleteItemAnimEntry(itemPos); int itemId = _itemList[itemPos].id; - _itemList[itemPos].id = 0xFFFF; + _itemList[itemPos].id = kItemNone; snd_playSoundEffect(0x0b); setMouseCursor(itemId); int str2 = 7; @@ -368,8 +368,8 @@ bool KyraEngine_HoF::isDropable(int x, int y) { return true; } -int KyraEngine_HoF::getItemCommandStringDrop(uint16 item) { - assert(item < _itemStringMapSize); +int KyraEngine_HoF::getItemCommandStringDrop(Item item) { + assert(item >= 0 && item < _itemStringMapSize); int stringId = _itemStringMap[item]; static const int dropStringIds[] = { @@ -380,8 +380,8 @@ int KyraEngine_HoF::getItemCommandStringDrop(uint16 item) { return dropStringIds[stringId]; } -int KyraEngine_HoF::getItemCommandStringPickUp(uint16 item) { - assert(item < _itemStringMapSize); +int KyraEngine_HoF::getItemCommandStringPickUp(Item item) { + assert(item >= 0 && item < _itemStringMapSize); int stringId = _itemStringMap[item]; static const int pickUpStringIds[] = { @@ -392,8 +392,8 @@ int KyraEngine_HoF::getItemCommandStringPickUp(uint16 item) { return pickUpStringIds[stringId]; } -int KyraEngine_HoF::getItemCommandStringInv(uint16 item) { - assert(item < _itemStringMapSize); +int KyraEngine_HoF::getItemCommandStringInv(Item item) { + assert(item >= 0 && item < _itemStringMapSize); int stringId = _itemStringMap[item]; static const int pickUpStringIds[] = { @@ -404,8 +404,8 @@ int KyraEngine_HoF::getItemCommandStringInv(uint16 item) { return pickUpStringIds[stringId]; } -bool KyraEngine_HoF::itemIsFlask(int item) { - for (int i = 0; _flaskTable[i] != -1; ++i) { +bool KyraEngine_HoF::itemIsFlask(Item item) { + for (int i = 0; _flaskTable[i] != kItemNone; ++i) { if (_flaskTable[i] == item) return true; } @@ -413,12 +413,12 @@ bool KyraEngine_HoF::itemIsFlask(int item) { return false; } -void KyraEngine_HoF::setMouseCursor(uint16 item) { +void KyraEngine_HoF::setMouseCursor(Item item) { int shape = 0; int hotX = 1; int hotY = 1; - if (item != 0xFFFF) { + if (item != kItemNone) { hotX = 8; hotY = 15; shape = item+64; diff --git a/engines/kyra/items_lok.cpp b/engines/kyra/items_lok.cpp index df46dfa4cd3..322314e3ad5 100644 --- a/engines/kyra/items_lok.cpp +++ b/engines/kyra/items_lok.cpp @@ -74,29 +74,31 @@ void KyraEngine_LoK::clearNoDropRects() { byte KyraEngine_LoK::findFreeItemInScene(int scene) { assert(scene < _roomTableSize); Room *room = &_roomTable[scene]; + for (int i = 0; i < 12; ++i) { - if (room->itemsTable[i] == 0xFF) + if (room->itemsTable[i] == kItemNone) return i; } + return 0xFF; } byte KyraEngine_LoK::findItemAtPos(int x, int y) { assert(_currentCharacter->sceneId < _roomTableSize); - const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable; + const int8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable; const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos; const uint8 *yposOffset = _roomTable[_currentCharacter->sceneId].itemsYPos; int highestYPos = -1; - byte returnValue = 0xFF; + Item returnValue = kItemNone; for (int i = 0; i < 12; ++i) { - if (*itemsTable != 0xFF) { + if (*itemsTable != kItemNone) { int xpos = *xposOffset - 11; int xpos2 = *xposOffset + 10; if (x > xpos && x < xpos2) { - assert(*itemsTable < ARRAYSIZE(_itemTable)); - int itemHeight = _itemTable[*itemsTable].height; + assert(*itemsTable >= 0); + int itemHeight = _itemHtDat[*itemsTable]; int ypos = *yposOffset + 3; int ypos2 = ypos - itemHeight - 3; @@ -108,6 +110,7 @@ byte KyraEngine_LoK::findItemAtPos(int x, int y) { } } } + ++xposOffset; ++yposOffset; ++itemsTable; @@ -170,7 +173,7 @@ void KyraEngine_LoK::placeItemInGenericMapScene(int item, int index) { } } -void KyraEngine_LoK::setHandItem(uint16 item) { +void KyraEngine_LoK::setHandItem(Item item) { _screen->hideMouse(); setMouseItem(item); _itemInHand = item; @@ -180,20 +183,21 @@ void KyraEngine_LoK::setHandItem(uint16 item) { void KyraEngine_LoK::removeHandItem() { _screen->hideMouse(); _screen->setMouseCursor(1, 1, _shapes[0]); - _itemInHand = -1; + _itemInHand = kItemNone; _screen->showMouse(); } -void KyraEngine_LoK::setMouseItem(uint16 item) { - if (item == 0xFFFF) +void KyraEngine_LoK::setMouseItem(Item item) { + if (item == kItemNone) _screen->setMouseCursor(1, 1, _shapes[6]); else _screen->setMouseCursor(8, 15, _shapes[216+item]); } void KyraEngine_LoK::wipeDownMouseItem(int xpos, int ypos) { - if (_itemInHand == -1) + if (_itemInHand == kItemNone) return; + xpos -= 8; ypos -= 15; _screen->hideMouse(); @@ -261,7 +265,7 @@ int KyraEngine_LoK::countItemsInScene(uint16 sceneId) { int items = 0; for (int i = 0; i < 12; ++i) { - if (currentRoom->itemsTable[i] != 0xFF) + if (currentRoom->itemsTable[i] != kItemNone) ++items; } @@ -284,7 +288,7 @@ int KyraEngine_LoK::processItemDrop(uint16 sceneId, uint8 item, int x, int y, in if (unk1 != 3) { for (int i = 0; i < 12; ++i) { - if (currentRoom->itemsTable[i] == 0xFF) { + if (currentRoom->itemsTable[i] == kItemNone) { freeItem = i; break; } @@ -301,13 +305,14 @@ int KyraEngine_LoK::processItemDrop(uint16 sceneId, uint8 item, int x, int y, in return 1; } - int itemHeight = _itemTable[item].height; + int itemHeight = _itemHtDat[item]; _lastProcessedItemHeight = itemHeight; - if (x == -1 && x == -1) { + if (x == -1) x = _rnd.getRandomNumberRng(16, 304); + + if (y == -1) y = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 135); - } int xpos = x; int ypos = y; @@ -618,7 +623,7 @@ void KyraEngine_LoK::itemSpecialFX1(int x, int y, int item) { void KyraEngine_LoK::itemSpecialFX2(int x, int y, int item) { x -= 8; y -= 15; - int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF); + int yAdd = (int8)(((16 - _itemHtDat[item]) >> 1) & 0xFF); backUpItemRect0(x, y); if (item >= 80 && item <= 89) snd_playSoundEffect(55); @@ -646,7 +651,8 @@ void KyraEngine_LoK::magicOutMouseItem(int animIndex, int itemPos) { int videoPageBackUp = _screen->_curPage; _screen->_curPage = 0; int x = 0, y = 0; - if (itemPos == -1) { + + if (itemPos == kItemNone) { Common::Point mouse = getMousePos(); x = mouse.x - 12; y = mouse.y - 18; @@ -655,7 +661,7 @@ void KyraEngine_LoK::magicOutMouseItem(int animIndex, int itemPos) { y = _itemPosY[itemPos] - 3; } - if (_itemInHand == -1 && itemPos == -1) + if (_itemInHand == kItemNone && itemPos == -1) return; int tableIndex = 0, loopStart = 0, maxLoops = 0; @@ -712,15 +718,17 @@ void KyraEngine_LoK::magicOutMouseItem(int animIndex, int itemPos) { delayUntil(nextTime); } restoreItemRect1(x, y); + if (itemPos == -1) { _screen->setMouseCursor(1, 1, _shapes[0]); - _itemInHand = -1; + _itemInHand = kItemNone; } else { - _characterList[0].inventoryItems[itemPos] = 0xFF; + _characterList[0].inventoryItems[itemPos] = kItemNone; _screen->hideMouse(); _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12, 0); _screen->showMouse(); } + _screen->showMouse(); _screen->_curPage = videoPageBackUp; } @@ -883,7 +891,8 @@ void KyraEngine_LoK::redrawInventory(int page) { _screen->hideMouse(); for (int i = 0; i < 10; ++i) { _screen->fillRect(_itemPosX[i], _itemPosY[i], _itemPosX[i] + 15, _itemPosY[i] + 15, _flags.platform == Common::kPlatformAmiga ? 19 : 12, page); - if (_currentCharacter->inventoryItems[i] != 0xFF) { + + if (_currentCharacter->inventoryItems[i] != kItemNone) { uint8 item = _currentCharacter->inventoryItems[i]; _screen->drawShape(page, _shapes[216+item], _itemPosX[i], _itemPosY[i], 0, 0); } @@ -913,12 +922,12 @@ void KyraEngine_LoK::restoreItemRect1(int xpos, int ypos) { _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]); } -int KyraEngine_LoK::getItemListIndex(uint16 item) { +int KyraEngine_LoK::getItemListIndex(Item item) { if (_flags.platform != Common::kPlatformAmiga) return item; // "Unknown item" is at 81. - if (item == 0xFFFF || item == 0xFF) + if (item == kItemNone) return 81; // The first item names are mapped directly else if (item <= 28) diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index 5b566d51db2..e99f3bf7019 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -110,10 +110,10 @@ void LoLEngine::takeCredits(int credits, int redraw) { } } -int LoLEngine::makeItem(int itemType, int curFrame, int flags) { +Item LoLEngine::makeItem(int itemType, int curFrame, int flags) { int cnt = 0; int r = 0; - int i = 1; + Item i = 1; for (; i < 400; i++) { if (_itemsInPlay[i].shpCurFrame_flg & 0x8000) { @@ -130,7 +130,7 @@ int LoLEngine::makeItem(int itemType, int curFrame, int flags) { continue; bool t = false; - int ii = i; + Item ii = i; while (ii && !t) { t = testUnkItemFlags(ii); if (t) @@ -145,7 +145,7 @@ int LoLEngine::makeItem(int itemType, int curFrame, int flags) { } } - int slot = i; + Item slot = i; if (cnt) { slot = r; if (testUnkItemFlags(r)) { @@ -154,7 +154,7 @@ int LoLEngine::makeItem(int itemType, int curFrame, int flags) { deleteItem(r); slot = r; } else { - int ii = _itemsInPlay[slot].nextAssignedObject; + uint16 ii = _itemsInPlay[slot].nextAssignedObject; while (ii) { if (testUnkItemFlags(ii)) { _itemsInPlay[slot].nextAssignedObject = _itemsInPlay[ii].nextAssignedObject; @@ -178,7 +178,7 @@ int LoLEngine::makeItem(int itemType, int curFrame, int flags) { return slot; } -void LoLEngine::placeMoveLevelItem(int itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight) { +void LoLEngine::placeMoveLevelItem(Item itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight) { calcCoordinates(_itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, block, xOffs, yOffs); if (_itemsInPlay[itemIndex].block) @@ -194,7 +194,7 @@ void LoLEngine::placeMoveLevelItem(int itemIndex, int level, int block, int xOff } } -bool LoLEngine::addItemToInventory(int itemIndex) { +bool LoLEngine::addItemToInventory(Item itemIndex) { int pos = 0; int i = 0; @@ -222,7 +222,7 @@ bool LoLEngine::addItemToInventory(int itemIndex) { return true; } -bool LoLEngine::testUnkItemFlags(int itemIndex) { +bool LoLEngine::testUnkItemFlags(Item itemIndex) { if (!(_itemsInPlay[itemIndex].shpCurFrame_flg & 0x4000)) return false; @@ -233,7 +233,7 @@ bool LoLEngine::testUnkItemFlags(int itemIndex) { } -void LoLEngine::deleteItem(int itemIndex) { +void LoLEngine::deleteItem(Item itemIndex) { memset(&_itemsInPlay[itemIndex], 0, sizeof(ItemInPlay)); _itemsInPlay[itemIndex].shpCurFrame_flg |= 0x8000; } @@ -245,7 +245,7 @@ ItemInPlay *LoLEngine::findObject(uint16 index) { return &_itemsInPlay[index]; } -void LoLEngine::runItemScript(int charNum, int item, int flags, int next, int reg4) { +void LoLEngine::runItemScript(int charNum, Item item, int flags, int next, int reg4) { EMCState scriptState; memset(&scriptState, 0, sizeof(EMCState)); @@ -270,7 +270,7 @@ void LoLEngine::runItemScript(int charNum, int item, int flags, int next, int re } } -void LoLEngine::setHandItem(uint16 itemIndex) { +void LoLEngine::setHandItem(Item itemIndex) { if (itemIndex && _itemProperties[_itemsInPlay[itemIndex].itemPropertyIndex].flags & 0x80) { runItemScript(-1, itemIndex, 0x400, 0, 0); if (_itemsInPlay[itemIndex].shpCurFrame_flg & 0x8000) @@ -307,7 +307,7 @@ bool LoLEngine::itemEquipped(int charNum, uint16 itemType) { return false; } -void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b) { +void LoLEngine::setItemPosition(Item item, uint16 x, uint16 y, int flyingHeight, int b) { if (!flyingHeight) { x = (x & 0xffc0) | 0x40; y = (y & 0xffc0) | 0x40; @@ -334,7 +334,7 @@ void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, checkSceneUpdateNeed(block); } -void LoLEngine::removeLevelItem(int item, int block) { +void LoLEngine::removeLevelItem(Item item, int block) { removeAssignedObjectFromBlock(&_levelBlockProperties[block], item); removeDrawObjectFromBlock(&_levelBlockProperties[block], item); runLevelScriptCustom(block, 0x100, -1, item, 0, 0); @@ -342,7 +342,7 @@ void LoLEngine::removeLevelItem(int item, int block) { _itemsInPlay[item].level = 0; } -bool LoLEngine::launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c) { +bool LoLEngine::launchObject(int objectType, Item item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c) { int sp = checkDrawObjectSpace(_partyPosX, _partyPosY, startX, startY); FlyingObject *t = _flyingObjects; int slot = -1; diff --git a/engines/kyra/items_mr.cpp b/engines/kyra/items_mr.cpp index 256753cc69c..2bc268ace32 100644 --- a/engines/kyra/items_mr.cpp +++ b/engines/kyra/items_mr.cpp @@ -29,7 +29,7 @@ namespace Kyra { void KyraEngine_MR::removeTrashItems() { - for (int i = 0; _trashItemList[i] != 0xFF; ++i) { + for (int i = 0; _trashItemList[i] != kItemNone; ++i) { for (int item = findItem(_trashItemList[i]); item != -1; item = findItem(_trashItemList[i])) { if (_itemList[item].sceneId != _mainCharacter.sceneId) resetItem(item); @@ -41,7 +41,7 @@ void KyraEngine_MR::removeTrashItems() { int KyraEngine_MR::findFreeInventorySlot() { for (int i = 0; i < 10; ++i) { - if (_mainCharacter.inventory[i] == 0xFFFF) + if (_mainCharacter.inventory[i] == kItemNone) return i; } return -1; @@ -52,7 +52,7 @@ int KyraEngine_MR::checkItemCollision(int x, int y) { int maxItemY = -1; for (int i = 0; i < 50; ++i) { - if (_itemList[i].id == 0xFFFF || _itemList[i].sceneId != _mainCharacter.sceneId) + if (_itemList[i].id == kItemNone || _itemList[i].sceneId != _mainCharacter.sceneId) continue; const int x1 = _itemList[i].x - 11; @@ -76,12 +76,12 @@ int KyraEngine_MR::checkItemCollision(int x, int y) { return itemIndex; } -void KyraEngine_MR::setMouseCursor(uint16 item) { +void KyraEngine_MR::setMouseCursor(Item item) { int shape = 0; int hotX = 1; int hotY = 1; - if (item != 0xFFFF) { + if (item != kItemNone) { hotX = 12; hotY = 19; shape = item+248; @@ -94,13 +94,13 @@ void KyraEngine_MR::setMouseCursor(uint16 item) { void KyraEngine_MR::setItemMouseCursor() { _mouseState = _itemInHand; - if (_itemInHand == -1) + if (_itemInHand == kItemNone) _screen->setMouseCursor(0, 0, _gameShapes[0]); else _screen->setMouseCursor(12, 19, _gameShapes[_itemInHand+248]); } -bool KyraEngine_MR::dropItem(int unk1, uint16 item, int x, int y, int unk2) { +bool KyraEngine_MR::dropItem(int unk1, Item item, int x, int y, int unk2) { if (_mouseState <= -1) return false; @@ -123,7 +123,7 @@ bool KyraEngine_MR::dropItem(int unk1, uint16 item, int x, int y, int unk2) { return false; } -bool KyraEngine_MR::processItemDrop(uint16 sceneId, uint16 item, int x, int y, int unk1, int unk2) { +bool KyraEngine_MR::processItemDrop(uint16 sceneId, Item item, int x, int y, int unk1, int unk2) { int itemPos = checkItemCollision(x, y); if (unk1) @@ -138,7 +138,7 @@ bool KyraEngine_MR::processItemDrop(uint16 sceneId, uint16 item, int x, int y, i if (unk2 != 3) { for (int i = 0; i < 50; ++i) { - if (_itemList[i].id == 0xFFFF) { + if (_itemList[i].id == kItemNone) { freeItemSlot = i; break; } @@ -227,7 +227,7 @@ bool KyraEngine_MR::processItemDrop(uint16 sceneId, uint16 item, int x, int y, i return true; } -void KyraEngine_MR::itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, uint16 item, int remove) { +void KyraEngine_MR::itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, Item item, int remove) { if (startX == dstX && startY == dstY) { _itemList[itemSlot].x = dstX; _itemList[itemSlot].y = dstY; @@ -323,7 +323,7 @@ void KyraEngine_MR::exchangeMouseItem(int itemPos, int runScript) { _screen->hideMouse(); deleteItemAnimEntry(itemPos); - int itemId = _itemList[itemPos].id; + Item itemId = _itemList[itemPos].id; _itemList[itemPos].id = _itemInHand; _itemInHand = itemId; @@ -353,8 +353,8 @@ bool KyraEngine_MR::pickUpItem(int x, int y, int runScript) { } else { _screen->hideMouse(); deleteItemAnimEntry(itemPos); - int itemId = _itemList[itemPos].id; - _itemList[itemPos].id = 0xFFFF; + Item itemId = _itemList[itemPos].id; + _itemList[itemPos].id = kItemNone; snd_playSoundEffect(0x0B, 0xC8); setMouseCursor(itemId); int itemString = 0; @@ -387,8 +387,9 @@ bool KyraEngine_MR::isDropable(int x, int y) { return true; } -bool KyraEngine_MR::itemListMagic(int handItem, int itemSlot) { - uint16 item = _itemList[itemSlot].id; +bool KyraEngine_MR::itemListMagic(Item handItem, int itemSlot) { + Item item = _itemList[itemSlot].id; + if (_currentChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { eelScript(); return true; @@ -410,7 +411,7 @@ bool KyraEngine_MR::itemListMagic(int handItem, int itemSlot) { } deleteItemAnimEntry(itemSlot); - _itemList[itemSlot].id = 0xFFFF; + _itemList[itemSlot].id = kItemNone; _screen->showMouse(); return true; } @@ -430,7 +431,7 @@ bool KyraEngine_MR::itemListMagic(int handItem, int itemSlot) { } for (int i = 0; _itemMagicTable[i] != 0xFF; i += 4) { - if (_itemMagicTable[i+0] != handItem || _itemMagicTable[i+1] != item) + if (_itemMagicTable[i+0] != handItem || (int8)_itemMagicTable[i+1] != item) continue; uint8 resItem = _itemMagicTable[i+2]; @@ -438,7 +439,7 @@ bool KyraEngine_MR::itemListMagic(int handItem, int itemSlot) { snd_playSoundEffect(0x0F, 0xC8); - _itemList[itemSlot].id = (resItem == 0xFF) ? 0xFFFF : resItem; + _itemList[itemSlot].id = (int8)resItem; _screen->hideMouse(); deleteItemAnimEntry(itemSlot); @@ -465,8 +466,9 @@ bool KyraEngine_MR::itemListMagic(int handItem, int itemSlot) { return false; } -bool KyraEngine_MR::itemInventoryMagic(int handItem, int invSlot) { - uint16 item = _mainCharacter.inventory[invSlot]; +bool KyraEngine_MR::itemInventoryMagic(Item handItem, int invSlot) { + Item item = _mainCharacter.inventory[invSlot]; + if (_currentChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { eelScript(); return true; @@ -482,7 +484,7 @@ bool KyraEngine_MR::itemInventoryMagic(int handItem, int invSlot) { delay(1*_tickLength, true); } - _mainCharacter.inventory[invSlot] = 0xFFFF; + _mainCharacter.inventory[invSlot] = kItemNone; clearInventorySlot(invSlot, 0); _screen->showMouse(); return true; @@ -497,7 +499,7 @@ bool KyraEngine_MR::itemInventoryMagic(int handItem, int invSlot) { snd_playSoundEffect(0x0F, 0xC8); - _mainCharacter.inventory[invSlot] = (resItem == 0xFF) ? 0xFFFF : resItem; + _mainCharacter.inventory[invSlot] = (int8)resItem; _screen->hideMouse(); clearInventorySlot(invSlot, 0); diff --git a/engines/kyra/items_v2.cpp b/engines/kyra/items_v2.cpp index 29901b2ddb0..90b6194f0d3 100644 --- a/engines/kyra/items_v2.cpp +++ b/engines/kyra/items_v2.cpp @@ -31,9 +31,9 @@ namespace Kyra { void KyraEngine_v2::initItemList(int size) { delete[] _itemList; - _itemList = new Item[size]; + _itemList = new ItemDefinition[size]; assert(_itemList); - memset(_itemList, 0, sizeof(Item)*size); + memset(_itemList, 0, sizeof(ItemDefinition)*size); _itemListSize = size; resetItemList(); @@ -41,7 +41,7 @@ void KyraEngine_v2::initItemList(int size) { int KyraEngine_v2::findFreeItem() { for (int i = 0; i < _itemListSize; ++i) { - if (_itemList[i].id == 0xFFFF) + if (_itemList[i].id == kItemNone) return i; } return -1; @@ -50,13 +50,13 @@ int KyraEngine_v2::findFreeItem() { int KyraEngine_v2::countAllItems() { int num = 0; for (int i = 0; i < _itemListSize; ++i) { - if (_itemList[i].id != 0xFFFF) + if (_itemList[i].id != kItemNone) ++num; } return num; } -int KyraEngine_v2::findItem(uint16 sceneId, uint16 id) { +int KyraEngine_v2::findItem(uint16 sceneId, Item id) { for (int i = 0; i < _itemListSize; ++i) { if (_itemList[i].id == id && _itemList[i].sceneId == sceneId) return i; @@ -64,7 +64,7 @@ int KyraEngine_v2::findItem(uint16 sceneId, uint16 id) { return -1; } -int KyraEngine_v2::findItem(uint16 item) { +int KyraEngine_v2::findItem(Item item) { for (int i = 0; i < _itemListSize; ++i) { if (_itemList[i].id == item) return i; @@ -78,17 +78,17 @@ void KyraEngine_v2::resetItemList() { } void KyraEngine_v2::resetItem(int index) { - _itemList[index].id = 0xFFFF; + _itemList[index].id = kItemNone; _itemList[index].sceneId = 0xFFFF; _itemList[index].x = 0; _itemList[index].y = 0; } -void KyraEngine_v2::setHandItem(uint16 item) { +void KyraEngine_v2::setHandItem(Item item) { Screen *scr = screen(); scr->hideMouse(); - if (item == 0xFFFF) { + if (item == kItemNone) { removeHandItem(); } else { setMouseCursor(item); @@ -102,8 +102,8 @@ void KyraEngine_v2::removeHandItem() { Screen *scr = screen(); scr->hideMouse(); scr->setMouseCursor(0, 0, getShapePtr(0)); - _itemInHand = -1; - _mouseState = -1; + _itemInHand = kItemNone; + _mouseState = kItemNone; scr->showMouse(); } diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 0fafaa15ce5..5c471a8c8b7 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -74,7 +74,7 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _mainCharX = _mainCharY = -1; _drawNoShapeFlag = false; _charPalEntry = 0; - _itemInHand = -1; + _itemInHand = kItemNone; _unkSceneScreenFlag1 = false; _noScriptEnter = true; _currentChapter = 0; @@ -441,7 +441,7 @@ void KyraEngine_HoF::startup() { if (_gameToLoad == -1) { snd_playWanderScoreViaMap(52, 1); enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); - saveGameState(0, "New Game", 0); + saveGameStateIntern(0, "New Game", 0); } else { loadGameStateCheck(_gameToLoad); } @@ -507,7 +507,7 @@ void KyraEngine_HoF::runLoop() { update(); if (inputFlag == 198 || inputFlag == 199) { - _unk3 = _mouseState; + _savedMouseState = _mouseState; handleInput(_mouseX, _mouseY); } @@ -528,7 +528,7 @@ void KyraEngine_HoF::handleInput(int x, int y) { if (!_screen->isMouseVisible()) return; - if (_unk3 == -2) { + if (_savedMouseState == -2) { snd_playSoundEffect(13); return; } @@ -537,8 +537,8 @@ void KyraEngine_HoF::handleInput(int x, int y) { if (x <= 6 || x >= 312 || y <= 6 || y >= 135) { bool exitOk = false; - assert(_unk3 + 6 >= 0); - switch (_unk3 + 6) { + assert(_savedMouseState + 6 >= 0); + switch (_savedMouseState + 6) { case 0: if (_sceneExit1 != 0xFFFF) exitOk = true; @@ -569,7 +569,7 @@ void KyraEngine_HoF::handleInput(int x, int y) { } } - if (checkCharCollision(x, y) && _unk3 >= -1) { + if (checkCharCollision(x, y) && _savedMouseState >= -1) { runSceneScript2(); return; } else if (pickUpItem(x, y)) { @@ -609,7 +609,7 @@ void KyraEngine_HoF::handleInput(int x, int y) { dropItem(0, _itemInHand, x, y, 1); } else { - if (_unk3 == -2 || y > 135) + if (_savedMouseState == -2 || y > 135) return; if (!_unk5) { @@ -790,7 +790,7 @@ void KyraEngine_HoF::updateMouse() { if ((mouse.y > 145) || (mouse.x > 6 && mouse.x < 312 && mouse.y > 6 && mouse.y < 135)) { _mouseState = _itemInHand; _screen->hideMouse(); - if (_itemInHand == -1) + if (_itemInHand == kItemNone) _screen->setMouseCursor(0, 0, getShapePtr(0)); else _screen->setMouseCursor(8, 15, getShapePtr(_itemInHand+64)); @@ -1169,25 +1169,25 @@ int KyraEngine_HoF::inputSceneChange(int x, int y, int unk1, int unk2) { _pathfinderFlag = 15; if (!_unkHandleSceneChangeFlag) { - if (_unk3 == -3) { + if (_savedMouseState == -3) { if (_sceneList[curScene].exit4 != 0xFFFF) { x = 4; y = _sceneEnterY4; _pathfinderFlag = 7; } - } else if (_unk3 == -5) { + } else if (_savedMouseState == -5) { if (_sceneList[curScene].exit2 != 0xFFFF) { x = 316; y = _sceneEnterY2; _pathfinderFlag = 7; } - } else if (_unk3 == -6) { + } else if (_savedMouseState == -6) { if (_sceneList[curScene].exit1 != 0xFFFF) { x = _sceneEnterX1; y = _sceneEnterY1 - 2; _pathfinderFlag = 14; } - } else if (_unk3 == -4) { + } else if (_savedMouseState == -4) { if (_sceneList[curScene].exit3 != 0xFFFF) { x = _sceneEnterX3; y = 147; @@ -1200,13 +1200,13 @@ int KyraEngine_HoF::inputSceneChange(int x, int y, int unk1, int unk2) { int vocH = _flags.isTalkie ? 131 : -1; if (_pathfinderFlag) { - if (findItem(curScene, 13) >= 0 && _unk3 <= -3) { + if (findItem(curScene, 13) >= 0 && _savedMouseState <= -3) { strId = 252; } else if (_itemInHand == 72) { strId = 257; - } else if (findItem(curScene, 72) >= 0 && _unk3 <= -3) { + } else if (findItem(curScene, 72) >= 0 && _savedMouseState <= -3) { strId = 256; - } else if (getInventoryItemSlot(72) != -1 && _unk3 <= -3) { + } else if (getInventoryItemSlot(72) != -1 && _savedMouseState <= -3) { strId = 257; } } diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index 05d04fe9933..576232740bf 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -443,16 +443,16 @@ protected: bool lineIsPassable(int x, int y); // item - void setMouseCursor(uint16 item); + void setMouseCursor(Item item); uint8 _itemHtDat[176]; int checkItemCollision(int x, int y); void updateWaterFlasks(); - bool dropItem(int unk1, uint16 item, int x, int y, int unk2); - bool processItemDrop(uint16 sceneId, uint16 item, int x, int y, int unk1, int unk2); - void itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, uint16 item); + bool dropItem(int unk1, Item item, int x, int y, int unk2); + bool processItemDrop(uint16 sceneId, Item item, int x, int y, int unk1, int unk2); + void itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, Item item); void exchangeMouseItem(int itemPos); bool pickUpItem(int x, int y); @@ -461,18 +461,18 @@ protected: static const byte _itemStringMap[]; static const int _itemStringMapSize; - static const int16 _flaskTable[]; - bool itemIsFlask(int item); + static const Item _flaskTable[]; + bool itemIsFlask(Item item); // inventory static const int _inventoryX[]; static const int _inventoryY[]; static const uint16 _itemMagicTable[]; - int getInventoryItemSlot(uint16 item); + int getInventoryItemSlot(Item item); void removeSlotFromInventory(int slot); - bool checkInventoryItemExchange(uint16 item, int slot); - void drawInventoryShape(int page, uint16 item, int slot); + bool checkInventoryItemExchange(Item item, int slot); + void drawInventoryShape(int page, Item item, int slot); void clearInventorySlot(int slot, int page); void redrawInventory(int page); void scrollInventoryWheel(); @@ -561,9 +561,9 @@ protected: void changeFileExtension(char *buffer); // - Just used in French version - int getItemCommandStringDrop(uint16 item); - int getItemCommandStringPickUp(uint16 item); - int getItemCommandStringInv(uint16 item); + int getItemCommandStringDrop(Item item); + int getItemCommandStringPickUp(Item item); + int getItemCommandStringInv(Item item); // - char _internStringBuf[200]; @@ -915,7 +915,7 @@ protected: int _dbgPass; // save/load specific - Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail); + Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail); Common::Error loadGameState(int slot); }; diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 159230e928a..d46fc2d5029 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -247,7 +247,7 @@ Common::Error KyraEngine_LoK::init() { _brandonPosX = _brandonPosY = -1; _poisonDeathCounter = 0; - memset(_itemTable, 0, sizeof(_itemTable)); + memset(_itemHtDat, 0, sizeof(_itemHtDat)); memset(_exitList, 0xFFFF, sizeof(_exitList)); _exitListPtr = 0; _pathfinderFlag = _pathfinderFlag2 = 0; @@ -260,7 +260,7 @@ Common::Error KyraEngine_LoK::init() { _marbleVaseItem = -1; memset(_foyerItemTable, -1, sizeof(_foyerItemTable)); - _itemInHand = -1; + _itemInHand = kItemNone; _currentRoom = 0xFFFF; _scenePhasingFlag = 0; @@ -373,7 +373,7 @@ void KyraEngine_LoK::startup() { for (int i = 0; i < _roomTableSize; ++i) { for (int item = 0; item < 12; ++item) { - _roomTable[i].itemsTable[item] = 0xFF; + _roomTable[i].itemsTable[item] = kItemNone; _roomTable[i].itemsXPos[item] = 0xFFFF; _roomTable[i].itemsYPos[item] = 0xFF; _roomTable[i].needInit[item] = 0; @@ -420,7 +420,7 @@ void KyraEngine_LoK::startup() { _gui->buttonMenuCallback(0); _menuDirectlyToLoad = false; } else if (!shouldQuit()) { - saveGameState(0, "New game", 0); + saveGameStateIntern(0, "New game", 0); } } else { _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); @@ -672,12 +672,13 @@ void KyraEngine_LoK::processInput(int xpos, int ypos) { runNpcScript(script); return; } - if (_itemInHand != -1) { + if (_itemInHand != kItemNone) { if (ypos < 155) { if (hasClickedOnExit(xpos, ypos)) { handleSceneChange(xpos, ypos, 1, 1); return; } + dropItem(0, _itemInHand, xpos, ypos, 1); } } else { @@ -691,14 +692,14 @@ void KyraEngine_LoK::processInput(int xpos, int ypos) { int KyraEngine_LoK::processInputHelper(int xpos, int ypos) { uint8 item = findItemAtPos(xpos, ypos); if (item != 0xFF) { - if (_itemInHand == -1) { + if (_itemInHand == kItemNone) { _screen->hideMouse(); _animator->animRemoveGameItem(item); snd_playSoundEffect(53); assert(_currentCharacter->sceneId < _roomTableSize); Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; int item2 = currentRoom->itemsTable[item]; - currentRoom->itemsTable[item] = 0xFF; + currentRoom->itemsTable[item] = kItemNone; setMouseItem(item2); assert(_itemList && _takenList); updateSentenceCommand(_itemList[getItemListIndex(item2)], _takenList[0], 179); @@ -830,7 +831,7 @@ void KyraEngine_LoK::updateMousePointer(bool forceUpdate) { if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) { _mouseState = _itemInHand; _screen->hideMouse(); - if (_itemInHand == -1) + if (_itemInHand == kItemNone) _screen->setMouseCursor(1, 1, _shapes[0]); else _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]); diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index 50f36d7b718..dfbf5bddd8d 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -30,6 +30,7 @@ #include "kyra/script.h" #include "kyra/screen_lok.h" #include "kyra/gui_lok.h" +#include "kyra/item.h" namespace Kyra { @@ -46,7 +47,7 @@ struct Character { uint8 height; uint8 facing; uint16 currentAnimFrame; - uint8 inventoryItems[10]; + int8 inventoryItems[10]; int16 x1, y1, x2, y2; }; @@ -62,19 +63,12 @@ struct Room { uint16 eastExit; uint16 southExit; uint16 westExit; - uint8 itemsTable[12]; + int8 itemsTable[12]; uint16 itemsXPos[12]; uint8 itemsYPos[12]; uint8 needInit[12]; }; -struct Item { - uint8 unk1; - uint8 height; - uint8 unk2; - uint8 unk3; -}; - struct SeqLoop { const uint8 *ptr; uint16 count; @@ -218,7 +212,7 @@ public: protected: int32 _speechPlayTime; - Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail); + Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail); Common::Error loadGameState(int slot); protected: // input @@ -288,11 +282,11 @@ protected: void placeItemInGenericMapScene(int item, int index); // -> mouse item - void setHandItem(uint16 item); + void setHandItem(Item item); void removeHandItem(); - void setMouseItem(uint16 item); + void setMouseItem(Item item); - int getItemListIndex(uint16 item); + int getItemListIndex(Item item); // -> graphics effects void wipeDownMouseItem(int xpos, int ypos); @@ -402,7 +396,7 @@ protected: bool _menuDirectlyToLoad; uint8 *_itemBkgBackUp[2]; uint8 *_shapes[373]; - int8 _itemInHand; + Item _itemInHand; bool _changedScene; int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3; int _beadStateVar; @@ -455,7 +449,7 @@ protected: int8 *_sceneAnimTable[50]; - Item _itemTable[145]; + uint8 _itemHtDat[145]; int _lastProcessedItem; int _lastProcessedItemHeight; diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index c224a76385a..5ac6da9f2bd 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -99,8 +99,8 @@ KyraEngine_MR::KyraEngine_MR(OSystem *system, const GameFlags &flags) : KyraEngi _unk5 = 0; _unkSceneScreenFlag1 = false; _noScriptEnter = true; - _itemInHand = _mouseState = -1; - _unk3 = -1; + _itemInHand = _mouseState = kItemNone; + _savedMouseState = -1; _unk4 = 0; _loadingState = false; _noStartupChat = false; @@ -653,7 +653,7 @@ void KyraEngine_MR::startup() { assert(_invWsa); _invWsa->open("MOODOMTR.WSA", 1, 0); _invWsaFrame = 6; - saveGameState(0, "New Game", 0); + saveGameStateIntern(0, "New Game", 0); if (_gameToLoad == -1) enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); else @@ -966,7 +966,7 @@ void KyraEngine_MR::runLoop() { _timer->update(); if (inputFlag == 198 || inputFlag == 199) { - _unk3 = _mouseState; + _savedMouseState = _mouseState; Common::Point mouse = getMousePos(); handleInput(mouse.x, mouse.y); } @@ -988,7 +988,7 @@ void KyraEngine_MR::handleInput(int x, int y) { if (!_screen->isMouseVisible()) return; - if (_unk3 == -3) { + if (_savedMouseState == -3) { snd_playSoundEffect(0x0D, 0x80); return; } @@ -997,7 +997,7 @@ void KyraEngine_MR::handleInput(int x, int y) { int skip = 0; - if (checkCharCollision(x, y) && _unk3 >= -1 && runSceneScript2()) { + if (checkCharCollision(x, y) && _savedMouseState >= -1 && runSceneScript2()) { return; } else if (_itemInHand != 27 && pickUpItem(x, y, 1)) { return; @@ -1023,7 +1023,7 @@ void KyraEngine_MR::handleInput(int x, int y) { if (checkCharCollision(x, y)) { if (runSceneScript2()) return; - } else if (_itemInHand >= 0 && _unk3 >= 0) { + } else if (_itemInHand >= 0 && _savedMouseState >= 0) { if (_itemInHand == 27) { makeCharFacingMouse(); } else if (y <= 187) { @@ -1033,10 +1033,10 @@ void KyraEngine_MR::handleInput(int x, int y) { dropItem(0, _itemInHand, x, y, 1); } return; - } else if (_unk3 == -3) { + } else if (_savedMouseState == -3) { return; } else { - if (y > 187 && _unk3 > -4) + if (y > 187 && _savedMouseState > -4) return; if (_unk5) { _unk5 = 0; @@ -1052,25 +1052,25 @@ int KyraEngine_MR::inputSceneChange(int x, int y, int unk1, int unk2) { _pathfinderFlag = 15; if (!_unkHandleSceneChangeFlag) { - if (_unk3 == -4) { + if (_savedMouseState == -4) { if (_sceneList[curScene].exit4 != 0xFFFF) { x = 4; y = _sceneEnterY4; _pathfinderFlag = 7; } - } else if (_unk3 == -6) { + } else if (_savedMouseState == -6) { if (_sceneList[curScene].exit2 != 0xFFFF) { x = 316; y = _sceneEnterY2; _pathfinderFlag = 7; } - } else if (_unk3 == -7) { + } else if (_savedMouseState == -7) { if (_sceneList[curScene].exit1 != 0xFFFF) { x = _sceneEnterX1; y = _sceneEnterY1 - 2; _pathfinderFlag = 14; } - } else if (_unk3 == -5) { + } else if (_savedMouseState == -5) { if (_sceneList[curScene].exit3 != 0xFFFF) { x = _sceneEnterX3; y = 191; @@ -1167,8 +1167,8 @@ void KyraEngine_MR::updateMouse() { } if (hasItemCollision && _mouseState < -1 && _itemInHand < 0) { - _mouseState = -1; - _itemInHand = -1; + _mouseState = kItemNone; + _itemInHand = kItemNone; _screen->setMouseCursor(0, 0, _gameShapes[0]); } diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 36b937f2a87..e6f75742f49 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -235,7 +235,7 @@ private: void showMessage(const char *string, uint8 c0, uint8 c1); void showMessageFromCCode(int string, uint8 c0, int); - void updateItemCommand(int item, int str, uint8 c0); + void updateItemCommand(Item item, int str, uint8 c0); void updateCommandLine(); void restoreCommandLine(); @@ -262,7 +262,7 @@ private: static const uint8 _inventoryY[]; void redrawInventory(int page); void clearInventorySlot(int slot, int page); - void drawInventorySlot(int page, int item, int slot); + void drawInventorySlot(int page, Item item, int slot); WSAMovie_v2 *_invWsa; int _invWsaFrame; @@ -284,24 +284,24 @@ private: int8 *_itemBuffer1; int8 *_itemBuffer2; - static const uint8 _trashItemList[]; + static const Item _trashItemList[]; void removeTrashItems(); void initItems(); int checkItemCollision(int x, int y); - bool dropItem(int unk1, uint16 item, int x, int y, int unk2); - bool processItemDrop(uint16 sceneId, uint16 item, int x, int y, int unk1, int unk2); - void itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, uint16 item, int remove); + bool dropItem(int unk1, Item item, int x, int y, int unk2); + bool processItemDrop(uint16 sceneId, Item item, int x, int y, int unk1, int unk2); + void itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, Item item, int remove); void exchangeMouseItem(int itemPos, int runScript); bool pickUpItem(int x, int y, int runScript); bool isDropable(int x, int y); const uint8 *_itemMagicTable; - bool itemListMagic(int handItem, int itemSlot); - bool itemInventoryMagic(int handItem, int invSlot); + bool itemListMagic(Item handItem, int itemSlot); + bool itemInventoryMagic(Item handItem, int invSlot); const uint8 *_itemStringMap; int _itemStringMapSize; @@ -315,7 +315,7 @@ private: // -> hand item void setItemMouseCursor(); - void setMouseCursor(uint16 item); + void setMouseCursor(Item item); // shapes void initMouseShapes(); @@ -585,7 +585,7 @@ private: int albumClose(Button *caller); // save/load - Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail); + Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail); Common::Error loadGameState(int slot); // opcodes diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 1c27716a674..26c4001578a 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -103,11 +103,14 @@ Common::Error KyraEngine_v1::init() { syncSoundSettings(); if (!_flags.useDigSound) { - // 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)); + // In Kyra 1 users who have specified a default MT-32 device in the launcher settings + // will get MT-32 music, otherwise AdLib. In Kyra 2 and LoL users who have specified a + // default GM device in the launcher will get GM music, otherwise AdLib. Users who want + // MT-32 music in Kyra2 or LoL have to select this individually (since we assume that + // most users rather have a GM device than a MT-32 device). + // Users who want PC speaker sound always have to select this individually for all + // Kyra games. + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : MDT_PREFER_MT32)); if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) @@ -179,7 +182,7 @@ Common::Error KyraEngine_v1::init() { #ifdef ENABLE_LOL _flags.gameID = GI_LOL; #else - error("Lands of Lore demo is not supported in this build."); + error("Lands of Lore demo is not supported in this build"); #endif // !ENABLE_LOL } @@ -275,7 +278,7 @@ int KyraEngine_v1::checkInput(Button *buttonList, bool mainLoop, int eventFlag) } else { char savegameName[14]; sprintf(savegameName, "Quicksave %d", event.kbd.keycode - Common::KEYCODE_0); - saveGameState(saveLoadSlot, savegameName, 0); + saveGameStateIntern(saveLoadSlot, savegameName, 0); } } else if (event.kbd.hasFlags(Common::KBD_CTRL)) { if (event.kbd.keycode == Common::KEYCODE_d) { diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index d077d3a3b06..31c07336a6c 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -37,6 +37,7 @@ #include "sound/mixer.h" #include "kyra/script.h" +#include "kyra/item.h" namespace Common { class SeekableReadStream; @@ -93,7 +94,7 @@ class KyraMetaEngine; * is pretty minor priority though, since the benefit would be mostly nicer code). The biggest * task left is the kyra.dat handling, which is currently being revised by LordHoto. * - * Supported games: + * Games using this engine: * - The Legend of Kyrandia (fully supported, except for Macintosh port, which lacks sound) * - (The) Hand of Fate (fully supported) * - Malcolm's Revenge (fully supported) @@ -339,7 +340,7 @@ protected: // items int _mouseState; - virtual void setHandItem(uint16 item) = 0; + virtual void setHandItem(Item item) = 0; virtual void removeHandItem() = 0; // game flags @@ -414,8 +415,8 @@ protected: void loadGameStateCheck(int slot); virtual Common::Error loadGameState(int slot) = 0; - Common::Error saveGameState(int slot, const char *saveName) { return saveGameState(slot, saveName, 0); } - virtual Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) = 0; + Common::Error saveGameState(int slot, const char *saveName) { return saveGameStateIntern(slot, saveName, 0); } + virtual Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) = 0; Common::SeekableReadStream *openSaveForReading(const char *filename, SaveHeader &header); Common::WriteStream *openSaveForWriting(const char *filename, const char *saveName, const Graphics::Surface *thumbnail) const; diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index 64140403446..39c9f0875ea 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -29,6 +29,7 @@ #include "kyra/kyra_v1.h" #include "kyra/gui.h" #include "kyra/wsamovie.h" +#include "kyra/item.h" #include "common/list.h" #include "common/hashmap.h" @@ -41,7 +42,7 @@ struct FrameControl { }; struct ItemAnimData_v2 { - int16 itemIndex; + Item itemIndex; uint8 numFrames; const FrameControl *frames; }; @@ -69,7 +70,7 @@ public: int animScriptFrameAdd; // Item specific - int maxItemId; + Item maxItemId; }; KyraEngine_v2(OSystem *system, const GameFlags &flags, const EngineDesc &desc); @@ -286,8 +287,8 @@ protected: int _pathfinderPositionIndexTable[200]; // items - struct Item { - uint16 id; + struct ItemDefinition { + Item id; uint16 sceneId; int16 x; uint8 y; @@ -295,25 +296,26 @@ protected: void initItemList(int size); - uint16 _hiddenItems[100]; + Item _hiddenItems[100]; - Item *_itemList; + ItemDefinition *_itemList; int _itemListSize; int _itemInHand; + int _savedMouseState; int findFreeItem(); int countAllItems(); - int findItem(uint16 sceneId, uint16 id); - int findItem(uint16 item); + int findItem(uint16 sceneId, Item id); + int findItem(Item item); void resetItemList(); void resetItem(int index); - virtual void setMouseCursor(uint16 item) = 0; + virtual void setMouseCursor(Item item) = 0; - void setHandItem(uint16 item); + void setHandItem(Item item); void removeHandItem(); // character @@ -324,7 +326,7 @@ protected: uint8 facing; uint16 animFrame; byte walkspeed; - uint16 inventory[20]; + Item inventory[20]; int16 x1, y1; int16 x2, y2; int16 x3, y3; @@ -360,7 +362,7 @@ protected: virtual void randomSceneChat() = 0; // unknown - int _unk3, _unk4, _unk5; + int _unk4, _unk5; bool _unkSceneScreenFlag1; bool _unkHandleSceneChangeFlag; diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 03d52ec4ac9..f6ac8a1a73c 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -1930,11 +1930,11 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int restorePortrait return 1; } -void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) { +void LoLEngine::giveItemToMonster(MonsterInPlay *monster, Item item) { uint16 *c = &monster->assignedItems; while (*c) c = &_itemsInPlay[*c].nextAssignedObject; - *c = item; + *c = (uint16)item; _itemsInPlay[item].nextAssignedObject = 0; } diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 57c127a94f6..f2c93f83fcb 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -225,7 +225,7 @@ struct FlyingObject { uint8 enable; uint8 objectType; uint16 attackerId; - uint16 item; + Item item; uint16 x; uint16 y; uint8 flyingHeight; @@ -1202,19 +1202,19 @@ private: // items void giveCredits(int credits, int redraw); void takeCredits(int credits, int redraw); - int makeItem(int itemType, int curFrame, int flags); - void placeMoveLevelItem(int itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight); - bool addItemToInventory(int itemIndex); - bool testUnkItemFlags(int itemIndex); - void deleteItem(int itemIndex); + Item makeItem(int itemType, int curFrame, int flags); + void placeMoveLevelItem(Item itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight); + bool addItemToInventory(Item itemIndex); + bool testUnkItemFlags(Item itemIndex); + void deleteItem(Item itemIndex); ItemInPlay *findObject(uint16 index); - void runItemScript(int charNum, int item, int flags, int next, int reg4); - void setHandItem(uint16 itemIndex); + void runItemScript(int charNum, Item item, int flags, int next, int reg4); + void setHandItem(Item itemIndex); bool itemEquipped(int charNum, uint16 itemType); - void setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b); - void removeLevelItem(int item, int block); - bool launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c); + void setItemPosition(Item item, uint16 x, uint16 y, int flyingHeight, int b); + void removeLevelItem(Item item, int block); + bool launchObject(int objectType, Item item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c); void endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock); void processObjectFlight(FlyingObject *t, int x, int y); void updateObjectFlightPosition(FlyingObject *t); @@ -1231,9 +1231,9 @@ private: ItemInPlay *_itemsInPlay; ItemProperty *_itemProperties; - int _itemInHand; - uint16 _inventory[48]; - int _inventoryCurItem; + Item _itemInHand; + Item _inventory[48]; + Item _inventoryCurItem; int _currentControlMode; int _specialSceneFlag; int _lastCharInventory; @@ -1269,10 +1269,10 @@ private: int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2); void setMonsterDirection(MonsterInPlay *monster, int dir); void monsterDropItems(MonsterInPlay *monster); - void removeAssignedObjectFromBlock(LevelBlockProperty *l, int id); - void removeDrawObjectFromBlock(LevelBlockProperty *l, int id); - void assignMonsterToBlock(uint16 *assignedBlockObjects, int id); - void giveItemToMonster(MonsterInPlay *monster, uint16 item); + void removeAssignedObjectFromBlock(LevelBlockProperty *l, uint16 id); + void removeDrawObjectFromBlock(LevelBlockProperty *l, uint16 id); + void assignMonsterToBlock(uint16 *assignedBlockObjects, uint16 id); + void giveItemToMonster(MonsterInPlay *monster, Item item); int checkBlockBeforeObjectPlacement(uint16 x, uint16 y, uint16 objectWidth, uint16 testFlag, uint16 wallFlag); int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int objectWidth, int testFlag, int wallFlag); int calcMonsterSkillLevel(int id, int a); @@ -1488,7 +1488,7 @@ private: // save Common::Error loadGameState(int slot); - Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail); + Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail); Graphics::Surface *generateSaveThumbnail() const; diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index 0d968de9ff5..445ea579a01 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -514,7 +514,7 @@ void FileExpanderSource::advSrcBitsBy1() { _key >>= 1; if (!--_bitsLeft) { if (_dataPtr < _endofBuffer) - _key = ((*_dataPtr++) << 8 ) | (_key & 0xff); + _key = ((*_dataPtr++) << 8) | (_key & 0xff); _bitsLeft = 8; } } diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index b1cc9541371..c9450e3f271 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -137,7 +137,7 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena kReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header); if (errorCode != kRSHENoError) { if (errorCode == kRSHEInvalidType) - warning("No ScummVM Kyra engine savefile header."); + warning("No ScummVM Kyra engine savefile header"); else if (errorCode == kRSHEInvalidVersion) warning("Savegame is not the right version (%u, '%s')", header.version, header.oldHeader ? "true" : "false"); else if (errorCode == kRSHEIoError) @@ -250,7 +250,7 @@ bool KyraEngine_v1::saveFileLoadable(int slot) { void KyraEngine_v1::checkAutosave() { if (shouldPerformAutoSave(_lastAutosave)) { - saveGameState(999, "Autosave", 0); + saveGameStateIntern(999, "Autosave", 0); _lastAutosave = _system->getMillis(); } } diff --git a/engines/kyra/saveload_hof.cpp b/engines/kyra/saveload_hof.cpp index 2d276cc6a46..e957718f95d 100644 --- a/engines/kyra/saveload_hof.cpp +++ b/engines/kyra/saveload_hof.cpp @@ -35,7 +35,7 @@ namespace Kyra { -Common::Error KyraEngine_HoF::saveGameState(int slot, const char *saveName, const Graphics::Surface *thumb) { +Common::Error KyraEngine_HoF::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) { const char *fileName = getSavegameFilename(slot); Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); @@ -64,7 +64,7 @@ Common::Error KyraEngine_HoF::saveGameState(int slot, const char *saveName, cons for (int i = 0; i < 25; ++i) out->writeSint16BE(_cauldronTable[i]); for (int i = 0; i < 20; ++i) - out->writeUint16BE(_hiddenItems[i]); + out->writeSint16BE(_hiddenItems[i]); for (int i = 0; i < 19; ++i) out->write(_conversationState[i], 14); out->write(_newSceneDlgState, 32); @@ -83,7 +83,7 @@ Common::Error KyraEngine_HoF::saveGameState(int slot, const char *saveName, cons out->writeSint16BE(_mainCharacter.y2); for (int i = 0; i < 30; ++i) { - out->writeUint16BE(_itemList[i].id); + out->writeSint16BE(_itemList[i].id); out->writeUint16BE(_itemList[i].sceneId); out->writeSint16BE(_itemList[i].x); out->writeByte(_itemList[i].y); @@ -183,7 +183,7 @@ Common::Error KyraEngine_HoF::loadGameState(int slot) { for (int i = 0; i < 25; ++i) _cauldronTable[i] = in.readSint16(); for (int i = 0; i < 20; ++i) - _hiddenItems[i] = in.readUint16(); + _hiddenItems[i] = in.readSint16(); if (header.originalSave) { assert(sizeof(_flagsTable) >= 0x41); @@ -222,7 +222,7 @@ Common::Error KyraEngine_HoF::loadGameState(int slot) { _mainCharacter.y2 = in.readSint16(); for (int i = 0; i < 30; ++i) { - _itemList[i].id = in.readUint16(); + _itemList[i].id = in.readSint16(); _itemList[i].sceneId = in.readUint16(); _itemList[i].x = in.readSint16(); _itemList[i].y = in.readByte(); diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index 1a61f9a9620..3e11d3dad3e 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -80,7 +80,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { } _marbleVaseItem = in->readSint16BE(); - _itemInHand = in->readByte(); + _itemInHand = (int8)in->readByte(); for (int i = 0; i < 4; ++i) _birthstoneGemTable[i] = in->readByte(); @@ -109,7 +109,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { for (int i = 0; i < _roomTableSize; ++i) { for (int item = 0; item < 12; ++item) { - _roomTable[i].itemsTable[item] = 0xFF; + _roomTable[i].itemsTable[item] = kItemNone; _roomTable[i].itemsXPos[item] = 0xFFFF; _roomTable[i].itemsYPos[item] = 0xFF; _roomTable[i].needInit[item] = 0; @@ -241,7 +241,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { return Common::kNoError; } -Common::Error KyraEngine_LoK::saveGameState(int slot, const char *saveName, const Graphics::Surface *thumb) { +Common::Error KyraEngine_LoK::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) { const char *fileName = getSavegameFilename(slot); if (shouldQuit()) diff --git a/engines/kyra/saveload_lol.cpp b/engines/kyra/saveload_lol.cpp index 480714e5c94..aee24957a0b 100644 --- a/engines/kyra/saveload_lol.cpp +++ b/engines/kyra/saveload_lol.cpp @@ -117,7 +117,7 @@ Common::Error LoLEngine::loadGameState(int slot) { _selectedCharacter = in.readSByte(); _currentLevel = in.readByte(); for (int i = 0; i < 48; i++) - _inventory[i] = in.readUint16BE(); + _inventory[i] = in.readSint16BE(); _inventoryCurItem = in.readSint16BE(); _itemInHand = in.readSint16BE(); _lastMouseRegion = in.readSint16BE(); @@ -243,7 +243,7 @@ Common::Error LoLEngine::loadGameState(int slot) { m->enable = in.readByte(); m->objectType = in.readByte(); m->attackerId = in.readUint16BE(); - m->item = in.readUint16BE(); + m->item = in.readSint16BE(); m->x = in.readUint16BE(); m->y = in.readUint16BE(); m->flyingHeight = in.readByte(); @@ -274,7 +274,7 @@ Common::Error LoLEngine::loadGameState(int slot) { return Common::kNoError; } -Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { +Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail) { const char *fileName = getSavegameFilename(slot); Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumbnail); @@ -340,7 +340,7 @@ Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Gra out->writeSByte(_selectedCharacter); out->writeByte(_currentLevel); for (int i = 0; i < 48; i++) - out->writeUint16BE(_inventory[i]); + out->writeSint16BE(_inventory[i]); out->writeSint16BE(_inventoryCurItem); out->writeSint16BE(_itemInHand); out->writeSint16BE(_lastMouseRegion); @@ -423,7 +423,7 @@ Common::Error LoLEngine::saveGameState(int slot, const char *saveName, const Gra out->writeByte(m->enable); out->writeByte(m->objectType); out->writeUint16BE(m->attackerId); - out->writeUint16BE(m->item); + out->writeSint16BE(m->item); out->writeUint16BE(m->x); out->writeUint16BE(m->y); out->writeByte(m->flyingHeight); diff --git a/engines/kyra/saveload_mr.cpp b/engines/kyra/saveload_mr.cpp index 737c83c33d4..80c9b2b83c8 100644 --- a/engines/kyra/saveload_mr.cpp +++ b/engines/kyra/saveload_mr.cpp @@ -32,7 +32,7 @@ namespace Kyra { -Common::Error KyraEngine_MR::saveGameState(int slot, const char *saveName, const Graphics::Surface *thumb) { +Common::Error KyraEngine_MR::saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumb) { const char *fileName = getSavegameFilename(slot); Common::OutSaveFile *out = openSaveForWriting(fileName, saveName, thumb); @@ -55,7 +55,7 @@ Common::Error KyraEngine_MR::saveGameState(int slot, const char *saveName, const out->write(_conversationState[i], 30); out->write(_newSceneDlgState, 40); for (int i = 0; i < 100; ++i) - out->writeUint16BE(_hiddenItems[i]); + out->writeSint16BE(_hiddenItems[i]); out->write(_scoreFlagTable, 26); out->writeUint16BE(_mainCharacter.sceneId); @@ -74,7 +74,7 @@ Common::Error KyraEngine_MR::saveGameState(int slot, const char *saveName, const out->writeSint16BE(_mainCharacter.y3); for (int i = 0; i < 50; ++i) { - out->writeUint16BE(_itemList[i].id); + out->writeSint16BE(_itemList[i].id); out->writeUint16BE(_itemList[i].sceneId); out->writeSint16BE(_itemList[i].x); out->writeSint16BE(_itemList[i].y); @@ -189,7 +189,7 @@ Common::Error KyraEngine_MR::loadGameState(int slot) { } for (int i = 0; i < 100; ++i) - _hiddenItems[i] = in.readUint16(); + _hiddenItems[i] = in.readSint16(); if (header.originalSave) in.read(_flagsTable, 69); @@ -216,7 +216,7 @@ Common::Error KyraEngine_MR::loadGameState(int slot) { _mainCharacter.y3 = in.readSint16(); for (int i = 0; i < 50; ++i) { - _itemList[i].id = in.readUint16(); + _itemList[i].id = in.readSint16(); _itemList[i].sceneId = in.readUint16(); _itemList[i].x = in.readSint16(); _itemList[i].y = in.readSint16(); diff --git a/engines/kyra/scene_hof.cpp b/engines/kyra/scene_hof.cpp index 4559554d779..79827361a3a 100644 --- a/engines/kyra/scene_hof.cpp +++ b/engines/kyra/scene_hof.cpp @@ -241,7 +241,7 @@ void KyraEngine_HoF::enterNewSceneUnk1(int facing, int unk1, int unk2) { } void KyraEngine_HoF::enterNewSceneUnk2(int unk1) { - _unk3 = -1; + _savedMouseState = -1; if (_flags.isTalkie) { if (_mainCharX == -1 && _mainCharY == -1 && _mainCharacter.sceneId != 61 && @@ -265,7 +265,7 @@ void KyraEngine_HoF::enterNewSceneUnk2(int unk1) { } _unk4 = 0; - _unk3 = -1; + _savedMouseState = -1; } int KyraEngine_HoF::trySceneChange(int *moveTable, int unk1, int updateChar) { @@ -339,16 +339,16 @@ int KyraEngine_HoF::checkSceneChange() { int facing = 0; int process = 0; - if (_screen->getLayer(charX, charY) == 1 && _unk3 == -6) { + if (_screen->getLayer(charX, charY) == 1 && _savedMouseState == -6) { facing = 0; process = 1; - } else if (charX >= 316 && _unk3 == -5) { + } else if (charX >= 316 && _savedMouseState == -5) { facing = 2; process = 1; - } else if (charY >= 142 && _unk3 == -4) { + } else if (charY >= 142 && _savedMouseState == -4) { facing = 4; process = 1; - } else if (charX <= 4 && _unk3 == -3) { + } else if (charX <= 4 && _savedMouseState == -3) { facing = 6; process = 1; } diff --git a/engines/kyra/scene_lok.cpp b/engines/kyra/scene_lok.cpp index f71c3bd7566..f7ada5d623c 100644 --- a/engines/kyra/scene_lok.cpp +++ b/engines/kyra/scene_lok.cpp @@ -824,13 +824,14 @@ void KyraEngine_LoK::initSceneScreen(int brandonAlive) { _emc->run(&_scriptClick); setTextFadeTimerCountdown(-1); + if (_currentCharacter->sceneId == 210) { - if (_itemInHand != -1) + if (_itemInHand != kItemNone) magicOutMouseItem(2, -1); _screen->hideMouse(); for (int i = 0; i < 10; ++i) { - if (_currentCharacter->inventoryItems[i] != 0xFF) + if (_currentCharacter->inventoryItems[i] != kItemNone) magicOutMouseItem(2, i); } _screen->showMouse(); diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index bf3320486a7..e070b91a44e 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -1618,7 +1618,7 @@ void LoLEngine::generateBlockDrawingBuffer() { _sceneDrawVarLeft = _dscBlockMap[_currentDirection + 8]; /******************************************* - * _visibleBlocks map * + * _visibleBlocks map * * * * | | | | | | * * 00 | 01 | 02 | 03 | 04 | 05 | 06 * diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index bd0a1fe5444..f1ea79f49bd 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -176,8 +176,8 @@ void KyraEngine_MR::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 setNextIdleAnimTimer(); if (_itemInHand < 0) { - _itemInHand = -1; - _mouseState = -1; + _itemInHand = kItemNone; + _mouseState = kItemNone; _screen->setMouseCursor(0, 0, _gameShapes[0]); } @@ -287,7 +287,7 @@ void KyraEngine_MR::enterNewSceneUnk1(int facing, int unk1, int unk2) { } void KyraEngine_MR::enterNewSceneUnk2(int unk1) { - _unk3 = -1; + _savedMouseState = -1; if (_mainCharX == -1 && _mainCharY == -1 && !unk1) { _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; updateCharacterAnim(0); @@ -300,7 +300,7 @@ void KyraEngine_MR::enterNewSceneUnk2(int unk1) { } _unk4 = 0; - _unk3 = -1; + _savedMouseState = -1; } void KyraEngine_MR::unloadScene() { @@ -556,8 +556,8 @@ void KyraEngine_MR::initSceneAnims(int unk1) { for (int i = 0; i < 50; ++i) { obj = &_animObjects[i+17]; - const Item &item = _itemList[i]; - if (item.id != 0xFFFF && item.sceneId == _mainCharacter.sceneId) { + const ItemDefinition &item = _itemList[i]; + if (item.id != kItemNone && item.sceneId == _mainCharacter.sceneId) { obj->xPos1 = item.x; obj->yPos1 = item.y; animSetupPaletteEntry(obj); @@ -696,16 +696,16 @@ int KyraEngine_MR::checkSceneChange() { int facing = 0; int process = 0; - if (_screen->getLayer(charX, charY) == 1 && _unk3 == -7) { + if (_screen->getLayer(charX, charY) == 1 && _savedMouseState == -7) { facing = 0; process = 1; - } else if (charX >= 316 && _unk3 == -6) { + } else if (charX >= 316 && _savedMouseState == -6) { facing = 2; process = 1; - } else if (charY >= 186 && _unk3 == -5) { + } else if (charY >= 186 && _savedMouseState == -5) { facing = 4; process = 1; - } else if (charX <= 4 && _unk3 == -4) { + } else if (charX <= 4 && _savedMouseState == -4) { facing = 6; process = 1; } @@ -742,7 +742,7 @@ int KyraEngine_MR::checkSceneChange() { return 1; } int KyraEngine_MR::runSceneScript1(int x, int y) { - if (y > 187 && _unk3 > -4) + if (y > 187 && _savedMouseState > -4) return 0; if (_deathHandler >= 0) return 0; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index e09cc8123ca..8b0a87f0c8e 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -787,7 +787,7 @@ void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPag } if (y2 < 0) { - if (y2 <= -h ) + if (y2 <= -h) return; h += y2; y1 -= y2; @@ -1084,7 +1084,7 @@ void Screen::setTextColor(const uint8 *cmap, int a, int b) { bool Screen::loadFont(FontId fontId, const char *filename) { if (fontId == FID_SJIS_FNT) { - warning("Trying to replace system SJIS font."); + warning("Trying to replace system SJIS font"); return true; } @@ -3313,7 +3313,7 @@ SJISFont::SJISFont(Screen *s, Graphics::FontSJIS *font, const uint8 invisColor, : _colorMap(0), _font(font), _invisColor(invisColor), _is16Color(is16Color), _screen(s) { assert(_font); - _font->enableOutline(outlineSize); + _font->setDrawingMode(outlineSize ? Graphics::FontSJIS::kOutlineMode : Graphics::FontSJIS::kDefaultMode); _sjisWidth = _font->getMaxFontWidth() >> 1; _fontHeight = _font->getFontHeight() >> 1; @@ -3345,9 +3345,9 @@ void SJISFont::setColorMap(const uint8 *src) { if (!_is16Color) { if (_colorMap[0] == _invisColor) - _font->enableOutline(false); + _font->setDrawingMode(Graphics::FontSJIS::kDefaultMode); else - _font->enableOutline(true); + _font->setDrawingMode(Graphics::FontSJIS::kOutlineMode); } } diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 654b7da6b73..e35b9b37b22 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -423,6 +423,7 @@ public: virtual void setScreenDim(int dim) = 0; virtual const ScreenDim *getScreenDim(int dim) = 0; + virtual int screenDimTableCount() const = 0; const ScreenDim *_curDim; diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h index 1c17a424b35..5117716ac03 100644 --- a/engines/kyra/screen_hof.h +++ b/engines/kyra/screen_hof.h @@ -39,6 +39,7 @@ public: void setScreenDim(int dim); const ScreenDim *getScreenDim(int dim); + int screenDimTableCount() const { return _screenDimTableCount; } // sequence player void generateGrayOverlay(const Palette &pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); diff --git a/engines/kyra/screen_lok.h b/engines/kyra/screen_lok.h index 2a5ef7e12ec..0d30c35bfd7 100644 --- a/engines/kyra/screen_lok.h +++ b/engines/kyra/screen_lok.h @@ -43,6 +43,7 @@ public: void setScreenDim(int dim); const ScreenDim *getScreenDim(int dim); + int screenDimTableCount() const { return _screenDimTableCount; } void setTextColorMap(const uint8 *cmap); diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index be3dbe5b21d..e8ec7bc180b 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -637,7 +637,7 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in d++; } - for (int ii = (i & 1) ^ 1; ii < ibw_2; ii += 2 ) { + for (int ii = (i & 1) ^ 1; ii < ibw_2; ii += 2) { *d = *s; d += 2; s += 2; diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 52e66df1ec2..9f4d751d0cc 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -43,8 +43,9 @@ public: void setScreenDim(int dim); const ScreenDim *getScreenDim(int dim); - int curDimIndex() { return _curDimIndex; } + int curDimIndex() const { return _curDimIndex; } void modifyScreenDim(int dim, int x, int y, int w, int h); + int screenDimTableCount() const { return _screenDimTableCount; } void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) GCC_PRINTF(2, 8); void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...) GCC_PRINTF(2, 9); diff --git a/engines/kyra/screen_mr.h b/engines/kyra/screen_mr.h index 4107003b122..c02fc4bfb26 100644 --- a/engines/kyra/screen_mr.h +++ b/engines/kyra/screen_mr.h @@ -39,6 +39,7 @@ public: void setScreenDim(int dim); const ScreenDim *getScreenDim(int dim); + int screenDimTableCount() const { return _screenDimTableCount; } int getLayer(int x, int y); diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index 216bf07f6f3..9c224d15628 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -64,9 +64,9 @@ uint8 *Screen_v2::generateOverlay(const Palette &pal, uint8 *buffer, int opColor } for (int i = 1; i != 256; ++i) { - const byte curR = pal[i * 3 + 0] - ((((pal[i * 3 + 0] - opR) * weight) >> 7) & 0x7F); - const byte curG = pal[i * 3 + 1] - ((((pal[i * 3 + 1] - opG) * weight) >> 7) & 0x7F); - const byte curB = pal[i * 3 + 2] - ((((pal[i * 3 + 2] - opB) * weight) >> 7) & 0x7F); + const byte curR = pal[i * 3 + 0] - (((pal[i * 3 + 0] - opR) * weight) >> 7); + const byte curG = pal[i * 3 + 1] - (((pal[i * 3 + 1] - opG) * weight) >> 7); + const byte curB = pal[i * 3 + 2] - (((pal[i * 3 + 2] - opB) * weight) >> 7); uint16 idxSum = _use16ColorMode ? 0xFFFF : 0x7FFF; byte index = opColor; @@ -187,16 +187,22 @@ uint8 *Screen_v2::getPtrToShape(uint8 *shpFile, int shape) { } int Screen_v2::getShapeScaledWidth(const uint8 *shpFile, int scale) { + if (!shpFile) + return 0; int width = READ_LE_UINT16(shpFile+3); return (width * scale) >> 8; } int Screen_v2::getShapeScaledHeight(const uint8 *shpFile, int scale) { + if (!shpFile) + return 0; int height = shpFile[2]; return (height * scale) >> 8; } uint16 Screen_v2::getShapeSize(const uint8 *shp) { + if (!shp) + return 0; return READ_LE_UINT16(shp+6); } diff --git a/engines/kyra/script_hof.cpp b/engines/kyra/script_hof.cpp index f30f5787e7f..d57bb7efc5f 100644 --- a/engines/kyra/script_hof.cpp +++ b/engines/kyra/script_hof.cpp @@ -410,7 +410,7 @@ int KyraEngine_HoF::o2_countItemsInScene(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_countItemsInScene(%p) (%d)", (const void *)script, stackPos(0)); int count = 0; for (int i = 0; i < 30; ++i) { - if (_itemList[i].sceneId == stackPos(0) && _itemList[i].id != 0xFFFF) + if (_itemList[i].sceneId == stackPos(0) && _itemList[i].id != kItemNone) ++count; } return count; @@ -1039,7 +1039,7 @@ int KyraEngine_HoF::o2_setColorCodeValue(EMCState *script) { int KyraEngine_HoF::o2_countItemInstances(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_HoF::o2_countItemInstances(%p) (%d)", (const void *)script, stackPos(0)); - uint16 item = stackPos(0); + Item item = stackPos(0); int count = 0; for (int i = 0; i < 20; ++i) { @@ -1047,7 +1047,7 @@ int KyraEngine_HoF::o2_countItemInstances(EMCState *script) { ++count; } - if (_itemInHand == int16(item)) + if (_itemInHand == item) ++count; for (int i = 0; i < 30; ++i) { @@ -1075,7 +1075,7 @@ int KyraEngine_HoF::o2_removeItemFromScene(EMCState *script) { const uint16 item = stackPos(1); for (int i = 0; i < 30; ++i) { if (_itemList[i].sceneId == scene && _itemList[i].id == item) - _itemList[i].id = 0xFFFF; + _itemList[i].id = kItemNone; } return 0; } diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 1b4a11f793b..a2bad8035ea 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -37,6 +37,7 @@ #include "kyra/sound.h" namespace Kyra { + int KyraEngine_LoK::o1_magicInMouseItem(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); magicInMouseItem(stackPos(0), stackPos(1), -1); @@ -203,9 +204,7 @@ int KyraEngine_LoK::o1_getElapsedSeconds(EMCState *script) { int KyraEngine_LoK::o1_mouseIsPointer(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_mouseIsPointer(%p) ()", (const void *)script); - if (_itemInHand == -1) - return 1; - return 0; + return (_itemInHand == kItemNone); } int KyraEngine_LoK::o1_runSceneAnimUntilDone(EMCState *script) { diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 1034e86d4e6..33fa16a22c9 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -267,6 +267,12 @@ int LoLEngine::olol_setItemProperty(EMCState *script) { tmp->nameStringId = stackPos(1); tmp->shpIndex = stackPos(2); tmp->type = stackPos(3); + + // WORKAROUND for unpatched early floppy versions. + // The Vaelan's cube should not be able to be equipped in a weapon slot. + if (stackPos(0) == 264 && tmp->type == 5) + tmp->type = 0; + tmp->itemScriptFunc = stackPos(4); tmp->might = stackPos(5); tmp->skill = stackPos(6); @@ -1065,6 +1071,7 @@ int LoLEngine::olol_createHandItem(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_createHandItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); if (_itemInHand) return 0; + setHandItem(makeItem(stackPos(0), stackPos(1), stackPos(2))); return 1; } diff --git a/engines/kyra/script_mr.cpp b/engines/kyra/script_mr.cpp index ae125b5b994..a9637a63781 100644 --- a/engines/kyra/script_mr.cpp +++ b/engines/kyra/script_mr.cpp @@ -216,7 +216,7 @@ int KyraEngine_MR::o3_removeInventoryItemInstances(EMCState *script) { const int item = stackPos(0); for (int i = 0; i < 10; ++i) { if (_mainCharacter.inventory[i] == item) - _mainCharacter.inventory[i] = 0xFFFF; + _mainCharacter.inventory[i] = kItemNone; } return 0; } @@ -293,7 +293,7 @@ int KyraEngine_MR::o3_updateScore(EMCState *script) { int KyraEngine_MR::o3_makeSecondChanceSave(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_makeSecondChanceSave(%p) ()", (const void *)script); - saveGameState(999, "Autosave", 0); + saveGameStateIntern(999, "Autosave", 0); return 0; } @@ -594,7 +594,7 @@ int KyraEngine_MR::o3_updateConversations(EMCState *script) { int KyraEngine_MR::o3_removeItemSlot(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_MR::o3_removeItemSlot(%p) (%d)", (const void *)script, stackPos(0)); deleteItemAnimEntry(stackPos(0)); - _itemList[stackPos(0)].id = 0xFFFF; + _itemList[stackPos(0)].id = kItemNone; return 1; } @@ -642,7 +642,7 @@ int KyraEngine_MR::o3_removeItemInstances(EMCState *script) { for (int i = 0; i < 10; ++i) { if (_mainCharacter.inventory[i] == item) { - _mainCharacter.inventory[i] = 0xFFFF; + _mainCharacter.inventory[i] = kItemNone; ++deleted; } } @@ -654,7 +654,7 @@ int KyraEngine_MR::o3_removeItemInstances(EMCState *script) { for (int i = 0; i < 50; ++i) { if (_itemList[i].id == item) { - _itemList[i].id = 0xFFFF; + _itemList[i].id = kItemNone; ++deleted; } } diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 907c5ee7bda..30291c67dbd 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -259,7 +259,7 @@ int TIMInterpreter::exec(TIM *tim, bool loop) { if (cur.ip) { cur.ip += cur.ip[0]; cur.lastTime = cur.nextTime; - cur.nextTime += (cur.ip[1] ) * _vm->tickLength(); + cur.nextTime += cur.ip[1] * _vm->tickLength(); } } } @@ -946,7 +946,7 @@ int TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, i } } - if (wsaFlags & 7) + if (wsa && (wsaFlags & 7)) wsa->displayFrame(0, 0, x, y, 0, 0, 0); if (wsaFlags & 3) { diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp index 01f058c383f..17e882398ed 100644 --- a/engines/kyra/script_v2.cpp +++ b/engines/kyra/script_v2.cpp @@ -69,7 +69,7 @@ int KyraEngine_v2::o2_trySceneChange(EMCState *script) { if (success) { _emc->init(script, script->dataPtr); _unk4 = 0; - _unk3 = -1; + _savedMouseState = -1; _unk5 = 1; return 0; } else { diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 0a3e13bb269..e92866490bb 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -2002,7 +2002,7 @@ void KyraEngine_HoF::seq_processText() { outputStr[linePos] = *srcStr; srcStr++; } - outputStr[linePos] = 0; + outputStr[linePos] = 0; if (*srcStr == 0x0d) srcStr++; @@ -2130,7 +2130,7 @@ void KyraEngine_HoF::seq_cmpFadeFrame(const char *cmpFile) { _screen->cmpFadeFrameStep(4, 320, 200, 0, 0, 2, 320, 200, 0, 0, 320, 200, 6); _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); _screen->updateScreen(); - delayUntil(endtime); + delayUntil(endtime); } _screen->copyPage(4, 0); diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index dc1a0f4d156..e8ea7a9dcba 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -81,6 +81,13 @@ int LoLEngine::processPrologue() { } switch (selection) { + case -1: + // This is sent on RTL for example, if we would not have any + // special case for this the default path would call quitGame + // and thus make the next game launched from the launcher + // quit instantly. + break; + case 0: // New game processSelection = 0; break; @@ -397,7 +404,8 @@ void LoLEngine::kingSelectionIntro() { _screen->fprintStringIntro("%s", 8, y + i * 10, 0x32, 0x00, 0x9C, 0x20, _tim->getCTableEntry(57 + i)); } - _sound->voicePlay("KING01", &_speechHandle); + if (_flags.isTalkie) + _sound->voicePlay("KING01", &_speechHandle); int index = 4; while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && !skipFlag()) { @@ -441,7 +449,8 @@ void LoLEngine::kingSelectionReminder() { _screen->fprintStringIntro("%s", 8, y + 10, 0x32, 0x00, 0x9C, 0x20, _tim->getCTableEntry(63)); } - _sound->voicePlay("KING02", &_speechHandle); + if (_flags.isTalkie) + _sound->voicePlay("KING02", &_speechHandle); int index = 0; while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelection == -1 && !shouldQuit() && index < 15) { @@ -468,7 +477,8 @@ void LoLEngine::kingSelectionReminder() { } void LoLEngine::kingSelectionOutro() { - _sound->voicePlay("KING03", &_speechHandle); + if (_flags.isTalkie) + _sound->voicePlay("KING03", &_speechHandle); int index = 0; while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && !shouldQuit() && !skipFlag()) { @@ -627,7 +637,8 @@ void LoLEngine::selectionCharInfoIntro(char *file) { if (speechEnabled() && !_sound->isVoicePresent(file)) break; - _sound->voicePlay(file, &_speechHandle); + if (_flags.isTalkie) + _sound->voicePlay(file, &_speechHandle); int i = 0; while ((!speechEnabled() || (speechEnabled() && _sound->voiceIsPlaying(&_speechHandle))) && _charSelectionInfoResult == -1 && !shouldQuit()) { @@ -1424,7 +1435,7 @@ void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { if (monsterAnimFrame >= 8) _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1); - _screen->drawShape(page, monsterShape, monsterX, monsterY, 0, 0x104 | ((!isRightMonster | (monsterAnimFrame < 20)) ? 0 : 1), _outroShapeTable, 1, _outroMonsterScaleTableX[monsterAnimFrame], _outroMonsterScaleTableY[monsterAnimFrame]); + _screen->drawShape(page, monsterShape, monsterX, monsterY, 0, 0x104 | ((!isRightMonster || monsterAnimFrame < 20) ? 0 : 1), _outroShapeTable, 1, _outroMonsterScaleTableX[monsterAnimFrame], _outroMonsterScaleTableY[monsterAnimFrame]); if (monsterAnimFrame < 8) _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 22) ? 0 : 1); diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 3b0fbbed0a1..8b83796d46a 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -94,7 +94,7 @@ public: * @param track track number * @return true if available, false otherwise */ - virtual bool hasSoundFile(uint file) { return (fileListEntry(file) != 0); } + virtual bool hasSoundFile(uint file) const { return (fileListEntry(file) != 0); } /** * Load a specifc sound file for use of diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp index 8458d751de3..a45972ece7d 100644 --- a/engines/kyra/sound_adlib.cpp +++ b/engines/kyra/sound_adlib.cpp @@ -2304,7 +2304,7 @@ void SoundAdLibPC::haltTrack() { //_vm->_system->delayMillis(3 * 60); } -bool SoundAdLibPC::isPlaying() { +bool SoundAdLibPC::isPlaying() const { return _driver->callback(7, int(0)) != 0; } diff --git a/engines/kyra/sound_adlib.h b/engines/kyra/sound_adlib.h index 0607e1dd7a9..aaca1b9138d 100644 --- a/engines/kyra/sound_adlib.h +++ b/engines/kyra/sound_adlib.h @@ -76,7 +76,7 @@ public: void playTrack(uint8 track); void haltTrack(); - bool isPlaying(); + bool isPlaying() const; void playSoundEffect(uint8 track); diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index 5b5a548f4a0..150bafbef3a 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -158,7 +158,6 @@ AUDStream::AUDStream(Common::SeekableReadStream *stream) : _stream(stream), _end _outBufferOffset(0), _outBufferSize(0), _inBuffer(0), _inBufferSize(0) { _rate = _stream->readUint16LE(); - _length = Audio::Timestamp(0, _rate); _totalSize = _stream->readUint32LE(); // TODO?: add checks @@ -167,6 +166,9 @@ AUDStream::AUDStream(Common::SeekableReadStream *stream) : _stream(stream), _end _streamStart = stream->pos(); + debugC(5, kDebugLevelSound, "AUD Info: rate: %d, totalSize: %d, flags: %d, type: %d, streamStart: %d", _rate, _totalSize, flags, type, _streamStart); + + _length = Audio::Timestamp(0, _rate); for (uint32 i = 0; i < _totalSize;) { uint16 size = _stream->readUint16LE(); uint16 outSize = _stream->readUint16LE(); @@ -460,6 +462,7 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer:: Common::strlcpy(use->filename, filename, sizeof(use->filename)); use->priority = priority; + debugC(5, kDebugLevelSound, "playSound: \"%s\"", use->filename); Audio::SeekableAudioStream *audioStream = _supportedCodecs[usedCodec].streamFunc(stream, DisposeAfterUse::YES); if (!audioStream) { warning("Couldn't create audio stream for file '%s'", filename); diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h index f8738bc7917..bc1c2be1e23 100644 --- a/engines/kyra/sound_intern.h +++ b/engines/kyra/sound_intern.h @@ -68,7 +68,7 @@ public: void playTrack(uint8 track); void haltTrack(); - bool isPlaying(); + bool isPlaying() const; void playSoundEffect(uint8 track); void stopAllSoundEffects(); diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp index 57da51ab5ae..8982c1cca4b 100644 --- a/engines/kyra/sound_midi.cpp +++ b/engines/kyra/sound_midi.cpp @@ -134,10 +134,14 @@ MidiOutput::MidiOutput(OSystem *system, MidiDriver *output, bool isMT32, bool de static const byte sysEx2[] = { 3, 4, 3, 4, 3, 4, 3, 4, 4 }; static const byte sysEx3[] = { 0, 3, 2 }; - sendSysEx(0x7F, 0x00, 0x00, sysEx1, 1); - sendSysEx(0x10, 0x00, 0x0D, sysEx1, 9); - sendSysEx(0x10, 0x00, 0x04, sysEx2, 9); - sendSysEx(0x10, 0x00, 0x01, sysEx3, 3); + if (_isMT32) { + sendSysEx(0x7F, 0x00, 0x00, sysEx1, 1); + sendSysEx(0x10, 0x00, 0x0D, sysEx1, 9); + sendSysEx(0x10, 0x00, 0x04, sysEx2, 9); + sendSysEx(0x10, 0x00, 0x01, sysEx3, 3); + } else { + _output->sendGMReset(); + } memset(_channels, 0, sizeof(_channels)); for (int i = 0; i < 16; ++i) { @@ -679,7 +683,7 @@ void SoundMidiPC::haltTrack() { _output->deinitSource(0); } -bool SoundMidiPC::isPlaying() { +bool SoundMidiPC::isPlaying() const { Common::StackLock lock(_mutex); return _music->isPlaying(); diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 16004159ab7..a674f9efb84 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -83,11 +83,11 @@ void SoundTowns::playTrack(uint8 track) { return; track -= 2; - const int32 *const tTable = (const int32 *const)cdaData(); + const int32 * const tTable = (const int32 *)cdaData(); int tTableIndex = 3 * track; - int trackNum = (int) READ_LE_UINT32(&tTable[tTableIndex + 2]); - int32 loop = (int32) READ_LE_UINT32(&tTable[tTableIndex + 1]); + int trackNum = (int)READ_LE_UINT32(&tTable[tTableIndex + 2]); + int32 loop = (int32)READ_LE_UINT32(&tTable[tTableIndex + 1]); if (track == _lastTrack && _musicEnabled) return; @@ -530,7 +530,7 @@ void SoundTownsPC98_v2::playTrack(uint8 track) { if (track == _lastTrack && _musicEnabled) return; - const uint16 *const cdaTracks = (const uint16 *const) cdaData(); + const uint16 * const cdaTracks = (const uint16 *)cdaData(); int trackNum = -1; if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { @@ -587,7 +587,7 @@ void SoundTownsPC98_v2::beginFadeOut() { } int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8, bool) { - //static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; + static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; static const char patternHOF[] = "%s.PCM"; static const char patternLOL[] = "%s.VOC"; @@ -608,7 +608,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, if (!src) return 0; - //uint16 sfxRate = rates[READ_LE_UINT16(src)]; + uint16 sfxRate = rates[READ_LE_UINT16(src)]; src += 2; bool compressed = (READ_LE_UINT16(src) & 1) ? true : false; src += 2; @@ -648,8 +648,7 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, sfx[i] = cmd; } - _currentSFX = Audio::makeRawStream(sfx, outsize, 11025, - Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN); + _currentSFX = Audio::makeRawStream(sfx, outsize, sfxRate * 10, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN); _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h], _currentSFX); if (handle) *handle = _soundChannels[h]; diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp index 4fa12fd6878..52689869c66 100644 --- a/engines/kyra/sprites.cpp +++ b/engines/kyra/sprites.cpp @@ -71,7 +71,7 @@ void Sprites::setupSceneAnims() { if (_anims[i].script != 0) { data = _anims[i].script; - assert( READ_LE_UINT16(data) == 0xFF86 ); + assert(READ_LE_UINT16(data) == 0xFF86); data += 4; _anims[i].disable = READ_LE_UINT16(data) != 0; @@ -509,7 +509,7 @@ void Sprites::loadDat(const char *filename, SceneExits &exits) { } void Sprites::freeSceneShapes() { - for (int i = 0; i < ARRAYSIZE(_sceneShapes); i++ ) { + for (int i = 0; i < ARRAYSIZE(_sceneShapes); i++) { delete[] _sceneShapes[i]; _sceneShapes[i] = 0; } diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index 3b63618d6dd..6245ecdd1f7 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -350,7 +350,7 @@ void LoLEngine::monsterDropItems(MonsterInPlay *monster) { } } -void LoLEngine::removeAssignedObjectFromBlock(LevelBlockProperty *l, int id) { +void LoLEngine::removeAssignedObjectFromBlock(LevelBlockProperty *l, uint16 id) { uint16 *blockItemIndex = &l->assignedObjects; ItemInPlay *i = 0; @@ -367,7 +367,7 @@ void LoLEngine::removeAssignedObjectFromBlock(LevelBlockProperty *l, int id) { } } -void LoLEngine::removeDrawObjectFromBlock(LevelBlockProperty *l, int id) { +void LoLEngine::removeDrawObjectFromBlock(LevelBlockProperty *l, uint16 id) { uint16 *blockItemIndex = &l->drawObjects; ItemInPlay *i = 0; @@ -384,7 +384,7 @@ void LoLEngine::removeDrawObjectFromBlock(LevelBlockProperty *l, int id) { } } -void LoLEngine::assignMonsterToBlock(uint16 *assignedBlockObjects, int id) { +void LoLEngine::assignMonsterToBlock(uint16 *assignedBlockObjects, uint16 id) { ItemInPlay *t = findObject(id); t->nextAssignedObject = *assignedBlockObjects; *assignedBlockObjects = id; @@ -901,6 +901,9 @@ void LoLEngine::calcSpriteRelPosition(uint16 x1, uint16 y1, int &x2, int &y2, ui } void LoLEngine::drawDoor(uint8 *shape, uint8 *doorPalette, int index, int unk2, int w, int h, int flags) { + if (!shape) + return; + uint8 c = _dscDoor1[(_currentDirection << 5) + unk2]; int r = (c / 5) + 5 * _dscDimMap[index]; uint16 d = _dscShapeOvlIndex[r]; diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 4b71b1d69de..edfa61e5b40 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -42,7 +42,7 @@ namespace Kyra { -#define RESFILE_VERSION 72 +#define RESFILE_VERSION 73 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -878,7 +878,7 @@ void KyraEngine_LoK::loadItems() { _shapes[323] = 0; - for (shape = 1; shape < 6; shape++ ) + for (shape = 1; shape < 6; shape++) _shapes[323 + shape] = _screen->encodeShape((shape - 1) * 32, 0, 32, 17, 0); for (shape = 330; shape <= 334; shape++) @@ -912,16 +912,7 @@ void KyraEngine_LoK::loadItems() { _shapes[216 + i] = _screen->encodeShape( (i % 20) * 16, i/20 * 16, 16, 16, 0); } - uint32 size; - uint8 *fileData = _res->fileData("_ITEM_HT.DAT", &size); - assert(fileData); - - for (int i = 0; i < 107; i++) { - _itemTable[i].height = fileData[i]; - _itemTable[i].unk1 = _itemTable[i].unk2 = 0; - } - - delete[] fileData; + _res->loadFileToBuf("_ITEM_HT.DAT", &_itemHtDat, sizeof(_itemHtDat)); } void KyraEngine_LoK::loadButtonShapes() { @@ -1866,9 +1857,9 @@ const uint8 KyraEngine_HoF::_cauldronStateTable[] = { 3, 3, 3, 3, 3, 3, 3 }; -const int16 KyraEngine_HoF::_flaskTable[] = { +const Item KyraEngine_HoF::_flaskTable[] = { 0x19, 0x14, 0x15, 0x16, 0x17, 0x18, 0x34, - 0x1B, 0x39, 0x1A, 0x3A, 0x4D, 0x72, -1 + 0x1B, 0x39, 0x1A, 0x3A, 0x4D, 0x72, kItemNone }; const uint8 KyraEngine_HoF::_rainbowRoomData[] = { @@ -1964,10 +1955,10 @@ const uint8 KyraEngine_MR::_inventoryY[] = { 0xB2, 0xB2, 0xB2, 0xB2, 0xB2 }; -const uint8 KyraEngine_MR::_trashItemList[] = { +const Item KyraEngine_MR::_trashItemList[] = { 0x1E, 0x1D, 0x1C, 0x1F, 0x0F, 0x05, 0x04, 0x00, 0x03, 0x22, 0x0B, 0x20, 0x21, 0x10, 0x11, 0x3A, - 0x39, 0x40, 0x3E, 0x3D, 0x3C, 0x3F, 0xFF + 0x39, 0x40, 0x3E, 0x3D, 0x3C, 0x3F, kItemNone }; const uint8 KyraEngine_MR::_itemStringPickUp[] = { diff --git a/engines/kyra/text_hof.cpp b/engines/kyra/text_hof.cpp index 9d20cdd51a7..4c292b70db3 100644 --- a/engines/kyra/text_hof.cpp +++ b/engines/kyra/text_hof.cpp @@ -544,7 +544,7 @@ void KyraEngine_HoF::processDialogue(int dlgOffset, int vocH, int csEntry) { } objectChat((const char *)_unkBuf500Bytes, 0, vocHi, vocLo); } else { - if (activeTimSequence != nextTimSequence ) { + if (activeTimSequence != nextTimSequence) { if (activeTimSequence > -1) { deinitTalkObject(activeTimSequence); activeTimSequence = -1; diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index 7f9531507c4..c5341cd8a63 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -46,7 +46,9 @@ TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm _currentLine = new char[85]; memset(_currentLine, 0, 85); - for (int i = 0; i < 14; i++){ + _textDimData = new TextDimData[_screen->screenDimTableCount()]; + + for (int i = 0; i < _screen->screenDimTableCount(); i++){ const ScreenDim *d = _screen->getScreenDim(i); _textDimData[i].color1 = d->unk8; _textDimData[i].color2 = d->unkA; @@ -59,6 +61,7 @@ TextDisplayer_LoL::~TextDisplayer_LoL() { delete[] _buffer; delete[] _dialogueBuffer; delete[] _currentLine; + delete[] _textDimData; } void TextDisplayer_LoL::setupField(bool mode) { diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h index 488be17cfff..1e5bc8884e9 100644 --- a/engines/kyra/text_lol.h +++ b/engines/kyra/text_lol.h @@ -90,7 +90,7 @@ private: uint8 line; }; - TextDimData _textDimData[14]; + TextDimData *_textDimData; }; } // End of namespace Kyra diff --git a/engines/kyra/timer_mr.cpp b/engines/kyra/timer_mr.cpp index 48fa55519c3..0d89decf5a7 100644 --- a/engines/kyra/timer_mr.cpp +++ b/engines/kyra/timer_mr.cpp @@ -60,7 +60,7 @@ void KyraEngine_MR::timerRunSceneScript7(int arg) { void KyraEngine_MR::timerFleaDeath(int arg) { _timer->setCountdown(4, 5400); - saveGameState(999, "Autosave", 0); + saveGameStateIntern(999, "Autosave", 0); _screen->hideMouse(); _timer->disable(4); runAnimationScript("FLEADTH1.EMC", 0, 0, 1, 1); diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp new file mode 100644 index 00000000000..88973c4b0b4 --- /dev/null +++ b/engines/lastexpress/data/animation.cpp @@ -0,0 +1,300 @@ +/* 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$ + * + */ + +// Based on Deniz Oezmen's code: http://oezmen.eu/ + +#include "lastexpress/data/animation.h" + +#include "lastexpress/data/sequence.h" +#include "lastexpress/data/snd.h" + +#include "lastexpress/debug.h" + +#include "common/events.h" +#include "engines/engine.h" + +namespace LastExpress { + +Animation::Animation() : _stream(NULL), _currentChunk(NULL), _overlay(NULL), _background1(NULL), _background2(NULL), _backgroundCurrent(0), _audio(NULL), _startTime(0), _changed(false), _flag(0) { +} + +Animation::~Animation() { + reset(); +} + +void Animation::reset() { + delete _overlay; + _overlay = NULL; + delete _background1; + _background1 = NULL; + delete _background2; + _background2 = NULL; + delete _audio; + _audio = NULL; + + _backgroundCurrent = 0; + _chunks.clear(); + + _currentChunk = NULL; + + delete _stream; +} + +bool Animation::load(Common::SeekableReadStream *stream, int flag) { + if (!stream) + return false; + + reset(); + + // Keep stream for later decoding of animation + _stream = stream; + + // Read header to get the number of chunks + uint32 numChunks = _stream->readUint32LE(); + debugC(3, kLastExpressDebugGraphics, "Number of chunks in NIS file: %d", numChunks); + + // Check if there is enough data + if (_stream->size() - _stream->pos() < (signed)(numChunks * sizeof(Chunk))) { + debugC(2, kLastExpressDebugGraphics, "NIS file seems to be corrupted!"); + return false; + } + + // Read all the chunks + for (uint32 i = 0; i < numChunks; ++i) { + Chunk chunk; + chunk.type = (ChunkType)_stream->readUint16LE(); + chunk.frame = _stream->readUint16LE(); + chunk.size = _stream->readUint32LE(); + + _chunks.push_back(chunk); + + debugC(9, kLastExpressDebugGraphics, "Chunk Entry: type 0x%.4x, frame=%d, size=%d", chunk.type, chunk.frame, chunk.size); + } + _currentChunk = _chunks.begin(); + _changed = false; + _startTime = g_engine->_system->getMillis(); + + return true; +} + +bool Animation::process() { + if (!_currentChunk) + error("Animation::process - internal error: the current chunk iterator is invalid!"); + + if (_stream == NULL || _chunks.size() == 0) + error("Trying to show an animation before loading data"); + + // TODO: substract the time paused by the GUI + uint32 currentFrame = (uint32)(((float)(g_engine->_system->getMillis() - _startTime)) / 33.33f); + + // Process all chunks until the current frame + while (!_changed && currentFrame > _currentChunk->frame && !hasEnded()) { + switch(_currentChunk->type) { + //TODO: some info chunks are probably subtitle/sync related + case kChunkTypeUnknown1: + case kChunkTypeUnknown2: + case kChunkTypeUnknown5: + debugC(9, kLastExpressDebugGraphics | kLastExpressDebugUnknown, " info chunk: type 0x%.4x (size %d)", _currentChunk->type, _currentChunk->size); + assert (_currentChunk->frame == 0); + //TODO: _currentChunk->size? + break; + + case kChunkTypeAudioInfo: + debugC(9, kLastExpressDebugGraphics, " audio info: %d blocks", _currentChunk->size); + assert (_currentChunk->frame == 0); + //TODO: save the size? + _audio = new AppendableSound(); + break; + + case kChunkTypeUnknown4: + debugC(9, kLastExpressDebugGraphics | kLastExpressDebugUnknown, " info block 4"); + assert (_currentChunk->frame == 0 && _currentChunk->size == 0); + //TODO unknown type of chunk + break; + + case kChunkTypeBackground1: + debugC(9, kLastExpressDebugGraphics, " background frame 1 (%d bytes, frame %d)", _currentChunk->size, _currentChunk->frame); + delete _background1; + _background1 = processChunkFrame(_stream, *_currentChunk); + break; + + case kChunkTypeSelectBackground1: + debugC(9, kLastExpressDebugGraphics, " select background 1"); + assert (_currentChunk->frame == 0 && _currentChunk->size == 0); + _backgroundCurrent = 1; + break; + + case kChunkTypeBackground2: + debugC(9, kLastExpressDebugGraphics, " background frame 2 (%d bytes, frame %d)", _currentChunk->size, _currentChunk->frame); + delete _background2; + _background2 = processChunkFrame(_stream, *_currentChunk); + break; + + case kChunkTypeSelectBackground2: + debugC(9, kLastExpressDebugGraphics, " select background 2"); + assert (_currentChunk->frame == 0 && _currentChunk->size == 0); + _backgroundCurrent = 2; + break; + + case kChunkTypeOverlay: + debugC(9, kLastExpressDebugGraphics, " overlay frame (%d bytes, frame %d)", _currentChunk->size, _currentChunk->frame); + delete _overlay; + _overlay = processChunkFrame(_stream, *_currentChunk); + break; + + case kChunkTypeUpdate: + case kChunkTypeUpdateTransition: + debugC(9, kLastExpressDebugGraphics, " update%s: frame %d", _currentChunk->type == 15 ? "" : " with transition", _currentChunk->frame); + assert (_currentChunk->size == 0); + _changed = true; + break; + + case kChunkTypeAudioData: + debugC(9, kLastExpressDebugGraphics, " audio (%d blocks, %d bytes, frame %d)", _currentChunk->size / _soundBlockSize, _currentChunk->size, _currentChunk->frame); + processChunkAudio(_stream, *_currentChunk); + + // Synchronize the audio by resetting the start time + if (_currentChunk->frame == 0) + _startTime = g_engine->_system->getMillis(); + break; + + case kChunkTypeAudioEnd: + debugC(9, kLastExpressDebugGraphics, " audio end: %d blocks", _currentChunk->frame); + assert (_currentChunk->size == 0); + _audio->finish(); + //TODO: we need to start the linked sound (.LNK) after the audio from the animation ends + break; + + default: + error(" UNKNOWN chunk type=%x frame=%d size=%d", _currentChunk->type, _currentChunk->frame, _currentChunk->size); + break; + } + _currentChunk++; + } + + return true; +} + +bool Animation::hasEnded() { + return _currentChunk == _chunks.end(); +} + +Common::Rect Animation::draw(Graphics::Surface *surface) { + if (!_overlay) + error("Animation::draw - internal error: the current overlay animation frame is invalid!"); + + // Paint the background + if (_backgroundCurrent == 1 && _background1) + _background1->draw(surface); + else if (_backgroundCurrent == 2 && _background2) + _background2->draw(surface); + + // Paint the overlay + _overlay->draw(surface); + + //TODO + return Common::Rect(); +} + +AnimFrame *Animation::processChunkFrame(Common::SeekableReadStream *in, const Chunk &c) const { + assert (c.frame == 0); + + // Create a temporary chunk buffer + Common::MemoryReadStream *str = in->readStream(c.size); + + // Read the frame information + FrameInfo i; + i.read(str, false); + + // Decode the frame + AnimFrame *f = new AnimFrame(str, i); + + // Delete the temporary chunk buffer + delete str; + + return f; +} + +void Animation::processChunkAudio(Common::SeekableReadStream *in, const Chunk &c) { + if (!_audio) + error("Animation::processChunkAudio - internal error: the audio stream is invalid!"); + + // Skip the Snd header, to queue just the audio blocks + uint32 size = c.size; + if ((c.size % 739) != 0) { + // Read Snd header + uint32 header1 = in->readUint32LE(); + uint16 header2 = in->readUint16LE(); + warning("Start ADPCM: %d, %d", header1, header2); + size -= 6; + } + + // Append the current chunk to the Snd + _audio->queueBuffer(in->readStream(size)); +} + +// TODO: this method will probably go away and be integrated in the main loop +void Animation::play() { + while (!hasEnded() && !g_engine->getEventManager()->shouldQuit() && !g_engine->getEventManager()->shouldRTL()) { + process(); + + if (_changed) { + // Create a temporary surface to merge the overlay with the background + Graphics::Surface *s = new Graphics::Surface; + s->create(640, 480, 2); + + draw(s); + + // XXX: Update the screen + g_system->copyRectToScreen((byte *)s->pixels, s->pitch, 0, 0, s->w, s->h); + + // Free the temporary surface + s->free(); + delete s; + + _changed = false; + } + + g_system->updateScreen(); + + //FIXME: implement subtitles + g_engine->_system->delayMillis(20); + + // Handle right-click to interrupt animations + Common::Event ev; + while (g_engine->getEventManager()->pollEvent(ev)) { + if (ev.type == Common::EVENT_RBUTTONUP) { + // Stop audio + if (_audio) + _audio->finish(); + + // TODO start LNK file sound? + return; + } + } + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/animation.h b/engines/lastexpress/data/animation.h new file mode 100644 index 00000000000..ca1f7c6fa01 --- /dev/null +++ b/engines/lastexpress/data/animation.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$ + * + */ + +#ifndef LASTEXPRESS_ANIMATION_H +#define LASTEXPRESS_ANIMATION_H + +/* + Animation format (.NIS) + + uint32 {4} - Number of chunks + + // for each chunk + uint16 {2} - Type + uint16 {2} - Tag + uint32 {4} - Size of chunk + byte {x} - Data (for "data" chunks: backgrounds, overlay & audio data) +*/ + +#include "lastexpress/drawable.h" + +#include "common/array.h" +#include "common/stream.h" + +namespace LastExpress { + +class AnimFrame; +class AppendableSound; + +class Animation : public Drawable { +public: + enum FlagType { + kFlagDefault = 16384, + kFlagProcess = 49152 + }; + + Animation(); + ~Animation(); + + bool load(Common::SeekableReadStream *stream, int flag = kFlagDefault); + bool process(); + bool hasEnded(); + Common::Rect draw(Graphics::Surface *surface); + void play(); + +private: + static const uint32 _soundBlockSize = 739; + + // despite their size field, info chunks don't have a payload + enum ChunkType { + kChunkTypeUnknown1 = 1, + kChunkTypeUnknown2 = 2, + kChunkTypeAudioInfo = 3, + kChunkTypeUnknown4 = 4, + kChunkTypeUnknown5 = 5, + kChunkTypeBackground1 = 10, + kChunkTypeSelectBackground1 = 11, + kChunkTypeBackground2 = 12, + kChunkTypeSelectBackground2 = 13, + kChunkTypeOverlay = 20, + kChunkTypeUpdate = 21, + kChunkTypeUpdateTransition = 22, + kChunkTypeSound1 = 30, + kChunkTypeSound2 = 31, + kChunkTypeAudioData = 32, + kChunkTypeAudioEnd = 99 + }; + + struct Chunk { + ChunkType type; + uint16 frame; + uint32 size; + }; + + void reset(); + AnimFrame *processChunkFrame(Common::SeekableReadStream *in, const Chunk &c) const; + void processChunkAudio(Common::SeekableReadStream *in, const Chunk &c); + + Common::SeekableReadStream *_stream; + Common::Array _chunks; + Common::Array::iterator _currentChunk; + AnimFrame *_overlay, *_background1, *_background2; + byte _backgroundCurrent; + AppendableSound *_audio; + + uint32 _startTime; + bool _changed; + int _flag; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_ANIMATION_H diff --git a/engines/lastexpress/data/archive.cpp b/engines/lastexpress/data/archive.cpp new file mode 100644 index 00000000000..1a5b6905a3f --- /dev/null +++ b/engines/lastexpress/data/archive.cpp @@ -0,0 +1,115 @@ +/* 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$ + * + */ + +// Based on the Xentax Wiki documentation: +// http://wiki.xentax.com/index.php/The_Last_Express_SND + +#include "lastexpress/data/archive.h" + +#include "lastexpress/debug.h" + +#include "common/debug.h" +#include "common/file.h" + +namespace LastExpress { + +HPFArchive::HPFArchive(const Common::String &path) { + _filename = path; + + // Open a stream to the archive + Common::SeekableReadStream *archive = SearchMan.createReadStreamForMember(_filename); + if (!archive) { + debugC(2, kLastExpressDebugResource, "Error opening file: %s", path.c_str()); + return; + } + + debugC(2, kLastExpressDebugResource, "Opened archive: %s", path.c_str()); + + // Read header to get the number of files + uint32 numFiles = archive->readUint32LE(); + debugC(3, kLastExpressDebugResource, "Number of files in archive: %d", numFiles); + + // Read the list of files + for (unsigned int i = 0; i < numFiles; ++i) { + char name[13]; + HPFEntry entry; + + archive->read(&name, sizeof(char) * _archiveNameSize); + entry.offset = archive->readUint32LE(); + entry.size = archive->readUint32LE(); + entry.isOnHD = archive->readUint16LE(); + + // Terminate string + name[12] = '\0'; + + Common::String filename(name); + filename.toLowercase(); + + _files[filename] = entry; + + //debugC(9, kLastExpressDebugResource, "File entry: %s (offset:%d - Size: %d - HD: %u)", &name, entry.offset, entry.size, entry.isOnHD); + } + + // Close stream + delete archive; +} + +bool HPFArchive::hasFile(const Common::String &name) { + return (_files.find(name) != _files.end()); +} + +int HPFArchive::listMembers(Common::ArchiveMemberList &list) { + int numMembers = 0; + + for (FileMap::const_iterator i = _files.begin(); i != _files.end(); ++i) { + list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(i->_key, this))); + numMembers++; + } + + return numMembers; +} + +Common::ArchiveMemberPtr HPFArchive::getMember(const Common::String &name) { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *HPFArchive::createReadStreamForMember(const Common::String &name) const { + FileMap::const_iterator fDesc = _files.find(name); + if (fDesc == _files.end()) + return NULL; + + Common::File *archive = new Common::File(); + if (!archive->open(_filename)) { + delete archive; + return NULL; + } + + return new Common::SeekableSubReadStream(archive, fDesc->_value.offset * _archiveSectorSize, fDesc->_value.offset * _archiveSectorSize + fDesc->_value.size * _archiveSectorSize, DisposeAfterUse::YES); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/archive.h b/engines/lastexpress/data/archive.h new file mode 100644 index 00000000000..3860245bc5d --- /dev/null +++ b/engines/lastexpress/data/archive.h @@ -0,0 +1,75 @@ +/* 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 LASTEXPRESS_HPFARCHIVE_H +#define LASTEXPRESS_HPFARCHIVE_H + +/* + Archive file format (.HPF) + + uint32 {4} - number of files + + // for each file + char {12} - name (zero-terminated) + uint32 {4} - offset (expressed in sectors of 2048 bytes) + uint32 {4} - size (expressed in sectors of 2048 bytes) + byte {2} - file status: 1 = on disk (ie. in HD.HPF), 0 = on CD +*/ + +#include "common/archive.h" + +namespace LastExpress { + +class HPFArchive : public Common::Archive { +public: + HPFArchive(const Common::String &path); + + bool hasFile(const Common::String &name); + int listMembers(Common::ArchiveMemberList &list); + Common::ArchiveMemberPtr getMember(const Common::String &name); + Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; + + int count() { return _files.size(); } + +private: + static const unsigned int _archiveNameSize = 12; + static const unsigned int _archiveSectorSize = 2048; + + // File entry + struct HPFEntry { + uint32 offset; ///< Offset (in sectors of 2048 bytes) + uint32 size; ///< Size (in sectors of 2048 bytes) + uint16 isOnHD; ///< File location (1: on HD; 0: on CD) + }; + + typedef Common::HashMap FileMap; + + FileMap _files; ///< List of files + Common::String _filename; ///< Filename of the archive +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_HPFARCHIVE_H diff --git a/engines/lastexpress/data/background.cpp b/engines/lastexpress/data/background.cpp new file mode 100644 index 00000000000..94d7fb16c33 --- /dev/null +++ b/engines/lastexpress/data/background.cpp @@ -0,0 +1,141 @@ +/* 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$ + * + */ + +// Based on Deniz Oezmen's code and Xentax Wiki documentation +// http://oezmen.eu/ +// http://wiki.xentax.com/index.php/The_Last_Express_BG + +#include "lastexpress/data/background.h" + +#include "lastexpress/debug.h" + +namespace LastExpress { + +Background::Background() : _data(NULL) { + memset(&_header, 0, sizeof(BackgroundHeader)); +} + +Background::~Background() { + delete[] _data; +} + +bool Background::load(Common::SeekableReadStream *stream) { + if (!stream) + return false; + + // Reset data + delete[] _data; + + // Load Background header + _header.posX = stream->readUint32LE(); + _header.posY = stream->readUint32LE(); + _header.width = stream->readUint32LE(); + _header.height = stream->readUint32LE(); + _header.redSize = stream->readUint32LE(); + _header.blueSize = stream->readUint32LE(); + _header.greenSize = stream->readUint32LE(); + + debugC(3, kLastExpressDebugGraphics, "Background Info: (%d, %d) - (%d x %d) - (%d, %d, %d)", + _header.posX, _header.posY, _header.width, _header.height, + _header.redSize, _header.blueSize, _header.greenSize); + + // Load and decompress Background channel data + uint32 numPix = _header.width * _header.height; + byte *dataR = decodeComponent(stream, _header.redSize, numPix); + byte *dataB = decodeComponent(stream, _header.blueSize, numPix); + byte *dataG = decodeComponent(stream, _header.greenSize, numPix); + + // Save to pixel buffer + // FIXME handle big-endian case + _data = new uint16[_header.width * _header.height]; + for (uint i = 0; i < _header.width * _header.height; i++) + _data[i] = (uint16)((dataR[i] << 10) + (dataG[i] << 5) + dataB[i]); + + // Cleanup buffers + delete[] dataR; + delete[] dataG; + delete[] dataB; + + delete stream; + + return true; +} + +Common::Rect Background::draw(Graphics::Surface *surface) { + if (!_data) { + debugC(2, kLastExpressDebugGraphics, "Trying to show a background before loading data!"); + return Common::Rect(); + } + + int i = 0; + for (uint16 y = 0; y < _header.height; y++) { + for (uint16 x = 0; x < _header.width; x++) { + surface->fillRect(Common::Rect((int16)(_header.posX + x), (int16)(_header.posY + y), (int16)(_header.posX + x + 1), (int16)(_header.posY + y + 1)), _data[i]); + i ++; + } + } + + return Common::Rect((int16)_header.posX, (int16)_header.posY, (int16)(_header.posX + _header.width), (int16)(_header.posY + _header.height)); +} + +byte *Background::decodeComponent(Common::SeekableReadStream *in, uint32 inSize, uint32 outSize) const { + // Create the destination array + byte *out = new byte[outSize]; + if (!out) + return NULL; + + // Initialize the decoding + uint32 inPos = 0; + uint32 outPos = 0; + + // Decode + while (inPos < inSize) { + byte inByte = in->readByte(); + inPos++; + + if (inByte < 0x80) { + // Direct decompression (RLE) + byte len = (inByte >> 5) + 1; + byte data = inByte & 0x1f; + for (int i = 0; i < len && outPos < outSize; i++) + out[outPos++] = data; + } else { + // Buffer back reference, 4096 byte window + // Take inByte and the following value as a big endian + // OfsLen while zeroing the first bit + uint16 ofsLen = ((inByte & 0x7F) << 8) | in->readByte(); + inPos++; + + int32 len = (ofsLen >> 12) + 3; + int32 hisPos = (int32)(outPos + (ofsLen & 0x0FFF) - 4096); + for (int i = 0; i < len && outPos < outSize; i++) + out[outPos++] = out[hisPos++]; + } + } + + return out; +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/background.h b/engines/lastexpress/data/background.h new file mode 100644 index 00000000000..fc1cc26fa4c --- /dev/null +++ b/engines/lastexpress/data/background.h @@ -0,0 +1,81 @@ +/* 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 LASTEXPRESS_BACKGROUND_H +#define LASTEXPRESS_BACKGROUND_H + +/* + Background file format (.BG) + + header: + uint32 {4} - position X on screen + uint32 {4} - position Y on screen + uint32 {4} - image width + uint32 {4} - image height + uint32 {4} - red colour channel data size + uint32 {4} - blue colour channel data size + uint32 {4} - green colour channel data size + + data: + byte {x} - red colour channel data + byte {x} - blue colour channel data + byte {x} - green colour channel data +*/ + +#include "lastexpress/drawable.h" + +#include "common/stream.h" + +namespace LastExpress { + +class Background : public Drawable { +public: + Background(); + ~Background(); + + bool load(Common::SeekableReadStream *stream); + + Common::Rect draw(Graphics::Surface *surface); + +private: + struct BackgroundHeader { + uint32 posX; ///< position X on screen + uint32 posY; ///< position Y on screen + uint32 width; ///< image width + uint32 height; ///< image height + uint32 redSize; ///< red color channel data size + uint32 blueSize; ///< blue color channel data size + uint32 greenSize; ///< green color channel data size + }; + + BackgroundHeader _header; + uint16 *_data; ///< decoded background data + + byte *decodeComponent(Common::SeekableReadStream *in, uint32 inSize, uint32 outSize) const; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_BACKGROUND_H diff --git a/engines/lastexpress/data/cursor.cpp b/engines/lastexpress/data/cursor.cpp new file mode 100644 index 00000000000..4e7003578a2 --- /dev/null +++ b/engines/lastexpress/data/cursor.cpp @@ -0,0 +1,144 @@ +/* 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 "lastexpress/data/cursor.h" + +#include "lastexpress/lastexpress.h" + +#include "common/system.h" +#include "graphics/cursorman.h" + +namespace LastExpress { + +Cursor::Cursor() : _current(kCursorMAX) { + memset(&_cursors, 0, sizeof(_cursors)); +} + +bool Cursor::load(Common::SeekableReadStream *stream) { + if (!stream) + return false; + + // Load the whole file to memory + Common::MemoryReadStream *data = stream->readStream((uint32) stream->size()); + delete stream; + if (!data) + return false; + + // Read the hotspot data + for (int i = 0; i < kCursorMAX; i++) { + _cursors[i].hotspotX = data->readUint16LE(); + _cursors[i].hotspotY = data->readUint16LE(); + debugC(15, kLastExpressDebugCursor | kLastExpressDebugAll, + "Cursor %d hotspot x: %d, hotspot y: %d", + i, _cursors[i].hotspotX, _cursors[i].hotspotY); + } + + // Read the pixel data + for (int i = 0; i < kCursorMAX; i++) + for (int pix = 0; pix < 32 * 32; pix++) + _cursors[i].image[pix] = data->readUint16LE(); + + delete data; + return true; +} + +void Cursor::show(bool visible) const { + CursorMan.showMouse(visible); +} + +bool Cursor::checkStyle(CursorStyle style) const { + if (style >= kCursorMAX) { + debugC(2, kLastExpressDebugGraphics, "Trying to use an invalid cursor style: was %d, max %d", (int)style, kCursorMAX); + return false; + } + + return true; +} + +void Cursor::setStyle(CursorStyle style) { + if (!checkStyle(style)) + return; + + if (style == _current) + return; + + debugC(10, kLastExpressDebugCursor | kLastExpressDebugAll, "Cursor: setting style: %d", style); + + // Save the new cursor + _current = style; + + // Reuse the screen pixel format + Graphics::PixelFormat pf = g_system->getScreenFormat(); + CursorMan.replaceCursor((const byte *)getCursorImage(style), + 32, 32, _cursors[style].hotspotX, _cursors[style].hotspotY, + 0, 1, &pf); +} + +const uint16 *Cursor::getCursorImage(CursorStyle style) const { + if (!checkStyle(style)) + return NULL; + + return _cursors[style].image; +} + + +Icon::Icon(CursorStyle style) : _style(style), _x(0), _y(0), _brightness(100) {} + +void Icon::setPosition(int16 x, int16 y) { + _x = x; + _y = y; +} + +void Icon::setBrightness(uint brightness) { + assert(brightness <= 100); + + _brightness = (uint8)brightness; +} + +Common::Rect Icon::draw(Graphics::Surface *surface) { + const uint16 *image = ((LastExpressEngine *)g_engine)->getCursor()->getCursorImage((CursorStyle)_style); + if (!image) + return Common::Rect(); + + // TODO adjust brightness. The original game seems to be using a table for that (at least in the highlighting case) + for (int j = 0; j < 32; j++) { + uint16 *s = (uint16 *)surface->getBasePtr(_x, _y + j); + for (int i = 0; i < 32; i++) { + if (_brightness == 100) + *s = *image; + else + // HACK change color to show highlight + *s = (*image & 0x739C) >> 1; + + // Update the image and surface pointers + image++; + s++; + } + } + + return Common::Rect(_x, _y, _x + 32, _y + 32); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/cursor.h b/engines/lastexpress/data/cursor.h new file mode 100644 index 00000000000..992266569ff --- /dev/null +++ b/engines/lastexpress/data/cursor.h @@ -0,0 +1,93 @@ +/* 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 LASTEXPRESS_CURSOR_H +#define LASTEXPRESS_CURSOR_H + +/* + Cursor format (CURSORS.TBM) + + style table: + (for each cursor) + uint16 {2} - hotspot X + uint16 {2} - hotspot Y + + data: + (for each cursor) + uint16 {32*32} - cursor data +*/ + +#include "lastexpress/drawable.h" + +#include "lastexpress/shared.h" + +#include "common/stream.h" + +namespace LastExpress { + +class Icon : public Drawable { +public: + Icon(CursorStyle style); + + void setPosition(int16 x, int16 y); + void setBrightness(uint brightness); + Common::Rect draw(Graphics::Surface *surface); + +private: + CursorStyle _style; + int16 _x, _y; + uint8 _brightness; +}; + +class Cursor { +public: + Cursor(); + + bool load(Common::SeekableReadStream *stream); + void show(bool visible) const; + + void setStyle(CursorStyle style); + CursorStyle getStyle() const { return _current; } + +private: + // Style + CursorStyle _current; + + // Cursors data + struct { + uint16 image[32 * 32]; + uint16 hotspotX, hotspotY; + } _cursors[kCursorMAX]; + + bool checkStyle(CursorStyle style) const; + const uint16 *getCursorImage(CursorStyle style) const; + + // Only allow full access for drawing (needed for getCursorImage) + friend Common::Rect Icon::draw(Graphics::Surface *surface); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_CURSOR_H diff --git a/engines/lastexpress/data/font.cpp b/engines/lastexpress/data/font.cpp new file mode 100644 index 00000000000..5f4b3b40b8c --- /dev/null +++ b/engines/lastexpress/data/font.cpp @@ -0,0 +1,205 @@ +/* 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 "lastexpress/data/font.h" + +#include "common/system.h" + +namespace LastExpress { + +Font::Font() : _numGlyphs(0), _glyphs(NULL), _glyphWidths(0) { + memset(&_palette, 0, sizeof(_palette)); + memset(&_charMap, 0, sizeof(_charMap)); +} + +Font::~Font() { + reset(); +} + +void Font::reset() { + delete[] _glyphs; + delete[] _glyphWidths; +} + +bool Font::load(Common::SeekableReadStream *stream) { + if (!stream) + return false; + + // Reset data + reset(); + + // Read the palette + for (uint i = 0; i < _paletteSize; i++) { + _palette[i] = stream->readUint16LE(); + } + + // Read the character map + stream->read(_charMap, _charMapSize); + + // Read the glyphs + _numGlyphs = stream->readUint16LE(); + _glyphs = new byte[_numGlyphs * 18 * 8]; + stream->read(_glyphs, _numGlyphs * 18 * 8); + + // TODO: Read something else? + //uint16 unknown = fontFile->readByte(); + //warning("unknown = %d", unknown); + //warning("pos = %d", fontFile->pos()); + //warning("left = %d", fontFile->size() - fontFile->pos()); + + //while (!fontFile->eos()) { + //unknown = fontFile->readByte(); + //warning("val = %d", unknown); + //} + + // Precalculate glyph widths + _glyphWidths = new byte[_numGlyphs]; + for (uint16 i = 0; i < _numGlyphs; i++) { + _glyphWidths[i] = getGlyphWidth(i); + } + + delete stream; + + return true; +} + + +uint16 Font::getCharGlyph(uint16 c) const { + //warning("%c", c); + if (c >= 0x200) + error("Express::Font: Invalid character %d", c); + + return _charMap[c]; +} + +byte *Font::getGlyphImg(uint16 g) { + if (!_glyphs) + error("Express::getGlyphImg: Invalid glyphs!"); + + if (g >= _numGlyphs) + error("Express::getGlyphImg: Invalid glyph %d (%d available)", g, _numGlyphs); + + return _glyphs + g * 18 * 8; +} + +uint8 Font::getGlyphWidth(uint16 g) { + byte *p = getGlyphImg(g); + + uint8 maxLineWidth = 0; + for (int j = 0; j < 18; j++) { + uint8 currentLineWidth = 0; + for (uint8 i = 0; i < 16; i++) { + byte index; + if (i % 2) + index = *p & 0xf; + else + index = *p >> 4; + uint16 color = _palette[index]; + if (color != 0x1f) + currentLineWidth = i; + if (i % 2) + p++; + } + if (currentLineWidth > maxLineWidth) + maxLineWidth = currentLineWidth; + } + + return maxLineWidth; +} + +byte *Font::getCharImg(uint16 c) { + return getGlyphImg(getCharGlyph(c)); +} + +uint8 Font::getCharWidth(uint16 c) const{ + if (c == 0x20) { + // Space is a special case + // TODO: this is an arbitrary value + return 10; + } else { + if (!_glyphWidths) + error("Express::getCharWidth: Invalid glyphs widths!"); + + return _glyphWidths[getCharGlyph(c)]; + } +} + +uint16 Font::getStringWidth(Common::String str) const { + uint16 width = 0; + for (uint i = 0; i < str.size(); i++) + width += getCharWidth((unsigned) (int)str[i]); + + return width; +} + +uint16 Font::getStringWidth(const uint16 *str, uint16 length) const { + uint16 width = 0; + for (uint i = 0; i < length; i++) + width += getCharWidth(str[i]); + + return width; +} + +void Font::drawChar(Graphics::Surface *surface, int16 x, int16 y, uint16 c) { + byte *p = getCharImg(c); + + for (int16 j = 0; j < 18; j++) { + for (int16 i = 0; i < 16; i++) { + byte index; + if (i % 2) + index = *p & 0xf; + else + index = *p >> 4; + uint16 color = _palette[index]; + if (color != 0x1f) { + surface->fillRect(Common::Rect(x+i, y+j, x+i+1, y+j+1), color); + } + if (i % 2) + p++; + } + } +} + +Common::Rect Font::drawString(Graphics::Surface *surface, int16 x, int16 y, Common::String str) { + int16 currentX = x; + for (uint i = 0; i < str.size(); i++) { + drawChar(surface, currentX, y, (unsigned) (int)str[i]); + currentX += getCharWidth((unsigned) (int)str[i]); + } + + return Common::Rect(x, y, x + currentX, y + (int16)_charHeight); +} + +Common::Rect Font::drawString(Graphics::Surface *surface, int16 x, int16 y, const uint16 *str, uint16 length) { + int16 currentX = x; + for (uint i = 0; i < length; i++) { + drawChar(surface, currentX, y, str[i]); + currentX += getCharWidth(str[i]); + } + + return Common::Rect(x, y, x + currentX, y + (int16)_charHeight); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/font.h b/engines/lastexpress/data/font.h new file mode 100644 index 00000000000..457c0c34324 --- /dev/null +++ b/engines/lastexpress/data/font.h @@ -0,0 +1,82 @@ +/* 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 LASTEXPRESS_FONT_H +#define LASTEXPRESS_FONT_H + +/* + Font format (FONT.DAT) + + uint16 {40} - Palette data + byte {200} - Character map + uint16 {2} - Number of glyphs + + // For each glyph + byte {18*8} - Glyph data + + byte {x} - Unknown data (probably just garbage) +*/ + +#include "common/stream.h" +#include "graphics/surface.h" + +namespace LastExpress { + +class Font { +public: + Font(); + ~Font(); + + bool load(Common::SeekableReadStream *stream); + Common::Rect drawString(Graphics::Surface *surface, int16 x, int16 y, Common::String str); + Common::Rect drawString(Graphics::Surface *surface, int16 x, int16 y, const uint16 *str, uint16 length); + +private: + static const uint32 _paletteSize = 0x10; + static const uint32 _charMapSize = 0x200; + static const uint32 _charHeight = 16; + + void reset(); + + uint16 getCharGlyph(uint16 c) const; + byte *getGlyphImg(uint16 g); + uint8 getGlyphWidth(uint16 g); + byte *getCharImg(uint16 c); + uint8 getCharWidth(uint16 c) const; + uint16 getStringWidth(Common::String str) const; + uint16 getStringWidth(const uint16 *str, uint16 length) const; + void drawChar(Graphics::Surface *surface, int16 x, int16 y, uint16 c); + + // Font data + uint16 _palette[_paletteSize]; + uint8 _charMap[_charMapSize]; + uint16 _numGlyphs; + byte *_glyphs; + uint8 *_glyphWidths; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FONT_H diff --git a/engines/lastexpress/data/scene.cpp b/engines/lastexpress/data/scene.cpp new file mode 100644 index 00000000000..4c8cb9bd17d --- /dev/null +++ b/engines/lastexpress/data/scene.cpp @@ -0,0 +1,292 @@ +/* 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 "lastexpress/data/scene.h" + +#include "lastexpress/data/background.h" + +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +SceneHotspot *SceneHotspot::load(Common::SeekableReadStream *stream) { + SceneHotspot *hs = new SceneHotspot(); + + // Rect + hs->rect.left = (int16)stream->readUint16LE(); + hs->rect.right = (int16)stream->readUint16LE(); + hs->rect.top = (int16)stream->readUint16LE(); + hs->rect.bottom = (int16)stream->readUint16LE(); + + hs->coordsOffset = stream->readUint32LE(); + hs->scene = (SceneIndex)stream->readUint16LE(); + hs->location = stream->readByte(); + hs->action = (Action)stream->readByte(); + hs->param1 = stream->readByte(); + hs->param2 = stream->readByte(); + hs->param3 = stream->readByte(); + hs->cursor = stream->readByte(); + hs->next = stream->readUint32LE(); + + debugC(10, kLastExpressDebugScenes, "\thotspot: scene=%d location=%02d action=%d param1=%02d param2=%02d param3=%02d cursor=%02d rect=(%d, %d)x(%d, %d)", + hs->scene, hs->location, hs->action, hs->param1, hs->param2, hs->param3, hs->cursor, hs->rect.left, hs->rect.top, hs->rect.right, hs->rect.bottom); + debugC(10, kLastExpressDebugScenes, "\t coords=%d next=%d ", hs->coordsOffset, hs->next); + + // Read all coords data + uint32 offset = hs->coordsOffset; + while (offset != 0) { + + SceneCoord *sceneCoord = new SceneCoord; + + stream->seek(offset, SEEK_SET); + + sceneCoord->field_0 = stream->readSint32LE(); + sceneCoord->field_4 = stream->readSint32LE(); + sceneCoord->field_8 = stream->readByte(); + sceneCoord->next = stream->readUint32LE(); + + hs->_coords.push_back(sceneCoord); + + offset = sceneCoord->next; + } + + return hs; +} + +Common::String SceneHotspot::toString() const { + Common::String output = ""; + + output += Common::String::printf(" hotspot: scene=%d location=%02d action=%d param1=%02d param2=%02d param3=%02d cursor=%02d rect=(%d, %d)x(%d, %d)", + scene, location, action, param1, param2, param3, cursor, rect.left, rect.top, rect.right, rect.bottom); + + return output; +} + +bool SceneHotspot::isInside(const Common::Point &point) { + + bool contains = rect.contains(point); + + if (_coords.empty() || !contains) + return contains; + + // Checks extended coordinates + for (uint i = 0; i < _coords.size(); i++) { + + SceneCoord *sCoord = _coords[i]; + + bool cont; + if (sCoord->field_8) + cont = (sCoord->field_4 + point.x * sCoord->field_0 + 1000 * point.y) >= 0; + else + cont = (sCoord->field_4 + point.x * sCoord->field_0 + 1000 * point.y) <= 0; + + if (!cont) + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// +// Scene +Scene::~Scene() { + // Free the hotspots + for (int i = 0; i < (int)_hotspots.size(); i++) + delete _hotspots[i]; +} + +Scene *Scene::load(Common::SeekableReadStream *stream) { + Scene *scene = new Scene(); + + stream->read(&scene->_name, sizeof(scene->_name)); + scene->_sig = stream->readByte(); + scene->entityPosition = (EntityPosition)stream->readUint16LE(); + scene->location = (Location)stream->readUint16LE(); + scene->car = (CarIndex)stream->readUint16LE(); + scene->position = stream->readByte(); + scene->type = (Type)stream->readByte(); + scene->param1 = stream->readByte(); + scene->param2 = stream->readByte(); + scene->param3 = stream->readByte(); + scene->_hotspot = stream->readUint32LE(); + + return scene; +} + +void Scene::loadHotspots(Common::SeekableReadStream *stream) { + if (!_hotspots.empty()) + return; + + debugC(10, kLastExpressDebugScenes, "Scene: name=%s, sig=%02d, entityPosition=%d, location=%d", _name, _sig, entityPosition, location); + debugC(10, kLastExpressDebugScenes, "\tcar=%02d, position=%02d, type=%02d, param1=%02d", car, position, type, param1); + debugC(10, kLastExpressDebugScenes, "\tparam2=%02d, param3=%02d, hotspot=%d\n", param2, param3, _hotspot); + + // Read all hotspots + if (_hotspot != 0) { + stream->seek((int32)_hotspot, SEEK_SET); + SceneHotspot *hotspot = SceneHotspot::load(stream); + while (hotspot) { + _hotspots.push_back(hotspot); + + if (hotspot->next == 0) + break; + + stream->seek((int32)hotspot->next, SEEK_SET); + hotspot = SceneHotspot::load(stream); + } + } +} + +bool Scene::checkHotSpot(const Common::Point &coord, SceneHotspot **hotspot) { + bool found = false; + int _location = 0; + + for (int i = 0; i < (int)_hotspots.size(); i++) { + if (_hotspots[i]->isInside(coord)) { + if (_location <= _hotspots[i]->location) { + _location = _hotspots[i]->location; + *hotspot = _hotspots[i]; + found = true; + } + } + } + + return found; +} + +SceneHotspot *Scene::getHotspot(uint index) { + if (_hotspots.empty()) + error("Scene::getHotspot: scene does not have any hotspots!"); + + if (index >= _hotspots.size()) + error("Scene::getHotspot: invalid index (was: %d, max: %d)", index, _hotspots.size() - 1); + + return _hotspots[index]; +} + +Common::Rect Scene::draw(Graphics::Surface *surface) { + // Safety checks + Common::Rect rect; + + Common::String sceneName(_name); + sceneName.trim(); + if (sceneName.empty()) + error("Scene::draw: This scene is not a valid drawing scene!"); + + // Load background + Background *background = ((LastExpressEngine *)g_engine)->getResourceManager()->loadBackground(sceneName); + if (background) { + rect = background->draw(surface); + delete background; + } + + return rect; +} + +Common::String Scene::toString() { + Common::String output = ""; + + output += Common::String::printf("Scene: name=%s, sig=%02d, entityPosition=%d, location=%d\n", _name, _sig, entityPosition, location); + output += Common::String::printf(" car=%02d, position=%02d, type=%02d, param1=%02d\n", car, position, type, param1); + output += Common::String::printf(" param2=%02d, param3=%02d, hotspot=%d\n", param2, param3, _hotspot); + + // Hotspots + if (_hotspots.size() != 0) { + output += "\nHotspots:\n"; + for (int i = 0; i < (int)_hotspots.size(); i++) + output += _hotspots[i]->toString() + "\n"; + } + + return output; +} + +////////////////////////////////////////////////////////////////////////// +// SceneLoader +SceneLoader::SceneLoader() : _stream(NULL) {} + +SceneLoader::~SceneLoader() { + clear(); +} + +void SceneLoader::clear() { + // Remove all scenes + for (int i = 0; i < (int)_scenes.size(); i++) + delete _scenes[i]; + + _scenes.clear(); + + delete _stream; +} + +bool SceneLoader::load(Common::SeekableReadStream *stream) { + if (!stream) + return false; + + clear(); + + _stream = stream; + + // Read the default scene to get the total number of scenes + Scene *header = Scene::load(_stream); + if (!header) + error("SceneLoader::load: Invalid data file!"); + + debugC(2, kLastExpressDebugScenes, " found %d entries", header->entityPosition); /* Header entityPosition is the scene count */ + + if (header->entityPosition > 2500) { + delete header; + + return false; + } + + _scenes.push_back(header); + + // Read all the chunks + for (uint i = 0; i < (uint)header->entityPosition; ++i) { + Scene *scene = Scene::load(_stream); + if (!scene) + break; + + _scenes.push_back(scene); + } + + return true; +} + +Scene *SceneLoader::get(SceneIndex index) { + if (_scenes.empty()) + return NULL; + + if (index > _scenes.size()) + return NULL; + + // Load the hotspots if needed + _scenes[(int)index]->loadHotspots(_stream); + + return _scenes[(int)index]; +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/scene.h b/engines/lastexpress/data/scene.h new file mode 100644 index 00000000000..c4a34e127b0 --- /dev/null +++ b/engines/lastexpress/data/scene.h @@ -0,0 +1,245 @@ +/* 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 LASTEXPRESS_SCENE_H +#define LASTEXPRESS_SCENE_H + +/* + Scene format (CDTRAIN.DAT) + + (text:00484750) + header (24 bytes) + char {8} - entry name (null terminated) + byte {1} - 0xCD + uint16 {2} - number of scenes (for first entry - always 0 after?) + uint16 {2} - 11 ?? + uint16 {2} - car + byte {1} - camera position (used to get the proper sequences to show) + byte {1} - type + byte {1} - param1 + byte {1} - param2 + byte {1} - param3 + uint32 {4} - Offset to hotspot info struct + + probably contains cursor type too / scene index : 0 - 2500 (max) + + hotspot info (24 bytes) + uint16 {2} - left + uint16 {2} - right + uint16 {2} - top + uint16 {2} - bottom + uint32 {4} - scene coords data + uint16 {2} - scene + byte {1} - location; + byte {1} - action; + byte {1} - param1; + byte {1} - param2; + byte {1} - param3 + byte {1} - cursor + uint32{4} - offset to next hotpost + + coords data (9 bytes) + uint32 {4} - ?? + uint32 {4} - ?? + byte {1} - ?? + uint32 {4} - offset to next coords data structure + +*/ + +#include "lastexpress/drawable.h" +#include "lastexpress/shared.h" + +#include "common/array.h" +#include "common/stream.h" + +namespace LastExpress { + +class Scene; + +class SceneHotspot { +public: + enum Action { + kActionInventory = 1, + kActionSavePoint = 2, + kActionPlaySound = 3, + kActionPlayMusic = 4, + kActionKnockOnDoor = 5, + kActionCompartment = 6, + kActionPlaySounds = 7, + kActionPlayAnimation = 8, + kActionOpenCloseObject = 9, + kActionObjectUpdateLocation2 = 10, + kActionSetItemLocation = 11, + kAction12 = 12, + kActionPickItem = 13, + kActionDropItem = 14, + kAction15 = 15, + kActionEnterCompartment = 16, + kActionGetOutsideTrain = 18, + kActionSlip = 19, + kActionGetInsideTrain = 20, + kActionClimbUpTrain = 21, + kActionClimbDownTrain = 22, + kActionJumpUpDownTrain = 23, + kActionUnbound = 24, + kAction25 = 25, + kAction26 = 26, + kAction27 = 27, + kActionConcertSitCough = 28, + kAction29 = 29, + kActionCatchBeetle = 30, + kActionExitCompartment = 31, + kAction32 = 32, + KActionUseWhistle = 33, + kActionOpenMatchBox = 34, + kActionOpenBed = 35, + kActionDialog = 37, + kActionEggBox = 38, + kAction39 = 39, + kActionBed = 40, + kAction41 = 41, + kAction42 = 42, + kActionSwitchChapter = 43, + kAction44 = 44 + }; + + struct SceneCoord { + int32 field_0; + int32 field_4; + byte field_8; + uint32 next; + + SceneCoord() { + field_0 = 0; + field_4 = 0; + field_8 = 0; + next = 0; + } + }; + + Common::Rect rect; + uint32 coordsOffset; + SceneIndex scene; + byte location; + Action action; + byte param1; + byte param2; + byte param3; + byte cursor; + uint32 next; + + SceneHotspot() {} + static SceneHotspot *load(Common::SeekableReadStream *stream); + + bool isInside(const Common::Point &point); + + Common::String toString() const; + +private: + Common::Array _coords; +}; + +class SceneLoader { +public: + SceneLoader(); + ~SceneLoader(); + + bool load(Common::SeekableReadStream *stream); + Scene *get(SceneIndex index); + + uint32 count() const { return _scenes.size() - 1; } + +private: + Common::SeekableReadStream *_stream; + Common::Array _scenes; + + void clear(); +}; + +class Scene : public Drawable { +public: + // Enumerations + enum Type { + // PreProcess + kTypeObject = 1, + kTypeItem = 2, + kTypeItem2 = 3, + kTypeObjectItem = 4, + kTypeItem3 = 5, + kTypeObjectLocation2 = 6, + kTypeCompartments = 7, + kTypeCompartmentsItem = 8, + + // PostProcess + kTypeList = 128, + kTypeSavePointChapter = 129, + kTypeLoadBeetleSequences = 130, + kTypeGameOver = 131, + kTypeReadText = 132, + kType133 = 133 + }; + + // Data + EntityPosition entityPosition; + Location location; + CarIndex car; + Position position; + Type type; + byte param1; + byte param2; + byte param3; + + ~Scene(); + + Common::Rect draw(Graphics::Surface *surface); + + // Hotspots + Common::Array *getHotspots() { return &_hotspots; } + bool checkHotSpot(const Common::Point &coord, SceneHotspot **hotspot); + SceneHotspot *getHotspot(uint index = 0); + + Common::String toString(); + +private: + char _name[8]; + byte _sig; + uint32 _hotspot; + + Scene() {} + Common::Array _hotspots; + + static Scene *load(Common::SeekableReadStream *stream); + void loadHotspots(Common::SeekableReadStream *stream); + + void clear(); + + // Only allow full access for loading the scene and the hotspots + friend bool SceneLoader::load(Common::SeekableReadStream *stream); + friend Scene *SceneLoader::get(SceneIndex index); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SCENE_H diff --git a/engines/lastexpress/data/sequence.cpp b/engines/lastexpress/data/sequence.cpp new file mode 100644 index 00000000000..cf71bd6a61c --- /dev/null +++ b/engines/lastexpress/data/sequence.cpp @@ -0,0 +1,482 @@ +/* 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$ + * + */ + +// Based on Deniz Oezmen's code: http://oezmen.eu/ + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/debug.h" + +namespace LastExpress { + +void FrameInfo::read(Common::SeekableReadStream *in, bool isSequence) { + // Save the current position + int32 basePos = in->pos(); + + dataOffset = in->readUint32LE(); + unknown = in->readUint32LE(); + paletteOffset = in->readUint32LE(); + xPos1 = in->readUint32LE(); + yPos1 = in->readUint32LE(); + xPos2 = in->readUint32LE(); + yPos2 = in->readUint32LE(); + initialSkip = in->readUint32LE(); + decompressedEndOffset = in->readUint32LE(); + + // Read the compression type for NIS files + if (!isSequence) { + in->seek(basePos + 0x124); + } else { + hotspot.left = (int16)in->readUint16LE(); + hotspot.right = (int16)in->readUint16LE(); + hotspot.top = (int16)in->readUint16LE(); + hotspot.bottom = (int16)in->readUint16LE(); + } + + compressionType = in->readByte(); + subType = (FrameSubType)in->readByte(); + + // Sequence information + field_2E = in->readByte(); + keepPreviousFrame = in->readByte(); + field_30 = in->readByte(); + field_31 = in->readByte(); + soundAction = in->readByte(); + field_33 = in->readByte(); + position = in->readByte(); + field_35 = in->readByte(); + field_36 = in->readUint16LE(); + field_38 = in->readUint32LE(); + entityPosition = (EntityPosition)in->readUint16LE(); + location = in->readUint16LE(); + next = in->readUint32LE(); +} + + +// AnimFrame + +AnimFrame::AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f) : _palette(NULL) { + _palSize = 1; + // TODO: use just the needed rectangle + _image.create(640, 480, 1); + + //debugC(6, kLastExpressDebugGraphics, " Offsets: data=%d, unknown=%d, palette=%d", f.dataOffset, f.unknown, f.paletteOffset); + //debugC(6, kLastExpressDebugGraphics, " Position: (%d, %d) - (%d, %d)", f.xPos1, f.yPos1, f.xPos2, f.yPos2); + //debugC(6, kLastExpressDebugGraphics, " Initial Skip: %d", f.initialSkip); + //debugC(6, kLastExpressDebugGraphics, " Decompressed end offset: %d", f.decompressedEndOffset); + //debugC(6, kLastExpressDebugGraphics, " Hotspot: (%d, %d) x (%d, %d)\n", f.hotspot.left, f.hotspot.top, f.hotspot.right, f.hotspot.bottom); + //debugC(6, kLastExpressDebugGraphics, " Compression type: %u / %u", f.compressionType, f.subType); + //debugC(6, kLastExpressDebugGraphics, " Unknown: %u - %u - %u - %u - %u - %u - %u - %d", f.field_2E, f.field_2F, f.field_30, f.field_31, f.field_33, f.field_35, f.field_36, f.field_38); + //debugC(6, kLastExpressDebugGraphics, " Sound action: %u", f.soundAction); + //debugC(6, kLastExpressDebugGraphics, " Position: %d", f.position); + //debugC(6, kLastExpressDebugGraphics, " Entity Position: %d", f.entityPosition); + //debugC(6, kLastExpressDebugGraphics, " Location: %d", f.location); + //debugC(6, kLastExpressDebugGraphics, " next: %d", f.next); + + switch (f.compressionType) { + case 0: + // Empty frame + break; + case 3: + decomp3(in, f); + break; + case 4: + decomp4(in, f); + break; + case 5: + decomp5(in, f); + break; + case 7: + decomp7(in, f); + break; + case 255: + decompFF(in, f); + break; + default: + error("Unknown frame compression: %d", f.compressionType); + } + + readPalette(in, f); + _rect = Common::Rect((int16)f.xPos1, (int16)f.yPos1, (int16)f.xPos2, (int16)f.yPos2); + //_rect.debugPrint(0, "Frame rect:"); +} + +AnimFrame::~AnimFrame() { + _image.free(); + delete[] _palette; +} + +Common::Rect AnimFrame::draw(Graphics::Surface *s) { + byte *inp = (byte *)_image.pixels; + uint16 *outp = (uint16 *)s->pixels; + for (int i = 0; i < 640 * 480; i++, inp++, outp++) { + if (*inp) + *outp = _palette[*inp]; + } + return _rect; +} + +void AnimFrame::readPalette(Common::SeekableReadStream *in, const FrameInfo &f) { + // Read the palette + in->seek((int)f.paletteOffset); + _palette = new uint16[_palSize]; + for (uint32 i = 0; i < _palSize; i++) { + _palette[i] = in->readUint16LE(); + } +} + +void AnimFrame::decomp3(Common::SeekableReadStream *in, const FrameInfo &f) { + decomp34(in, f, 0x7, 3); +} + +void AnimFrame::decomp4(Common::SeekableReadStream *in, const FrameInfo &f) { + decomp34(in, f, 0xf, 4); +} + +void AnimFrame::decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byte mask, byte shift) { + byte *p = (byte *)_image.getBasePtr(0, 0); + + uint32 skip = f.initialSkip / 2; + uint32 size = f.decompressedEndOffset / 2; + //warning("skip: %d, %d", skip % 640, skip / 640); + //warning("size: %d, %d", size % 640, size / 640); + //assert (f.yPos1 == skip / 640); + //assert (f.yPos2 == size / 640); + + uint32 numBlanks = 640 - (f.xPos2 - f.xPos1); + + in->seek((int)f.dataOffset); + for (uint32 out = skip; out < size; ) { + uint16 opcode = in->readByte(); + + if (opcode & 0x80) { + if (opcode & 0x40) { + opcode &= 0x3f; + out += numBlanks + opcode + 1; + } else { + opcode &= 0x3f; + if (opcode & 0x20) { + opcode = ((opcode & 0x1f) << 8) + in->readByte(); + if (opcode & 0x1000) { + out += opcode & 0xfff; + continue; + } + } + out += opcode + 2; + } + } else { + byte value = opcode & mask; + opcode >>= shift; + if (_palSize <= value) + _palSize = value + 1; + if (!opcode) + opcode = in->readByte(); + for (int i = 0; i < opcode; i++, out++) { + p[out] = value; + } + } + } +} + +void AnimFrame::decomp5(Common::SeekableReadStream *in, const FrameInfo &f) { + byte *p = (byte *)_image.getBasePtr(0, 0); + + uint32 skip = f.initialSkip / 2; + uint32 size = f.decompressedEndOffset / 2; + //warning("skip: %d, %d", skip % 640, skip / 640); + //warning("size: %d, %d", size % 640, size / 640); + //assert (f.yPos1 == skip / 640); + //assert (f.yPos2 == size / 640); + + in->seek((int)f.dataOffset); + for (uint32 out = skip; out < size; ) { + uint16 opcode = in->readByte(); + if (!(opcode & 0x1f)) { + opcode = (uint16)((opcode << 3) + in->readByte()); + if (opcode & 0x400) { + // skip these 10 bits + out += (opcode & 0x3ff); + } else { + out += opcode + 2; + } + } else { + byte value = opcode & 0x1f; + opcode >>= 5; + if (_palSize <= value) + _palSize = value + 1; + if (!opcode) + opcode = in->readByte(); + for (int i = 0; i < opcode; i++, out++) { + p[out] = value; + } + } + } +} + +void AnimFrame::decomp7(Common::SeekableReadStream *in, const FrameInfo &f) { + byte *p = (byte *)_image.getBasePtr(0, 0); + + uint32 skip = f.initialSkip / 2; + uint32 size = f.decompressedEndOffset / 2; + //warning("skip: %d, %d", skip % 640, skip / 640); + //warning("size: %d, %d", size % 640, size / 640); + //assert (f.yPos1 == skip / 640); + //assert (f.yPos2 == size / 640); + + uint32 numBlanks = 640 - (f.xPos2 - f.xPos1); + + in->seek((int)f.dataOffset); + for (uint32 out = skip; out < size; ) { + uint16 opcode = in->readByte(); + if (opcode & 0x80) { + if (opcode & 0x40) { + if (opcode & 0x20) { + opcode &= 0x1f; + out += numBlanks + opcode + 1; + } else { + opcode &= 0x1f; + if (opcode & 0x10) { + opcode = ((opcode & 0xf) << 8) + in->readByte(); + if (opcode & 0x800) { + // skip these 11 bits + out += (opcode & 0x7ff); + continue; + } + } + + // skip these 4 bits + out += opcode + 2; + } + } else { + opcode &= 0x3f; + byte value = in->readByte(); + if (_palSize <= value) + _palSize = value + 1; + for (int i = 0; i < opcode; i++, out++) { + p[out] = value; + } + } + } else { + if (_palSize <= opcode) + _palSize = opcode + 1; + // set the given value + p[out] = (byte)opcode; + out++; + } + } +} + +void AnimFrame::decompFF(Common::SeekableReadStream *in, const FrameInfo &f) { + byte *p = (byte *)_image.getBasePtr(0, 0); + + uint32 skip = f.initialSkip / 2; + uint32 size = f.decompressedEndOffset / 2; + + in->seek((int)f.dataOffset); + for (uint32 out = skip; out < size; ) { + uint16 opcode = in->readByte(); + + if (opcode < 0x80) { + if (_palSize <= opcode) + _palSize = opcode + 1; + // set the given value + p[out] = (byte)opcode; + out++; + } else { + if (opcode < 0xf0) { + if (opcode < 0xe0) { + // copy old part + uint32 old = out + ((opcode & 0x7) << 8) + in->readByte() - 2048; + opcode = ((opcode >> 3) & 0xf) + 3; + for (int i = 0; i < opcode; i++, out++, old++) { + p[out] = p[old]; + } + } else { + opcode = (opcode & 0xf) + 1; + byte value = in->readByte(); + if (_palSize <= value) + _palSize = value + 1; + for (int i = 0; i < opcode; i++, out++) { + p[out] = value; + } + } + } else { + out += ((opcode & 0xf) << 8) + in->readByte(); + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +// SEQUENCE +////////////////////////////////////////////////////////////////////////// + +Sequence::~Sequence() { + reset(); +} + +void Sequence::reset() { + _frames.clear(); + delete _stream; + _stream = NULL; +} + +Sequence *Sequence::load(Common::String name, Common::SeekableReadStream *stream, byte field30) { + Sequence *sequence = new Sequence(name); + + if (!sequence->load(stream, field30)) { + delete sequence; + return NULL; + } + + return sequence; +} + +bool Sequence::load(Common::SeekableReadStream *stream, byte field30) { + if (!stream) + return false; + + // Reset data + reset(); + + _field30 = field30; + + // Keep stream for later decoding of sequence + _stream = stream; + + // Read header to get the number of frames + _stream->seek(0); + uint32 numframes = _stream->readUint32LE(); + uint32 unknown = _stream->readUint32LE(); + debugC(3, kLastExpressDebugGraphics, "Number of frames in sequence: %d / unknown=0x%x", numframes, unknown); + + // Store frames information + for (uint i = 0; i < numframes; i++) { + + // Move stream to start of frame + _stream->seek((int32)(_sequenceHeaderSize + i * _sequenceFrameSize), SEEK_SET); + if (_stream->eos()) + error("Couldn't seek to the current frame data"); + + // Check if there is enough data + if ((unsigned)(_stream->size() - _stream->pos()) < _sequenceFrameSize) + error("The sequence frame does not have a valid header"); + + FrameInfo info; + info.read(_stream, true); + _frames.push_back(info); + } + + _isLoaded = true; + + return true; +} + +FrameInfo *Sequence::getFrameInfo(uint16 index) { + if (_frames.size() == 0) + error("Trying to decode a sequence before loading its data"); + + if (index > _frames.size() - 1) + error("Invalid sequence frame requested: %d, max %d", index, _frames.size() - 1); + + return &_frames[index]; +} + +AnimFrame *Sequence::getFrame(uint16 index) { + + FrameInfo *frame = getFrameInfo(index); + + if (!frame) + return NULL; + + // Skip "invalid" frames + if (frame->compressionType == 0) + return NULL; + + debugC(9, kLastExpressDebugGraphics, "Decoding sequence %s: frame %d / %d", _name.c_str(), index, _frames.size() - 1); + + return new AnimFrame(_stream, *frame); +} + +////////////////////////////////////////////////////////////////////////// +// SequenceFrame +SequenceFrame::~SequenceFrame() { + if (_dispose && _sequence) { + delete _sequence; + } + + _sequence = NULL; +} + +Common::Rect SequenceFrame::draw(Graphics::Surface *surface) { + if (!_sequence || _frame >= _sequence->count()) + return Common::Rect(); + + AnimFrame *f = _sequence->getFrame(_frame); + if (!f) + return Common::Rect(); + + Common::Rect rect = f->draw(surface); + + delete f; + + return rect; +} + +bool SequenceFrame::setFrame(uint16 frame) { + if (!_sequence) + return false; + + if (frame < _sequence->count()) { + _frame = frame; + return true; + } else + return false; +} + +bool SequenceFrame::nextFrame() { + return setFrame(_frame + 1); +} + +FrameInfo *SequenceFrame::getInfo() { + if (!_sequence) + error("SequenceFrame::getFrameInfo: Invalid sequence!"); + + return _sequence->getFrameInfo(_frame); +} + +Common::String SequenceFrame::getName() { + if (!_sequence) + error("SequenceFrame::getName: Invalid sequence!"); + + return _sequence->getName(); +} + +bool SequenceFrame::equal(const SequenceFrame *other) const { + return _sequence->getName() == other->_sequence->getName() && _frame == other->_frame; +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/sequence.h b/engines/lastexpress/data/sequence.h new file mode 100644 index 00000000000..25170993dfe --- /dev/null +++ b/engines/lastexpress/data/sequence.h @@ -0,0 +1,205 @@ +/* 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 LASTEXPRESS_SEQUENCE_H +#define LASTEXPRESS_SEQUENCE_H + +/* + Sequence format (.SEQ / .NIS (frame header & data only)) + + uint32 {4} - Number of frames in sequence + uint32 {4} - Unknown + + frames headers (68 bytes): + // for each frame + uint32 {4} - Data offset (from beginning of file) + uint32 {4} - Unknown + uint32 {4} - Palette offset (from beginning of file) + uint32 {4} - Top-left X coordinate + uint32 {4} - Top-left Y coordinate + uint32 {4} - Bottom-right X coordinate + uint32 {4} - Bottom-right Y coordinate + uint32 {4} - Initial offset of decompressed data (doubled, since each pixel occupies one color word) + uint32 {4} - End of data after decompression + + (for SEQ files only) + uint16 {2} - Hotspot left + uint16 {2} - Hotspot right + uint16 {2} - Hotspot top + uint16 {2} - Hotspot bottom + byte {1} - Compression type + byte {1} - Subtype (determines which set of decompression functions will be called) => 0, 1, 2, 3 + byte {1} - Unknown + byte {1} - Unknown + uint16 {2} - Unknown + byte {1} - Sound action + byte {1} - Unknown + uint32 {4} - positionId + uint32 {4} - Unknown + uint16 {2} - Entity Position + uint16 {2} - Location (~z-order) + uint32 {4} - Next sequence in the linked list + + (for NIS files: found at 0x124) + byte {1} - Compression type + + palette data: + uint16 {x} - palette data (max size: 256) + + data + byte {x} - compressed image data +*/ + +#include "lastexpress/drawable.h" + +#include "lastexpress/shared.h" + +#include "common/array.h" +#include "common/stream.h" + +namespace LastExpress { + +enum FrameSubType { + kFrameTypeNone = 0, + kFrameType1 = 1, + kFrameType2 = 2, + kFrameType3 = 3 +}; + +struct FrameInfo { + void read(Common::SeekableReadStream *in, bool isSequence); + + uint32 dataOffset; ///< Data offset (from beginning of file) + uint32 unknown; ///< FIXME: unknown data + uint32 paletteOffset; ///< Palette offset (from beginning of file) + uint32 xPos1; ///< Top-left X coordinate + uint32 yPos1; ///< Top-left Y coordinate + uint32 xPos2; ///< Bottom-right X coordinate + uint32 yPos2; ///< Bottom-right Y coordinate + uint32 initialSkip; ///< Initial on-screen offset of decompressed data (doubled, since each pixel occupies one color word) + uint32 decompressedEndOffset; ///< End of data after decompression + + // NIS frame headers end here. SEQ frame headers have additional 32 bytes of + // data, notably the compression type at the position outlined above in + // CompPos_SEQ + + Common::Rect hotspot; + + byte compressionType; ///< Type of frame compression (0x03, 0x04, 0x05, 0x07, 0xFF) + FrameSubType subType; ///< Subtype (byte) + + byte field_2E; + byte keepPreviousFrame; + byte field_30; + byte field_31; + byte soundAction; + byte field_33; + Position position; + byte field_35; + int16 field_36; + uint32 field_38; + EntityPosition entityPosition; + uint16 location; + uint32 next; +}; + +class AnimFrame : public Drawable { +public: + AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f); + ~AnimFrame(); + Common::Rect draw(Graphics::Surface *s); + +private: + void decomp3(Common::SeekableReadStream *in, const FrameInfo &f); + void decomp4(Common::SeekableReadStream *in, const FrameInfo &f); + void decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byte mask, byte shift); + void decomp5(Common::SeekableReadStream *in, const FrameInfo &f); + void decomp7(Common::SeekableReadStream *in, const FrameInfo &f); + void decompFF(Common::SeekableReadStream *in, const FrameInfo &f); + void readPalette(Common::SeekableReadStream *in, const FrameInfo &f); + + Graphics::Surface _image; + uint16 _palSize; + uint16 *_palette; + Common::Rect _rect; +}; + +class Sequence { +public: + Sequence(Common::String name) : _stream(NULL), _isLoaded(false), _name(name), _field30(15) {} + ~Sequence(); + + static Sequence *load(Common::String name, Common::SeekableReadStream *stream = NULL, byte field30 = 15); + + bool load(Common::SeekableReadStream *stream, byte field30 = 15); + + uint16 count() const { return (uint16)_frames.size(); } + AnimFrame *getFrame(uint16 index = 0); + FrameInfo *getFrameInfo(uint16 index = 0); + + Common::String getName() { return _name; } + byte getField30() { return _field30; } + + bool isLoaded() { return _isLoaded; } + +private: + static const uint32 _sequenceHeaderSize = 8; + static const uint32 _sequenceFrameSize = 68; + + void reset(); + + Common::Array _frames; + Common::SeekableReadStream *_stream; + bool _isLoaded; + + Common::String _name; + byte _field30; // used when copying sequences +}; + +class SequenceFrame : public Drawable { +public: + SequenceFrame(Sequence *sequence, uint16 frame = 0, bool dispose = false) : _sequence(sequence), _frame(frame), _dispose(dispose) {} + ~SequenceFrame(); + + Common::Rect draw(Graphics::Surface *surface); + + bool setFrame(uint16 frame); + uint32 getFrame() { return _frame; } + bool nextFrame(); + + Common::String getName(); + FrameInfo *getInfo(); + + bool equal(const SequenceFrame *other) const; + +private: + Sequence *_sequence; + uint16 _frame; + bool _dispose; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SEQUENCE_H diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp new file mode 100644 index 00000000000..496bd587728 --- /dev/null +++ b/engines/lastexpress/data/snd.cpp @@ -0,0 +1,141 @@ +/* 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$ + * + */ + +// Based on the Xentax Wiki documentation: +// http://wiki.xentax.com/index.php/The_Last_Express_SND + +#include "lastexpress/data/snd.h" + +#include "lastexpress/debug.h" + +#include "sound/decoders/adpcm.h" +#include "sound/audiostream.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Sound +////////////////////////////////////////////////////////////////////////// +SimpleSound::SimpleSound() : _size(0), _blocks(0), _blockSize(0) {} + +SimpleSound::~SimpleSound() { + stop(); +} + +// Stop the sound +void SimpleSound::stop() const { + g_system->getMixer()->stopHandle(_handle); +} + +void SimpleSound::loadHeader(Common::SeekableReadStream *in) { + _size = in->readUint32LE(); + _blocks = in->readUint16LE(); + debugC(5, kLastExpressDebugSound, " sound header data: size=\"%d\", %d blocks", _size, _blocks); + + assert (_size % _blocks == 0); + _blockSize = _size / _blocks; +} + +Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size) const { + return Audio::makeADPCMStream(in, DisposeAfterUse::YES, size, Audio::kADPCMMSImaLastExpress, 44100, 1, _blockSize); +} + +void SimpleSound::play(Audio::AudioStream *as) { + g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, as); +} + +////////////////////////////////////////////////////////////////////////// +// StreamedSound +////////////////////////////////////////////////////////////////////////// +StreamedSound::StreamedSound() {} +StreamedSound::~StreamedSound() {} + +bool StreamedSound::load(Common::SeekableReadStream *stream) { + if (!stream) + return false; + + g_system->getMixer()->stopHandle(_handle); + + loadHeader(stream); + + // Start decoding the input stream + Audio::AudioStream *as = makeDecoder(stream, _size); + + // Start playing the decoded audio stream + play(as); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +// StreamedSound +////////////////////////////////////////////////////////////////////////// +AppendableSound::AppendableSound() : SimpleSound() { + // Create an audio stream where the decoded chunks will be appended + _as = Audio::makeQueuingAudioStream(44100, false); + _finished = false; + + // Start playing the decoded audio stream + play(_as); + + // Initialize the block size + // TODO: get it as an argument? + _blockSize = 739; +} + +AppendableSound::~AppendableSound() { + finish(); + + _as = NULL; +} + +void AppendableSound::queueBuffer(const byte *data, uint32 size) { + Common::MemoryReadStream *buffer = new Common::MemoryReadStream(data, size); + queueBuffer(buffer); +} + +void AppendableSound::queueBuffer(Common::SeekableReadStream *bufferIn) { + if (!_as) + error("AppendableSound::queueBuffer - internal error: the audio stream is invalid!"); + + // Setup the ADPCM decoder + uint32 sizeIn = (uint32)bufferIn->size(); + Audio::AudioStream *adpcm = makeDecoder(bufferIn, sizeIn); + + // Queue the stream + _as->queueAudioStream(adpcm); +} + +void AppendableSound::finish() { + if (!_as) + error("AppendableSound::queueBuffer - internal error: the audio stream is invalid!"); + + if (!_finished) + _as->finish(); + + _finished = true; +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h new file mode 100644 index 00000000000..2e0bc8c1b08 --- /dev/null +++ b/engines/lastexpress/data/snd.h @@ -0,0 +1,97 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef LASTEXPRESS_SND_H +#define LASTEXPRESS_SND_H + +/* + Sound format (.SND / .LNK) + + uint32 {4} - data size + uint16 {2} - number of blocks + + // for each block + int16 {2} - initial sample + byte {1} - initial index + byte {1} - unused (00) + byte {x} - IMA ADPCM sample codes +*/ + +#include "common/stream.h" +#include "sound/mixer.h" + +namespace Audio { + class AudioStream; + class QueuingAudioStream; +} + +namespace LastExpress { + +class SimpleSound { +public: + SimpleSound(); + virtual ~SimpleSound(); + + void stop() const; + +protected: + void loadHeader(Common::SeekableReadStream *in); + Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size) const; + void play(Audio::AudioStream *as); + + uint32 _size; ///< data size + ///< - NIS: size of all blocks, including those located in the matching LNK file + ///< - LNK: size of the LNK file itself, including the header + ///< - SND: size of all blocks + uint16 _blocks; ///< number of blocks + uint32 _blockSize; + Audio::SoundHandle _handle; +}; + +class StreamedSound : public SimpleSound { +public: + StreamedSound(); + ~StreamedSound(); + + bool load(Common::SeekableReadStream *stream); +}; + +class AppendableSound : public SimpleSound { +public: + AppendableSound(); + ~AppendableSound(); + + void queueBuffer(const byte *data, uint32 size); + void queueBuffer(Common::SeekableReadStream *bufferIn); + void finish(); + +private: + Audio::QueuingAudioStream *_as; + bool _finished; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SND_H diff --git a/engines/lastexpress/data/subtitle.cpp b/engines/lastexpress/data/subtitle.cpp new file mode 100644 index 00000000000..67d6445ab93 --- /dev/null +++ b/engines/lastexpress/data/subtitle.cpp @@ -0,0 +1,244 @@ +/* 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$ + * + */ + +// Based on the Xentax Wiki documentation: +// http://wiki.xentax.com/index.php/The_Last_Express_SBE + +#include "lastexpress/data/subtitle.h" + +#include "lastexpress/data/font.h" + +#include "lastexpress/debug.h" + +#include "common/debug.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Subtitle +////////////////////////////////////////////////////////////////////////// +class Subtitle { +public: + Subtitle() : _timeStart(0), _timeStop(0), _topLength(0), _topText(NULL), + _bottomLength(0), _bottomText(NULL) {} + ~Subtitle() { reset(); } + + bool load(Common::SeekableReadStream *in); + Common::Rect draw(Graphics::Surface *surface, Font *font); + + uint16 getTimeStart() const { return _timeStart; } + uint16 getTimeStop() const { return _timeStop; } + +private: + uint16 _timeStart; ///< display start time + uint16 _timeStop; ///< display stop time + + uint16 _topLength; ///< top line length + uint16 *_topText; ///< bottom line length + + uint16 _bottomLength; ///< top line (UTF-16 string) + uint16 *_bottomText; ///< bottom line (UTF-16 string) + + void reset(); +}; + +void Subtitle::reset() { + delete[] _topText; + delete[] _bottomText; + _topText = NULL; + _bottomText = NULL; +} + +template +T *newArray(size_t n) { + if (n <= (size_t)-1 / sizeof(T)) + return new T[n]; + + // n is too large + return NULL; +} + +bool Subtitle::load(Common::SeekableReadStream *in) { + reset(); + + if (!in) + return false; + + // Read the display times + _timeStart = in->readUint16LE(); + _timeStop = in->readUint16LE(); + + // Read the text lengths + _topLength = in->readUint16LE(); + _bottomLength = in->readUint16LE(); + + // Create the buffers + if (_topLength) { + _topText = newArray(_topLength + 1); + if (!_topText) + return false; + + _topText[_topLength] = 0; + } + if (_bottomLength) { + _bottomText = newArray(_bottomLength + 1); + if (!_bottomText) + return false; + + _bottomText[_bottomLength] = 0; + } + + // Read the texts + for (int i = 0; i < _topLength; i++) + _topText[i] = in->readUint16LE(); + for (int i = 0; i < _bottomLength; i++) + _bottomText[i] = in->readUint16LE(); + + debugC(9, kLastExpressDebugSubtitle, " %d -> %d:", _timeStart, _timeStop); + if (_topLength) + debugC(9, kLastExpressDebugSubtitle, "\t%ls", (wchar_t *)_topText); + if (_bottomLength) + debugC(9, kLastExpressDebugSubtitle, "\t%ls", (wchar_t *)_bottomText); + + return true; +} + +Common::Rect Subtitle::draw(Graphics::Surface *surface, Font *font) { + Common::Rect rectTop, rectBottom; + + //FIXME find out proper subtitles coordinates (and hope it's hardcoded and not stored in the sequence or animation) + rectTop = font->drawString(surface, 100, 100, _topText, _topLength); + rectBottom = font->drawString(surface, 100, 300, _bottomText, _bottomLength); + + rectTop.extend(rectBottom); + + return rectTop; +} + + +////////////////////////////////////////////////////////////////////////// +// SubtitleManager +////////////////////////////////////////////////////////////////////////// +SubtitleManager::SubtitleManager(Font *font) : _font(font), _maxTime(0), _currentIndex(-1), _lastIndex(-1) {} + +SubtitleManager::~SubtitleManager() { + reset(); + + // Zero passed pointers + _font = NULL; +} + +void SubtitleManager::reset() { + for (int i = 0; i < (int)_subtitles.size(); i++) + delete _subtitles[i]; + + _subtitles.clear(); + _currentIndex = -1; + _lastIndex = -1; +} + +bool SubtitleManager::load(Common::SeekableReadStream *stream) { + if (!stream) + return false; + + reset(); + + // Read header to get the number of subtitles + uint32 numSubtitles = stream->readUint16LE(); + if (stream->eos()) + error("Cannot read from subtitle file"); + + debugC(3, kLastExpressDebugSubtitle, "Number of subtitles in file: %d", numSubtitles); + + // TODO: Check that stream contain enough data + //if (stream->size() < (signed)(numSubtitles * sizeof(SubtitleData))) { + //debugC(2, kLastExpressDebugSubtitle, "Subtitle file does not contain valid data!"); + //return false; + //} + + // Read the list of subtitles + _maxTime = 0; + for (uint i = 0; i < numSubtitles; i++) { + Subtitle *subtitle = new Subtitle(); + if (!subtitle->load(stream)) { + // Failed to read this line + reset(); + + delete subtitle; + + return false; + } + + // Update the max time + if (subtitle->getTimeStop() > _maxTime) + _maxTime = subtitle->getTimeStop(); + + _subtitles.push_back(subtitle); + } + + delete stream; + + return true; +} + +uint16 SubtitleManager::getMaxTime() const { + return _maxTime; +} + +void SubtitleManager::setTime(uint16 time) { + _currentIndex = -1; + + // Find the appropriate line to show + for (int16 i = 0; i < (int16)_subtitles.size(); i++) { + if ((time >= _subtitles[i]->getTimeStart()) && (time <= _subtitles[i]->getTimeStop())) { + // Keep the index of the line to show + _currentIndex = i; + return; + } + } +} + +bool SubtitleManager::hasChanged() const { + // TODO: mark the old line rect as dirty + if (_currentIndex != _lastIndex) + return true; + else + return false; +} + +Common::Rect SubtitleManager::draw(Graphics::Surface *surface) { + // Update the last drawn index + _lastIndex = _currentIndex; + + // Return if we don't have to draw any line + if (_currentIndex == -1) + return Common::Rect(); + + // Draw the current line + assert(_currentIndex >= 0 && _currentIndex < (int16)_subtitles.size()); + return _subtitles[_currentIndex]->draw(surface, _font); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/data/subtitle.h b/engines/lastexpress/data/subtitle.h new file mode 100644 index 00000000000..9acb7068f17 --- /dev/null +++ b/engines/lastexpress/data/subtitle.h @@ -0,0 +1,79 @@ +/* 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 LASTEXPRESS_SUBTITLE_H +#define LASTEXPRESS_SUBTITLE_H + +/* + Subtitle format (.SBE) + + uint16 {2} - number of subtitles + + // for each subtitle + uint16 {2} - display start time + uint16 {2} - display stop time + uint16 {2} - top line length + uint16 {2} - bottom line length + byte {x} - top line (UTF-16 string) + byte {x} - bottom line (UTF-16 string) + + Subtitles seem to be drawn on screen at (80, 420) x (560, 458) +*/ + +#include "lastexpress/drawable.h" + +#include "common/array.h" +#include "common/stream.h" + +namespace LastExpress { + +class Font; +class Subtitle; + +class SubtitleManager : public Drawable { +public: + SubtitleManager(Font *font); + ~SubtitleManager(); + + bool load(Common::SeekableReadStream *stream); + uint16 getMaxTime() const; + void setTime(uint16 time); + bool hasChanged() const; + Common::Rect draw(Graphics::Surface *surface); + +private: + Common::Array _subtitles; + Font *_font; + uint16 _maxTime; + + int16 _currentIndex; + int16 _lastIndex; + + void reset(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SUBTITLE_H diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp new file mode 100644 index 00000000000..35a87cf14b6 --- /dev/null +++ b/engines/lastexpress/debug.cpp @@ -0,0 +1,1178 @@ +/* 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 "lastexpress/debug.h" + +// Data +#include "lastexpress/data/animation.h" +#include "lastexpress/data/background.h" +#include "lastexpress/data/cursor.h" +#include "lastexpress/data/scene.h" +#include "lastexpress/data/sequence.h" +#include "lastexpress/data/snd.h" +#include "lastexpress/data/subtitle.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/beetle.h" +#include "lastexpress/game/fight.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savegame.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/graphics.h" +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +#include "common/debug-channels.h" +#include "common/events.h" +#include "common/md5.h" + +namespace LastExpress { + +Debugger::Debugger(LastExpressEngine *engine) : _engine(engine), _command(NULL), _numParams(0), _commandParams(NULL) { + + ////////////////////////////////////////////////////////////////////////// + // Register the debugger commands + + // General + DCmd_Register("help", WRAP_METHOD(Debugger, cmdHelp)); + + // Data + DCmd_Register("ls", WRAP_METHOD(Debugger, cmdListFiles)); + DCmd_Register("dump", WRAP_METHOD(Debugger, cmdDumpFiles)); + + DCmd_Register("showframe", WRAP_METHOD(Debugger, cmdShowFrame)); + DCmd_Register("showbg", WRAP_METHOD(Debugger, cmdShowBg)); + DCmd_Register("playseq", WRAP_METHOD(Debugger, cmdPlaySeq)); + DCmd_Register("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd)); + DCmd_Register("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe)); + DCmd_Register("playnis", WRAP_METHOD(Debugger, cmdPlayNis)); + + // Scene & interaction + DCmd_Register("loadscene", WRAP_METHOD(Debugger, cmdLoadScene)); + DCmd_Register("fight", WRAP_METHOD(Debugger, cmdFight)); + DCmd_Register("beetle", WRAP_METHOD(Debugger, cmdBeetle)); + + // Game + DCmd_Register("delta", WRAP_METHOD(Debugger, cmdTimeDelta)); + DCmd_Register("time", WRAP_METHOD(Debugger, cmdTime)); + DCmd_Register("show", WRAP_METHOD(Debugger, cmdShow)); + DCmd_Register("entity", WRAP_METHOD(Debugger, cmdEntity)); + + // Misc + DCmd_Register("loadgame", WRAP_METHOD(Debugger, cmdLoadGame)); + DCmd_Register("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter)); + DCmd_Register("clear", WRAP_METHOD(Debugger, cmdClear)); + + resetCommand(); + + _soundStream = new StreamedSound(); +} + +Debugger::~Debugger() { + DebugMan.clearAllDebugChannels(); + + delete _soundStream; + resetCommand(); + + _command = NULL; + _commandParams = NULL; + + // Zero passed pointers + _engine = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Helper functions +////////////////////////////////////////////////////////////////////////// +bool Debugger::hasCommand() const { + return (_numParams != 0); +} + +void Debugger::resetCommand() { + SAFE_DELETE(_command); + + if (_commandParams) + for (int i = 0; i < _numParams; i++) + free(_commandParams[i]); + + free(_commandParams); + _commandParams = NULL; + _numParams = 0; +} + +int Debugger::getNumber(const char *arg) const { + return strtol(arg, (char **)NULL, 0); +} + +void Debugger::copyCommand(int argc, const char **argv) { + _commandParams = (char **)malloc(sizeof(char *) * (uint)argc); + if (!_commandParams) + return; + + _numParams = argc; + + for (int i = 0; i < _numParams; i++) { + _commandParams[i] = (char *)malloc(strlen(argv[i]) + 1); + memset(_commandParams[i], 0, strlen(argv[i]) + 1); + strcpy(_commandParams[i], argv[i]); + } + + // Exit the debugger! + Cmd_Exit(0, 0); +} + +void Debugger::callCommand() { + if (_command) + (*_command)(_numParams, const_cast(_commandParams)); +} + +void Debugger::loadArchive(ArchiveIndex index) const { + _engine->getResourceManager()->loadArchive(index); + getScenes()->loadSceneDataFile(index); +} + +// Restore loaded archive +void Debugger::restoreArchive() const { + + ArchiveIndex index = kArchiveCd1; + + switch (getProgress().chapter) { + default: + case kChapter1: + index = kArchiveCd1; + break; + + case kChapter2: + case kChapter3: + index = kArchiveCd2; + break; + + case kChapter4: + case kChapter5: + index = kArchiveCd3; + break; + } + + _engine->getResourceManager()->loadArchive(index); + getScenes()->loadSceneDataFile(index); +} + +////////////////////////////////////////////////////////////////////////// +// Debugger commands +////////////////////////////////////////////////////////////////////////// +bool Debugger::cmdHelp(int, const char **) { + DebugPrintf("Debug flags\n"); + DebugPrintf("-----------\n"); + DebugPrintf(" debugflag_list - Lists the available debug flags and their status\n"); + DebugPrintf(" debugflag_enable - Enables a debug flag\n"); + DebugPrintf(" debugflag_disable - Disables a debug flag\n"); + DebugPrintf("\n"); + DebugPrintf("Commands\n"); + DebugPrintf("--------\n"); + DebugPrintf(" ls - list files in the archive\n"); + DebugPrintf(" dump - dump a list of files in all archives\n"); + DebugPrintf("\n"); + DebugPrintf(" showframe - show a frame from a sequence\n"); + DebugPrintf(" showbg - show a background\n"); + DebugPrintf(" playseq - play a sequence\n"); + DebugPrintf(" playsnd - play a sound\n"); + DebugPrintf(" playsbe - play a subtitle\n"); + DebugPrintf(" playnis - play an animation\n"); + DebugPrintf("\n"); + DebugPrintf(" loadscene - load a scene\n"); + DebugPrintf(" fight - start a fight\n"); + DebugPrintf(" beetle - start the beetle game\n"); + DebugPrintf("\n"); + DebugPrintf(" delta - Adjust the time delta\n"); + DebugPrintf(" show - show game data\n"); + DebugPrintf(" entity - show entity data\n"); + DebugPrintf("\n"); + DebugPrintf(" loadgame - load a saved game\n"); + DebugPrintf(" chapter - switch to a specific chapter\n"); + DebugPrintf(" clear - clear the screen\n"); + DebugPrintf("\n"); + return true; +} + +/** + * Command: list files in archive + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdListFiles(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + Common::String filter(const_cast(argv[1])); + + // Load the proper archive + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + Common::ArchiveMemberList list; + int count = _engine->getResourceManager()->listMatchingMembers(list, filter); + + DebugPrintf("Number of matches: %d\n", count); + for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) + DebugPrintf(" %s\n", (*it)->getName().c_str()); + + // Restore archive + if (argc == 3) + restoreArchive(); + } else { + DebugPrintf("Syntax: ls (use * for all) ()\n"); + } + + return true; +} + +/** + * Command: Dump the list of files in the archive + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdDumpFiles(int argc, const char **) { +#define OUTPUT_ARCHIVE_FILES(name, filename) { \ + _engine->getResourceManager()->reset(); \ + _engine->getResourceManager()->loadArchive(filename); \ + Common::ArchiveMemberList list; \ + int count = _engine->getResourceManager()->listMatchingMembers(list, "*"); \ + debugC(1, kLastExpressDebugResource, "\n\n--------------------------------------------------------------------\n"); \ + debugC(1, kLastExpressDebugResource, "-- " #name " (%d files)\n", count); \ + debugC(1, kLastExpressDebugResource, "--------------------------------------------------------------------\n\n"); \ + debugC(1, kLastExpressDebugResource, "Filename,Size,MD5\n"); \ + for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { \ + Common::SeekableReadStream *stream = getArchive((*it)->getName()); \ + if (!stream) { \ + DebugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \ + restoreArchive(); \ + return true; \ + } \ + char md5str[32+1]; \ + Common::md5_file_string(*stream, md5str, (uint32)stream->size()); \ + debugC(1, kLastExpressDebugResource, "%s, %d, %s", (*it)->getName().c_str(), stream->size(), (char *)&md5str); \ + delete stream; \ + } \ +} + + if (argc == 1) { + // For each archive file, dump the list of files + if (_engine->isDemo()) { + OUTPUT_ARCHIVE_FILES("DEMO", "DEMO.HPF"); + } else { + OUTPUT_ARCHIVE_FILES("HD", "HD.HPF"); + OUTPUT_ARCHIVE_FILES("CD 1", "CD1.HPF"); + OUTPUT_ARCHIVE_FILES("CD 2", "CD2.HPF"); + OUTPUT_ARCHIVE_FILES("CD 3", "CD3.HPF"); + } + + // Restore current loaded archive + restoreArchive(); + } else { + DebugPrintf("Syntax: dump"); + } + + return true; +} + +/** + * Command: Shows a frame + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdShowFrame(int argc, const char **argv) { + if (argc == 3 || argc == 4) { + Common::String filename(const_cast(argv[1])); + filename += ".seq"; + + if (argc == 4) + loadArchive((ArchiveIndex)getNumber(argv[3])); + + if (!_engine->getResourceManager()->hasFile(filename)) { + DebugPrintf("Cannot find file: %s\n", filename.c_str()); + return true; + } + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdShowFrame); + copyCommand(argc, argv); + + return Cmd_Exit(0, 0); + } else { + Sequence sequence(filename); + if (sequence.load(getArchive(filename))) { + _engine->getCursor()->show(false); + clearBg(GraphicsManager::kBackgroundOverlay); + + AnimFrame *frame = sequence.getFrame((uint16)getNumber(argv[2])); + if (!frame) { + DebugPrintf("Invalid frame index: %i\n", filename.c_str()); + resetCommand(); + return true; + } + + _engine->getGraphicsManager()->draw(frame, GraphicsManager::kBackgroundOverlay); + delete frame; + + askForRedraw(); + redrawScreen(); + + _engine->_system->delayMillis(1000); + _engine->getCursor()->show(true); + } + + resetCommand(); + + if (argc == 4) + restoreArchive(); + } + } else { + DebugPrintf("Syntax: cmd_showframe ()\n"); + } + return true; +} + +/** + * Command: shows a background + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdShowBg(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + Common::String filename(const_cast(argv[1])); + + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + if (!_engine->getResourceManager()->hasFile(filename + ".BG")) { + DebugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str()); + return true; + } + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdShowBg); + copyCommand(argc, argv); + + return Cmd_Exit(0, 0); + } else { + clearBg(GraphicsManager::kBackgroundC); + + Background *background = _engine->getResourceManager()->loadBackground(filename); + if (background) { + _engine->getGraphicsManager()->draw(background, GraphicsManager::kBackgroundC); + delete background; + askForRedraw(); + } + + redrawScreen(); + + if (argc == 3) + restoreArchive(); + + // Pause for a second to be able to see the background + _engine->_system->delayMillis(1000); + + resetCommand(); + } + } else { + DebugPrintf("Syntax: showbg ()\n"); + } + return true; +} + +/** + * Command: plays a sequence. + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdPlaySeq(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + Common::String filename(const_cast(argv[1])); + filename += ".seq"; + + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + if (!_engine->getResourceManager()->hasFile(filename)) { + DebugPrintf("Cannot find file: %s\n", filename.c_str()); + return true; + } + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdPlaySeq); + copyCommand(argc, argv); + + return Cmd_Exit(0, 0); + } else { + Sequence *sequence = new Sequence(filename); + if (sequence->load(getArchive(filename))) { + + // Check that we have at least a frame to show + if (sequence->count() == 0) { + delete sequence; + return false; + } + + _engine->getCursor()->show(false); + + SequenceFrame player(sequence, 0, true); + do { + // Clear screen + clearBg(GraphicsManager::kBackgroundA); + + _engine->getGraphicsManager()->draw(&player, GraphicsManager::kBackgroundA); + + askForRedraw(); + redrawScreen(); + + // Handle right-click to interrupt sequence + Common::Event ev; + _engine->getEventManager()->pollEvent(ev); + if (ev.type == Common::EVENT_RBUTTONUP) + break; + + _engine->_system->delayMillis(175); + + // go to the next frame + } while (player.nextFrame()); + _engine->getCursor()->show(true); + } else { + // Sequence player is deleting his reference to the sequence, but we need to take care of it if the + // sequence could not be loaded + delete sequence; + } + + resetCommand(); + + if (argc == 3) + restoreArchive(); + } + } else { + DebugPrintf("Syntax: playseq ()\n"); + } + return true; +} + +/** + * Command: plays a sound + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdPlaySnd(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + // Add .SND at the end of the filename if needed + Common::String name(const_cast(argv[1])); + if (!name.contains('.')) + name += ".SND"; + + if (!_engine->getResourceManager()->hasFile(name)) { + DebugPrintf("Cannot find file: %s\n", name.c_str()); + return true; + } + + _engine->_system->getMixer()->stopAll(); + + _soundStream->load(getArchive(name)); + + if (argc == 3) + restoreArchive(); + } else { + DebugPrintf("Syntax: playsnd ()\n"); + } + return true; +} + +/** + * Command: plays subtitles + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdPlaySbe(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + Common::String filename(const_cast(argv[1])); + + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + filename += ".sbe"; + + if (!_engine->getResourceManager()->hasFile(filename)) { + DebugPrintf("Cannot find file: %s\n", filename.c_str()); + return true; + } + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdPlaySbe); + copyCommand(argc, argv); + + return Cmd_Exit(0, 0); + } else { + SubtitleManager subtitle(_engine->getFont()); + if (subtitle.load(getArchive(filename))) { + _engine->getCursor()->show(false); + for (uint16 i = 0; i < subtitle.getMaxTime(); i += 25) { + clearBg(GraphicsManager::kBackgroundAll); + + subtitle.setTime(i); + _engine->getGraphicsManager()->draw(&subtitle, GraphicsManager::kBackgroundOverlay); + + askForRedraw(); + redrawScreen(); + + // Handle right-click to interrupt sequence + Common::Event ev; + _engine->getEventManager()->pollEvent(ev); + if (ev.type == Common::EVENT_RBUTTONUP) + break; + + _engine->_system->delayMillis(500); + } + _engine->getCursor()->show(true); + } + + if (argc == 3) + restoreArchive(); + + resetCommand(); + } + } else { + DebugPrintf("Syntax: playsbe ()\n"); + } + return true; +} + +/** + * Command: plays a NIS animation sequence. + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdPlayNis(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + Common::String name(const_cast(argv[1])); + + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + // If we got a nis filename, check that the file exists + if (name.contains('.') && _engine->getResourceManager()->hasFile(name)) { + DebugPrintf("Cannot find file: %s\n", name.c_str()); + return true; + } + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdPlayNis); + copyCommand(argc, argv); + + return Cmd_Exit(0, 0); + } else { + // Make sure we are not called in a loop + _numParams = 0; + + + // Check if we got a nis filename or an animation index + if (name.contains('.')) { + Animation animation; + if (animation.load(getArchive(name))) { + _engine->getCursor()->show(false); + animation.play(); + _engine->getCursor()->show(true); + } + } else { + getAction()->playAnimation((EventIndex)atoi(name.c_str()), true); + } + + if (argc == 3) + restoreArchive(); + + resetCommand(); + } + } else { + DebugPrintf("Syntax: playnis ()\n"); + } + return true; +} + +/** + * Command: loads a scene + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdLoadScene(int argc, const char **argv) { + if (argc == 2 || argc == 3) { + int cd = 1; + SceneIndex index = (SceneIndex)getNumber(argv[1]); + + // Check args + if (argc == 3) + loadArchive((ArchiveIndex)getNumber(argv[2])); + + if (index > 2500) { + DebugPrintf("Error: invalid index value (0-2500)"); + return true; + } + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdLoadScene); + copyCommand(argc, argv); + + return Cmd_Exit(0, 0); + } else { + + clearBg(GraphicsManager::kBackgroundAll); + + /************ DEBUG *************************/ + // Use to find scenes with certain values + + //for (int i = index; i < 2500; i++) { + // loadSceneObject(scene, i); + + // if (scene.getHeader() && scene.getHeader()->car == 5 && scene.getHeader()->position == 81) { + // DebugPrintf("Found scene: %d", i); + + // // Draw scene found + // _engine->getGraphicsManager()->draw(&scene, GraphicsManager::kBackgroundC); + + // askForRedraw(); + // redrawScreen(); + // _engine->_system->delayMillis(500); + + // break; + // } + //} + + //delete _sceneLoader; + //resetCommand(); + //return true; + + /*********************************************/ + Scene *scene = getScenes()->get(index); + if (!scene) { + DebugPrintf("Cannot load scene %i from CD %i", index, cd); + resetCommand(); + + return true; + } + + _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC); + + askForRedraw(); + redrawScreen(); + + // Pause for a second to be able to see the scene + _engine->_system->delayMillis(500); + + if (argc == 3) + restoreArchive(); + + resetCommand(); + } + } else { + DebugPrintf("Syntax: loadscene ()\n"); + } + return true; +} + +/** + * Command: starts a fight sequence + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdFight(int argc, const char **argv) { + if (argc == 2) { + FightType type = (FightType)getNumber(argv[1]); + + // Load proper data file + ArchiveIndex index = kArchiveCd1; + switch (type) { + default: + goto error; + + case kFightMilos: + index = kArchiveCd1; + break; + + case kFightAnna: + index = kArchiveCd2; + break; + + case kFightIvo: + case kFightSalko: + case kFightVesna: + index = kArchiveCd3; + break; + } + + loadArchive(index); + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdFight); + copyCommand(argc, argv); + + return false; + } else { + // Make sure we are not called in a loop + _numParams = 0; + + clearBg(GraphicsManager::kBackgroundAll); + askForRedraw(); + redrawScreen(); + + SceneIndex lastScene = getState()->scene; + + getFight()->setup(type) ? DebugPrintf("Lost fight!\n") : DebugPrintf("Won fight!\n"); + + // Pause for a second to be able to see the final scene + _engine->_system->delayMillis(1000); + + // Restore loaded archive + restoreArchive(); + + // Stop audio and restore scene + getSound()->stopAllSound(); + + clearBg(GraphicsManager::kBackgroundAll); + + Scene *scene = getScenes()->get(lastScene); + _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC); + + askForRedraw(); + redrawScreen(); + + resetCommand(); + } + } else { +error: + DebugPrintf("Syntax: fight (id=2001-2005)\n"); + } + + return true; +} + +/** + * Command: starts the beetle sequence + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdBeetle(int argc, const char **argv) { + if (argc == 1) { + // Load proper data file (beetle game in in Cd2) + loadArchive(kArchiveCd2); + + // Store command + if (!hasCommand()) { + _command = WRAP_METHOD(Debugger, cmdBeetle); + copyCommand(argc, argv); + + return false; + } else { + clearBg(GraphicsManager::kBackgroundAll); + askForRedraw(); + redrawScreen(); + + // Save current state + SceneIndex previousScene = getState()->scene; + ObjectLocation previousLocation = getInventory()->get(kItemBeetle)->location; + ChapterIndex previousChapter = (ChapterIndex)getProgress().chapter; + + // Setup scene & inventory + getProgress().chapter = kChapter2; + Scene *scene = getScenes()->get(kSceneBeetle); + getInventory()->get(kItemBeetle)->location = kObjectLocation3; + + askForRedraw(); + redrawScreen(); + + // Load the beetle game + Action *action = NULL; + Beetle *beetle = new Beetle(_engine); + if (!beetle->isLoaded()) + beetle->load(); + + // Play the game + Common::Event ev; + bool playgame = true; + while (playgame) { + // Update beetle + beetle->update(); + + askForRedraw(); + redrawScreen(); + + while (g_engine->getEventManager()->pollEvent(ev)) { + + switch (ev.type) { + default: + break; + + case Common::EVENT_KEYDOWN: + // Exit beetle game on escape + if (ev.kbd.keycode == Common::KEYCODE_ESCAPE) + playgame = false; + + break; + + case Common::EVENT_MOUSEMOVE: { + // Update cursor + CursorStyle style = kCursorNormal; + SceneHotspot *hotspot = NULL; + if (scene->checkHotSpot(ev.mouse, &hotspot)) { + if (!action) + action = new Action(_engine); + + style = action->getCursor(*hotspot); + } + + _engine->getCursor()->setStyle(style); + break; + } + + + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + // Update coordinates + getLogic()->getGameState()->setCoordinates(ev.mouse); + + if (beetle->catchBeetle()) + playgame = false; + break; + } + + _engine->_system->delayMillis(10); + } + } + + // Cleanup + beetle->unload(); + delete beetle; + delete action; + + // Pause for a second to be able to see the final scene + _engine->_system->delayMillis(1000); + + // Restore state + getProgress().chapter = previousChapter; + getInventory()->get(kItemBeetle)->location = previousLocation; + + // Restore loaded archive + restoreArchive(); + + // Stop audio and restore scene + getSound()->stopAllSound(); + + clearBg(GraphicsManager::kBackgroundAll); + + Scene *oldScene = getScenes()->get(previousScene); + _engine->getGraphicsManager()->draw(oldScene, GraphicsManager::kBackgroundC); + + askForRedraw(); + redrawScreen(); + + resetCommand(); + } + } else { + DebugPrintf("Syntax: beetle\n"); + } + + return true; +} + +/** + * Command: adjusts the time delta + * + * @param argc The argument count. + * @param argv The values. + * + * @return true if it was handled, false otherwise + */ +bool Debugger::cmdTimeDelta(int argc, const char **argv) { + if (argc == 2) { + int delta = getNumber(argv[1]); + + if (delta <= 0 || delta > 500) + goto label_error; + + getState()->timeDelta = (uint)delta; + } else { +label_error: + DebugPrintf("Syntax: delta