diff options
50 files changed, 3046 insertions, 161 deletions
@@ -34,6 +34,8 @@ For a more comprehensive changelog of the latest experimental code, see: - The option to toggle sound effect types between digitized and synthesized has been disabled until a more user-friendly GUI option is possible. Digital sound effects are always preferred for now. + - Fixed a case where starting a new song didn't fully reset its channels, + thus some notes sounded wrong. 1.4.0 (2011-11-11) New Games: @@ -2039,6 +2039,10 @@ The Legend of Kyrandia adds the following non-standard keyword: walkspeed int The walk speed (0-4) +The 7th Guest adds the following non-standard keyword: + + t7g_speed string Video playback speed (normal, tweaked, im_an_ios) + 9.0) Compiling: ---- ---------- diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp index 4b707eace6..6a4a9fa909 100644 --- a/backends/midi/coreaudio.cpp +++ b/backends/midi/coreaudio.cpp @@ -27,22 +27,36 @@ #ifdef MACOSX -// HACK to disable deprecated warnings under Mac OS X 10.5. Apple deprecated the +// With the release of Mac OS X 10.5 in October 2007, Apple deprecated the // AUGraphNewNode & AUGraphGetNodeInfo APIs in favor of the new AUGraphAddNode & // AUGraphNodeInfo APIs. While it is easy to switch to those, it breaks // compatibility with all pre-10.5 systems. -// If you want to retain compatibility with old systems, enable the following -// switch. But Apple will eventually remove these APIs, at which point the -// switch needs to be disabled. // -// Also note that only the new API is available on the iPhone! -#define USE_DEPRECATED_COREAUDIO_API - +// Since 10.5 was the last system to support PowerPC, we use the old, deprecated +// APIs on PowerPC based systems by default. On all other systems (such as Mac +// OS X running on Intel hardware, or iOS running on ARM), we use the new API by +// default. +// +// This leaves Mac OS X 10.4 running on x86 processors as the only system +// combination that this code will not support by default. It seems quite +// reasonable to assume that anybody with an Intel system has since then moved +// on to a newer Mac OS X release. But if for some reason you absolutely need to +// build an x86 version of this code using the old, deprecated API, you can +// simply do so by manually enable the USE_DEPRECATED_COREAUDIO_API switch (e.g. +// by adding setting it suitably in CPPFLAGS). +#if !defined(USE_DEPRECATED_COREAUDIO_API) + #if TARGET_CPU_PPC || TARGET_CPU_PPC64 || !defined(MAC_OS_X_VERSION_10_6) + #define USE_DEPRECATED_COREAUDIO_API 1 + #else + #define USE_DEPRECATED_COREAUDIO_API 0 + #endif +#endif -#ifdef USE_DEPRECATED_COREAUDIO_API -#include <AvailabilityMacros.h> -#undef DEPRECATED_ATTRIBUTE -#define DEPRECATED_ATTRIBUTE +#if USE_DEPRECATED_COREAUDIO_API + #include <AvailabilityMacros.h> + // Try to silence warnings about use of deprecated APIs + #undef DEPRECATED_ATTRIBUTE + #define DEPRECATED_ATTRIBUTE #endif @@ -114,7 +128,7 @@ int MidiDriver_CORE::open() { RequireNoErr(NewAUGraph(&_auGraph)); AUNode outputNode, synthNode; -#ifdef USE_DEPRECATED_COREAUDIO_API +#if USE_DEPRECATED_COREAUDIO_API ComponentDescription desc; #else AudioComponentDescription desc; @@ -126,7 +140,7 @@ int MidiDriver_CORE::open() { desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; -#ifdef USE_DEPRECATED_COREAUDIO_API +#if USE_DEPRECATED_COREAUDIO_API RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &outputNode)); #else RequireNoErr(AUGraphAddNode(_auGraph, &desc, &outputNode)); @@ -136,7 +150,7 @@ int MidiDriver_CORE::open() { desc.componentType = kAudioUnitType_MusicDevice; desc.componentSubType = kAudioUnitSubType_DLSSynth; desc.componentManufacturer = kAudioUnitManufacturer_Apple; -#ifdef USE_DEPRECATED_COREAUDIO_API +#if USE_DEPRECATED_COREAUDIO_API RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &synthNode)); #else RequireNoErr(AUGraphAddNode(_auGraph, &desc, &synthNode)); @@ -150,7 +164,7 @@ int MidiDriver_CORE::open() { RequireNoErr(AUGraphInitialize(_auGraph)); // Get the music device from the graph. -#ifdef USE_DEPRECATED_COREAUDIO_API +#if USE_DEPRECATED_COREAUDIO_API RequireNoErr(AUGraphGetNodeInfo(_auGraph, synthNode, NULL, NULL, NULL, &_synth)); #else RequireNoErr(AUGraphNodeInfo(_auGraph, synthNode, NULL, &_synth)); diff --git a/backends/platform/sdl/macosx/appmenu_osx.mm b/backends/platform/sdl/macosx/appmenu_osx.mm index bb089a6b61..97c7edba3e 100755 --- a/backends/platform/sdl/macosx/appmenu_osx.mm +++ b/backends/platform/sdl/macosx/appmenu_osx.mm @@ -35,6 +35,11 @@ - (void)setAppleMenu:(NSMenu *)menu; @end +NSString *constructNSStringFromCString(const char* rawCString, NSStringEncoding stringEncoding) { + NSData *nsData = [NSData dataWithBytes:rawCString length:strlen(rawCString)]; + return [[NSString alloc] initWithData:nsData encoding:stringEncoding]; +} + void replaceApplicationMenuItems() { // Code mainly copied and adapted from SDLmain.m @@ -50,34 +55,47 @@ void replaceApplicationMenuItems() { // Create new application menu appleMenu = [[NSMenu alloc] initWithTitle:@""]; + NSString *nsString = NULL; + // Get current encoding #ifdef USE_TRANSLATION - NSStringEncoding stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)[NSString stringWithCString:(TransMan.getCurrentCharset()).c_str() encoding:NSASCIIStringEncoding])); + nsString = constructNSStringFromCString((TransMan.getCurrentCharset()).c_str(), NSASCIIStringEncoding); + NSStringEncoding stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)nsString)); + [nsString release]; #else NSStringEncoding stringEncoding = NSASCIIStringEncoding; #endif - + // Add "About ScummVM" menu item - [appleMenu addItemWithTitle:[NSString stringWithCString:_("About ScummVM") encoding:stringEncoding] action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + nsString = constructNSStringFromCString(_("About ScummVM"), stringEncoding); + [appleMenu addItemWithTitle:nsString action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + [nsString release]; // Add separator [appleMenu addItem:[NSMenuItem separatorItem]]; // Add "Hide ScummVM" menu item - [appleMenu addItemWithTitle:[NSString stringWithCString:_("Hide ScummVM") encoding:stringEncoding] action:@selector(hide:) keyEquivalent:@"h"]; + nsString = constructNSStringFromCString(_("Hide ScummVM"), stringEncoding); + [appleMenu addItemWithTitle:nsString action:@selector(hide:) keyEquivalent:@"h"]; + [nsString release]; // Add "Hide Others" menu item - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:[NSString stringWithCString:_("Hide Others") encoding:stringEncoding] action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + nsString = constructNSStringFromCString(_("Hide Others"), stringEncoding); + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:nsString action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; // Add "Show All" menu item - [appleMenu addItemWithTitle:[NSString stringWithCString:_("Show All") encoding:stringEncoding] action:@selector(unhideAllApplications:) keyEquivalent:@""]; + nsString = constructNSStringFromCString(_("Show All"), stringEncoding); + [appleMenu addItemWithTitle:nsString action:@selector(unhideAllApplications:) keyEquivalent:@""]; + [nsString release]; // Add separator [appleMenu addItem:[NSMenuItem separatorItem]]; // Add "Quit ScummVM" menu item - [appleMenu addItemWithTitle:[NSString stringWithCString:_("Quit ScummVM") encoding:stringEncoding] action:@selector(terminate:) keyEquivalent:@"q"]; + nsString = constructNSStringFromCString(_("Quit ScummVM"), stringEncoding); + [appleMenu addItemWithTitle:nsString action:@selector(terminate:) keyEquivalent:@"q"]; + [nsString release]; // Put application menu into the menubar menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; @@ -89,16 +107,22 @@ void replaceApplicationMenuItems() { // Create new "Window" menu - windowMenu = [[NSMenu alloc] initWithTitle:[NSString stringWithCString:_("Window") encoding:stringEncoding]]; + nsString = constructNSStringFromCString(_("Window"), stringEncoding); + windowMenu = [[NSMenu alloc] initWithTitle:nsString]; + [nsString release]; // Add "Minimize" menu item - menuItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithCString:_("Minimize") encoding:stringEncoding] action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + nsString = constructNSStringFromCString(_("Minimize"), stringEncoding); + menuItem = [[NSMenuItem alloc] initWithTitle:nsString action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; + [nsString release]; // Put menu into the menubar - menuItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithCString:_("Window") encoding:stringEncoding] action:nil keyEquivalent:@""]; + nsString = constructNSStringFromCString(_("Window"), stringEncoding); + menuItem = [[NSMenuItem alloc] initWithTitle:nsString action:nil keyEquivalent:@""]; [menuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:menuItem]; + [nsString release]; // Tell the application object that this is now the window menu. [NSApp setWindowsMenu:windowMenu]; diff --git a/common/zlib.cpp b/common/zlib.cpp index 70133fea30..7d765fc539 100644 --- a/common/zlib.cpp +++ b/common/zlib.cpp @@ -49,7 +49,7 @@ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long return Z_OK == ::uncompress(dst, dstLen, src, srcLen); } -bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen) { +bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict, uint dictLen) { if (!dst || !dstLen || !src || !srcLen) return false; @@ -68,6 +68,13 @@ bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen) if (err != Z_OK) return false; + // Set the dictionary, if provided + if (dict != 0) { + err = inflateSetDictionary(&stream, const_cast<byte *>(dict), dictLen); + if (err != Z_OK) + return false; + } + err = inflate(&stream, Z_SYNC_FLUSH); if (err != Z_OK && err != Z_STREAM_END) { inflateEnd(&stream); diff --git a/common/zlib.h b/common/zlib.h index 7af7df0da8..61322c286a 100644 --- a/common/zlib.h +++ b/common/zlib.h @@ -37,7 +37,19 @@ class WriteStream; * it possible to uncompress data in engines without being forced to link * them against zlib, thus simplifying the build system. * - * @return true on success (i.e. Z_OK), false otherwise + * Taken from the zlib manual: + * Decompresses the src buffer into the dst buffer. + * srcLen is the byte length of the source buffer. Upon entry, dstLen is the + * total size of the destination buffer, which must be large enough to hold + * the entire uncompressed data. Upon exit, dstLen is the actual size of the + * compressed buffer. + * + * @param dst the buffer to store into. + * @param dstLen a pointer to the size of the destination buffer. + * @param src the data to be decompressed. + * @param srcLen the size of the compressed data. + * + * @return true on success (i.e. Z_OK), false otherwise. */ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long srcLen); @@ -46,9 +58,24 @@ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long * necessary inflate functions to uncompress data compressed with deflate * but *not* with the standard zlib header. * - * @return true on success (Z_OK or Z_STREAM_END), false otherwise + * Decompresses the src buffer into the dst buffer. + * srcLen is the byte length of the source buffer, dstLen is the byte + * length of the output buffer. + * It decompress as much data as possible, up to dstLen bytes. + * If a dictionary is provided through the dict buffer, uses it to initializes + * the internal decompression dictionary, before the decompression takes place. + * + * @param dst the buffer to store into. + * @param dstLen the size of the destination buffer. + * @param src the data to be decompressed. + * @param dstLen the size of the compressed data. + * @param dict (optional) a decompress dictionary. + * @param dictLen (optional) the size of the dictionary. + * Mandatory if dict is not 0. + * + * @return true on success (Z_OK or Z_STREAM_END), false otherwise. */ -bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen); +bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict = 0, uint dictLen = 0); #endif @@ -1682,7 +1682,7 @@ esac # Determine a data type with the given length # find_type_with_size() { - for datatype in int short char long unknown; do + for datatype in int short char long "long long" unknown; do cat > tmp_find_type_with_size.cpp << EOF typedef $datatype ac__type_sizeof_; int main() { @@ -1706,6 +1706,35 @@ EOF } # +# Check whether the system is 32-bit +# +pointer_is_32bit() { + cat > tmp_pointer_is_32bit.cpp << EOF +int main() { + static int test_array[1 - 2 * !(sizeof(void *) == 4)]; + test_array[0] = 0; + return 0; +} +EOF + $CXX $CXXFLAGS -c -o $TMPO.o tmp_pointer_is_32bit.cpp 2>/dev/null + status=$? + cc_check_clean tmp_pointer_is_32bit.cpp + return $status +} + +echo_n "Checking 64-bitness... " +pointer_is_32bit +if test $? -eq 0; then + type_ptr=int32 + echo "no" + add_line_to_config_h "/* #define SCUMM_64BITS */" +else + type_ptr=int64 + echo "yes" + add_line_to_config_h "#define SCUMM_64BITS" +fi + +# # Determine data type sizes # echo_n "Type with 1 byte... " @@ -1726,6 +1755,17 @@ TMPR="$?" echo "$type_4_byte" test $TMPR -eq 0 || exit 1 # check exit code of subshell +echo_n "Type with 8 bytes... " +type_8_byte=`find_type_with_size 8` +TMPR="$?" +echo "$type_8_byte" +if test $TMPR -eq 0; then + _def_64bit_type_signed="typedef signed $type_8_byte int64;" + _def_64bit_type_unsigned="typedef unsigned $type_8_byte uint64;" +fi +# force cleanup after check for 8 bytes type +cc_check_clean tmp_find_type_with_size.cpp + # # Check whether memory alignment is required # @@ -3853,6 +3893,17 @@ typedef signed $type_1_byte int8; typedef signed $type_2_byte int16; typedef signed $type_4_byte int32; +/* 64-bit stuff */ +$_def_64bit_type_signed +#if defined(__APPLE__) && !defined(__ppc__) +#ifndef _UINT64 +#define _UINT64 +$_def_64bit_type_unsigned +#endif +#else +$_def_64bit_type_unsigned +#endif + #endif /* CONFIG_H */ EOF diff --git a/dists/debian/copyright b/dists/debian/copyright index e0885ae9e6..318c06f62b 100644 --- a/dists/debian/copyright +++ b/dists/debian/copyright @@ -7,7 +7,7 @@ It was downloaded from <http://www.scummvm.org/>. Upstream Authors: see `/usr/share/doc/scummvm/AUTHORS'. -Scummvm is Copyright © 2002-2010 The ScummVM Project +Scummvm is Copyright © 2002-2012 The ScummVM Project 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 diff --git a/dists/macosx/DS_Store b/dists/macosx/DS_Store Binary files differindex 2d4193a6af..7ad5a19d61 100644 --- a/dists/macosx/DS_Store +++ b/dists/macosx/DS_Store diff --git a/dists/win32/ScummVM.iss b/dists/win32/ScummVM.iss index 7f3359f530..14536d0cbf 100644 --- a/dists/win32/ScummVM.iss +++ b/dists/win32/ScummVM.iss @@ -1,5 +1,5 @@ [Setup] -AppCopyright=2011 +AppCopyright=2012 AppName=ScummVM AppVerName=ScummVM Git AppPublisher=The ScummVM Team diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp index 154073250c..31dfe62dee 100644 --- a/engines/draci/barchive.cpp +++ b/engines/draci/barchive.cpp @@ -212,7 +212,8 @@ void BArchive::openArchive(const Common::String &path) { _files[i]._offset = fileOffset; // Offset of file from start - assert(_f.readByte() == 0 && + byte compressionType = _f.readByte(); + assert(compressionType == 0 && "Compression type flag is non-zero (file is compressed)"); _files[i]._crc = _f.readByte(); // CRC checksum of the file @@ -221,7 +222,8 @@ void BArchive::openArchive(const Common::String &path) { } // Last footer item should be equal to footerOffset - assert(reader.readUint32LE() == footerOffset && "Footer offset mismatch"); + uint32 footerOffset2 = reader.readUint32LE(); + assert(footerOffset2 == footerOffset && "Footer offset mismatch"); // Indicate that the archive has been successfully opened _opened = true; diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index 91aabc89d9..79c5e0d7be 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -195,6 +195,7 @@ DreamWebEngine::DreamWebEngine(OSystem *syst, const DreamWebGameDescription *gam _timedX = 0; _needToDumpTimed = 0; _loadingOrSave = 0; + _saveLoadPage = 0; _currentSlot = 0; _cursorPos = 0; _colourPos = 0; diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h index e261010902..b9623f54fa 100644 --- a/engines/dreamweb/dreamweb.h +++ b/engines/dreamweb/dreamweb.h @@ -227,8 +227,8 @@ protected: Common::Point _lineData[200]; // Output of Bresenham // from saveload.cpp - char _saveNames[17*7]; - char _saveNamesOld[17*7]; + char _saveNames[17*21]; + char _saveNamesOld[17*21]; // from vgagrafx.cpp uint8 _workspace[(0x1000 + 2) * 16]; @@ -421,6 +421,7 @@ public: uint8 _timedX; uint8 _needToDumpTimed; uint8 _loadingOrSave; + uint8 _saveLoadPage; uint8 _currentSlot; uint8 _cursorPos; uint8 _colourPos; @@ -692,6 +693,7 @@ public: void loadSaveBox(); void showNames(); void checkInput(); + void selectSaveLoadPage(); void selectSlot(); void showSlots(); void showOpBox(); diff --git a/engines/dreamweb/saveload.cpp b/engines/dreamweb/saveload.cpp index 386319db34..761ce7696f 100644 --- a/engines/dreamweb/saveload.cpp +++ b/engines/dreamweb/saveload.cpp @@ -143,6 +143,7 @@ void DreamWebEngine::doLoad(int savegameId) { { kOpsx+176,kOpsx+192,kOpsy+60,kOpsy+76,&DreamWebEngine::getBackToOps }, { kOpsx+128,kOpsx+190,kOpsy+12,kOpsy+100,&DreamWebEngine::actualLoad }, { kOpsx+2,kOpsx+92,kOpsy+4,kOpsy+81,&DreamWebEngine::selectSlot }, + { kOpsx+158,kOpsx+158+(18*3),kOpsy-17,kOpsy-1,&DreamWebEngine::selectSaveLoadPage }, { 0,320,0,200,&DreamWebEngine::blank }, { 0xFFFF,0,0,0,0 } }; @@ -234,6 +235,7 @@ void DreamWebEngine::saveGame() { { kOpsx+176,kOpsx+192,kOpsy+60,kOpsy+76,&DreamWebEngine::getBackToOps }, { kOpsx+128,kOpsx+190,kOpsy+12,kOpsy+100,&DreamWebEngine::actualSave }, { kOpsx+2,kOpsx+92,kOpsy+4,kOpsy+81,&DreamWebEngine::selectSlot }, + { kOpsx+158,kOpsx+158+(18*3),kOpsy-17,kOpsy-1,&DreamWebEngine::selectSaveLoadPage }, { 0,320,0,200,&DreamWebEngine::blank }, { 0xFFFF,0,0,0,0 } }; @@ -286,11 +288,11 @@ void DreamWebEngine::saveGame() { } void DreamWebEngine::namesToOld() { - memcpy(_saveNamesOld, _saveNames, 17*7); + memcpy(_saveNamesOld, _saveNames, 17*21); } void DreamWebEngine::oldToNames() { - memcpy(_saveNames, _saveNamesOld, 17*7); + memcpy(_saveNames, _saveNamesOld, 17*21); } void DreamWebEngine::saveLoad() { @@ -440,7 +442,7 @@ void DreamWebEngine::actualSave() { if (!(_mouseButton & 1)) return; - unsigned int slot = _currentSlot; + unsigned int slot = _currentSlot + 7 * _saveLoadPage; const char *desc = &_saveNames[17*slot]; if (desc[1] == 0) // The actual description string starts at desc[1] @@ -464,13 +466,13 @@ void DreamWebEngine::actualLoad() { if (_mouseButton == _oldButton || _mouseButton != 1) return; - unsigned int slot = _currentSlot; + unsigned int slot = _currentSlot + 7 * _saveLoadPage; const char *desc = &_saveNames[17*slot]; if (desc[1] == 0) // The actual description string starts at desc[1] return; - loadPosition(_currentSlot); + loadPosition(slot); _getBack = 1; } @@ -582,10 +584,10 @@ void DreamWebEngine::loadPosition(unsigned int slot) { if (len[0] != 17) ::error("Error loading save: description buffer isn't 17 bytes"); - if (slot < 7) { + if (slot < 21) { inSaveFile->read(&_saveNames[17*slot], len[0]); } else { - // The savenames buffer only has room for 7 descriptions + // The savenames buffer only has room for 21 descriptions uint8 namebuf[17]; inSaveFile->read(namebuf, 17); } @@ -644,8 +646,10 @@ void DreamWebEngine::loadPosition(unsigned int slot) { // Count number of save files, and load their descriptions into _saveNames uint DreamWebEngine::scanForNames() { - // Initialize the first 7 slots (like the original code expects) - for (unsigned int slot = 0; slot < 7; ++slot) { + // There are 21 save slots, each of which are 17 bytes. The first byte + // doesn't seem to be used. The name starts at the second byte. All the + // slots are initialized to be empty. + for (unsigned int slot = 0; slot < 21; ++slot) { _saveNames[17 * slot + 0] = 2; _saveNames[17 * slot + 1] = 0; for (int i = 2; i < 17; ++i) @@ -670,7 +674,7 @@ uint DreamWebEngine::scanForNames() { int slotNum = atoi(file.c_str() + file.size() - 2); SaveStateDescriptor sd(slotNum, name); saveList.push_back(sd); - if (slotNum < 7) + if (slotNum < 21) Common::strlcpy(&_saveNames[17 * slotNum + 1], name, 16); // the first character is unused } @@ -709,9 +713,10 @@ void DreamWebEngine::loadSaveBox() { // show savegame names (original interface), and set kCursorpos void DreamWebEngine::showNames() { + unsigned int offset = 7 * _saveLoadPage; for (int slot = 0; slot < 7; ++slot) { // The first character of the savegame name is unused - Common::String name(&_saveNames[17*slot + 1]); + Common::String name(&_saveNames[17 * (slot + offset) + 1]); if (slot != _currentSlot) { printDirect((const uint8 *)name.c_str(), kOpsx + 21, kOpsy + 10*slot + 10, 200, false); @@ -737,8 +742,10 @@ void DreamWebEngine::checkInput() { readKey(); + unsigned int slot = _currentSlot + 7 * _saveLoadPage; + // The first character of the savegame name is unused - char *name = &_saveNames[17*_currentSlot + 1]; + char *name = &_saveNames[17*slot + 1]; if (_currentKey == 0) { return; @@ -768,6 +775,21 @@ void DreamWebEngine::checkInput() { workToScreenM(); } +void DreamWebEngine::selectSaveLoadPage() { + commandOnlyCond(31, 254); + + if (_mouseButton != 1 || _mouseButton == _oldButton) + return; + uint saveLoadPage = (_mouseX - (kOpsx + 158)) / 18; + if (saveLoadPage != _saveLoadPage) { + _saveLoadPage = saveLoadPage; + // This will also make the first slot the selected one, based + // on the mouse Y position. I can't decide if this is a feature + // or not. + selectSlot(); + } +} + void DreamWebEngine::selectSlot() { commandOnlyCond(45, 244); @@ -798,6 +820,8 @@ void DreamWebEngine::selectSlot() { } void DreamWebEngine::showSlots() { + showFrame(_icons1, kOpsx + 158, kOpsy - 11, 12, 0); + showFrame(_icons1, kOpsx + 158 + 18 * _saveLoadPage, kOpsy - 11, 13 + _saveLoadPage, 0); showFrame(_tempGraphics, kOpsx + 7, kOpsy + 8, 2, 0); uint16 y = kOpsy + 11; diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp index 741e358143..5a2378f4d0 100644 --- a/engines/kyra/animator_hof.cpp +++ b/engines/kyra/animator_hof.cpp @@ -115,15 +115,14 @@ void KyraEngine_HoF::refreshAnimObjects(int force) { void KyraEngine_HoF::updateItemAnimations() { bool nextFrame = false; - if (_itemAnimData[0].itemIndex == -1 || _inventorySaved) + if (_itemAnimDefinition[0].itemIndex == -1 || _inventorySaved) return; - const ItemAnimData_v2 *s = &_itemAnimData[_nextAnimItem]; + const ItemAnimDefinition *s = &_itemAnimDefinition[_nextAnimItem]; ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem]; - _nextAnimItem = (_nextAnimItem + 1) % _itemAnimDataSize; + _nextAnimItem = (_nextAnimItem + 1) % _itemAnimDefinitionSize; - uint32 ctime = _system->getMillis(); - if (ctime < a->nextFrame) + if (_system->getMillis() < a->nextFrameTime) return; uint16 shpIdx = s->frames[a->currentFrame].index + 64; @@ -164,7 +163,7 @@ void KyraEngine_HoF::updateItemAnimations() { } if (nextFrame) { - a->nextFrame = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength); + a->nextFrameTime = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength); a->currentFrame = (a->currentFrame + 1) % s->numFrames; } } diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp index 31c5cd1a53..29fa3aba80 100644 --- a/engines/kyra/animator_mr.cpp +++ b/engines/kyra/animator_mr.cpp @@ -187,15 +187,14 @@ void KyraEngine_MR::refreshAnimObjects(int force) { void KyraEngine_MR::updateItemAnimations() { bool nextFrame = false; - if (_itemAnimData[0].itemIndex == -1) + if (_itemAnimDefinition[0].itemIndex == -1) return; - const ItemAnimData_v2 *s = &_itemAnimData[_nextAnimItem]; + const ItemAnimDefinition *s = &_itemAnimDefinition[_nextAnimItem]; ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem]; _nextAnimItem = (_nextAnimItem + 1) % 10; - uint32 ctime = _system->getMillis(); - if (ctime < a->nextFrame) + if (_system->getMillis() < a->nextFrameTime) return; uint16 shpIdx = s->frames[a->currentFrame].index + 248; @@ -230,7 +229,7 @@ void KyraEngine_MR::updateItemAnimations() { } if (nextFrame) { - a->nextFrame = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength); + a->nextFrameTime = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength); a->currentFrame = (a->currentFrame + 1) % s->numFrames; } } diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index 95c6162c36..6514984b93 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -205,6 +205,7 @@ void Debugger_LoK::initialize() { DCmd_Register("scenes", WRAP_METHOD(Debugger_LoK, cmd_listScenes)); DCmd_Register("give", WRAP_METHOD(Debugger_LoK, cmd_giveItem)); DCmd_Register("birthstones", WRAP_METHOD(Debugger_LoK, cmd_listBirthstones)); + Debugger::initialize(); } bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) { @@ -295,6 +296,7 @@ void Debugger_v2::initialize() { DCmd_Register("scene_info", WRAP_METHOD(Debugger_v2, cmd_sceneInfo)); DCmd_Register("scene_to_facing", WRAP_METHOD(Debugger_v2, cmd_sceneToFacing)); DCmd_Register("give", WRAP_METHOD(Debugger_v2, cmd_giveItem)); + Debugger::initialize(); } bool Debugger_v2::cmd_enterScene(int argc, const char **argv) { @@ -445,6 +447,7 @@ Debugger_HoF::Debugger_HoF(KyraEngine_HoF *vm) : Debugger_v2(vm), _vm(vm) { void Debugger_HoF::initialize() { DCmd_Register("pass_codes", WRAP_METHOD(Debugger_HoF, cmd_passcodes)); + Debugger_v2::initialize(); } bool Debugger_HoF::cmd_passcodes(int argc, const char **argv) { diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index c3c4e6083c..fd2c1870a8 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -88,7 +88,7 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _currentTalkSections.ENDTim = 0; memset(&_invWsa, 0, sizeof(_invWsa)); - _itemAnimData = 0; + _itemAnimDefinition = 0; _demoAnimData = 0; _nextAnimItem = 0; @@ -211,8 +211,8 @@ void KyraEngine_HoF::pauseEngineIntern(bool pause) { _nextIdleAnim += pausedTime; - for (int x = 0; x < _itemAnimDataSize; x++) - _activeItemAnim[x].nextFrame += pausedTime; + for (int x = 0; x < _itemAnimDefinitionSize; x++) + _activeItemAnim[x].nextFrameTime += pausedTime; _tim->refreshTimersAfterPause(pausedTime); } diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index 4b8303b2e4..320f930b56 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -874,8 +874,8 @@ protected: const char * const *_ingameTimJpStr; int _ingameTimJpStrSize; const HofSeqData *_sequences; - const ItemAnimData_v2 *_itemAnimData; - int _itemAnimDataSize; + const ItemAnimDefinition *_itemAnimDefinition; + int _itemAnimDefinitionSize; const ItemAnimData_v1 *_demoAnimData; int _demoAnimSize; diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index c195f0275a..74db67d22b 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -510,7 +510,14 @@ void KyraEngine_LoK::delay(uint32 amount, bool update, bool isMainLoop) { updateTextFade(); updateMousePointer(); } else { - _screen->updateScreen(); + // We call OSystem::updateScreen here and not Screen::updateScreen + // to avoid new graphics changes to be copied to the screen. + // This assures the workaround of bug #1498221 + // "KYRA1: Glitches when meeting Zanthia" is working correctly. + // Since we only call updateScreen here to let systems with frame + // update count limitations not miss any graphics updates it + // should not cause any problems. + _system->updateScreen(); } _isSaveAllowed = isMainLoop; diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index 38ff271037..7c022534a2 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -219,7 +219,7 @@ private: bool _nextIdleType; void showIdleAnim(); - const ItemAnimData_v2 *_itemAnimData; + const ItemAnimDefinition *_itemAnimDefinition; ActiveItemAnim _activeItemAnim[10]; int _nextAnimItem; diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index 3d7b9c4997..72d743710d 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -38,7 +38,7 @@ struct FrameControl { uint16 delay; }; -struct ItemAnimData_v2 { +struct ItemAnimDefinition { Item itemIndex; uint8 numFrames; const FrameControl *frames; @@ -46,7 +46,7 @@ struct ItemAnimData_v2 { struct ActiveItemAnim { uint16 currentFrame; - uint32 nextFrame; + uint32 nextFrameTime; }; class Screen_v2; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 5b0af9840d..5de1577943 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -744,7 +744,7 @@ public: const Room *loadRoomTable(int id, int &entries); const HofSeqData *loadHofSequenceData(int id, int &entries); const ItemAnimData_v1 *loadShapeAnimData_v1(int id, int &entries); - const ItemAnimData_v2 *loadShapeAnimData_v2(int id, int &entries); + const ItemAnimDefinition *loadItemAnimDefinition(int id, int &entries); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) const uint16 *loadRawDataBe16(int id, int &entries); const uint32 *loadRawDataBe32(int id, int &entries); @@ -787,7 +787,7 @@ private: bool loadRoomTable(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadHofSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadShapeAnimData_v1(Common::SeekableReadStream &stream, void *&ptr, int &size); - bool loadShapeAnimData_v2(Common::SeekableReadStream &stream, void *&ptr, int &size); + bool loadItemAnimDefinition(Common::SeekableReadStream &stream, void *&ptr, int &size); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) bool loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadRawDataBe32(Common::SeekableReadStream &stream, void *&ptr, int &size); @@ -813,7 +813,7 @@ private: void freeRoomTable(void *&ptr, int &size); void freeHofSequenceData(void *&ptr, int &size); void freeHofShapeAnimDataV1(void *&ptr, int &size); - void freeHofShapeAnimDataV2(void *&ptr, int &size); + void freeItemAnimDefinition(void *&ptr, int &size); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) void freeRawDataBe16(void *&ptr, int &size); void freeRawDataBe32(void *&ptr, int &size); @@ -840,7 +840,7 @@ private: k2SeqData = 5, k2ShpAnimDataV1 = 6, - k2ShpAnimDataV2 = 7, + k2ItemAnimDefinition = 7, kLoLCharData = 8, kLoLSpellData = 9, diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index b27f0df137..686c3c9320 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -234,6 +234,8 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { int32 dly = _tickLength - (now - _seqSubFrameStartTime); if (dly > 0) delay(MIN<uint32>(dly, tdiff)); + else + updateInput(); } } @@ -263,6 +265,8 @@ void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { int32 dly = _tickLength - (now - _seqSubFrameStartTime); if (dly > 0) delay(MIN<uint32>(dly, tdiff)); + else + updateInput(); } seq_sequenceCommand(cseq.finalCommand); @@ -2773,15 +2777,15 @@ void KyraEngine_HoF::seq_init() { return; if (_flags.isDemo && !_flags.isTalkie) { - _demoAnimData = _staticres->loadShapeAnimData_v1(k2SeqplayShapeAnimData, _itemAnimDataSize); + _demoAnimData = _staticres->loadShapeAnimData_v1(k2SeqplayShapeAnimData, _itemAnimDefinitionSize); uint8 *shp = _res->fileData("icons.shp", 0); uint32 outsize = READ_LE_UINT16(shp + 4); _animShapeFiledata = new uint8[outsize]; Screen::decodeFrame4(shp + 10, _animShapeFiledata, outsize); delete[] shp; - for (int numShp = 0; getShapePtr(numShp); ++numShp) - addShapeToPool(_screen->getPtrToShape(_animShapeFiledata, numShp), numShp); + for (int i = 0; i < 20; i++) + addShapeToPool(_screen->getPtrToShape(_animShapeFiledata, i), i); } else { const MainMenu::StaticData data = { { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98], 0 }, diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 6c95451c5f..99ad6ea7aa 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -247,7 +247,7 @@ bool StaticResource::init() { { k2SeqData, proc(loadHofSequenceData), proc(freeHofSequenceData) }, { k2ShpAnimDataV1, proc(loadShapeAnimData_v1), proc(freeHofShapeAnimDataV1) }, - { k2ShpAnimDataV2, proc(loadShapeAnimData_v2), proc(freeHofShapeAnimDataV2) }, + { k2ItemAnimDefinition, proc(loadItemAnimDefinition), proc(freeItemAnimDefinition) }, #ifdef ENABLE_LOL { kLoLCharData, proc(loadCharData), proc(freeCharData) }, @@ -316,8 +316,8 @@ const ItemAnimData_v1 *StaticResource::loadShapeAnimData_v1(int id, int &entries return (const ItemAnimData_v1 *)getData(id, k2ShpAnimDataV1, entries); } -const ItemAnimData_v2 *StaticResource::loadShapeAnimData_v2(int id, int &entries) { - return (const ItemAnimData_v2 *)getData(id, k2ShpAnimDataV2, entries); +const ItemAnimDefinition *StaticResource::loadItemAnimDefinition(int id, int &entries) { + return (const ItemAnimDefinition *)getData(id, k2ItemAnimDefinition, entries); } bool StaticResource::prefetchId(int id) { @@ -610,9 +610,9 @@ bool StaticResource::loadShapeAnimData_v1(Common::SeekableReadStream &stream, vo return true; } -bool StaticResource::loadShapeAnimData_v2(Common::SeekableReadStream &stream, void *&ptr, int &size) { +bool StaticResource::loadItemAnimDefinition(Common::SeekableReadStream &stream, void *&ptr, int &size) { size = stream.readByte(); - ItemAnimData_v2 *loadTo = new ItemAnimData_v2[size]; + ItemAnimDefinition *loadTo = new ItemAnimDefinition[size]; assert(loadTo); for (int i = 0; i < size; i++) { @@ -699,8 +699,8 @@ void StaticResource::freeHofShapeAnimDataV1(void *&ptr, int &size) { size = 0; } -void StaticResource::freeHofShapeAnimDataV2(void *&ptr, int &size) { - ItemAnimData_v2 *d = (ItemAnimData_v2 *)ptr; +void StaticResource::freeItemAnimDefinition(void *&ptr, int &size) { + ItemAnimDefinition *d = (ItemAnimDefinition *)ptr; for (int i = 0; i < size; i++) delete[] d[i].frames; delete[] d; @@ -1007,7 +1007,7 @@ void KyraEngine_HoF::initStaticResource() { _cdaTrackTableFinale = _staticres->loadRawData(k2SeqplayFinaleCDA, _cdaTrackTableFinaleSize); _ingameTalkObjIndex = (const uint16 *)_staticres->loadRawData(k2IngameTalkObjIndex, _ingameTalkObjIndexSize); _ingameTimJpStr = _staticres->loadStrings(k2IngameTimJpStrings, _ingameTimJpStrSize); - _itemAnimData = _staticres->loadShapeAnimData_v2(k2IngameShapeAnimData, _itemAnimDataSize); + _itemAnimDefinition = _staticres->loadItemAnimDefinition(k2IngameShapeAnimData, _itemAnimDefinitionSize); // replace sequence talkie files with localized versions const char *const *seqSoundList = _staticres->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); @@ -1143,7 +1143,7 @@ void KyraEngine_MR::initStaticResource() { _scoreTable = _staticres->loadRawData(k3ScoreTable, _scoreTableSize); _sfxFileList = _staticres->loadStrings(k3SfxFiles, _sfxFileListSize); _sfxFileMap = _staticres->loadRawData(k3SfxMap, _sfxFileMapSize); - _itemAnimData = _staticres->loadShapeAnimData_v2(k3ItemAnimData, tmp); + _itemAnimDefinition = _staticres->loadItemAnimDefinition(k3ItemAnimData, tmp); _itemMagicTable = _staticres->loadRawData(k3ItemMagicTable, tmp); _itemStringMap = _staticres->loadRawData(k3ItemStringMap, _itemStringMapSize); } diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index 2f6d0f23aa..c7e7e81900 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -2334,9 +2334,11 @@ void Hotspot::saveToStream(Common::WriteStream *stream) { void Hotspot::loadFromStream(Common::ReadStream *stream) { if (_data) _data->npcSchedule.loadFromStream(stream); - else + else { // Dummy read of terminator for empty actions list - assert(stream->readByte() == 0xff); + byte dummy = stream->readByte(); + assert(dummy == 0xff); + } _pathFinder.loadFromStream(stream); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index fe0c9fc2ef..622511c906 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -610,6 +610,12 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_DUMMY(DeletePic), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_DUMMY(GetSierraProfileString), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // Unused / debug functions in the in-between SCI2.1 interpreters + { MAP_DUMMY(PreloadResource), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_DUMMY(CheckCDisc), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_DUMMY(GetSaveCDisc), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_DUMMY(TestPoly), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + // SCI2.1 unmapped functions - TODO! // MovePlaneItems - used by SQ6 to scroll through the inventory via the up/down buttons diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 76c6778f0a..cfeaaaa803 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -25,6 +25,7 @@ #include "engines/util.h" #include "graphics/cursorman.h" #include "graphics/surface.h" +#include "graphics/palette.h" // temporary, for the fadeIn()/fadeOut() functions below #include "gui/message.h" @@ -1212,7 +1213,8 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) { switch (operation) { case 0: { // Set remapping to base. 0 turns remapping off. int16 base = (argc >= 2) ? argv[1].toSint16() : 0; - warning("kRemapColors: Set remapping to base %d", base); + if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning + warning("kRemapColors: Set remapping to base %d", base); } break; case 1: { // unknown @@ -1440,6 +1442,46 @@ reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// Taken from the SCI16 GfxTransitions class +static void fadeOut() { + byte oldPalette[3 * 256], workPalette[3 * 256]; + int16 stepNr, colorNr; + // Sierra did not fade in/out color 255 for sci1.1, but they used it in + // several pictures (e.g. qfg3 demo/intro), so the fading looked weird + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; + + g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256); + + for (stepNr = 100; stepNr >= 0; stepNr -= 10) { + for (colorNr = 1; colorNr <= tillColorNr; colorNr++) { + if (g_sci->_gfxPalette->colorIsFromMacClut(colorNr)) { + workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3]; + workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1]; + workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2]; + } else { + workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100; + workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100; + workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100; + } + } + g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr); + g_sci->getEngineState()->wait(2); + } +} + +// Taken from the SCI16 GfxTransitions class +static void fadeIn() { + int16 stepNr; + // Sierra did not fade in/out color 255 for sci1.1, but they used it in + // several pictures (e.g. qfg3 demo/intro), so the fading looked weird + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; + + for (stepNr = 0; stepNr <= 100; stepNr += 10) { + g_sci->_gfxPalette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true); + g_sci->getEngineState()->wait(2); + } +} + /** * Used for scene transitions, replacing (but reusing parts of) the old * transition code. @@ -1450,31 +1492,65 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) { // tables inside graphics/transitions.cpp uint16 showStyle = argv[0].toUint16(); // 0 - 15 reg_t planeObj = argv[1]; // the affected plane - //argv[2] // seconds that the transition lasts - //argv[3] // back color to be used(?) - //int16 priority = argv[4].toSint16(); - //argv[5] // boolean, animate or not while the transition lasts - //argv[6] // refFrame + uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts + uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff + int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out + uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts + uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out + int16 divisions; // If the game has the pFadeArray selector, another parameter is used here, // before the optional last parameter - /*bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0; + bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0; if (hasFadeArray) { // argv[7] - //int16 unk7 = (argc >= 9) ? argv[8].toSint16() : 0; // divisions (transition steps?) + divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?) } else { - //int16 unk7 = (argc >= 8) ? argv[7].toSint16() : 0; // divisions (transition steps?) - }*/ + divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?) + } if (showStyle > 15) { warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj)); return s->r_acc; } + // TODO: Proper implementation. This is a very basic version. I'm not even + // sure if the rest of the styles will work with this mechanism. + + // Check if the passed parameters are the ones we expect + if (showStyle == 13 || showStyle == 14) { // fade out / fade in + if (seconds != 1) + warning("kSetShowStyle(fade): seconds isn't 1, it's %d", seconds); + if (backColor != 0 && backColor != 0xFFFF) + warning("kSetShowStyle(fade): backColor isn't 0 or 0xFFFF, it's %d", backColor); + if (priority != 200) + warning("kSetShowStyle(fade): priority isn't 200, it's %d", priority); + if (animate != 0) + warning("kSetShowStyle(fade): animate isn't 0, it's %d", animate); + if (refFrame != 0) + warning("kSetShowStyle(fade): refFrame isn't 0, it's %d", refFrame); + if (divisions >= 0 && divisions != 20) + warning("kSetShowStyle(fade): divisions isn't 20, it's %d", divisions); + } + // TODO: Check if the plane is in the list of planes to draw - // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now - kStub(s, argc, argv); + switch (showStyle) { + //case 0: // no transition, perhaps? (like in the previous SCI versions) + case 13: // fade out + // TODO: Temporary implementation, which ignores all additional parameters + fadeOut(); + break; + case 14: // fade in + // TODO: Temporary implementation, which ignores all additional parameters + g_sci->_gfxFrameout->kernelFrameout(); // draw new scene before fading in + fadeIn(); + break; + default: + // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now + kStub(s, argc, argv); + break; + } return s->r_acc; } diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 7efcb42f4b..187f1ce021 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -366,7 +366,7 @@ const uint16 freddypharkasPatchLadderEvent[] = { // script, description, magic DWORD, adjust const SciScriptSignature freddypharkasSignatures[] = { { 0, "CD: score early disposal", 1, PATCH_MAGICDWORD(0x39, 0x0d, 0x43, 0x75), -3, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal }, - { 235, "CD: canister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang }, + { 235, "CD: canister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang }, { 320, "ladder event issue", 2, PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -437,8 +437,68 @@ const uint16 gk1PatchDay5PhoneFreeze[] = { PATCH_END }; +// Floppy version: Interrogation::dispose() compares an object reference +// (stored in the view selector) with a number, leading to a crash (this kind +// of comparison was not used in SCI32). The view selector is used to store +// both a view number (in some cases), and a view reference (in other cases). +// In the floppy version, the checks are in the wrong order, so there is a +// comparison between a number an an object. In the CD version, the checks are +// in the correct order, thus the comparison is correct, thus we use the code +// from the CD version in the floppy one. +const byte gk1SignatureInterrogationBug[] = { + 43, + 0x65, 0x4c, // aTop 4c + 0x67, 0x50, // pTos 50 + 0x34, 0x10, 0x27, // ldi 2710 + 0x1e, // gt? + 0x31, 0x08, // bnt 08 [05a0] + 0x67, 0x50, // pTos 50 + 0x34, 0x10, 0x27, // ldi 2710 + 0x04, // sub + 0x65, 0x50, // aTop 50 + 0x63, 0x50, // pToa 50 + 0x31, 0x15, // bnt 15 [05b9] + 0x39, 0x0e, // pushi 0e + 0x76, // push0 + 0x4a, 0x04, 0x00, // send 0004 + 0xa5, 0x00, // sat 00 + 0x38, 0x93, 0x00, // pushi 0093 + 0x76, // push0 + 0x63, 0x50, // pToa 50 + 0x4a, 0x04, 0x00, // send 0004 + 0x85, 0x00, // lat 00 + 0x65, 0x50, // aTop 50 + 0 +}; + +const uint16 gk1PatchInterrogationBug[] = { + 0x65, 0x4c, // aTop 4c + 0x63, 0x50, // pToa 50 + 0x31, 0x15, // bnt 15 [05b9] + 0x39, 0x0e, // pushi 0e + 0x76, // push0 + 0x4a, 0x04, 0x00, // send 0004 + 0xa5, 0x00, // sat 00 + 0x38, 0x93, 0x00, // pushi 0093 + 0x76, // push0 + 0x63, 0x50, // pToa 50 + 0x4a, 0x04, 0x00, // send 0004 + 0x85, 0x00, // lat 00 + 0x65, 0x50, // aTop 50 + 0x67, 0x50, // pTos 50 + 0x34, 0x10, 0x27, // ldi 2710 + 0x1e, // gt? + 0x31, 0x08, // bnt 08 [05b9] + 0x67, 0x50, // pTos 50 + 0x34, 0x10, 0x27, // ldi 2710 + 0x04, // sub + 0x65, 0x50, // aTop 50 + PATCH_END +}; + // script, description, magic DWORD, adjust const SciScriptSignature gk1Signatures[] = { + { 51, "interrogation bug", 1, PATCH_MAGICDWORD(0x65, 0x4c, 0x67, 0x50), 0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug }, { 212, "day 5 phone freeze", 1, PATCH_MAGICDWORD(0x35, 0x03, 0x65, 0x1a), 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze }, { 230, "day 6 police beignet timer issue", 1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -16, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet }, { 230, "day 6 police sleep timer issue", 1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -5, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep }, diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 7bb4162020..e3fac80f7c 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -101,7 +101,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) { } void GfxFrameout::kernelUpdatePlane(reg_t object) { - for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { // Read some information it->priority = readSelectorValue(_segMan, object, SELECTOR(priority)); @@ -178,8 +178,10 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { } void GfxFrameout::kernelDeletePlane(reg_t object) { + deletePlaneItems(object); deletePlanePictures(object); - for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) { + + for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) { if (it->object == object) { _planes.erase(it); Common::Rect planeRect; @@ -193,10 +195,6 @@ void GfxFrameout::kernelDeletePlane(reg_t object) { planeRect.left = (planeRect.left * screenRect.width()) / _scriptsRunningWidth; planeRect.bottom = (planeRect.bottom * screenRect.height()) / _scriptsRunningHeight; planeRect.right = (planeRect.right * screenRect.width()) / _scriptsRunningWidth; - planeRect.clip(screenRect); // we need to do this, at least in gk1 on cemetary we get bottom right -> 201, 321 - // FIXME: The code above incorrectly added 1 pixel to the plane's - // bottom and right, so probably the plane clipping code is no - // longer necessary // Blackout removed plane rect _paint32->fillRect(planeRect, 0); return; @@ -276,6 +274,18 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) { _screenItems.remove(itemEntry); } +void GfxFrameout::deletePlaneItems(reg_t planeObject) { + FrameoutList::iterator listIterator = _screenItems.begin(); + + while (listIterator != _screenItems.end()) { + reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane)); + if (planeObject == itemPlane) + listIterator = _screenItems.erase(listIterator); + else + ++listIterator; + } +} + FrameoutEntry *GfxFrameout::findScreenItem(reg_t object) { for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) { FrameoutEntry *itemEntry = *listIterator; @@ -498,7 +508,8 @@ void GfxFrameout::kernelFrameout() { // There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX. // Since I first wrote the patch, the race has stopped occurring for me though. // I'll leave this for investigation later, when someone can reproduce. - if (it->pictureId == 0xffff) + //if (it->pictureId == 0xffff) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes) + if (it->planeBack) _paint32->fillRect(it->planeRect, it->planeBack); GuiResourceId planeMainPictureId = it->pictureId; diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index a4a0a853e4..8c3cc261d5 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -94,6 +94,7 @@ public: void kernelAddScreenItem(reg_t object); void kernelUpdateScreenItem(reg_t object); void kernelDeleteScreenItem(reg_t object); + void deletePlaneItems(reg_t planeObject); FrameoutEntry *findScreenItem(reg_t object); int16 kernelGetHighPlanePri(); void kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY); diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 000bb691dc..e7595fbdaf 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -175,6 +175,7 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) { void GfxText32::drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t textObject) { reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); + uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); // Sanity check: Check if the hunk is set. If not, either the game scripts // didn't set it, or an old saved game has been loaded, where it wasn't set. if (hunkId.isNull()) @@ -204,7 +205,7 @@ void GfxText32::drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t for (int curY = 0; curY < height; curY++) { for (int curX = 0; curX < width; curX++) { byte pixel = surface[curByte++]; - if (pixel != skipColor) + if (pixel != skipColor && pixel != backColor) _screen->putFontPixel(textY, curX + textX, curY, pixel); } } diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index d047eb10a1..438cf376a5 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -295,12 +295,12 @@ void GfxTransitions::fadeOut() { int16 stepNr, colorNr; // Sierra did not fade in/out color 255 for sci1.1, but they used it in // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 256 : 255; + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256); for (stepNr = 100; stepNr >= 0; stepNr -= 10) { - for (colorNr = 1; colorNr < tillColorNr; colorNr++) { + for (colorNr = 1; colorNr <= tillColorNr; colorNr++) { if (_palette->colorIsFromMacClut(colorNr)) { workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3]; workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1]; @@ -311,7 +311,7 @@ void GfxTransitions::fadeOut() { workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100; } } - g_system->getPaletteManager()->setPalette(workPalette + 3, 1, 254); + g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr); g_sci->getEngineState()->wait(2); } } @@ -322,10 +322,10 @@ void GfxTransitions::fadeIn() { int16 stepNr; // Sierra did not fade in/out color 255 for sci1.1, but they used it in // several pictures (e.g. qfg3 demo/intro), so the fading looked weird - int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 256 : 255; + int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254; for (stepNr = 0; stepNr <= 100; stepNr += 10) { - _palette->kernelSetIntensity(1, tillColorNr, stepNr, true); + _palette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true); g_sci->getEngineState()->wait(2); } } diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index cfc4b3c419..37ea3a9a9f 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -29,6 +29,7 @@ #include "scumm/resource.h" #include "scumm/util.h" #include "scumm/scumm_v2.h" +#include "scumm/sound.h" #include "scumm/verbs.h" namespace Scumm { @@ -935,6 +936,17 @@ void ScummEngine::runExitScript() { } if (VAR_EXIT_SCRIPT2 != 0xFF && VAR(VAR_EXIT_SCRIPT2)) runScript(VAR(VAR_EXIT_SCRIPT2), 0, 0, 0); + +#ifdef ENABLE_SCUMM_7_8 + // WORKAROUND: The spider lair (room 44) will optionally play the sound + // of trickling water (sound 215), but it never stops it. The same sound + // effect is also used in room 33, so let's do the same fade out that it + // does in that room's exit script. + if (_game.id == GID_DIG && _currentRoom == 44) { + int scriptCmds[] = { 14, 215, 0x600, 0, 30, 0, 0, 0 }; + _sound->soundKludge(scriptCmds, ARRAYSIZE(scriptCmds)); + } +#endif } void ScummEngine::runEntryScript() { diff --git a/engines/sword2/sprite.cpp b/engines/sword2/sprite.cpp index 73a4eca8bd..cb0923cc2f 100644 --- a/engines/sword2/sprite.cpp +++ b/engines/sword2/sprite.cpp @@ -772,14 +772,18 @@ int32 Screen::drawSprite(SpriteInfo *s) { src = sprite + rs.top * srcPitch + rs.left; dst = _buffer + _screenWide * rd.top + rd.left; - if (s->type & RDSPR_BLEND && !Sword2Engine::isPsx()) { // Blending is unavailable in PSX version + if (s->type & RDSPR_BLEND) { // The original code had two different blending cases. One for // s->blend & 0x01 and one for s->blend & 0x02. However, the // only values that actually appear in the cluster files are // 0, 513 and 1025 so the s->blend & 0x02 case was never used. // Which is just as well since that code made no sense to me. - if (!(_renderCaps & RDBLTFX_SPRITEBLEND)) { + // TODO: In PSX version, blending is done through hardware transparency. + // The only correct way to simulate this would be using 16-bit mode. + // As this is not yet available for this engine, fake transparency is used + // as placeholder. + if (!(_renderCaps & RDBLTFX_SPRITEBLEND) || Sword2Engine::isPsx()) { for (i = 0; i < rs.height(); i++) { for (j = 0; j < rs.width(); j++) { if (src[j] && ((i & 1) == (j & 1))) diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp index ad7d0d1e0c..1ac426518d 100644 --- a/engines/tsage/globals.cpp +++ b/engines/tsage/globals.cpp @@ -381,27 +381,49 @@ void Ringworld2Globals::reset() { _v5657C = 0; _v565F5 = 0; _v565AE = 0; - for (int i = 0; i < 14; i++) - _v56605[i] = 0; + + _v56605[0] = 0; + _v56605[1] = 3; + _v56605[2] = 5; + _v56605[3] = 1; + _v56605[4] = 2; + _v56605[5] = 5; + _v56605[6] = 9; + _v56605[7] = 14; + _v56605[8] = 15; + _v56605[9] = 18; + _v56605[10] = 20; + _v56605[11] = 25; + _v56605[12] = 27; + _v56605[13] = 31; + _v566A6 = 3800; - _v566A8 = 0; + _v566A8 = 5; _v566A9 = 0; _v566AA = 0; for (int i = 0; i < 1000; i++) _v566AB[i] = 0; - _v56A93 = 0; - _v56A99 = 0; + _v56A93 = -1; + _v56A99 = 5; _v56A9E = 0; _v56AA0 = 0; _v56AA1 = 0; + _v56AA2 = 60; + _v56AA4 = 660; + _v56AA6 = 1; + _v56AA7 = 1; + _v56AA8 = 1; _v56AAB = 0; _v57C2C = 0; _v58CE2 = 0; - Common::fill(&_v565F1[0], &_v565F1[MAX_CHARACTERS], 0); + _v565EC[0] = 0; + _v565EC[1] = 27; + _v565EC[2] = 27; + _v565EC[3] = 4; + _v565EC[4] = 4; + Common::fill(&_v565F1[0], &_v565F1[MAX_CHARACTERS], 1); _speechSubtitles = SPEECH_VOICE | SPEECH_TEXT; _insetUp = 0; - - Common::fill(&_v565F1[0], &_v565F1[MAX_CHARACTERS], 0); Common::fill(&_stripManager_lookupList[0], &_stripManager_lookupList[12], 0); _stripManager_lookupList[0] = 1; _stripManager_lookupList[1] = 1; @@ -434,13 +456,18 @@ void Ringworld2Globals::synchronize(Serializer &s) { s.syncAsSint16LE(_v566A6); s.syncAsSint16LE(_v56A93); s.syncAsSint16LE(_v56A9E); + s.syncAsSint16LE(_v56AA2); + s.syncAsSint16LE(_v56AA4); s.syncAsSint16LE(_v56AAB); s.syncAsSint16LE(_v57C2C); s.syncAsSint16LE(_v58CE2); s.syncAsSint16LE(_speechSubtitles); + for (i = 0; i < 5; i++) + s.syncAsByte(_v565EC[i]); + for (i = 0; i < MAX_CHARACTERS; ++i) - s.syncAsSint16LE(_v565F1[i]); + s.syncAsByte(_v565F1[i]); s.syncAsByte(_v565AE); s.syncAsByte(_v566A8); @@ -448,6 +475,9 @@ void Ringworld2Globals::synchronize(Serializer &s) { s.syncAsByte(_v566AA); s.syncAsByte(_v56AA0); s.syncAsByte(_v56AA1); + s.syncAsByte(_v56AA6); + s.syncAsByte(_v56AA7); + s.syncAsByte(_v56AA8); for (i = 0; i < 14; ++i) s.syncAsByte(_v56605[i]); diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h index 227058f1d6..9d00e618a4 100644 --- a/engines/tsage/globals.h +++ b/engines/tsage/globals.h @@ -265,11 +265,17 @@ public: int _v56A9E; byte _v56AA0; byte _v56AA1; + int _v56AA2; + int _v56AA4; + byte _v56AA6; + byte _v56AA7; + byte _v56AA8; int _v56AAB; int _v57C2C; int _v58CE2; int _speechSubtitles; - int _v565F1[4]; + byte _v565EC[5]; + byte _v565F1[4]; byte _stripManager_lookupList[12]; virtual void reset(); diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp index 8436afe2e8..5acd191b11 100644 --- a/engines/tsage/graphics.cpp +++ b/engines/tsage/graphics.cpp @@ -259,6 +259,12 @@ void GfxSurface::updateScreen() { for (Common::List<Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) { Rect r = *i; + // Make sure that there is something to update. If not, skip this + // rectangle. An example case is the speedbike closeup at the beginning + // of Ringworld (third screen). + if (r.isEmpty()) + continue; + const byte *srcP = (const byte *)_customSurface->getBasePtr(r.left, r.top); g_system->copyRectToScreen(srcP, _customSurface->pitch, r.left, r.top, r.width(), r.height()); @@ -1302,19 +1308,29 @@ int GfxManager::getAngle(const Common::Point &p1, const Common::Point &p2) { } } +// FIXME: The two checks for screenSurface inside these two copyFrom() methods +// are meant for Ringworld 2, but the corresponding setBounds cases cause +// issues with the popup menus when right clicking in all games (e.g. the popup +// menu is always shown on the top left of the screen). Therefore, these two +// code fragments are disabled for now, till the glitches they cause are fixed. void GfxManager::copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion) { +#if 0 if (&_surface == &(GLOBALS._screenSurface)) _surface.setBounds(Rect(0, 0, _bounds.width(), _bounds.height())); else +#endif _surface.setBounds(_bounds); _surface.copyFrom(src, destBounds, priorityRegion); } + void GfxManager::copyFrom(GfxSurface &src, int destX, int destY) { +#if 0 if (&_surface == &(GLOBALS._screenSurface)) _surface.setBounds(Rect(0, 0, _bounds.width(), _bounds.height())); else +#endif _surface.setBounds(_bounds); _surface.copyFrom(src, destX, destY); diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp index fa7895f407..2f537c4ebe 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.cpp +++ b/engines/tsage/ringworld2/ringworld2_logic.cpp @@ -36,6 +36,8 @@ namespace TsAGE { namespace Ringworld2 { Scene *Ringworld2Game::createScene(int sceneNumber) { + warning("Switching to scene %d", sceneNumber); + switch (sceneNumber) { /* Scene group #0 */ case 50: @@ -102,11 +104,20 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { case 1100: return new Scene1100(); case 1200: + return new Scene1200(); case 1330: + error("Missing scene %d from group 1", sceneNumber); case 1500: + // Cutscene: Ship landing + return new Scene1500(); case 1525: + // Cutscene - Ship + return new Scene1525(); case 1530: + // Cutscene - Elevator + return new Scene1530(); case 1550: + return new Scene1550(); case 1575: case 1580: case 1625: diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h index bb6aa25f85..9b64063803 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.h +++ b/engines/tsage/ringworld2/ringworld2_logic.h @@ -265,6 +265,7 @@ public: int _state; SceneActorExt() { _state = 0; } + virtual Common::String getClassName() { return "SceneActorExt"; } virtual void synchronize(Serializer &s) { SceneActor::synchronize(s); diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp index e773c52805..45aec17fbf 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp @@ -856,5 +856,2197 @@ void Scene1100::saveCharacter(int characterIndex) { R2_GLOBALS._sound1.fadeOut2(NULL); SceneExt::saveCharacter(characterIndex); } + +/*-------------------------------------------------------------------------- + * Scene 1200 - + * + *--------------------------------------------------------------------------*/ +Scene1200::Scene1200() { + _field412 = 0; + _field414 = 0; + _field416 = 0; + _field418 = 0; + _field41A = 0; + _field41C = 1; //CHECKME: Only if fixup_flag == 6?? +} + +void Scene1200::synchronize(Serializer &s) { + SceneExt::synchronize(s); + + s.syncAsSint16LE(_field412); + s.syncAsSint16LE(_field414); + s.syncAsSint16LE(_field416); + s.syncAsSint16LE(_field418); + s.syncAsSint16LE(_field41A); + s.syncAsSint16LE(_field41C); +} + +Scene1200::Area1::Area1() { + _field20 = 0; +} + +void Scene1200::Area1::synchronize(Serializer &s) { + SceneArea::synchronize(s); + + s.syncAsByte(_field20); +} + +void Scene1200::Area1::Actor3::init(int state) { + _state = state; + + SceneActor::postInit(); + setup(1003, 1, 1); + fixPriority(255); + + switch (_state) { + case 1: + switch (R2_GLOBALS._v56AA6) { + case 1: + setFrame2(2); + setPosition(Common::Point(129, 101)); + break; + case 2: + setFrame2(3); + setPosition(Common::Point(135, 95)); + break; + default: + break; + } + case 2: + switch (R2_GLOBALS._v56AA7) { + case 1: + setFrame2(2); + setPosition(Common::Point(152, 101)); + break; + case 2: + setFrame2(3); + setPosition(Common::Point(158, 122)); + break; + case 3: + setFrame2(3); + setPosition(Common::Point(135, 122)); + break; + default: + break; + } + case 3: + switch (R2_GLOBALS._v56AA8) { + case 1: + setFrame2(3); + setPosition(Common::Point(158, 95)); + break; + case 2: + setFrame2(2); + setPosition(Common::Point(175, 101)); + break; + default: + break; + } + default: + break; + } + + setDetails(1200, 12, -1, -1, 2, (SceneItem *) NULL); +} + +bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) { + if (action != CURSOR_USE) + return SceneActor::startAction(action, event); + + R2_GLOBALS._sound2.play(260); + switch (_state) { + case 1: + if (R2_GLOBALS._v56AA6 == 1) { + R2_GLOBALS._v56AA6 = 2; + setFrame2(3); + setPosition(Common::Point(135, 95)); + } else { + R2_GLOBALS._v56AA6 = 1; + setFrame2(2); + setPosition(Common::Point(129, 101)); + } + break; + case 2: + ++R2_GLOBALS._v56AA7; + if (R2_GLOBALS._v56AA7 == 4) + R2_GLOBALS._v56AA7 = 1; + + switch (R2_GLOBALS._v56AA7) { + case 1: + setFrame2(1); + setPosition(Common::Point(152, 101)); + break; + case 2: + setFrame2(3); + setPosition(Common::Point(158, 122)); + break; + case 3: + setFrame2(3); + setPosition(Common::Point(135, 122)); + break; + default: + break; + } + break; + case 3: + if (R2_GLOBALS._v56AA8 == 1) { + R2_GLOBALS._v56AA8 = 2; + setFrame2(2); + setPosition(Common::Point(175, 101)); + } else { + R2_GLOBALS._v56AA8 = 1; + setFrame2(3); + setPosition(Common::Point(158, 95)); + } + break; + default: + break; + } + + Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; + scene->_field418 = 0; + + if ((R2_GLOBALS._v56AA6 == 1) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1)) + scene->_field418 = 1; + else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1)) + scene->_field418 = 2; + else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 2)) + scene->_field418 = 3; + else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 3) && (R2_GLOBALS._v56AA8 == 1)) + scene->_field418 = 4; + + return true; +} + +void Scene1200::Area1::postInit() { + Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; + + scene->_field41A = 1; + R2_GLOBALS._events.setCursor(CURSOR_USE); + proc12(1003, 1, 1, 100, 40); + proc13(1200, 11, -1, -1); + R2_GLOBALS._sound2.play(259); + _actor3.init(1); + _actor4.init(2); + _actor5.init(3); + + R2_GLOBALS._player._canWalk = false; +} + +void Scene1200::Area1::remove() { + Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; + + scene->_field41A = 0; + warning("Unexpected _sceneAreas.remove() call"); +// scene->_sceneAreas.remove(&_actor3); +// scene->_sceneAreas.remove(&_actor4); +// scene->_sceneAreas.remove(&_actor5); + _actor3.remove(); + _actor4.remove(); + _actor5.remove(); + + // sub201EA + R2_GLOBALS._sceneItems.remove((SceneItem *)this); + _actor2.remove(); + SceneArea::remove(); + R2_GLOBALS._insetUp--; + // + + R2_GLOBALS._player._canWalk = true; +} + +void Scene1200::Area1::process(Event &event) { + if (_field20 != R2_GLOBALS._insetUp) + return; + + CursorType cursor = R2_GLOBALS._events.getCursor(); + + if (_actor2._bounds.contains(event.mousePos.x + g_globals->gfxManager()._bounds.left , event.mousePos.y)) { + if (cursor == _cursorNum) + warning("TODO: _cursorState = ???"); + R2_GLOBALS._events.setCursor(_savedCursorNum); //, _cursorState); + } else if (event.mousePos.y < 168) { + if (cursor != _cursorNum) { + _savedCursorNum = cursor; + warning("TODO: _cursorState = ???"); + R2_GLOBALS._events.setCursor(CURSOR_INVALID); + } + if (event.eventType == EVENT_BUTTON_DOWN) { + event.handled = true; + warning("TODO: _cursorState = ???"); + R2_GLOBALS._events.setCursor(_savedCursorNum); //, _cursorState); + remove(); + } + } +} + +void Scene1200::Area1::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) { + Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; + + _actor2.postInit(); + _actor2.setup(visage, stripFrameNum, frameNum); + _actor2.setPosition(Common::Point(posX, posY)); + _actor2.fixPriority(250); + _cursorNum = CURSOR_INVALID; + scene->_sceneAreas.push_front(this); + ++R2_GLOBALS._insetUp; + _field20 = R2_GLOBALS._insetUp; +} + +void Scene1200::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) { + _actor2.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL); +} + +Scene1200::Object1::Object1() { + _field16 = _field26 = _field28 = _field2A = _field2C = _field2E = _field30 = 0; +} + +void Scene1200::Object1::synchronize(Serializer &s) { + SavedObject::synchronize(s); + + s.syncAsSint16LE(_field16); + s.syncAsSint16LE(_field26); + s.syncAsSint16LE(_field28); + s.syncAsSint16LE(_field2A); + s.syncAsSint16LE(_field2C); + s.syncAsSint16LE(_field2E); + s.syncAsSint16LE(_field30); +} + +int Scene1200::Object1::sub51AF8(Common::Point pt) { + if (!_rect1.contains(pt)) + return -1; + + int tmp1 = (pt.x - _rect1.left + _field2E) / _field2A; + int tmp2 = (pt.y - _rect1.top + _field30) / _field2C; + + if ((tmp1 >= 0) && (tmp2 >= 0) && (_field26 > tmp1) && (_field28 > tmp2)) + return _field16 + (((_field26 * tmp2) + tmp1)* 2); + + return -1; +} + +bool Scene1200::Object1::sub51AFD(Common::Point pt) { + int retval = false; + + _field2E = pt.x; + _field30 = pt.y; + + if (_field2E < _rect2.top) { + _field2E = _rect2.top; + retval = true; + } + + if (_field30 < _rect2.left) { + _field30 = _rect2.left; + retval = true; + } + + if (_field2E + _rect1.width() > _rect2.right) { + _field2E = _rect2.right - _rect1.width(); + retval = true; + } + + if (_field30 + _rect1.height() > _rect2.bottom) { + _field30 = _rect2.bottom - _rect1.height(); + retval = true; + } + + return retval; +} + +void Scene1200::Object1::sub9EDE8(Rect rect) { + _rect1 = rect; + warning("FIXME: Scene1200::Object1::sub9EDE8()"); +// _rect1.clip(g_globals->gfxManager()._bounds); +} + +void Scene1200::postInit(SceneObjectList *OwnerList) { + Rect tmpRect; + + loadScene(1200); + SceneExt::postInit(); + + if (R2_GLOBALS._sceneManager._previousScene < 3200) + R2_GLOBALS._sound1.play(257); + + _field412 = 1; + _field414 = 0; + _field416 = 0; + _field418 = 0; + _field41A = 0; + _field41C = 0; + + if ((R2_GLOBALS._v56AA6 == 1) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1)) + _field418 = 1; + else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1)) + _field418 = 2; + else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 2)) + _field418 = 3; + else if ((R2_GLOBALS._v56AA6 == 2) && (R2_GLOBALS._v56AA7 == 3) && (R2_GLOBALS._v56AA8 == 1)) + _field418 = 4; + + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player.disableControl(); + R2_GLOBALS._player.setup(3156, 1, 6); + R2_GLOBALS._player.setPosition(Common::Point(160, 70)); + R2_GLOBALS._player._numFrames = 10; + R2_GLOBALS._player._oldCharacterScene[3] = 1200; + + _actor1.postInit(); + _actor1.hide(); + + tmpRect.set(110, 20, 210, 120); + _object1.sub9EDE8(tmpRect); + + warning("_object1.sub51AE9(1);"); + _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); + warning("int unk = set_pane_p(_paneNumber);"); + warning("_object1.sub51B02();"); + warning("set_pane_p(unk);"); + + R2_GLOBALS._player.enableControl(); + _item1.setDetails(Rect(0, 0, 320, 200), 1200, 0, 1, 2, 1, NULL); +} + +void Scene1200::signal() { + switch (_sceneMode++) { + case 1: + // No break on purpose + case 1200: + // No break on purpose + case 1201: + // No break on purpose + case 1202: + // No break on purpose + case 1203: + R2_GLOBALS._player.enableControl(); + warning("_eventManager.waitEvent()"); + _sceneMode = 2; + break; + case 10: + _field416 = 1; + _field414 = 6; + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.setStrip(1); + R2_GLOBALS._player.setFrame(5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 11: + // No break on purpose + case 21: + // No break on purpose + case 31: + // No break on purpose + case 41: + _field416 = 0; + break; + case 12: + _field414 = 14; + R2_GLOBALS._player._numFrames = 10; + R2_GLOBALS._player.setup(3155, 1, 4); + R2_GLOBALS._player.setPosition(Common::Point(160, 70)); + R2_GLOBALS._player.animate(ANIM_MODE_2, NULL); + break; + case 13: + // No break on purpose + case 16: + // No break on purpose + case 23: + // No break on purpose + case 26: + // No break on purpose + case 33: + // No break on purpose + case 36: + // No break on purpose + case 43: + // No break on purpose + case 46: + R2_GLOBALS._player.setFrame(4); + _sceneMode = 1; + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 15: + // No break on purpose + case 25: + // No break on purpose + case 35: + // No break on purpose + case 45: + _field414 = 20; + R2_GLOBALS._player.animate(ANIM_MODE_2, NULL); + break; + case 20: + _field416 = 1; + _field414 = 6; + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.setStrip(2); + R2_GLOBALS._player.setFrame(5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 22: + _field414 = 14; + R2_GLOBALS._player._numFrames = 10; + R2_GLOBALS._player.setup(3155, 2, 4); + R2_GLOBALS._player.setPosition(Common::Point(160, 70)); + R2_GLOBALS._player.animate(ANIM_MODE_2, NULL); + break; + case 30: + _field416 = 1; + _field414 = 6; + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.setStrip(3); + R2_GLOBALS._player.setFrame(5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 32: + _field414 = 14; + R2_GLOBALS._player._numFrames = 10; + R2_GLOBALS._player.setup(3155, 3, 4); + R2_GLOBALS._player.setPosition(Common::Point(160, 70)); + R2_GLOBALS._player.animate(ANIM_MODE_2, NULL); + break; + case 40: + _field416 = 1; + _field414 = 6; + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.setStrip(4); + R2_GLOBALS._player.setFrame(5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 42: + _field414 = 14; + R2_GLOBALS._player._numFrames = 10; + R2_GLOBALS._player.setup(3155, 4, 4); + R2_GLOBALS._player.setPosition(Common::Point(160, 70)); + R2_GLOBALS._player.animate(ANIM_MODE_2, NULL); + break; + case 50: + // No break on purpose + case 55: + // No break on purpose + case 60: + R2_GLOBALS._player.setup(3156, 5, 1); + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 51: + // No break on purpose + case 56: + // No break on purpose + case 117: + R2_GLOBALS._player.setup(3157, 1, 1); + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 52: + // No break on purpose + case 82: + // No break on purpose + case 118: + R2_GLOBALS._player.setup(3156, 3, 6); + _sceneMode = 1; + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 57: + // No break on purpose + case 91: + // No break on purpose + case 96: + R2_GLOBALS._player.setup(3157, 2, 1); + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 58: + // No break on purpose + case 92: + // No break on purpose + case 122: + R2_GLOBALS._player.setup(3156, 2, 6); + _sceneMode = 1; + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 61: + R2_GLOBALS._player.setup(3157, 4, 5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 62: + // No break on purpose + case 72: + // No break on purpose + case 98: + R2_GLOBALS._player.setup(3156, 4, 6); + _sceneMode = 1; + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 70: + // No break on purpose + case 75: + // No break on purpose + case 80: + R2_GLOBALS._player.setup(3156, 6, 1); + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 71: + // No break on purpose + case 76: + // No break on purpose + case 97: + R2_GLOBALS._player.setup(3157, 3, 1); + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 77: + // No break on purpose + case 111: + // No break on purpose + case 116: + R2_GLOBALS._player.setup(3157, 3, 1); + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 78: + // No break on purpose + case 102: + // No break on purpose + case 112: + R2_GLOBALS._player.setup(3156, 1, 6); + _sceneMode = 1; + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 81: + R2_GLOBALS._player.setup(3157, 2, 5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 90: + // No break on purpose + case 95: + // No break on purpose + case 100: + R2_GLOBALS._player.setup(3156, 7, 1); + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 101: + R2_GLOBALS._player.setup(3157, 1, 5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 110: + // No break on purpose + case 115: + // No break on purpose + case 120: + R2_GLOBALS._player.setup(3156, 8, 1); + R2_GLOBALS._player._numFrames = 5; + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 121: + R2_GLOBALS._player.setup(3157, 3, 5); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + default: + warning("_eventManager.waitEvent()"); + _sceneMode = 2; + break; + } +} + +void Scene1200::process(Event &event) { + if (_field414 != 0) + return; + + Scene::process(event); + + if (!R2_GLOBALS._player._canWalk) + return; + + if (event.eventType == EVENT_BUTTON_DOWN) { + warning("_object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);"); + int unk = _object1.sub51AF8(event.mousePos); + switch (R2_GLOBALS._events.getCursor()) { + case CURSOR_ARROW: + event.handled = true; + if ((event.mousePos.x > 179) && (event.mousePos.x < 210) && (event.mousePos.y > 50) && (event.mousePos.y < 89)) + warning("sub9DAD6(1);"); + + if ((event.mousePos.x > 109) && (event.mousePos.x < 140) && (event.mousePos.y > 50) && (event.mousePos.y < 89)) + warning("sub9DAD6(2);"); + + if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 89) && (event.mousePos.y < 120)) + warning("sub9DAD6(3);"); + + if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 19) && (event.mousePos.y < 50)) + warning("sub9DAD6(4);"); + break; + case CURSOR_USE: + if (unk > 36) { + if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33)) + || ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33)) + || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41)) + || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5)) + || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21)) + || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21)) + || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5)) + || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9)) + || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17)) + || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17)) + || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17)) + || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) ) { + _area1.postInit(); + event.handled = true; + } + } + + if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) { + if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 9)) + || ((R2_GLOBALS._v56AA2 == 11) && (R2_GLOBALS._v56AA4 == 27)) + || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 7)) + || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 27)) + || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 33)) + || (R2_GLOBALS._v56AA2 == 33) ) { + switch (R2_GLOBALS._v56AA2) { + case 3: + R2_GLOBALS._sceneManager.changeScene(3150); + break; + case 33: + if (R2_GLOBALS._v56AA1 >= 4) + R2_GLOBALS._sceneManager.changeScene(3250); + else + SceneItem::display(1200, 6, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999); + break; + default: + SceneItem::display(1200, 5, 0, 280, 1, 160, 9, 1, 2, 20, 7, 154, -999); + break; + } + event.handled = true; + } + } + break; + case CURSOR_LOOK: + if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) { + event.handled = true; + switch (R2_GLOBALS._v56AA2) { + case 3: + SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + case 9: + R2_GLOBALS._sceneManager.changeScene(3240); + break; + case 11: + if (R2_GLOBALS._v56AA4 == 27) + R2_GLOBALS._sceneManager.changeScene(3210); + else + SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + case 17: + switch (R2_GLOBALS._v56AA4) { + case 5: + R2_GLOBALS._sceneManager.changeScene(3230); + break; + case 21: + R2_GLOBALS._sceneManager.changeScene(3220); + break; + case 33: + R2_GLOBALS._sceneManager.changeScene(3200); + break; + default: + SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + } + case 33: + R2_GLOBALS._sceneManager.changeScene(3245); + break; + default: + SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + } + } + if (unk > 36) { + event.handled = true; + SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + } + break; + case CURSOR_TALK: + event.handled = true; + break; + default: + return; + } + } else if (event.eventType == EVENT_KEYPRESS) { + if (_field414 == 0) { + event.handled = false; + return; + } + + switch (event.kbd.keycode) { + case Common::KEYCODE_1: + warning("FIXME: keycode = 0x4800"); + warning("sub9DAD6(4);"); + break; + case Common::KEYCODE_2: + warning("FIXME: keycode = 0x4B00"); + warning("sub9DAD6(2);"); + break; + case Common::KEYCODE_3: + warning("FIXME: keycode = 0x4D00"); + warning("sub9DAD6(1);"); + break; + case Common::KEYCODE_4: + warning("FIXME: keycode = 0x5000"); + warning("sub9DAD6(3);"); + break; + default: + event.handled = false; + return; + break; + } + } else { + return; + } +} + +void Scene1200::dispatch() { + Rect tmpRect; + Scene::dispatch(); + if (_field41C != 0) { + _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); + warning("int unk = set_pane_p(_paneNumber);"); + warning("_object1.sub51B02();"); + warning("_gfxManager.sub294AC(unk);"); + warning("tmpRect.sub14DF3();"); + _field41C = 0; + } + + if (_field414 != 0) { + tmpRect.set(110, 20, 210, 120); + _field414--; + switch (_field412 - 1) { + case 0: + R2_GLOBALS._v56AA2 += 2; + break; + case 1: + R2_GLOBALS._v56AA2 -= 2; + break; + case 2: + R2_GLOBALS._v56AA4 += 2; + break; + case 3: + R2_GLOBALS._v56AA4 -= 2; + break; + default: + break; + } + _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); + warning("int unk = set_pane_p(_paneNumber);"); + warning("_object1.sub51B02();"); + warning("_gfxManager.sub294AC(unk);"); + warning("tmpRect.sub14DF3();"); + + if (_field416 != 0) { + switch(_field412 - 1) { + case 0: + R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x - 2, R2_GLOBALS._player._position.y)); + break; + case 1: + R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x + 2, R2_GLOBALS._player._position.y)); + break; + case 2: + R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y - 2)); + break; + case 3: + R2_GLOBALS._player.setPosition(Common::Point(R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 2)); + break; + default: + break; + } + } + if (_field414 == 0) { + if (_field416 == 0) + R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL); + signal(); + } + } +} + +void Scene1200::saveCharacter(int characterIndex) { + R2_GLOBALS._sound1.fadeOut2(NULL); + SceneExt::saveCharacter(characterIndex); +} + +/*-------------------------------------------------------------------------- + * Scene 1500 - Cutscene: Ship landing + * + *--------------------------------------------------------------------------*/ +void Scene1500::postInit(SceneObjectList *OwnerList) { + loadScene(1500); + R2_GLOBALS._v58CE2 = 0; + R2_GLOBALS._v5589E.top = 0; + R2_GLOBALS._v5589E.bottom = 200; + setZoomPercents(170, 13, 240, 100); + SceneExt::postInit(); + scalePalette(65, 65, 65); + + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player.hide(); + R2_GLOBALS._player.disableControl(); + + _actor2.postInit(); + _actor2.setup(1401, 1, 1); + _actor2._effect = 5; + _actor2.fixPriority(10); + _actor2._field9C = _field312; + + _actor1.postInit(); + _actor1.setup(1400, 1, 1); + _actor1._moveDiff = Common::Point(1, 1); + _actor1._linkedActor = &_actor2; + + if (R2_GLOBALS._sceneManager._previousScene != 1010) { + _actor4.postInit(); + _actor4.setup(1401, 2, 1); + _actor4._effect = 5; + _actor4.fixPriority(10); + _actor4._field9C = _field312; + + _actor3.postInit(); + _actor3._moveRate = 30; + _actor3._moveDiff = Common::Point(1, 1); + _actor3._linkedActor = &_actor4; + } + + if (R2_GLOBALS._sceneManager._previousScene == 300) { + _actor1.setPosition(Common::Point(189, 139), 5); + + _actor3.setup(1400, 1, 2); + _actor3.setPosition(Common::Point(148, 108), 0); + + _sceneMode = 20; + R2_GLOBALS._sound1.play(110); + } else if (R2_GLOBALS._sceneManager._previousScene == 1550) { + _actor1.setPosition(Common::Point(189, 139), 5); + + _actor3.setup(1400, 2, 1); + _actor3.changeZoom(-1); + _actor3.setPosition(Common::Point(298, 258), 5); + + _sceneMode = 10; + R2_GLOBALS._sound1.play(106); + } else { + _actor1.setPosition(Common::Point(289, 239), -30); + _sceneMode = 0; + R2_GLOBALS._sound1.play(102); + } + signal(); +} + +void Scene1500::remove() { + R2_GLOBALS._v5589E.top = 3; + R2_GLOBALS._v5589E.bottom = 168; + R2_GLOBALS._v58CE2 = 1; + + SceneExt::remove(); +} + +void Scene1500::signal() { + switch(_sceneMode++) { + case 0: + R2_GLOBALS.setFlag(25); + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + // No break on purpose + case 1: + if (_actor1._yDiff < 50) { + _actor1.setPosition(Common::Point(289, 239), _actor1._yDiff + 1); + _sceneMode = 1; + } + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 2: { + Common::Point pt(189, 139); + NpcMover *mover = new NpcMover(); + _actor1.addMover(mover, &pt, this); + } + break; + case 3: + if (_actor1._yDiff > 5) { + _actor1.setPosition(Common::Point(189, 139), _actor1._yDiff - 1); + _sceneMode = 3; + } + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 13: + R2_GLOBALS._player._characterIndex = R2_MIRANDA; + // No break on purpose + case 4: + R2_GLOBALS._sceneManager.changeScene(300); + break; + case 10: + // No break on purpose + case 20: + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 11: { + Common::Point pt(148, 108); + NpcMover *mover = new NpcMover(); + _actor3.addMover(mover, &pt, this); + } + break; + case 12: + setAction(&_sequenceManager, this, 2, &R2_GLOBALS._player, NULL); + break; + case 21: { + Common::Point pt(-2, -42); + NpcMover *mover = new NpcMover(); + _actor3.addMover(mover, &pt, NULL); + signal(); + } + break; + case 22: + if (_actor1._yDiff < 50) { + _actor1.setPosition(Common::Point(189, 139), _actor1._yDiff + 1); + _sceneMode = 22; + } + setAction(&_sequenceManager, this, 1, &R2_GLOBALS._player, NULL); + break; + case 23: { + Common::Point pt(-13, -61); + NpcMover *mover = new NpcMover(); + _actor1.addMover(mover, &pt, this); + } + break; + case 24: + R2_GLOBALS._sceneManager.changeScene(300); + break; + default: + break; + } +} + +void Scene1500::dispatch() { + if (_sceneMode > 10) { + float yDiff = sqrt((float) (_actor3._position.x * _actor3._position.x) + (_actor3._position.y * _actor3._position.y)); + if (yDiff > 6) + _actor3.setPosition(_actor3._position, (int) yDiff); + } + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 1525 - Cutscene - Ship + * + *--------------------------------------------------------------------------*/ +void Scene1525::postInit(SceneObjectList *OwnerList) { + loadScene(1525); + R2_GLOBALS._v58CE2 = 0; + SceneExt::postInit(); + + R2_GLOBALS._player.postInit(); + if (R2_GLOBALS._sceneManager._previousScene == 525) + R2_GLOBALS._player.setup(1525, 1, 1); + else + R2_GLOBALS._player.setup(1525, 1, 16); + R2_GLOBALS._player.setPosition(Common::Point(244, 148)); + R2_GLOBALS._player.disableControl(); + + _sceneMode = 0; + setAction(&_sequenceManager, this, 2, &R2_GLOBALS._player, NULL); +} + +void Scene1525::signal() { + switch (_sceneMode++) { + case 0: + if (R2_GLOBALS._sceneManager._previousScene == 525) + setAction(&_sequenceManager, this, 1525, &R2_GLOBALS._player, NULL); + else + setAction(&_sequenceManager, this, 1526, &R2_GLOBALS._player, NULL); + break; + case 1: + setAction(&_sequenceManager, this, 2, &R2_GLOBALS._player, NULL); + break; + case 2: + if (R2_GLOBALS._sceneManager._previousScene == 1530) + R2_GLOBALS._sceneManager.changeScene(1550); + else + R2_GLOBALS._sceneManager.changeScene(1530); + default: + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 1530 - Cutscene - Elevator + * + *--------------------------------------------------------------------------*/ +void Scene1530::postInit(SceneObjectList *OwnerList) { + if (R2_GLOBALS._sceneManager._previousScene == 1000) + loadScene(1650); + else if (R2_GLOBALS._sceneManager._previousScene == 1580) + loadScene(1550); + else + loadScene(1530); + + R2_GLOBALS._v58CE2 = 0; + SceneExt::postInit(); + + _stripManager.addSpeaker(&_quinnSpeaker); + _stripManager.addSpeaker(&_seekerSpeaker); + + if (R2_GLOBALS._sceneManager._previousScene == 1000) { + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player.hide(); + R2_GLOBALS._player.disableControl(); + + R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + _stripManager.start(538, this); + R2_GLOBALS._sound1.play(114); + + _sceneMode = 3; + } else if (R2_GLOBALS._sceneManager._previousScene == 1580) { + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player._characterIndex = R2_QUINN; + R2_GLOBALS._player.setObjectWrapper(NULL); + R2_GLOBALS._player.setup(1516, 6, 1); + R2_GLOBALS._player.setPosition(Common::Point(160, 125)); + R2_GLOBALS._player._moveRate = 30; + R2_GLOBALS._player._moveDiff = Common::Point(4, 1); + + _actor2.postInit(); + _actor2.setup(1516, 7, 1); + _actor2.setPosition(Common::Point(121, 41)); + _actor2.animate(ANIM_MODE_2, NULL); + + _actor3.postInit(); + _actor3.setup(1516, 8, 1); + _actor3.setPosition(Common::Point(107, 116)); + _actor3.animate(ANIM_MODE_2, NULL); + + R2_GLOBALS._player.disableControl(); + Common::Point pt(480, 75); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + R2_GLOBALS._sound1.play(111); + + _sceneMode = 1; + } else { + _actor1.postInit(); + _actor1._effect = 1; + + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player.animate(ANIM_MODE_1, NULL); + R2_GLOBALS._player.disableControl(); + + setAction(&_sequenceManager, this, 1530, &R2_GLOBALS._player, &_actor1, NULL); + + _sceneMode = 2; + } + +} + +void Scene1530::signal() { + switch (_sceneMode - 1) { + case 0: + R2_GLOBALS._sceneManager.changeScene(1000); + break; + case 1: + R2_GLOBALS._sceneManager.changeScene(1525); + break; + case 2: + R2_GLOBALS._player.disableControl(); + _sceneMode = 4; + R2_GLOBALS._player.show(); + setAction(&_sequenceManager, this, 1650, &R2_GLOBALS._player, NULL); + break; + case 3: + R2_GLOBALS._sceneManager.changeScene(1700); + break; + default: + break; + } +} + +void Scene1530::dispatch() { + int16 x = R2_GLOBALS._player._position.x; + int16 y = R2_GLOBALS._player._position.y; + + _actor2.setPosition(Common::Point(x - 39, y - 85)); + _actor3.setPosition(Common::Point(x - 53, y - 9)); + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 1550 - + * + *--------------------------------------------------------------------------*/ +Scene1550::UnkObj15501::UnkObj15501() { + _fieldA4 = _fieldA6 = 0; +} + +void Scene1550::UnkObj15501::synchronize(Serializer &s) { + SceneActor::synchronize(s); + + s.syncAsSint16LE(_fieldA4); + s.syncAsSint16LE(_fieldA6); +} + +bool Scene1550::UnkObj15501::startAction(CursorType action, Event &event) { + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + switch (action) { + case CURSOR_USE: + if (_visage == 1561) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 40; + Common::Point pt(_position.x + 5, _position.y + 20); + PlayerMover *mover = new PlayerMover(); + R2_GLOBALS._player.addMover(mover, &pt, scene); + return true; + } + return SceneActor::startAction(action, event); + break; + case CURSOR_LOOK: + if (_visage == 1561) { + switch (_frame) { + case 2: + SceneItem::display(1550, 23, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + case 3: + SceneItem::display(1550, 26, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + case 4: + SceneItem::display(1550, 35, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + default: + break; + } + } else { + switch ((((_strip - 1) * 5) + _frame) % 3) { + case 0: + SceneItem::display(1550, 62, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + case 1: + SceneItem::display(1550, 53, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + case 2: + SceneItem::display(1550, 76, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + break; + default: + break; + } + } + return true; + break; + default: + return SceneActor::startAction(action, event); + break; + } +} + +Scene1550::UnkObj15502::UnkObj15502() { + _fieldA4 = 0; +} + +void Scene1550::UnkObj15502::synchronize(Serializer &s) { + SceneActor::synchronize(s); + + s.syncAsSint16LE(_fieldA4); +} + +bool Scene1550::UnkObj15502::startAction(CursorType action, Event &event) { + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + switch (action) { + case CURSOR_USE: + if (_fieldA4 == 8) { + scene->_field412 = 1; + R2_GLOBALS._player.disableControl(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1576; + else + scene->_sceneMode = 1584; + // strcpy(scene->_arrUnkObj15502[7]._actorName, 'hatch'); + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[7], NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case CURSOR_LOOK: + if (_fieldA4 == 8) + SceneItem::display(1550, 75, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + else if (_frame == 1) + SceneItem::display(1550, 70, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + else + SceneItem::display(1550, 71, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + return true; + break; + case R2_17: + scene->_field412 = 1; + if (_fieldA4 == 6) { + R2_GLOBALS._player.disableControl(); + scene->_actor1.postInit(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1574; + else + scene->_sceneMode = 1582; + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[5], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case R2_18: + scene->_field412 = 1; + if (_fieldA4 == 3) { + R2_GLOBALS._player.disableControl(); + scene->_actor1.postInit(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1571; + else + scene->_sceneMode = 1581; + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[2], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case R2_22: + scene->_field412 = 1; + if (_fieldA4 == 1) { + R2_GLOBALS._player.disableControl(); + scene->_actor1.postInit(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1569; + else + scene->_sceneMode = 1579; + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[0], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case R2_23: + scene->_field412 = 1; + if (_fieldA4 == 4) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 1572; + scene->_actor1.postInit(); + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[3], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case R2_25: + scene->_field412 = 1; + if (_fieldA4 == 2) { + R2_GLOBALS._player.disableControl(); + scene->_actor1.postInit(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1570; + else + scene->_sceneMode = 1580; + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[1], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case R2_27: + scene->_field412 = 1; + if (_fieldA4 == 5) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 1573; + scene->_actor1.postInit(); + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[4], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + case R2_45: + scene->_field412 = 1; + if (_fieldA4 == 7) { + R2_GLOBALS._player.disableControl(); + scene->_actor1.postInit(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1575; + else + scene->_sceneMode = 1583; + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_arrUnkObj15502[6], &scene->_actor1, NULL); + return true; + } + return SceneActor::startAction(action, event); + break; + default: + return SceneActor::startAction(action, event); + break; + } +} + +Scene1550::UnkObj15503::UnkObj15503() { + _fieldA4 = 0; +} + +void Scene1550::UnkObj15503::synchronize(Serializer &s) { + SceneActor::synchronize(s); + + s.syncAsSint16LE(_fieldA4); +} + +bool Scene1550::UnkObj15503::startAction(CursorType action, Event &event) { + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + if (action != CURSOR_USE) + return SceneActor::startAction(action, event); + switch (_fieldA4) { + case 1: + if (scene->_actor13._frame == 5) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 25; + if (scene->_actor4._frame == 1) { + scene->setAction(&scene->_sequenceManager1, scene, 1560, &scene->_actor4, NULL); + R2_GLOBALS.setFlag(20); + setFrame(2); + } else { + scene->setAction(&scene->_sequenceManager1, scene, 1561, &scene->_actor4, NULL); + R2_GLOBALS.clearFlag(20); + setFrame(1); + } + scene->_unkArea1.remove(); + } + break; + case 2: + R2_GLOBALS._player.disableControl(); + if (scene->_actor13._frame == 1) { + scene->_sceneMode = 23; + scene->setAction(&scene->_sequenceManager1, scene, 1560, this, NULL); + } else { + if (scene->_actor4._frame == 1) + scene->_sceneMode = 24; + else + scene->_sceneMode = 22; + scene->setAction(&scene->_sequenceManager1, scene, 1561, this, NULL); + } + break; + default: + break; + } + return true; +} + +void Scene1550::UnkArea1550::remove() { + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + _unkObj155031.remove(); + _unkObj155032.remove(); + // sub201EA is a common part with UnkArea1200 + R2_GLOBALS._sceneItems.remove((SceneItem *)this); + _areaActor.remove(); + SceneArea::remove(); + R2_GLOBALS._insetUp--; + // + if ((scene->_sceneMode >= 20) and (scene->_sceneMode <= 29)) + return; + + R2_GLOBALS._player.disableControl(); + if (scene->_actor4._frame == 1) { + scene->_sceneMode = 1559; + scene->setAction(&scene->_sequenceManager1, scene, 1559, &R2_GLOBALS._player, NULL); + } else { + scene->_sceneMode = 1562; + scene->setAction(&scene->_sequenceManager1, scene, 1562, &R2_GLOBALS._player, NULL); + } +} +void Scene1550::UnkArea1550::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) { + warning("Scene1550::UnkArea1550::proc12() should be based on Scene1550::UnkArea1200::proc12()"); +} + +bool Scene1550::Hotspot1::startAction(CursorType action, Event &event) { + return SceneHotspot::startAction(action, event); +} + +bool Scene1550::Hotspot3::startAction(CursorType action, Event &event) { + // Arrays related to this scene are all hacky in the origina: they are based on the impossibility to use Miranda + assert ((R2_GLOBALS._player._characterIndex == 1) || (R2_GLOBALS._player._characterIndex == 2)); + // The original contains a debug message when CURSOR_TALK is used. + if (action == CURSOR_TALK) + warning("Location: %d/%d - %d", R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex], R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2], _v5A4D6[(R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] * 30)] + R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]); + + return SceneHotspot::startAction(action, event); +} + +bool Scene1550::Actor6::startAction(CursorType action, Event &event) { + return SceneActor::startAction(action, event); +} + +bool Scene1550::Actor7::startAction(CursorType action, Event &event) { + if (action != CURSOR_TALK) + return SceneActor::startAction(action, event); + + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + scene->_sceneMode = 80; + scene->signal(); + + return true; +} + +bool Scene1550::Actor8::startAction(CursorType action, Event &event) { + if (action != CURSOR_USE) + return SceneActor::startAction(action, event); + + R2_GLOBALS._player.disableControl(); + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + scene->_field412 = 1; + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1552; + else + scene->_sceneMode = 1588; + + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor8, NULL); + return true; +} + +bool Scene1550::Actor9::startAction(CursorType action, Event &event) { + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + switch (action) { + case CURSOR_USE: + scene->_sceneMode = 50; + R2_GLOBALS._player.disableControl(); + R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_stripManager.start(518, scene); + else + scene->_stripManager.start(520, scene); + return true; + break; + case CURSOR_LOOK: + SceneItem::display(1550, 41, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + return true; + break; + default: + return SceneActor::startAction(action, event); + } +} + +bool Scene1550::Actor10::startAction(CursorType action, Event &event) { + if (action != CURSOR_USE) + return SceneActor::startAction(action, event); + + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + R2_GLOBALS._player.disableControl(); + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1555; + else + scene->_sceneMode = 1589; + + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor10, NULL); + return true; +} + +bool Scene1550::Actor11::startAction(CursorType action, Event &event) { + if (action != CURSOR_USE) + return SceneActor::startAction(action, event); + + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + R2_GLOBALS._player.disableControl(); + scene->_field412 = 1; + if (R2_GLOBALS._player._characterIndex == 1) + scene->_sceneMode = 1586; + else + scene->_sceneMode = 1587; + + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, &scene->_actor11, NULL); + return true; +} + +bool Scene1550::Actor12::startAction(CursorType action, Event &event) { + if (action != CURSOR_USE) + return SceneActor::startAction(action, event); + + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + if (R2_GLOBALS._player._characterIndex == 2) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 1585; + scene->setAction(&scene->_sequenceManager1, scene, 1585, &R2_GLOBALS._player, NULL); + } else { + R2_GLOBALS._player.disableControl(); + switch(scene->_field415) { + case 0: + scene->_actor13.fixPriority(168); + scene->_actor4.fixPriority(125); + scene->_sceneMode = 1558; + scene->setAction(&scene->_sequenceManager1, scene, 1558, &R2_GLOBALS._player, NULL); + break; + case 1: + return SceneActor::startAction(action, event); + break; + case 2: + scene->_field415 = 1; + scene->_sceneMode = 1563; + scene->setAction(&scene->_sequenceManager1, scene, 1563, &R2_GLOBALS._player, &scene->_actor4, NULL); + break; + default: + break; + } + } + return true; + +} + +bool Scene1550::Actor13::startAction(CursorType action, Event &event) { + Scene1550 *scene = (Scene1550 *)R2_GLOBALS._sceneManager._scene; + + switch (action) { + case CURSOR_USE: + if (scene->_field415 != 2) + return SceneActor::startAction(action, event); + + if (R2_INVENTORY.getObjectScene(R2_45) == 1550) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 1564; + scene->setAction(&scene->_sequenceManager1, scene, 1564, &R2_GLOBALS._player, NULL); + } else + SceneItem::display(1550, 64, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + return true; + break; + case CURSOR_LOOK: + if (scene->_field415 != 2) + return SceneActor::startAction(action, event); + + if (R2_INVENTORY.getObjectScene(R2_45) == 1550) { + SceneItem::display(1550, 74, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + } else + SceneItem::display(1550, 64, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + return true; + break; + default: + return SceneActor::startAction(action, event); + break; + } +} + +Scene1550::Scene1550() { + _field412 = 0; + _field414 = 0; + _field415 = 0; + _field417 = 0; + _field419 = 0; +} + +void Scene1550::synchronize(Serializer &s) { + SceneExt::synchronize(s); + + s.syncAsSint16LE(_field412); + s.syncAsByte(_field414); + s.syncAsSint16LE(_field415); + s.syncAsSint16LE(_field417); + s.syncAsSint16LE(_field419); +} + +void Scene1550::postInit(SceneObjectList *OwnerList) { + if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11)) + loadScene(1234); + else + loadScene(1550); + + scalePalette(65, 65, 65); + setZoomPercents(30, 75, 170, 100); + _field417 = 1550; + _field419 = 0; + SceneExt::postInit(); + + if (R2_GLOBALS._sceneManager._previousScene == -1) + R2_GLOBALS.setFlag(R2_16); + + if ((R2_GLOBALS._player._characterScene[1] != 1550) && (R2_GLOBALS._player._characterScene[1] != 1580)) { + R2_GLOBALS._player._characterScene[1] = 1550; + R2_GLOBALS._player._characterScene[2] = 1550; + } + + _stripManager.setColors(60, 255); + _stripManager.setFontNumber(3); + _stripManager.addSpeaker(&_quinnSpeaker); + _stripManager.addSpeaker(&_seekerSpeaker); + + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player._effect = 6; + + if (R2_GLOBALS._player._characterIndex == 1) + R2_GLOBALS._player.setup(1500, 3, 1); + else + R2_GLOBALS._player.setup(1505, 3, 1); + + R2_GLOBALS._player._moveDiff = Common::Point(5, 3); + + if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11)) + R2_GLOBALS._player.setPosition(Common::Point(157, 135)); + else + R2_GLOBALS._player.setPosition(Common::Point(160, 100)); + + R2_GLOBALS._player.animate(ANIM_MODE_1, NULL); + R2_GLOBALS._player.disableControl(); + + _field414 = 0; + _actor7.changeZoom(-1); + R2_GLOBALS._player.changeZoom(-1); + + switch (R2_GLOBALS._sceneManager._previousScene) { + case 1530: + R2_GLOBALS._v565AE = 0; + // No break on purpose + case 300: + // No break on purpose + case 1500: + // No break on purpose + case 3150: + R2_GLOBALS._sound1.play(105); + break; + case 1580: + if (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] == 1580) { + R2_GLOBALS._player.disableControl(); + R2_GLOBALS._player.animate(ANIM_MODE_NONE, NULL); + + _field412 = 1; + + _actor1.postInit(); + warning("_arrUnkObj15502[7].subA5CDF()"); + _arrUnkObj15502[7].hide(); + if (R2_GLOBALS._player._characterIndex == 1) + _sceneMode = 1577; + else + _sceneMode = 1578; + + setAction(&_sequenceManager1, this, _sceneMode, &R2_GLOBALS._player, &_actor1, &_arrUnkObj15502[7], NULL); + R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 1550; + } else { + R2_GLOBALS._player.enableControl(); + } + break; + default: + break; + } + warning("subA2B2F();"); + _item1.setDetails(16, 1550, 10, -1, -1); + _item2.setDetails(24, 1550, 10, -1, -1); + _item3.setDetails(Rect(0, 0, 320, 200), 1550, 0, 1, -1, 1, NULL); + + if ((R2_GLOBALS._sceneManager._previousScene == 1500) && (R2_GLOBALS.getFlag(16))) { + _sceneMode = 70; + if (!R2_GLOBALS._sceneObjects->contains(&_actor7)) + _actor7.postInit(); + + if (R2_GLOBALS._player._characterIndex == 1) + _actor7.setVisage(1505); + else + _actor7.setVisage(1500); + + _actor7.changeZoom(77); + _actor7.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL); + + warning("R2_GLOBALS._walkRegions.enableRegion(R2_GLOBALS._v14A72[_field419]);"); + setAction(&_sequenceManager1, this, 1590, &_actor7, NULL); + } else if ((_sceneMode != 1577) && (_sceneMode != 1578)) + R2_GLOBALS._player.enableControl(); +} + +void Scene1550::signal() { + switch (_sceneMode) { + case 1: + // No break on purpose + case 3: + // No break on purpose + case 5: + // No break on purpose + case 7: + _field412 = 0; + R2_GLOBALS._v56AAB = 0; + R2_GLOBALS._player.enableControl(CURSOR_ARROW); + break; + case 20: + // No break on purpose + case 21: + // No break on purpose + case 25: + // No break on purpose + case 1563: + R2_GLOBALS.clearFlag(20); + _unkArea1.proc12(1559, 1, 1, 160, 125); + R2_GLOBALS._player.enableControl(); + _sceneMode = 0; + break; + case 22: + _unkArea1.remove(); + _sceneMode = 24; + setAction(&_sequenceManager1, this, 1561, &_actor4, NULL); + R2_GLOBALS.clearFlag(20); + break; + case 23: + _unkArea1.remove(); + _sceneMode = 20; + setAction(&_sequenceManager1, this, 1566, &_actor13, &_actor5, NULL); + R2_GLOBALS.setFlag(21); + break; + case 24: + _unkArea1.remove(); + _sceneMode = 21; + setAction(&_sequenceManager1, this, 1567, &_actor13, &_actor5, NULL); + R2_GLOBALS.clearFlag(19); + break; + case 30: + // No break on purpose + case 1556: + // No break on purpose + case 1557: + // Nothing on purpose + break; + case 40: { + _sceneMode = 41; + Common::Point pt(_arrUnkObj15501[0]._position.x, _arrUnkObj15501[0]._position.y + 20); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + break; + case 41: + _sceneMode = 42; + if (R2_GLOBALS._player._characterIndex == 1) { + R2_GLOBALS._player.setup(1502, 8, 1); + } else { + R2_GLOBALS._player.changeZoom(R2_GLOBALS._player._percent + 14); + R2_GLOBALS._player.setup(1516, 4, 1); + } + R2_GLOBALS._player.animate(ANIM_MODE_5, this); + break; + case 42: + _sceneMode = 43; + warning("TODO: unknown use of arrUnkObj15501[0]._fieldA6"); + switch (_arrUnkObj15501[0]._frame - 1) { + case 0: + R2_INVENTORY.setObjectScene(26, R2_GLOBALS._player._characterIndex); + break; + case 1: + R2_INVENTORY.setObjectScene(17, R2_GLOBALS._player._characterIndex); + break; + case 2: + R2_INVENTORY.setObjectScene(22, R2_GLOBALS._player._characterIndex); + break; + case 3: + R2_INVENTORY.setObjectScene(25, R2_GLOBALS._player._characterIndex); + break; + case 4: + R2_INVENTORY.setObjectScene(45, R2_GLOBALS._player._characterIndex); + break; + case 5: + R2_INVENTORY.setObjectScene(28, R2_GLOBALS._player._characterIndex); + break; + default: + break; + } + _arrUnkObj15501[0].remove(); + R2_GLOBALS._player.animate(ANIM_MODE_6, this); + break; + case 43: + warning("TODO: unknown use of arrUnkObj15501[0]._fieldA6"); + if (R2_GLOBALS._player._characterIndex == 1) + R2_GLOBALS._player.setVisage(1500); + else { + R2_GLOBALS._player.changeZoom(-1); + R2_GLOBALS._player.setVisage(1505); + } + R2_GLOBALS._player.animate(ANIM_MODE_1, this); + R2_GLOBALS._player.setStrip(8); + R2_GLOBALS._player.enableControl(); + break; + case 50: + warning("STUB: sub_1D227()"); + ++_sceneMode; + setAction(&_sequenceManager1, this, 1591, &R2_GLOBALS._player, NULL); + if (g_globals->_sceneObjects->contains(&_actor7)) + signal(); + else { + _actor7.postInit(); + if (R2_GLOBALS._player._characterIndex == 1) + _actor7.setVisage(1505); + else + _actor7.setVisage(1500); + _actor7.changeZoom(77); + _actor7.setAction(&_sequenceManager2, this, 1590, &_actor7, NULL); + _actor7.setDetails(1550, -1, -1, -1, 2, (SceneItem *) NULL); + } + break; + case 51: + ++_sceneMode; + break; + case 52: + _actor7.changeZoom(-1); + _sceneMode = 1592; + if (R2_GLOBALS._player._characterIndex == 1) + setAction(&_sequenceManager1, this, 1592, &R2_GLOBALS._player, &_actor7, &_arrUnkObj15501[0], &_actor9, NULL); + else + setAction(&_sequenceManager1, this, 1593, &R2_GLOBALS._player, &_actor7, &_arrUnkObj15501[0], &_actor9, NULL); + break; + case 61: + R2_GLOBALS._player.enableControl(CURSOR_USE); + R2_GLOBALS._player._canWalk = false; + _field415 = 2; + break; + case 62: + R2_GLOBALS._player.enableControl(CURSOR_TALK); + if (_field415 == 2) { + R2_GLOBALS._player.enableControl(CURSOR_USE); + R2_GLOBALS._player._canWalk = false; + } + break; + case 70: + R2_GLOBALS._v565EC[2] = R2_GLOBALS._v565EC[1]; + R2_GLOBALS._v565EC[4] = R2_GLOBALS._v565EC[3]; + R2_GLOBALS._v565EC[0] = 1; + _sceneMode = 60; + R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + _stripManager.start(500, this); + break; + case 80: + if (R2_GLOBALS.getFlag(16)) { + _sceneMode = 60; + R2_GLOBALS._player.disableControl(); + R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + if (R2_GLOBALS._v565AE >= 3) { + if (R2_GLOBALS._player._characterIndex == 1) + _stripManager.start(572, this); + else + _stripManager.start(573, this); + } else { + ++R2_GLOBALS._v565AE; + if (R2_GLOBALS._player._characterIndex == 1) + _stripManager.start(499 + R2_GLOBALS._v565AE, this); + else + _stripManager.start(502 + R2_GLOBALS._v565AE, this); + } + } else { + _sceneMode = 60; + R2_GLOBALS._player.disableControl(); + R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + if (R2_GLOBALS._v565AE >= 4) { + if (R2_GLOBALS._player._characterIndex == 1) + _stripManager.start(572, this); + else + _stripManager.start(573, this); + } else { + ++R2_GLOBALS._v565AE; + if (R2_GLOBALS._player._characterIndex == 1) + _stripManager.start(563 + R2_GLOBALS._v565AE, this); + else + _stripManager.start(567 + R2_GLOBALS._v565AE, this); + } + } + break; + case 1550: + R2_GLOBALS._sceneManager.changeScene(1525); + break; + case 1552: + // No break on purpose + case 1588: + R2_INVENTORY.setObjectScene(R2_19, R2_GLOBALS._player._characterIndex); + _actor8.remove(); + _field412 = 0; + R2_GLOBALS._player.enableControl(); + break; + case 1553: + R2_GLOBALS._sceneManager.changeScene(1575); + break; + case 1554: + R2_GLOBALS._player.enableControl(); + _field412 = 0; + break; + case 1555: + // No break on purpose + case 1589: + R2_INVENTORY.setObjectScene(R2_18, R2_GLOBALS._player._characterIndex); + _actor10.remove(); + R2_GLOBALS._player.enableControl(); + break; + case 1558: + _actor13.fixPriority(124); + _field415 = 1; + _unkArea1.proc12(1559, 1, 1, 160, 125); + R2_GLOBALS._player.enableControl(); + break; + case 1559: + _actor13.fixPriority(168); + _actor4.fixPriority(169); + R2_GLOBALS._player.fixPriority(-1); + R2_GLOBALS._player.changeZoom(-1); + _field415 = 0; + R2_GLOBALS._player.enableControl(); + break; + case 1562: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field415 = 2; + break; + case 1564: + R2_INVENTORY.setObjectScene(R2_45, 1); + _sceneMode = 1565; + setAction(&_sequenceManager1, this, 1565, &R2_GLOBALS._player, NULL); + break; + case 1565: + R2_GLOBALS._player.enableControl(CURSOR_USE); + R2_GLOBALS._player._canWalk = false; + break; + case 1569: + // No break on purpose + case 1579: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_22, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1570: + // No break on purpose + case 1580: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_25, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1571: + // No break on purpose + case 1581: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_18, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1572: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_23, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1573: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_27, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1574: + // No break on purpose + case 1582: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_17, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1575: + // No break on purpose + case 1583: + _field412 = 0; + _actor1.remove(); + R2_INVENTORY.setObjectScene(R2_45, 0); + R2_GLOBALS._player.enableControl(); + break; + case 1576: + // No break on purpose + case 1584: + R2_GLOBALS._sceneManager.changeScene(1580); + R2_GLOBALS._player.enableControl(); + break; + case 1577: + // No break on purpose + case 1578: + _sceneMode = 0; + _actor1.remove(); + _field412 = 0; + R2_GLOBALS._player.fixPriority(-1); + R2_GLOBALS._player.enableControl(); + break; + case 1585: + SceneItem::display(1550, 66, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + R2_GLOBALS._player.enableControl(); + break; + case 1586: + // No break on purpose + case 1587: + R2_INVENTORY.setObjectScene(R2_28, R2_GLOBALS._player._characterIndex); + _actor1.remove(); + _field412 = 0; + R2_GLOBALS._player.enableControl(); + break; + case 1592: + _actor9.remove(); + R2_INVENTORY.setObjectScene(R2_26, 1); + if (R2_GLOBALS._player._characterIndex == 1) { + R2_GLOBALS._v565EC[2] = R2_GLOBALS._v565EC[1]; + R2_GLOBALS._v565EC[4] = R2_GLOBALS._v565EC[3]; + } else { + R2_GLOBALS._v565EC[1] = R2_GLOBALS._v565EC[2]; + R2_GLOBALS._v565EC[3] = R2_GLOBALS._v565EC[4]; + } + R2_GLOBALS._player.enableControl(); + break; + default: + _sceneMode = 62; + setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL); + break; + } +} + +void Scene1550::process(Event &event) { + if ((!R2_GLOBALS._player._canWalk) && (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN) && (event.eventType == EVENT_BUTTON_DOWN) && (this->_screenNumber == 1234)) { + int curReg = R2_GLOBALS._sceneRegions.indexOf(event.mousePos); + if (curReg == 0) + _field412 = 1; + else if (((R2_GLOBALS._player._position.y < 90) && (event.mousePos.y > 90)) || ((R2_GLOBALS._player._position.y > 90) && (event.mousePos.y < 90))) + _field412 = 1; + else + _field412 = 0; + + if ((curReg == 13) || (curReg == 14)) + _field412 = 0; + } + + Scene::process(event); +} + +void Scene1550::dispatch() { + Scene::dispatch(); + + // Arrays related to this scene are all hacky in the origina: they are based on the impossibility to use Miranda + assert ((R2_GLOBALS._player._characterIndex == 1) || (R2_GLOBALS._player._characterIndex == 2)); + + if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 15) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 16)) { + R2_GLOBALS._player._shade = 0; + // Original game contains a switch based on an uninitialised variable. + // Until we understand what should really happen there, this code is unused on purpose + int missingVariable = 0; + switch (missingVariable) { + case 144: + // No break on purpose + case 146: + _actor13._frame = 5; + R2_GLOBALS._player._shade = 3; + break; + case 148: + // No break on purpose + case 149: + _actor13._frame = 1; + // No break on purpose + case 147: + // No break on purpose + case 150: + R2_GLOBALS._player._shade = 3; + break; + default: + break; + } + } + + if (_field412 != 0) + return; + + switch (R2_GLOBALS._player.getRegionIndex() - 11) { + case 0: + // No break on purpose + case 5: + R2_GLOBALS._player.disableControl(); + _sceneMode = 1; + _field412 = 1; + --R2_GLOBALS._v565EC[2 + R2_GLOBALS._player._characterIndex]; + warning("subA2B2F();"); + R2_GLOBALS._player.setPosition(Common::Point( 160 - (((((160 - R2_GLOBALS._player._position.x) * 100) / 108) * 172) / 100), 145)); + if (R2_GLOBALS._player._position.x < 160) { + Common::Point pt(R2_GLOBALS._player._position.x + 5, 135); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else if (R2_GLOBALS._player._position.x <= 160) { // the check is really in the original... + Common::Point pt(R2_GLOBALS._player._position.x, 135); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else { + Common::Point pt(R2_GLOBALS._player._position.x - 5, 135); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + break; + case 1: + R2_GLOBALS._player.disableControl(); + _sceneMode = 3; + _field412 = 1; + ++R2_GLOBALS._v565EC[2 + R2_GLOBALS._player._characterIndex]; + warning("subA2B2F();"); + R2_GLOBALS._player.setPosition(Common::Point( 160 - (((((160 - R2_GLOBALS._player._position.x) * 100) / 172) * 108) / 100), 19)); + if (R2_GLOBALS._player._position.x < 160) { + Common::Point pt(R2_GLOBALS._player._position.x + 5, 29); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else if (R2_GLOBALS._player._position.x <= 160) { // the check is really in the original... + Common::Point pt(R2_GLOBALS._player._position.x, 29); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else { + Common::Point pt(R2_GLOBALS._player._position.x - 5, 29); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + break; + case 2: + R2_GLOBALS._player.disableControl(); + _sceneMode = 5; + _field412 = 1; + ++R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]; + warning("subA2B2F();"); + if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11) && (R2_GLOBALS._player._position.y > 50) && (R2_GLOBALS._player._position.y < 135)) { + if (R2_GLOBALS._player._position.y >= 85) { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 10)); + Common::Point pt(R2_GLOBALS._player._position.x + 30, R2_GLOBALS._player._position.y + 20); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y - 10)); + Common::Point pt(R2_GLOBALS._player._position.x + 30, R2_GLOBALS._player._position.y - 20); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + } else { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y)); + Common::Point pt(R2_GLOBALS._player._position.x + 10, R2_GLOBALS._player._position.y); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + break; + case 3: + R2_GLOBALS._player.disableControl(); + _sceneMode = 7; + _field412 = 1; + --R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex]; + if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 24) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11)) { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y / 2)); + Common::Point pt(265, 29); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else if ((R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex] == 9) && (R2_GLOBALS._v565EC[R2_GLOBALS._player._characterIndex + 2] == 11) && (R2_GLOBALS._player._position.y > 50) && (R2_GLOBALS._player._position.y < 135)) { + if (R2_GLOBALS._player._position.y >= 85) { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y + 10)); + Common::Point pt(R2_GLOBALS._player._position.x - 30, R2_GLOBALS._player._position.y + 20); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } else { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y - 10)); + Common::Point pt(R2_GLOBALS._player._position.x - 30, R2_GLOBALS._player._position.y - 20); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + } else { + R2_GLOBALS._player.setPosition(Common::Point(320 - R2_GLOBALS._player._position.x, R2_GLOBALS._player._position.y)); + Common::Point pt(R2_GLOBALS._player._position.x - 10, R2_GLOBALS._player._position.y); + NpcMover *mover = new NpcMover(); + R2_GLOBALS._player.addMover(mover, &pt, this); + } + break; + default: + break; + } +} + +void Scene1550::saveCharacter(int characterIndex) { + if (R2_GLOBALS._player._characterIndex == 3) + R2_GLOBALS._sound1.fadeOut2(NULL); + + SceneExt::saveCharacter(characterIndex); +} + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h index a21869b6ad..6d2bd3b084 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes1.h +++ b/engines/tsage/ringworld2/ringworld2_scenes1.h @@ -59,15 +59,15 @@ public: class Scene1100 : public SceneExt { class Actor16 : public SceneActor { public: - bool startAction(CursorType action, Event &event); + virtual bool startAction(CursorType action, Event &event); }; class Actor17 : public SceneActor { public: - bool startAction(CursorType action, Event &event); + virtual bool startAction(CursorType action, Event &event); }; class Actor18 : public SceneActor { public: - bool startAction(CursorType action, Event &event); + virtual bool startAction(CursorType action, Event &event); }; public: @@ -117,6 +117,259 @@ public: virtual void saveCharacter(int characterIndex); }; +class Scene1200 : public SceneExt { + class Area1: public SceneArea { + public: + class Actor3 : public SceneActorExt { + public: + void init(int state); + virtual bool startAction(CursorType action, Event &event); + }; + + SceneActor _actor2; + Actor3 _actor3; + Actor3 _actor4; + Actor3 _actor5; + + byte _field20; + + Area1(); + void synchronize(Serializer &s); + + virtual void postInit(); + virtual void remove(); + virtual void process(Event &event); + virtual void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY); + virtual void proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum); + }; + + class Object1 : public SavedObject { + public: + Rect _rect1; + Rect _rect2; + + int _field16; + int _field26; + int _field28; + int _field2A; + int _field2C; + int _field2E; + int _field30; + + Object1(); + void synchronize(Serializer &s); + + int sub51AF8(Common::Point pt); + bool sub51AFD(Common::Point pt); + void sub9EDE8(Rect rect); + virtual Common::String getClassName() { return "UnkObject1200"; } + }; + +public: + NamedHotspot _item1; + SceneActor _actor1; + Area1 _area1; + Object1 _object1; + SequenceManager _sequenceManager; + + int _field412; + int _field414; + int _field416; + int _field418; + int _field41A; + int _field41C; + + Scene1200(); + void synchronize(Serializer &s); + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); + virtual void saveCharacter(int characterIndex); +}; + +class Scene1500 : public SceneExt { +public: + SceneActor _actor1; + SceneActor _actor2; + SceneActor _actor3; + SceneActor _actor4; + SequenceManager _sequenceManager; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void remove(); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene1525 : public SceneExt { +public: + SequenceManager _sequenceManager; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); +}; + +class Scene1530 : public SceneExt { +public: + SpeakerQuinn _quinnSpeaker; + SpeakerSeeker _seekerSpeaker; + SceneActor _actor1; + SceneActor _actor2; + SceneActor _actor3; + + SequenceManager _sequenceManager; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene1550 : public SceneExt { + class UnkObj15501 : public SceneActor { + public: + int _fieldA4; + int _fieldA6; + + UnkObj15501(); + void synchronize(Serializer &s); + + virtual bool startAction(CursorType action, Event &event); + }; + + class UnkObj15502 : public SceneActor { + public: + int _fieldA4; + + UnkObj15502(); + void synchronize(Serializer &s); + + virtual bool startAction(CursorType action, Event &event); + }; + + class UnkObj15503 : public SceneActor { + public: + int _fieldA4; + + UnkObj15503(); + void synchronize(Serializer &s); + + virtual bool startAction(CursorType action, Event &event); + }; + + class UnkArea1550 : public SceneArea { + public: + byte _field20; + SceneActor _areaActor; + UnkObj15503 _unkObj155031; + UnkObj15503 _unkObj155032; + + virtual void remove(); + virtual void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY); + }; + + class Hotspot1 : public NamedHotspot { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Hotspot3 : public NamedHotspot { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor6 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor7 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor8 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor9 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor10 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor11 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor12 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor13 : public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Actor14 : public SceneActor { + // Nothing specific found in the original + // TODO: check if it's an useless class + }; + +public: + SpeakerQuinn _quinnSpeaker; + SpeakerSeeker _seekerSpeaker; + Hotspot1 _item1; + Hotspot1 _item2; + Hotspot3 _item3; + SceneActor _actor1; + SceneActor _actor2; + SceneActor _actor3; + SceneActor _actor4; + SceneActor _actor5; + Actor6 _actor6; + Actor7 _actor7; + Actor8 _actor8; + Actor9 _actor9; + Actor10 _actor10; + Actor11 _actor11; + Actor12 _actor12; + Actor13 _actor13; + UnkObj15501 _arrUnkObj15501[8]; + Actor14 _actor14; + Actor14 _actor15; + Actor14 _actor16; + Actor14 _actor17; + Actor14 _actor18; + Actor14 _actor19; + UnkObj15502 _arrUnkObj15502[8]; + UnkArea1550 _unkArea1; + SequenceManager _sequenceManager1; + SequenceManager _sequenceManager2; + + int _field412; + byte _field414; + int _field415; + int _field417; + int _field419; + + Scene1550(); + void synchronize(Serializer &s); + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); + virtual void saveCharacter(int characterIndex); +}; } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp index cc93c4f35f..1251b6d262 100644 --- a/engines/tsage/staticres.cpp +++ b/engines/tsage/staticres.cpp @@ -237,6 +237,29 @@ char const *const F7 = "F7"; char const *const F8 = "F8"; char const *const F10 = "F10"; +const byte _v5A4D6[] = { + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, + 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, + 13, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14 +}; + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h index 5b6f4393c4..ae2aa28aeb 100644 --- a/engines/tsage/staticres.h +++ b/engines/tsage/staticres.h @@ -190,6 +190,9 @@ extern char const *const F7; extern char const *const F8; extern char const *const F10; +// Scene 1550 map +extern const byte _v5A4D6[]; + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/gui/browser_osx.mm b/gui/browser_osx.mm index 017b31b9a8..b8aa7c50ee 100644 --- a/gui/browser_osx.mm +++ b/gui/browser_osx.mm @@ -62,11 +62,7 @@ int BrowserDialog::runModal() { NSOpenPanel * panel = [NSOpenPanel openPanel]; [panel setCanChooseDirectories:YES]; if ([panel runModalForTypes:nil] == NSOKButton) { -#ifdef __POWERPC__ - const char *filename = [[panel filename] cString]; -#else - const char *filename = [[panel filename] cStringUsingEncoding:NSUTF8StringEncoding]; -#endif + const char *filename = [[panel filename] UTF8String]; _choice = Common::FSNode(filename); choiceMade = true; } diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip Binary files differindex cba92201d3..867cf91c5b 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip diff --git a/gui/themes/scummmodern/eraser.bmp b/gui/themes/scummmodern/eraser.bmp Binary files differindex 782b13dc62..b927a6384f 100644 --- a/gui/themes/scummmodern/eraser.bmp +++ b/gui/themes/scummmodern/eraser.bmp @@ -110,7 +110,7 @@ OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libfaad.a endif ifdef USE_ZLIB -OSX_ZLIB ?= -lz +OSX_ZLIB ?= $(STATICLIBPATH)/lib/libz.a endif ifdef USE_SPARKLE @@ -165,10 +165,10 @@ osxsnap: bundle mkdir ScummVM-snapshot/doc/it cp $(srcdir)/doc/it/GuidaRapida ./ScummVM-snapshot/doc/it/GuidaRapida mkdir ScummVM-snapshot/doc/no-nb - cp $(srcdir)doc/no-nb/HurtigStart ./ScummVM-snapshot/doc/no-nb/HurtigStart + cp $(srcdir)/doc/no-nb/HurtigStart ./ScummVM-snapshot/doc/no-nb/HurtigStart mkdir ScummVM-snapshot/doc/se - cp $(srcdir)doc/se/LasMig ./ScummVM-snapshot/doc/se/LasMig - cp $(srcdir)doc/se/Snabbstart ./ScummVM-snapshot/doc/se/Snabbstart + cp $(srcdir)/doc/se/LasMig ./ScummVM-snapshot/doc/se/LasMig + cp $(srcdir)/doc/se/Snabbstart ./ScummVM-snapshot/doc/se/Snabbstart /Developer/Tools/SetFile -t ttro -c ttxt ./ScummVM-snapshot/* xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/cz/* xattr -w "com.apple.TextEncoding" "utf-8;134217984" ./ScummVM-snapshot/doc/de/* diff --git a/video/bink_decoder.cpp b/video/bink_decoder.cpp index 46ac8ac386..c5dc5f280b 100644 --- a/video/bink_decoder.cpp +++ b/video/bink_decoder.cpp @@ -113,23 +113,33 @@ BinkDecoder::BinkDecoder() { } _audioStream = 0; - _audioStarted = false; } -BinkDecoder::~BinkDecoder() { - close(); -} +void BinkDecoder::startAudio() { + if (_audioTrack < _audioTracks.size()) { + const AudioTrack &audio = _audioTracks[_audioTrack]; -void BinkDecoder::close() { - reset(); + _audioStream = Audio::makeQueuingAudioStream(audio.outSampleRate, audio.outChannels == 2); + g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audioHandle, _audioStream); + } // else no audio +} +void BinkDecoder::stopAudio() { if (_audioStream) { - // Stop audio g_system->getMixer()->stopHandle(_audioHandle); _audioStream = 0; } +} + +BinkDecoder::~BinkDecoder() { + close(); +} - _audioStarted = false; +void BinkDecoder::close() { + reset(); + + // Stop audio + stopAudio(); for (int i = 0; i < 4; i++) { delete[] _curPlanes[i]; _curPlanes[i] = 0; @@ -173,7 +183,7 @@ void BinkDecoder::close() { uint32 BinkDecoder::getElapsedTime() const { if (_audioStream && g_system->getMixer()->isSoundHandleActive(_audioHandle)) - return g_system->getMixer()->getSoundElapsedTime(_audioHandle); + return g_system->getMixer()->getSoundElapsedTime(_audioHandle) + _audioStartOffset; return g_system->getMillis() - _startTime; } @@ -241,11 +251,6 @@ const Graphics::Surface *BinkDecoder::decodeNextFrame() { if (_curFrame == 0) _startTime = g_system->getMillis(); - if (!_audioStarted && _audioStream) { - _audioStarted = true; - g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audioHandle, _audioStream); - } - return &_surface; } @@ -510,6 +515,11 @@ void BinkDecoder::mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte * } bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) { + Graphics::PixelFormat format = g_system->getScreenFormat(); + return loadStream(stream, format); +} + +bool BinkDecoder::loadStream(Common::SeekableReadStream *stream, const Graphics::PixelFormat &format) { close(); _id = stream->readUint32BE(); @@ -589,7 +599,6 @@ bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) { _hasAlpha = _videoFlags & kVideoFlagAlpha; _swapPlanes = (_id == kBIKhID) || (_id == kBIKiID); // BIKh and BIKi swap the chroma planes - Graphics::PixelFormat format = g_system->getScreenFormat(); _surface.create(width, height, format); // Give the planes a bit extra space @@ -618,11 +627,8 @@ bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) { initBundles(); initHuffman(); - if (_audioTrack < _audioTracks.size()) { - const AudioTrack &audio = _audioTracks[_audioTrack]; - - _audioStream = Audio::makeQueuingAudioStream(audio.outSampleRate, audio.outChannels == 2); - } + startAudio(); + _audioStartOffset = 0; return true; } diff --git a/video/bink_decoder.h b/video/bink_decoder.h index dd1b7ca67d..3d5e882dd7 100644 --- a/video/bink_decoder.h +++ b/video/bink_decoder.h @@ -76,7 +76,9 @@ public: // FixedRateVideoDecoder Common::Rational getFrameRate() const { return _frameRate; } -private: + // Bink specific + bool loadStream(Common::SeekableReadStream *stream, const Graphics::PixelFormat &format); +protected: static const int kAudioChannelsMax = 2; static const int kAudioBlockSizeMax = (kAudioChannelsMax << 11); @@ -221,15 +223,13 @@ private: Audio::SoundHandle _audioHandle; Audio::QueuingAudioStream *_audioStream; - bool _audioStarted; + int32 _audioStartOffset; uint32 _videoFlags; ///< Video frame features. bool _hasAlpha; ///< Do video frames have alpha? bool _swapPlanes; ///< Are the planes ordered (A)YVU instead of (A)YUV? - uint32 _audioFrame; - Common::Array<AudioTrack> _audioTracks; ///< All audio tracks. Common::Array<VideoFrame> _frames; ///< All video frames. @@ -259,7 +259,7 @@ private: /** Decode an audio packet. */ void audioPacket(AudioTrack &audio); /** Decode a video packet. */ - void videoPacket(VideoFrame &video); + virtual void videoPacket(VideoFrame &video); /** Decode a plane. */ void decodePlane(VideoFrame &video, int planeIdx, bool isChroma); @@ -327,6 +327,11 @@ private: void IDCT(int16 *block); void IDCTPut(DecodeContext &ctx, int16 *block); void IDCTAdd(DecodeContext &ctx, int16 *block); + + /** Start playing the audio track */ + void startAudio(); + /** Stop playing the audio track */ + void stopAudio(); }; } // End of namespace Video |