diff options
author | Travis Howell | 2009-07-06 06:34:40 +0000 |
---|---|---|
committer | Travis Howell | 2009-07-06 06:34:40 +0000 |
commit | f63b02b9200606069a605e27d828f4c8c59119fc (patch) | |
tree | 705a39e27a252ed5fe897d0ef0e08b7091d43cd8 /engines | |
parent | 4b1c6b526dbfa8d084fbd2475b4d4caa173e442c (diff) | |
parent | 08df8dc2721808c7019f49d9051e2eebfe8dad9c (diff) | |
download | scummvm-rg350-f63b02b9200606069a605e27d828f4c8c59119fc.tar.gz scummvm-rg350-f63b02b9200606069a605e27d828f4c8c59119fc.tar.bz2 scummvm-rg350-f63b02b9200606069a605e27d828f4c8c59119fc.zip |
Merged revisions 42087-42088,42093-42095,42097-42099,42104-42107,42110,42112-42113,42115-42132,42134-42150,42153-42155,42161-42162 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk
........
r42087 | thebluegr | 2009-07-04 21:24:09 +1000 (Sat, 04 Jul 2009) | 1 line
Newer DoSound() semantics are now detected automatically, by the existence of the "setVol" selector. Removed game flag GF_SCI1_NEWDOSOUND
........
r42088 | thebluegr | 2009-07-04 21:33:51 +1000 (Sat, 04 Jul 2009) | 1 line
Removed silly FIXME (mixup between debug and engine debug levels)
........
r42093 | thebluegr | 2009-07-05 01:22:42 +1000 (Sun, 05 Jul 2009) | 1 line
Added a new console command, "selector", which attempts to find a selector by name
........
r42094 | thebluegr | 2009-07-05 01:39:31 +1000 (Sun, 05 Jul 2009) | 1 line
- Changed some comments to DOxygen style
........
r42095 | thebluegr | 2009-07-05 01:45:04 +1000 (Sun, 05 Jul 2009) | 3 lines
- Kernel function names are no longer loaded from vocab.999, but are constructed from the hardcoded function table, depending on the SCI version used
- SCI0 games using older graphics functions are now detected by the presence of the "curAngle" selector
- SCI0 games using a SCI1 table (like KQ1 demo version and full version) are detected by the presence of the "sightAngle" selector (as no SCI0 game seems to have it)
........
r42097 | thebluegr | 2009-07-05 02:30:20 +1000 (Sun, 05 Jul 2009) | 3 lines
- Merged the "early" and "late" SCI1 versions - these are functionally equivalent, and the code that does the version check is unreliable (e.g. it sets SQ1 VGA to SCI1 "late" and EcoQuest 1 to SCI1 "early")
- Cleanup of the vocabulary setting functions
- Cleanup of the cursor manipulation code
........
r42098 | thebluegr | 2009-07-05 02:36:56 +1000 (Sun, 05 Jul 2009) | 1 line
Merged SCI1 versions in one more file
........
r42099 | thebluegr | 2009-07-05 03:39:43 +1000 (Sun, 05 Jul 2009) | 1 line
Cursors without a palette are now initialized correctly (from patch #2816652). Fixes the cursor transparent color in QFG3
........
r42104 | lordhoto | 2009-07-05 04:54:06 +1000 (Sun, 05 Jul 2009) | 1 line
Add GCC_PRINTF parameter.
........
r42105 | lordhoto | 2009-07-05 04:54:27 +1000 (Sun, 05 Jul 2009) | 1 line
Fix mismatching format arguments.
........
r42106 | lordhoto | 2009-07-05 04:54:43 +1000 (Sun, 05 Jul 2009) | 1 line
Kyra1 PC-98 never offered English as language settings, thus remove it. (The CD version *does* supply English files, but those will work as FM-Towns version, so this causes no drawback for the user and is faithful to the original)
........
r42107 | lordhoto | 2009-07-05 05:04:39 +1000 (Sun, 05 Jul 2009) | 1 line
After discussing with Max, disable -Wmissing-format-attribute again. Also added a comment explaining why it is disabled.
........
r42110 | athrxx | 2009-07-05 07:18:20 +1000 (Sun, 05 Jul 2009) | 1 line
KYRA: fix minor bug in Screen::drawShape()
........
r42112 | wjpalenstijn | 2009-07-05 09:52:24 +1000 (Sun, 05 Jul 2009) | 1 line
When morphing a TeeSongIterator, transfer death listeners to remaining child
........
r42113 | wjpalenstijn | 2009-07-05 11:16:53 +1000 (Sun, 05 Jul 2009) | 1 line
When creating a CleanupSongIterator, transfer death listeners to it
........
r42115 | dreammaster | 2009-07-05 17:21:17 +1000 (Sun, 05 Jul 2009) | 1 line
Bugfix for word-wrapping of text, which sometimes failed for strings with special characters
........
r42116 | jvprat | 2009-07-05 19:34:54 +1000 (Sun, 05 Jul 2009) | 3 lines
- Refactorized Groovie::MusicPlayer to make it extensible
- Added an empty MusicPlayerMac to let the Macintosh version of The 7th Guest start
........
r42117 | thebluegr | 2009-07-05 20:34:43 +1000 (Sun, 05 Jul 2009) | 1 line
Removed validity check for atoi, which prevented console commands from interacting with resources with id 0
........
r42118 | thebluegr | 2009-07-05 21:08:53 +1000 (Sun, 05 Jul 2009) | 1 line
SCI1 games with absolute parameters to lofs instructions are automatically detected now. Removed the GF_SCI1_LOFSABSOLUTE game flag
........
r42119 | drmccoy | 2009-07-05 21:26:23 +1000 (Sun, 05 Jul 2009) | 1 line
Adding an enum MouseButtons
........
r42120 | drmccoy | 2009-07-05 21:26:42 +1000 (Sun, 05 Jul 2009) | 1 line
Commenting prepareStr a bit and renaming it to cleanupStr
........
r42121 | drmccoy | 2009-07-05 21:27:11 +1000 (Sun, 05 Jul 2009) | 1 line
Added a Key and ShortKey enum
........
r42122 | drmccoy | 2009-07-05 21:27:26 +1000 (Sun, 05 Jul 2009) | 1 line
Added a skipBlock() method
........
r42123 | drmccoy | 2009-07-05 21:27:54 +1000 (Sun, 05 Jul 2009) | 1 line
Moving the "Collision" stuff to Hotspots in hotspots.cpp/.h
........
r42124 | drmccoy | 2009-07-05 21:28:09 +1000 (Sun, 05 Jul 2009) | 1 line
Wrapping the block end marker checks into Hotspots::Hotspot::isEnd()
........
r42125 | drmccoy | 2009-07-05 21:28:25 +1000 (Sun, 05 Jul 2009) | 1 line
Removing the now empty Game_Fascination class
........
r42126 | drmccoy | 2009-07-05 21:28:38 +1000 (Sun, 05 Jul 2009) | 1 line
Fixing indent
........
r42127 | drmccoy | 2009-07-05 21:28:57 +1000 (Sun, 05 Jul 2009) | 1 line
Merging Game_v1's and Game_v2's prepareStart()
........
r42128 | drmccoy | 2009-07-05 21:29:13 +1000 (Sun, 05 Jul 2009) | 1 line
Merging Game's and Game_v6's totSub()
........
r42129 | drmccoy | 2009-07-05 21:29:30 +1000 (Sun, 05 Jul 2009) | 1 line
Merging playTot()
........
r42130 | drmccoy | 2009-07-05 21:29:54 +1000 (Sun, 05 Jul 2009) | 1 line
Putting the Urban noCD check into Init_v6::initGame()
........
r42131 | drmccoy | 2009-07-05 21:30:14 +1000 (Sun, 05 Jul 2009) | 1 line
Removing the now unneeded Game_v* classes
........
r42132 | thebluegr | 2009-07-05 21:49:05 +1000 (Sun, 05 Jul 2009) | 2 lines
- Fixed feature auto-detection for Conquests of Camelot
- Auto-detected features are now printed in the console (to ease debugging)
........
r42134 | thebluegr | 2009-07-05 21:58:42 +1000 (Sun, 05 Jul 2009) | 1 line
Updated the MSVC project files of the gob engine
........
r42135 | drmccoy | 2009-07-05 22:52:14 +1000 (Sun, 05 Jul 2009) | 1 line
Adding a workaround for an invalid expression in Gob1 EGA
........
r42136 | thebluegr | 2009-07-05 23:07:11 +1000 (Sun, 05 Jul 2009) | 1 line
Merged the two SCI1 versions in one more file
........
r42137 | lordhoto | 2009-07-06 00:11:54 +1000 (Mon, 06 Jul 2009) | 1 line
Got rid of HACK, which was used to setup new cursor on theme change.
........
r42138 | lordhoto | 2009-07-06 00:12:04 +1000 (Mon, 06 Jul 2009) | 1 line
Removed pushing of EVENT_SCREEN_CHANGED on theme load. This event should only be pushed by the backend.
........
r42139 | marcus_c | 2009-07-06 00:57:03 +1000 (Mon, 06 Jul 2009) | 1 line
Refresh the screen if pollEvent() is called without updateScreen() being called for a long time.
........
r42140 | athrxx | 2009-07-06 00:58:22 +1000 (Mon, 06 Jul 2009) | 1 line
LOL: - reduce code duplication
........
r42141 | athrxx | 2009-07-06 02:29:17 +1000 (Mon, 06 Jul 2009) | 1 line
LOL: cleanup
........
r42142 | drmccoy | 2009-07-06 05:56:03 +1000 (Mon, 06 Jul 2009) | 1 line
Encapsulating hotspot state reading
........
r42143 | drmccoy | 2009-07-06 05:56:23 +1000 (Mon, 06 Jul 2009) | 1 line
Correcting an input related mistake
........
r42144 | drmccoy | 2009-07-06 05:56:40 +1000 (Mon, 06 Jul 2009) | 1 line
More state-related encapsulation
........
r42145 | drmccoy | 2009-07-06 05:56:54 +1000 (Mon, 06 Jul 2009) | 1 line
Split off Hotspots::evaluateNew()
........
r42146 | drmccoy | 2009-07-06 05:57:08 +1000 (Mon, 06 Jul 2009) | 1 line
Ooops, fixing monospaced text input again
........
r42147 | drmccoy | 2009-07-06 05:57:22 +1000 (Mon, 06 Jul 2009) | 1 line
Split off some drawing related functions
........
r42148 | drmccoy | 2009-07-06 05:57:37 +1000 (Mon, 06 Jul 2009) | 1 line
More input related split-offs
........
r42149 | drmccoy | 2009-07-06 05:57:55 +1000 (Mon, 06 Jul 2009) | 1 line
Renaming FontDesc::extraData to charWidths
........
r42150 | drmccoy | 2009-07-06 05:58:09 +1000 (Mon, 06 Jul 2009) | 1 line
Reordering some methods
........
r42153 | drmccoy | 2009-07-06 07:39:55 +1000 (Mon, 06 Jul 2009) | 1 line
Renaming the last occurences of "Collision" to "Hotspot"
........
r42154 | drmccoy | 2009-07-06 07:40:20 +1000 (Mon, 06 Jul 2009) | 1 line
Adding some hotspot debug messages
........
r42155 | drmccoy | 2009-07-06 07:40:51 +1000 (Mon, 06 Jul 2009) | 1 line
Added an enum for the hotspot states
........
r42161 | drmccoy | 2009-07-06 11:41:29 +1000 (Mon, 06 Jul 2009) | 1 line
Adding more comments
........
r42162 | dreammaster | 2009-07-06 12:46:59 +1000 (Mon, 06 Jul 2009) | 1 line
Bugfix for node enabling/disabling, which was previously allowing the player to walk through closed doors and into the walls
........
svn-id: r42165
Diffstat (limited to 'engines')
66 files changed, 3331 insertions, 5457 deletions
diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp index be4639af4d..11d5f582ed 100644 --- a/engines/cruise/ctp.cpp +++ b/engines/cruise/ctp.cpp @@ -209,9 +209,9 @@ int setNodeState(int nodeIdx, int nodeState) { int oldState = walkboxState[nodeIdx]; if (nodeState == -1) - return + return oldState; - walkboxState[nodeIdx] = nodeState; + walkboxState[nodeIdx] = nodeState; return oldState; } diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp index d5010b2bf8..8da3621bdc 100644 --- a/engines/cruise/font.cpp +++ b/engines/cruise/font.cpp @@ -242,7 +242,7 @@ int32 prepareWordRender(int32 inRightBorder_X, int16 wordSpacingWidth, if (character == '|' || !character) { finish = 1; } else { - if (charData) { + if (charData >= 0) { if (pixelCount + wordSpacingWidth + (int16)fontData[charData].charWidth >= inRightBorder_X) { finish = 1; diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index eab69c6846..d0443ef458 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -828,7 +828,7 @@ int16 Op_Preload(void) { } int16 Op_LoadCt(void) { - return initCt((char*)popPtr()); + return initCt((const char *)popPtr()); } int16 Op_EndAnim(void) { diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp index 0229bb7515..7f65721ce5 100644 --- a/engines/gob/demos/demoplayer.cpp +++ b/engines/gob/demos/demoplayer.cpp @@ -222,7 +222,7 @@ void DemoPlayer::playVideoDoubled() { int16 key; bool end = false; while (_vm->_util->checkKey(key)) - if (key == 0x011B) + if (key == kKeyEscape) end = true; if (end) break; diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index b3e5e7418c..c20bece7b4 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -360,9 +360,9 @@ int Draw::stringLength(const char *str, int16 fontIndex) { } else { - if (_fonts[fontIndex]->extraData) + if (_fonts[fontIndex]->charWidths) while (*str != 0) - len += *(_fonts[fontIndex]->extraData + (*str++ - _fonts[fontIndex]->startItem)); + len += *(_fonts[fontIndex]->charWidths + (*str++ - _fonts[fontIndex]->startItem)); else len = (strlen(str) * _fonts[fontIndex]->itemWidth); @@ -376,10 +376,10 @@ void Draw::drawString(const char *str, int16 x, int16 y, int16 color1, int16 col while (*str != '\0') { _vm->_video->drawLetter(*str, x, y, font, transp, color1, color2, dest); - if (!font->extraData) + if (!font->charWidths) x += font->itemWidth; else - x += *(font->extraData + (*str - font->startItem)); + x += *(font->charWidths + (*str - font->startItem)); str++; } } @@ -415,12 +415,12 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right, _fontIndex = fontIndex; _frontColor = color; _textToPrint = str; - if (_fonts[fontIndex]->extraData != 0) { - byte *data = _fonts[fontIndex]->extraData; + if (_fonts[fontIndex]->charWidths != 0) { + uint8 *widths = _fonts[fontIndex]->charWidths; int length = strlen(str); for (int i = 0; i < length; i++) - width += *(data + (str[i] - _fonts[_fontIndex]->startItem)); + width += *(widths + (str[i] - _fonts[_fontIndex]->startItem)); } else width = strlen(str) * _fonts[fontIndex]->itemWidth; diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 94ee32a031..91f2a45637 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -33,6 +33,7 @@ #include "gob/util.h" #include "gob/game.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/sound/sound.h" @@ -44,6 +45,12 @@ Draw_v1::Draw_v1(GobEngine *vm) : Draw(vm) { void Draw_v1::initScreen() { _backSurface = _vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, 0); + _frontSurface = _vm->_global->_primarySurfDesc; + + _cursorSprites = + _vm->_video->initSurfDesc(_vm->_global->_videoMode, 32, 16, 2); + _scummvmCursor = + _vm->_video->initSurfDesc(_vm->_global->_videoMode, 16, 16, SCUMMVM_CURSOR); } void Draw_v1::closeScreen() { @@ -58,7 +65,6 @@ void Draw_v1::blitCursor() { } void Draw_v1::animateCursor(int16 cursor) { - Game::Collision *ptr; int16 cursorIndex = cursor; int16 newX = 0, newY = 0; uint16 hotspotX = 0, hotspotY = 0; @@ -66,29 +72,10 @@ void Draw_v1::animateCursor(int16 cursor) { _showCursor = 2; if (cursorIndex == -1) { - cursorIndex = 0; - for (ptr = _vm->_game->_collisionAreas; ptr->left != 0xFFFF; ptr++) { - if (ptr->flags & 0xFFF0) - continue; - - if (ptr->left > _vm->_global->_inter_mouseX) - continue; - - if (ptr->right < _vm->_global->_inter_mouseX) - continue; - - if (ptr->top > _vm->_global->_inter_mouseY) - continue; + cursorIndex = + _vm->_game->_hotspots->findCursor(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); - if (ptr->bottom < _vm->_global->_inter_mouseY) - continue; - - if ((ptr->flags & 0xF) < 3) - cursorIndex = 1; - else - cursorIndex = 3; - break; - } if (_cursorAnimLow[cursorIndex] == -1) cursorIndex = 1; } @@ -317,7 +304,7 @@ void Draw_v1::printTotText(int16 id) { _renderFlags = savedFlags; if (_renderFlags & RENDERFLAG_COLLISIONS) - _vm->_game->checkCollisions(0, 0, 0, 0); + _vm->_game->_hotspots->check(0, 0); if ((_renderFlags & RENDERFLAG_CAPTUREPOP) && *_vm->_scenery->_pCaptureCounter != 0) { (*_vm->_scenery->_pCaptureCounter)--; diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 2843456f42..a0be23516c 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -34,6 +34,7 @@ #include "gob/game.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/video.h" @@ -82,7 +83,6 @@ void Draw_v2::blitCursor() { } void Draw_v2::animateCursor(int16 cursor) { - Game::Collision *ptr; int16 cursorIndex = cursor; int16 newX = 0, newY = 0; uint16 hotspotX = 0, hotspotY = 0; @@ -91,32 +91,10 @@ void Draw_v2::animateCursor(int16 cursor) { // .-- _draw_animateCursorSUB1 --- if (cursorIndex == -1) { - cursorIndex = 0; - for (ptr = _vm->_game->_collisionAreas; ptr->left != 0xFFFF; ptr++) { - if ((ptr->flags & 0xF00) || (ptr->id & 0x4000)) - continue; - - if (ptr->left > _vm->_global->_inter_mouseX) - continue; - - if (ptr->right < _vm->_global->_inter_mouseX) - continue; - - if (ptr->top > _vm->_global->_inter_mouseY) - continue; - - if (ptr->bottom < _vm->_global->_inter_mouseY) - continue; - - if ((ptr->flags & 0xF000) == 0) { - if ((ptr->flags & 0xF) >= 3) { - cursorIndex = 3; - break; - } else if (((ptr->flags & 0xF0) != 0x10) && (cursorIndex == 0)) - cursorIndex = 1; - } else if (cursorIndex == 0) - cursorIndex = (ptr->flags >> 12) & 0xF; - } + cursorIndex = + _vm->_game->_hotspots->findCursor(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); + if (_cursorAnimLow[cursorIndex] == -1) cursorIndex = 1; } @@ -407,8 +385,8 @@ void Draw_v2::printTotText(int16 id) { adjustCoords(2, &rectRight, &rectBottom); if (colId != -1) - _vm->_game->addNewCollision(colId + 0xD000, rectLeft, rectTop, - rectRight, rectBottom, 2, 0, 0, 0); + _vm->_game->_hotspots->add(colId + 0xD000, rectLeft, rectTop, + rectRight, rectBottom, (uint16) Hotspots::kTypeClick, 0, 0, 0, 0); if (_needAdjust != 2) printTextCentered(colCmd & 0x0F, rectLeft + 4, rectTop + 4, @@ -501,8 +479,8 @@ void Draw_v2::printTotText(int16 id) { rectBottom = destY + (int16)READ_LE_UINT16(ptr + 6); adjustCoords(2, &rectLeft, &rectTop); adjustCoords(2, &rectRight, &rectBottom); - _vm->_game->addNewCollision(colId + 0x0D000, rectLeft, rectTop, - rectRight, rectBottom, 2, 0, 0, 0); + _vm->_game->_hotspots->add(colId + 0x0D000, rectLeft, rectTop, + rectRight, rectBottom, (uint16) Hotspots::kTypeClick, 0, 0, 0, 0); ptr += 8; } break; @@ -604,7 +582,7 @@ void Draw_v2::printTotText(int16 id) { if (!(_renderFlags & RENDERFLAG_COLLISIONS)) return; - _vm->_game->checkCollisions(0, 0, 0, 0); + _vm->_game->_hotspots->check(0, 0); if (*_vm->_scenery->_pCaptureCounter != 0) { (*_vm->_scenery->_pCaptureCounter)--; @@ -784,7 +762,7 @@ void Draw_v2::spriteOperation(int16 operation) { if ((_fontIndex >= 4) || (_fontToSprite[_fontIndex].sprite == -1)) { - if (!_fonts[_fontIndex]->extraData) { + if (!_fonts[_fontIndex]->charWidths) { if (((int8) _textToPrint[0]) == -1) { _vm->validateLanguage(); @@ -807,7 +785,7 @@ void Draw_v2::spriteOperation(int16 operation) { _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, _destSpriteY, _fonts[_fontIndex], _transparency, _frontColor, _backColor, *_spritesArray[_destSurface]); - _destSpriteX += *(_fonts[_fontIndex]->extraData + + _destSpriteX += *(_fonts[_fontIndex]->charWidths + (_textToPrint[i] - _fonts[_fontIndex]->startItem)); } else diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index 5771ee9f76..d201019d08 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -29,14 +29,15 @@ #include "gob/game.h" #include "gob/helper.h" #include "gob/global.h" -#include "gob/util.h" #include "gob/dataio.h" #include "gob/variables.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/inter.h" #include "gob/draw.h" #include "gob/mult.h" +#include "gob/scenery.h" #include "gob/videoplayer.h" #include "gob/sound/sound.h" @@ -170,30 +171,14 @@ bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const Game::Game(GobEngine *vm) : _vm(vm) { - _collisionAreas = 0; - _shouldPushColls = 0; - _captureCount = 0; - _collStackSize = 0; - - for (int i = 0; i < 5; i++) { - _collStack[i] = 0; - _collStackElemSizes[i] = 0; - } - _curTotFile[0] = 0; _totToLoad[0] = 0; _startTimeKey = 0; - _mouseButtons = 0; - - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; + _mouseButtons = kMouseButtonsNone; - _activeCollResId = 0; - _activeCollIndex = 0; _handleMouse = 0; _forceHandleMouse = 0; _menuLevel = 0; @@ -201,10 +186,7 @@ Game::Game(GobEngine *vm) : _vm(vm) { _preventScroll = false; _scrollHandleMouse = false; - _noCd = false; - _tempStr[0] = 0; - _collStr[0] = 0; _numEnvironments = 0; _curEnvironment = 0; @@ -212,19 +194,181 @@ Game::Game(GobEngine *vm) : _vm(vm) { _environments = new Environments(_vm); _script = new Script(_vm); _resources = new Resources(_vm); + _hotspots = new Hotspots(_vm); } Game::~Game() { delete _environments; delete _script; delete _resources; + delete _hotspots; } -void Game::freeCollision(int16 id) { - for (int i = 0; i < 250; i++) { - if (_collisionAreas[i].id == id) - _collisionAreas[i].left = 0xFFFF; +void Game::prepareStart() { + _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; + _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; + _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; + + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + + _vm->_draw->initScreen(); + _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, + _vm->_video->_surfWidth - 1, _vm->_video->_surfHeight - 1, 1); + + _vm->_util->setMousePos(152, 92); + _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; + _vm->_draw->_cursorY = _vm->_global->_inter_mouseY = 92; + + _vm->_draw->_invalidatedCount = 0; + _vm->_draw->_noInvalidated = true; + _vm->_draw->_applyPal = false; + _vm->_draw->_paletteCleared = false; + _vm->_draw->_cursorWidth = 16; + _vm->_draw->_cursorHeight = 16; + _vm->_draw->_transparentCursor = 1; + + for (int i = 0; i < 40; i++) { + _vm->_draw->_cursorAnimLow[i] = -1; + _vm->_draw->_cursorAnimDelays[i] = 0; + _vm->_draw->_cursorAnimHigh[i] = 0; } + + _vm->_draw->_renderFlags = 0; + _vm->_draw->_backDeltaX = 0; + _vm->_draw->_backDeltaY = 0; + + _startTimeKey = _vm->_util->getTimeKey(); +} + +void Game::playTot(int16 skipPlay) { + char savedTotName[20]; + int16 *oldCaptureCounter; + int16 *oldBreakFrom; + int16 *oldNestLevel; + int16 _captureCounter; + int16 breakFrom; + int16 nestLevel; + + oldNestLevel = _vm->_inter->_nestLevel; + oldBreakFrom = _vm->_inter->_breakFromLevel; + oldCaptureCounter = _vm->_scenery->_pCaptureCounter; + + _script->push(); + + _vm->_inter->_nestLevel = &nestLevel; + _vm->_inter->_breakFromLevel = &breakFrom; + _vm->_scenery->_pCaptureCounter = &_captureCounter; + strcpy(savedTotName, _curTotFile); + + if (skipPlay <= 0) { + while (!_vm->shouldQuit()) { + if (_vm->_inter->_variables) + _vm->_draw->animateCursor(4); + + if (skipPlay != -1) { + _vm->_inter->initControlVars(1); + + for (int i = 0; i < 4; i++) { + _vm->_draw->_fontToSprite[i].sprite = -1; + _vm->_draw->_fontToSprite[i].base = -1; + _vm->_draw->_fontToSprite[i].width = -1; + _vm->_draw->_fontToSprite[i].height = -1; + } + + _vm->_mult->initAll(); + _vm->_mult->zeroMultData(); + + _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; + _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; + _vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites; + } else + _vm->_inter->initControlVars(0); + + _vm->_draw->_cursorHotspotXVar = -1; + _totToLoad[0] = 0; + + if ((_curTotFile[0] == 0) && (!_script->isLoaded())) + break; + + if (skipPlay == -2) { + _vm->_vidPlayer->primaryClose(); + skipPlay = 0; + } + + if (!_script->load(_curTotFile)) { + _vm->_draw->blitCursor(); + _vm->_inter->_terminate = 2; + break; + } + + _resources->load(_curTotFile); + + _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); + if (!_vm->_inter->_variables) + _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); + + _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); + + _vm->_inter->renewTimeInVars(); + + WRITE_VAR(13, _vm->_global->_useMouse); + WRITE_VAR(14, _vm->_global->_soundFlags); + WRITE_VAR(15, _vm->_global->_fakeVideoMode); + WRITE_VAR(16, _vm->_global->_language); + + _vm->_inter->callSub(2); + + if (_totToLoad[0] != 0) + _vm->_inter->_terminate = 0; + + _vm->_draw->blitInvalidated(); + + _script->unload(); + + _resources->unload(); + + for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) + capturePop(0); + + if (skipPlay != -1) { + _vm->_goblin->freeObjects(); + + _vm->_sound->blasterStop(0); + + for (int i = 0; i < Sound::kSoundsCount; i++) { + SoundDesc *sound = _vm->_sound->sampleGetBySlot(i); + + if (sound && + ((sound->getType() == SOUND_SND) || (sound->getType() == SOUND_WAV))) + _vm->_sound->sampleFree(sound); + } + } + + if (_totToLoad[0] == 0) + break; + + strcpy(_curTotFile, _totToLoad); + } + } else { + _vm->_inter->initControlVars(0); + _vm->_scenery->_pCaptureCounter = oldCaptureCounter; + _script->seek(_script->getFunctionOffset(skipPlay + 1)); + + _menuLevel++; + _vm->_inter->callSub(2); + _menuLevel--; + + if (_vm->_inter->_terminate != 0) + _vm->_inter->_terminate = 2; + } + + strcpy(_curTotFile, savedTotName); + + _vm->_inter->_nestLevel = oldNestLevel; + _vm->_inter->_breakFromLevel = oldBreakFrom; + _vm->_scenery->_pCaptureCounter = oldCaptureCounter; + + _script->pop(); } void Game::capturePush(int16 left, int16 top, int16 width, int16 height) { @@ -349,7 +493,7 @@ void Game::evaluateScroll(int16 x, int16 y) { } int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, - int16 *pButtons, char handleMouse) { + MouseButtons *pButtons, char handleMouse) { _vm->_util->processInput(true); @@ -373,28 +517,17 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, if (pMouseX && pMouseY && pButtons) { _vm->_util->getMouseState(pMouseX, pMouseY, pButtons); - if (*pButtons == 3) - *pButtons = 0; + if (*pButtons == kMouseButtonsBoth) + *pButtons = kMouseButtonsNone; } return _vm->_util->checkKey(); } -int16 Game::adjustKey(int16 key) { - if (key <= 0x60 || key >= 0x7B) - return key; - - return key - 0x20; -} - -void Game::start(void) { - _collisionAreas = new Collision[250]; - memset(_collisionAreas, 0, 250 * sizeof(Collision)); - +void Game::start() { prepareStart(); playTot(-2); - delete[] _collisionAreas; _vm->_draw->closeScreen(); for (int i = 0; i < SPRITES_COUNT; i++) @@ -406,6 +539,9 @@ void Game::start(void) { void Game::totSub(int8 flags, const char *newTotFile) { int8 curBackupPos; + if ((flags == 16) || (flags == 17)) + warning("Urban Stub: Game::totSub(), flags == %d", flags); + if (_numEnvironments >= Environments::kEnvironmentCount) return; @@ -417,13 +553,14 @@ void Game::totSub(int8 flags, const char *newTotFile) { _script = new Script(_vm); _resources = new Resources(_vm); + + if (flags & 0x80) + warning("Urban Stub: Game::totSub(), flags & 0x80"); + if (flags & 1) _vm->_inter->_variables = 0; strncpy0(_curTotFile, newTotFile, 9); -// if (_vm->getGameType() == kGameTypeGeisha) -// strcat(_curTotFile, ".0OT"); -// else strcat(_curTotFile, ".TOT"); if (_vm->_inter->_terminate != 0) { @@ -431,7 +568,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { return; } - pushCollisions(0); + _hotspots->push(0, true); if (flags & 2) playTot(-1); @@ -441,7 +578,8 @@ void Game::totSub(int8 flags, const char *newTotFile) { if (_vm->_inter->_terminate != 2) _vm->_inter->_terminate = 0; - popCollisions(); + _hotspots->clear(); + _hotspots->pop(); if ((flags & 1) && _vm->_inter->_variables) { _vm->_inter->delocateVars(); @@ -489,13 +627,13 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { return; } - pushCollisions(0); + _hotspots->push(0, true); playTot(skipPlay); if (_vm->_inter->_terminate != 2) _vm->_inter->_terminate = 0; - popCollisions(); + _hotspots->pop(); clearUnusedEnvironment(); @@ -504,87 +642,6 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { _environments->get(_curEnvironment); } -void Game::setCollisions(byte arg_0) { - uint16 left; - uint16 top; - uint16 width; - uint16 height; - Collision *collArea; - - for (collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) { - if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) - continue; - - _script->call(collArea->funcSub); - - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && - (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - if (_vm->_draw->_needAdjust != 2) { - _vm->_draw->adjustCoords(0, &left, &top); - if ((collArea->flags & 0x0F) < 3) - _vm->_draw->adjustCoords(2, &width, &height); - else { - height &= 0xFFFE; - _vm->_draw->adjustCoords(2, 0, &height); - } - } - collArea->left = left; - collArea->top = top; - collArea->right = left + width - 1; - collArea->bottom = top + height - 1; - - _script->pop(); - } -} - -void Game::collSub(uint16 offset) { - int16 collStackSize; - - _script->call(offset); - - _shouldPushColls = 1; - collStackSize = _collStackSize; - - _vm->_inter->funcBlock(0); - - if (collStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->pop(); - - setCollisions(); -} - -void Game::collAreaSub(int16 index, int8 enter) { - uint16 collId; - - collId = _collisionAreas[index].id & 0xF000; - - if ((collId == 0xA000) || (collId == 0x9000)) { - if (enter == 0) - WRITE_VAR(17, _collisionAreas[index].id & 0x0FFF); - else - WRITE_VAR(17, -(_collisionAreas[index].id & 0x0FFF)); - } - - if (enter != 0) { - if (_collisionAreas[index].funcEnter != 0) - collSub(_collisionAreas[index].funcEnter); - } else { - if (_collisionAreas[index].funcLeave != 0) - collSub(_collisionAreas[index].funcLeave); - } -} - void Game::clearUnusedEnvironment() { if (!_environments->has(_script)) { delete _script; @@ -594,7 +651,6 @@ void Game::clearUnusedEnvironment() { delete _resources; _resources = 0; } - } } // End of namespace Gob diff --git a/engines/gob/game.h b/engines/gob/game.h index ead4a56492..d3a758f014 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -26,11 +26,14 @@ #ifndef GOB_GAME_H #define GOB_GAME_H +#include "gob/util.h" + namespace Gob { class Script; class Resources; class Variables; +class Hotspots; class Environments { public: @@ -67,53 +70,30 @@ private: class Game { public: - -#include "common/pack-start.h" // START STRUCT PACKING - - struct Collision { - int16 id; - uint16 left; - uint16 top; - uint16 right; - uint16 bottom; - int16 flags; - int16 key; - uint16 funcEnter; - uint16 funcLeave; - uint16 funcSub; - Script *script; - } PACKED_STRUCT; - - struct InputDesc { - int16 fontIndex; - int16 backColor; - int16 frontColor; - byte *ptr; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - - Collision *_collisionAreas; - Collision *_collStack[5]; - - Script *_script; + Script *_script; Resources *_resources; + Hotspots *_hotspots; char _curTotFile[14]; char _totToLoad[20]; int32 _startTimeKey; - int16 _mouseButtons; + MouseButtons _mouseButtons; bool _noScroll; bool _preventScroll; bool _scrollHandleMouse; - bool _noCd; + byte _handleMouse; + char _forceHandleMouse; Game(GobEngine *vm); virtual ~Game(); + void prepareStart(); + + void playTot(int16 skipPlay); + void capturePush(int16 left, int16 top, int16 width, int16 height); void capturePop(char doDraw); @@ -122,60 +102,21 @@ public: void evaluateScroll(int16 x, int16 y); int16 checkKeys(int16 *pMousex = 0, int16 *pMouseY = 0, - int16 *pButtons = 0, char handleMouse = 0); - void start(void); - - virtual void totSub(int8 flags, const char *newTotFile); - virtual void switchTotSub(int16 index, int16 skipPlay); + MouseButtons *pButtons = 0, char handleMouse = 0); + void start(); - void freeCollision(int16 id); - - virtual void playTot(int16 skipPlay) = 0; - - virtual void clearCollisions(void) = 0; - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0) = 0; - virtual void collisionsBlock(void) = 0; - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true) = 0; - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true) = 0; - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex) = 0; - - virtual void prepareStart(void) = 0; - - virtual void pushCollisions(char all) = 0; - virtual void popCollisions(void) = 0; + void totSub(int8 flags, const char *newTotFile); + void switchTotSub(int16 index, int16 skipPlay); protected: - int16 _lastCollKey; - int16 _lastCollAreaIndex; - int16 _lastCollId; - - int16 _activeCollResId; - int16 _activeCollIndex; - byte _handleMouse; - char _forceHandleMouse; uint32 _menuLevel; char _tempStr[256]; - int16 _collStackSize; - int16 _collStackElemSizes[5]; - - char _shouldPushColls; - // Capture Common::Rect _captureStack[20]; int16 _captureCount; - char _collStr[256]; - // For totSub() int8 _curEnvironment; int8 _numEnvironments; @@ -183,129 +124,9 @@ protected: GobEngine *_vm; - virtual int16 adjustKey(int16 key); - - void collAreaSub(int16 index, int8 enter); - - virtual void setCollisions(byte arg_0 = 1); - virtual void collSub(uint16 offset); - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex) = 0; - void clearUnusedEnvironment(); }; -class Game_v1 : public Game { -public: - virtual void playTot(int16 skipPlay); - - virtual void clearCollisions(void); - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - virtual void collisionsBlock(void); - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - virtual void popCollisions(void); - - Game_v1(GobEngine *vm); - virtual ~Game_v1() {} - -protected: - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); -}; - -class Game_v2 : public Game_v1 { -public: - virtual void playTot(int16 skipPlay); - - virtual void clearCollisions(void); - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - virtual void collisionsBlock(void); - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - virtual void popCollisions(void); - - Game_v2(GobEngine *vm); - virtual ~Game_v2() {} - -protected: - struct CollLast { - int16 key; - int16 id; - int16 areaIndex; - }; - - CollLast _collLasts[5]; - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); -}; - -class Game_v6 : public Game_v2 { -public: - virtual void totSub(int8 flags, const char *newTotFile); - - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - virtual void collisionsBlock(void); - - Game_v6(GobEngine *vm); - virtual ~Game_v6() {} - -protected: - uint32 _someTimeDly; - - virtual void setCollisions(byte arg_0 = 1); - virtual void collSub(uint16 offset); - - virtual int16 adjustKey(int16 key); - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); - - void collSubReenter(); -}; - -class Game_Fascination : public Game_v2 { -public: - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - Game_Fascination(GobEngine *vm); - virtual ~Game_Fascination() {} -}; - } // End of namespace Gob #endif // GOB_GAME_H diff --git a/engines/gob/game_fascin.cpp b/engines/gob/game_fascin.cpp deleted file mode 100644 index 38ad03f0f8..0000000000 --- a/engines/gob/game_fascin.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/draw.h" -#include "gob/goblin.h" -#include "gob/inter.h" -#include "gob/mult.h" -#include "gob/scenery.h" -#include "gob/video.h" -#include "gob/videoplayer.h" -#include "gob/sound/sound.h" - -namespace Gob { - -Game_Fascination::Game_Fascination(GobEngine *vm) : Game_v2(vm) { -} - -int16 Game_Fascination::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - int16 newkey; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) { - if ((handleMouse==1) && (_vm->_draw->_renderFlags & RENDERFLAG_UNKNOWN)) - warning("checkCollisions : RENDERFLAG_UNKNOWN - Unknown behavior"); - _vm->_draw->animateCursor(-1); - } - - timeKey = _vm->_util->getTimeKey(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && (key != _lastCollKey)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else if ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY)) { - - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - newkey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (newkey != _lastCollKey) { - if ((_lastCollKey != 0) && (oldId & 0x8000)) - collAreaSub(oldIndex, 0); - - _lastCollKey = newkey; - - if ((newkey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - } - } - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == 0)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - _vm->_util->delay(10); - } -} - -} // End of namespace Gob diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp deleted file mode 100644 index 87dc78e3b1..0000000000 --- a/engines/gob/game_v1.cpp +++ /dev/null @@ -1,1426 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/helper.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/script.h" -#include "gob/resources.h" -#include "gob/draw.h" -#include "gob/inter.h" -#include "gob/mult.h" -#include "gob/video.h" -#include "gob/scenery.h" -#include "gob/sound/sound.h" - -namespace Gob { - -Game_v1::Game_v1(GobEngine *vm) : Game(vm) { -} - -void Game_v1::playTot(int16 skipPlay) { - int16 _captureCounter; - int16 breakFrom; - int16 nestLevel; - - int16 *oldNestLevel = _vm->_inter->_nestLevel; - int16 *oldBreakFrom = _vm->_inter->_breakFromLevel; - int16 *oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - - _script->push(); - - _vm->_inter->_nestLevel = &nestLevel; - _vm->_inter->_breakFromLevel = &breakFrom; - _vm->_scenery->_pCaptureCounter = &_captureCounter; - - char savedTotName[20]; - strcpy(savedTotName, _curTotFile); - - if (skipPlay <= 0) { - while (!_vm->shouldQuit()) { - for (int i = 0; i < 4; i++) { - _vm->_draw->_fontToSprite[i].sprite = -1; - _vm->_draw->_fontToSprite[i].base = -1; - _vm->_draw->_fontToSprite[i].width = -1; - _vm->_draw->_fontToSprite[i].height = -1; - } - - if ((_vm->getPlatform() == Common::kPlatformMacintosh)|| - (_vm->getPlatform() == Common::kPlatformWindows)) - _vm->_sound->adlibStop(); - else - _vm->_sound->cdStop(); - - _vm->_draw->animateCursor(4); - _vm->_inter->initControlVars(1); - _vm->_mult->initAll(); - _vm->_mult->zeroMultData(); - - for (int i = 0; i < SPRITES_COUNT; i++) - _vm->_draw->freeSprite(i); - - _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; - _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; - _vm->_draw->_spritesArray[23] = _vm->_draw->_cursorSprites; - - for (int i = 0; i < 20; i++) - freeSoundSlot(i); - - _totToLoad[0] = 0; - - if ((_curTotFile[0] == 0) && !_script->isLoaded()) - break; - - if (!_script->load(_curTotFile)) { - _vm->_draw->blitCursor(); - break; - } - - _resources->load(_curTotFile); - - _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); - if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - - _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); - - _vm->_inter->renewTimeInVars(); - - WRITE_VAR(13, _vm->_global->_useMouse); - WRITE_VAR(14, _vm->_global->_soundFlags); - WRITE_VAR(15, _vm->_global->_videoMode); - WRITE_VAR(16, _vm->_global->_language); - - _vm->_inter->callSub(2); - _script->setFinished(false); - - if (_totToLoad[0] != 0) - _vm->_inter->_terminate = 0; - - _vm->_draw->blitInvalidated(); - - _script->unload(); - - _resources->unload(); - - for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) - capturePop(0); - - _vm->_mult->checkFreeMult(); - _vm->_mult->freeAll(); - - for (int i = 0; i < SPRITES_COUNT; i++) - _vm->_draw->freeSprite(i); - _vm->_sound->blasterStop(0); - - for (int i = 0; i < 20; i++) - freeSoundSlot(i); - - if (_totToLoad[0] == 0) - break; - - strcpy(_curTotFile, _totToLoad); - } - } - - strcpy(_curTotFile, savedTotName); - - _vm->_inter->_nestLevel = oldNestLevel; - _vm->_inter->_breakFromLevel = oldBreakFrom; - _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - - _script->pop(); -} - -void Game_v1::clearCollisions() { - for (int i = 0; i < 250; i++) { - _collisionAreas[i].id = 0; - _collisionAreas[i].left = 0xFFFF; - } -} - -int16 Game_v1::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 250; i++) { - if (_collisionAreas[i].left != 0xFFFF) - continue; - - ptr = &_collisionAreas[i]; - ptr->id = id; - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = 0; - - return i; - } - error("Game_v1::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v1::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (srcPtr->id & 0x8000)) - size++; - } - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - _collStackElemSizes[_collStackSize] = size; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (srcPtr->id & 0x8000)) { - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -void Game_v1::popCollisions(void) { - Collision *destPtr; - Collision *srcPtr; - - debugC(1, kDebugCollisions, "popCollision"); - - _collStackSize--; - for (destPtr = _collisionAreas; destPtr->left != 0xFFFF; destPtr++) - ; - - srcPtr = _collStack[_collStackSize]; - memcpy(destPtr, srcPtr, - _collStackElemSizes[_collStackSize] * sizeof(Collision)); - - delete[] _collStack[_collStackSize]; -} - -int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - uint32 timeKey; - bool firstIteration = true; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - timeKey = _vm->_util->getTimeKey(); - - if ((_vm->_draw->_cursorIndex == -1) && (handleMouse != 0) && - (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - while (1) { - if (_vm->_inter->_terminate) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - } - - // NOTE: the original asm does the below checkKeys call - // _before_ this check. However, that can cause keypresses to get lost - // since there's a return statement in this check. - // Additionally, I added a 'deltaTime == -1' check there, since - // when this function is called with deltaTime == -1 in inputArea, - // and the return value is then discarded. - if (deltaTime < 0) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((deltaTime == -1) || (((curtime + deltaTime) > timeKey) && !firstIteration)) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse == 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - } - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - oldIndex = 0; - - _vm->_draw->animateCursor(2); - if (deltaTime <= 0) { - if (handleMouse == 1) - _vm->_util->waitMouseRelease(1); - } else if (deltaTime > 0) - _vm->_util->delay(deltaTime); - - _vm->_draw->animateCursor(-1); - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse == 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - _lastCollKey = 0; - return key; - } - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - _lastCollKey = - checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - } else { - - if ((handleMouse != 0) && - ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY))) { - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - - key = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (key != _lastCollKey) { - if ((_lastCollKey != 0) && ((oldId & 0x8000) != 0)) { - - _script->call(_collisionAreas[oldIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - _lastCollKey = key; - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - } - } - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - if (deltaTime < -10) - _vm->_util->delay(10); - - firstIteration = false; - } -} - -void Game_v1::prepareStart(void) { - clearCollisions(); - - _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; - _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; - _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; - - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - - _vm->_draw->initScreen(); - _vm->_video->fillRect(*_vm->_draw->_backSurface, 0, 0, 319, 199, 1); - _vm->_draw->_frontSurface = _vm->_global->_primarySurfDesc; - _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, 319, 199, 1); - - _vm->_util->setMousePos(152, 92); - _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; - _vm->_draw->_cursorY = _vm->_global->_inter_mouseY = 92; - - _vm->_draw->_invalidatedCount = 0; - _vm->_draw->_noInvalidated = true; - _vm->_draw->_applyPal = false; - _vm->_draw->_paletteCleared = false; - _vm->_draw->_cursorWidth = 16; - _vm->_draw->_cursorHeight = 16; - _vm->_draw->_transparentCursor = 1; - - for (int i = 0; i < 40; i++) { - _vm->_draw->_cursorAnimLow[i] = -1; - _vm->_draw->_cursorAnimDelays[i] = 0; - _vm->_draw->_cursorAnimHigh[i] = 0; - } - - _vm->_draw->_cursorAnimLow[1] = 0; - _vm->_draw->_cursorSprites = - _vm->_video->initSurfDesc(_vm->_global->_videoMode, 32, 16, 2); - _vm->_draw->_scummvmCursor = - _vm->_video->initSurfDesc(_vm->_global->_videoMode, 16, 16, SCUMMVM_CURSOR); - _vm->_draw->_renderFlags = 0; - _vm->_draw->_backDeltaX = 0; - _vm->_draw->_backDeltaY = 0; - - _startTimeKey = _vm->_util->getTimeKey(); -} - -void Game_v1::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[250]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 var_22; - int16 index; - int16 curEditIndex; - int16 deltaTime; - int16 descIndex2; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 savedCollStackSize; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - uint32 timeKey; - - if (_shouldPushColls) - pushCollisions(1); - - collResId = -1; - _script->skip(1); - count = _script->readByte(); - _handleMouse = _script->readByte(); - deltaTime = 1000 * _script->readByte(); - descIndex2 = _script->readByte(); - stackPos2 = _script->readByte(); - descIndex = _script->readByte(); - - if ((stackPos2 != 0) || (descIndex != 0)) - deltaTime /= 100; - - timeVal = deltaTime; - _script->skip(1); - - uint32 startPos = _script->pos(); - - WRITE_VAR(16, 0); - var_22 = 0; - index = 0; - curEditIndex = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - cmd &= 0x7F; - - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - - _vm->_util->clearKeyBuf(); - var_22 = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd < 5) || (cmd > 8)) { - descArray[index].ptr = 0; - } else { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->readInt16()); - } - - if (left == 0xFFFF) - break; - - if ((cmd & 1) == 0) { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - } else { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, 0); - } - index++; - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, _script->pos(), 0); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, - top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, - startPos, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, - startPos, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - } - } - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_22 != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, - descArray, &_activeCollResId, &_activeCollIndex); - - if (key == 0x1C0D) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - collResId = _collisionAreas[i].id; - _activeCollResId = collResId; - collResId &= 0x7FFF; - _activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &_activeCollResId, &_activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (_activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - - if (_activeCollResId == 0) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if ((adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else { - - if ((deltaTime != 0) && (VAR(16) == 0)) { - if (stackPos2 != 0) { - collStackPos = 0; - collPtr = _collisionAreas; - - for (i = 0, collPtr = _collisionAreas; - collPtr->left != 0xFFFF; i++, collPtr++) { - - if ((collPtr->id & 0x8000) == 0) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - _activeCollResId = collPtr->id; - _activeCollIndex = i; - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, _mouseButtons); - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - - if (collPtr->funcLeave != 0) { - timeKey = _vm->_util->getTimeKey(); - - uint32 savedPos = _script->pos(); - - _script->seek(collPtr->funcLeave); - - _shouldPushColls = 1; - savedCollStackSize = _collStackSize; - _vm->_inter->funcBlock(0); - - if (savedCollStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->seek(savedPos); - - deltaTime = timeVal - - (_vm->_util->getTimeKey() - timeKey); - - if (deltaTime < 2) - deltaTime = 2; - } - - if (VAR(16) == 0) - _activeCollResId = 0; - break; - } - } else { - if (descIndex != 0) { - counter = 0; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - counter++; - if (counter != descIndex) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } else { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else { - if (descIndex2 != 0) { - counter = 0; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - counter++; - if (counter != descIndex2) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } - } - - if (_activeCollResId == 0) - continue; - - if (_collisionAreas[_activeCollIndex].funcLeave != 0) - continue; - - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, _mouseButtons); - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - - if (_collisionAreas[_activeCollIndex].funcEnter != 0) { - uint32 savedPos = _script->pos(); - - _script->seek(_collisionAreas[_activeCollIndex].funcEnter); - - _shouldPushColls = 1; - - collStackPos = _collStackSize; - _vm->_inter->funcBlock(0); - if (collStackPos != _collStackSize) - popCollisions(); - _shouldPushColls = 0; - - _script->seek(savedPos); - } - - WRITE_VAR(16, 0); - _activeCollResId = 0; - } - while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if (((uint16) _activeCollResId & ~0x8000) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' ')) != 0) { - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - ptr = strchr(_tempStr, ' '); - } - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (!_vm->_inter->_terminate) { - _script->seek(_collisionAreas[_activeCollIndex].funcLeave); - - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, _mouseButtons); - - if (VAR(16) == 0) - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); -} - -int16 Game_v1::multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc * inpDesc, int16 *collResId, int16 *collIndex, bool mono) { - Collision *collArea; - int16 descInd; - int16 key; - int16 found = -1; - int16 i; - - descInd = 0; - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - strncpy0(_tempStr, GET_VARO_STR(collArea->key), 255); - - _vm->_draw->_destSpriteX = collArea->left; - _vm->_draw->_destSpriteY = collArea->top; - _vm->_draw->_spriteRight = collArea->right - collArea->left + 1; - _vm->_draw->_spriteBottom = collArea->bottom - collArea->top + 1; - - _vm->_draw->_destSurface = 21; - - _vm->_draw->_backColor = inpDesc[descInd].backColor; - _vm->_draw->_frontColor = inpDesc[descInd].frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - _vm->_draw->_destSpriteY += - ((collArea->bottom - collArea->top + 1) - 8) / 2; - - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - descInd++; - } - - for (i = 0; i < 40; i++) - WRITE_VAR_OFFSET(i * 4 + 0x44, 0); - - while (1) { - descInd = 0; - - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (descInd == *pCurPos) { - found = i; - break; - } - - descInd++; - } - - assert(found != -1); - - collArea = &_collisionAreas[found]; - - key = inputArea(collArea->left, collArea->top, - collArea->right - collArea->left + 1, - collArea->bottom - collArea->top + 1, - inpDesc[*pCurPos].backColor, inpDesc[*pCurPos].frontColor, - GET_VARO_STR(collArea->key), inpDesc[*pCurPos].fontIndex, - collArea->flags, &time, collResId, collIndex); - - if (_vm->_inter->_terminate) - return 0; - - switch (key) { - case 0: - if (*collResId == 0) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) < 3) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) > 10) - return 0; - - *pCurPos = 0; - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (i == *collIndex) - break; - - pCurPos[0]++; - } - break; - - case 0x3B00: - case 0x3C00: - case 0x3D00: - case 0x3E00: - case 0x3F00: - case 0x4000: - case 0x4100: - case 0x4200: - case 0x4300: - case 0x4400: - return key; - - case 0x1C0D: - - if (index == 1) - return key; - - if (*pCurPos == index - 1) { - *pCurPos = 0; - break; - } - - pCurPos[0]++; - break; - - case 0x5000: - if (index - 1 > *pCurPos) - pCurPos[0]++; - break; - - case 0x4800: - if (*pCurPos > 0) - pCurPos[0]--; - break; - } - } -} - -int16 Game_v1::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, int16 *collIndex, bool mono) { - int16 handleMouse; - uint32 editSize; - Video::FontDesc *pFont; - char curSym; - int16 key; - const char *str1; - const char *str2; - int16 i; - uint32 pos; - int16 flag; - int16 savedKey; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - pos = strlen(str); - pFont = _vm->_draw->_fonts[fontIndex]; - editSize = width / pFont->itemWidth; - - while (1) { - strncpy0(_tempStr, str, 254); - strcat(_tempStr, " "); - if (strlen(_tempStr) > editSize) - strncpy0(_tempStr, str, 255); - - _vm->_draw->_destSpriteX = xPos; - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteRight = editSize * pFont->itemWidth; - _vm->_draw->_spriteBottom = height; - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - _vm->_draw->_destSpriteY = yPos + (height - 8) / 2; - - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - if (pos == editSize) - pos--; - - curSym = _tempStr[pos]; - - flag = 1; - - while (1) { - _tempStr[0] = curSym; - _tempStr[1] = 0; - - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = frontColor; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - if (flag != 0) - key = checkCollisions(handleMouse, -1, collResId, collIndex); - flag = 0; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (*pTotTime > 0) { - *pTotTime -= 300; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - _vm->_draw->_destSpriteY = yPos + (height - 8) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - - if ((key != 0) || (*collResId != 0)) - break; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (*pTotTime > 0) { - *pTotTime -= 300; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - - if ((key != 0) || (*collResId != 0)) - break; - - if (_vm->_inter->_terminate) - return 0; - } - - if ((key == 0) || (*collResId != 0) || _vm->_inter->_terminate) - return 0; - - switch (key) { - case 0x4D00: // Right Arrow - if ((pos < strlen(str)) && (pos < (editSize - 1))) { - pos++; - continue; - } - return 0x5000; - - case 0x4B00: // Left Arrow - if (pos > 0) { - pos--; - continue; - } - return 0x4800; - - case 0xE08: // Backspace - if (pos > 0) { - _vm->_util->cutFromStr(str, pos - 1, 1); - pos--; - continue; - } - - case 0x5300: // Del - - if (pos >= strlen(str)) - continue; - - _vm->_util->cutFromStr(str, pos, 1); - continue; - - case 0x1C0D: // Enter - case 0x3B00: // F1 - case 0x3C00: // F2 - case 0x3D00: // F3 - case 0x3E00: // F4 - case 0x3F00: // F5 - case 0x4000: // F6 - case 0x4100: // F7 - case 0x4200: // F8 - case 0x4300: // F9 - case 0x4400: // F10 - case 0x4800: // Up arrow - case 0x5000: // Down arrow - return key; - - case 0x11B: // Escape - if (_vm->_global->_useMouse != 0) - continue; - - _forceHandleMouse = !_forceHandleMouse; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - if (_vm->_global->_pressedKeys[1] == 0) - continue; - - while (_vm->_global->_pressedKeys[1] != 0) - ; - continue; - - default: - - savedKey = key; - key &= 0xFF; - - if (((inpType == 9) || (inpType == 10)) && - (key >= ' ') && (key <= 0xFF)) { - str1 = "0123456789-.,+ "; - str2 = "0123456789-,,+ "; - - if (((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) - key = ((savedKey >> 8) - 1) % 10 + '0'; - - for (i = 0; str1[i] != 0; i++) { - if (key == str1[i]) { - key = str2[i]; - break; - } - } - - if (i == (int16) strlen(str1)) - key = 0; - } - - if ((key >= ' ') && (key <= 0xFF)) { - if (editSize == strlen(str)) - _vm->_util->cutFromStr(str, strlen(str) - 1, 1); - - if ((key >= 'a') && (key <= 'z')) - key += ('A' - 'a'); - - pos++; - _tempStr[0] = key; - _tempStr[1] = 0; - - _vm->_util->insertStr(_tempStr, str, pos - 1); - } - - } - } -} - -int16 Game_v1::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xFF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xFF00) != 0) - continue; - - if (((ptr->flags & 0xF) != 1) && ((ptr->flags & 0xF) != 2)) - continue; - - if ((((ptr->flags & 0xF0) >> 4) != (_mouseButtons - 1)) - && (((ptr->flags & 0xF0) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - return ptr->key; - } - } - - if ((_mouseButtons != 1) && (all == 0)) - return 0x11B; - - return 0; -} - -} // End of namespace Gob diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp deleted file mode 100644 index 08184e73d0..0000000000 --- a/engines/gob/game_v2.cpp +++ /dev/null @@ -1,1563 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/helper.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/script.h" -#include "gob/resources.h" -#include "gob/draw.h" -#include "gob/goblin.h" -#include "gob/inter.h" -#include "gob/mult.h" -#include "gob/scenery.h" -#include "gob/video.h" -#include "gob/videoplayer.h" -#include "gob/sound/sound.h" - -namespace Gob { - -Game_v2::Game_v2(GobEngine *vm) : Game_v1(vm) { -} - -void Game_v2::playTot(int16 skipPlay) { - char savedTotName[20]; - int16 *oldCaptureCounter; - int16 *oldBreakFrom; - int16 *oldNestLevel; - int16 _captureCounter; - int16 breakFrom; - int16 nestLevel; - - oldNestLevel = _vm->_inter->_nestLevel; - oldBreakFrom = _vm->_inter->_breakFromLevel; - oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - - _script->push(); - - _vm->_inter->_nestLevel = &nestLevel; - _vm->_inter->_breakFromLevel = &breakFrom; - _vm->_scenery->_pCaptureCounter = &_captureCounter; - strcpy(savedTotName, _curTotFile); - - if (skipPlay <= 0) { - while (!_vm->shouldQuit()) { - if (_vm->_inter->_variables) - _vm->_draw->animateCursor(4); - - if (skipPlay != -1) { - _vm->_inter->initControlVars(1); - - for (int i = 0; i < 4; i++) { - _vm->_draw->_fontToSprite[i].sprite = -1; - _vm->_draw->_fontToSprite[i].base = -1; - _vm->_draw->_fontToSprite[i].width = -1; - _vm->_draw->_fontToSprite[i].height = -1; - } - - _vm->_mult->initAll(); - _vm->_mult->zeroMultData(); - - _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; - _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; - _vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites; - } else - _vm->_inter->initControlVars(0); - - _vm->_draw->_cursorHotspotXVar = -1; - _totToLoad[0] = 0; - - if ((_curTotFile[0] == 0) && (!_script->isLoaded())) - break; - - if (skipPlay == -2) { - _vm->_vidPlayer->primaryClose(); - skipPlay = 0; - } - - if (!_script->load(_curTotFile)) { - _vm->_draw->blitCursor(); - _vm->_inter->_terminate = 2; - break; - } - - _resources->load(_curTotFile); - - _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); - if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - - _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); - - _vm->_inter->renewTimeInVars(); - - WRITE_VAR(13, _vm->_global->_useMouse); - WRITE_VAR(14, _vm->_global->_soundFlags); - WRITE_VAR(15, _vm->_global->_fakeVideoMode); - WRITE_VAR(16, _vm->_global->_language); - - _vm->_inter->callSub(2); - - if (_totToLoad[0] != 0) - _vm->_inter->_terminate = 0; - - _vm->_draw->blitInvalidated(); - - _script->unload(); - - _resources->unload(); - - for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) - capturePop(0); - - if (skipPlay != -1) { - _vm->_goblin->freeObjects(); - - _vm->_sound->blasterStop(0); - - for (int i = 0; i < Sound::kSoundsCount; i++) { - SoundDesc *sound = _vm->_sound->sampleGetBySlot(i); - - if (sound && - ((sound->getType() == SOUND_SND) || (sound->getType() == SOUND_WAV))) - _vm->_sound->sampleFree(sound); - } - } - - if (_totToLoad[0] == 0) - break; - - strcpy(_curTotFile, _totToLoad); - } - } else { - _vm->_inter->initControlVars(0); - _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _script->seek(_script->getFunctionOffset(skipPlay + 1)); - - _menuLevel++; - _vm->_inter->callSub(2); - _menuLevel--; - - if (_vm->_inter->_terminate != 0) - _vm->_inter->_terminate = 2; - } - - strcpy(_curTotFile, savedTotName); - - _vm->_inter->_nestLevel = oldNestLevel; - _vm->_inter->_breakFromLevel = oldBreakFrom; - _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - - _script->pop(); -} - -void Game_v2::clearCollisions() { - _lastCollKey = 0; - - for (int i = 0; i < 150; i++) - _collisionAreas[i].left = 0xFFFF; -} - -int16 Game_v2::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 150; i++) { - if ((_collisionAreas[i].left != 0xFFFF) && (_collisionAreas[i].id != id)) - continue; - - ptr = &_collisionAreas[i]; - ptr->id = id; - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = 0; - - return i; - } - error("Game_v2::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v2::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) - if (all || (((uint16) srcPtr->id) >= 20)) - size++; - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - - if (_vm->_inter->_terminate) - return; - - _collStackElemSizes[_collStackSize] = size; - - if (_shouldPushColls != 0) - _collStackElemSizes[_collStackSize] |= 0x8000; - - _shouldPushColls = 0; - _collLasts[_collStackSize].key = _lastCollKey; - _collLasts[_collStackSize].id = _lastCollId; - _collLasts[_collStackSize].areaIndex = _lastCollAreaIndex; - _lastCollKey = 0; - _lastCollId = 0; - _lastCollAreaIndex = 0; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (((uint16) srcPtr->id) >= 20)) { - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -void Game_v2::popCollisions(void) { - Collision *destPtr; - Collision *srcPtr; - - debugC(1, kDebugCollisions, "popCollision"); - - _collStackSize--; - - _shouldPushColls = _collStackElemSizes[_collStackSize] & 0x8000 ? 1 : 0; - _collStackElemSizes[_collStackSize] &= 0x7FFF; - - _lastCollKey = _collLasts[_collStackSize].key; - _lastCollId = _collLasts[_collStackSize].id; - _lastCollAreaIndex = _collLasts[_collStackSize].areaIndex; - - for (destPtr = _collisionAreas; destPtr->left != 0xFFFF; destPtr++) - ; - - srcPtr = _collStack[_collStackSize]; - memcpy(destPtr, srcPtr, - _collStackElemSizes[_collStackSize] * sizeof(Collision)); - - delete[] _collStack[_collStackSize]; -} - -int16 Game_v2::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - int16 newkey; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - timeKey = _vm->_util->getTimeKey(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && (key != _lastCollKey)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else if ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY)) { - - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - newkey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (newkey != _lastCollKey) { - if ((_lastCollKey != 0) && (oldId & 0x8000)) - collAreaSub(oldIndex, 0); - - _lastCollKey = newkey; - - if ((newkey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - } - } - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == 0)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - _vm->_util->delay(10); - } -} - -void Game_v2::prepareStart(void) { - clearCollisions(); - - _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; - _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; - _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; - - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - - _vm->_draw->initScreen(); - _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, - _vm->_video->_surfWidth - 1, _vm->_video->_surfHeight - 1, 1); - - _vm->_util->setMousePos(152, 92); - _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; - _vm->_draw->_cursorY = _vm->_global->_inter_mouseY = 92; - - _vm->_draw->_invalidatedCount = 0; - _vm->_draw->_noInvalidated = true; - _vm->_draw->_applyPal = false; - _vm->_draw->_paletteCleared = false; - _vm->_draw->_cursorWidth = 16; - _vm->_draw->_cursorHeight = 16; - _vm->_draw->_transparentCursor = 1; - - for (int i = 0; i < 40; i++) { - _vm->_draw->_cursorAnimLow[i] = -1; - _vm->_draw->_cursorAnimDelays[i] = 0; - _vm->_draw->_cursorAnimHigh[i] = 0; - } - - _vm->_draw->_renderFlags = 0; - _vm->_draw->_backDeltaX = 0; - _vm->_draw->_backDeltaY = 0; - - _startTimeKey = _vm->_util->getTimeKey(); -} - -void Game_v2::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[250]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 var_1C; - int16 index; - int16 curEditIndex; - int16 deltaTime; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - Collision *collArea; - int16 timeKey; - byte collAreaStart; - uint32 startPos; - uint32 offsetPos; - - if (_shouldPushColls) - pushCollisions(0); - - collAreaStart = 0; - while (_collisionAreas[collAreaStart].left != 0xFFFF) - collAreaStart++; - collArea = &_collisionAreas[collAreaStart]; - - _shouldPushColls = 0; - collResId = -1; - - _script->skip(1); - count = _script->readByte(); - - _handleMouse = _script->readByte(); - deltaTime = 1000 * _script->readByte(); - _script->skip(1); - stackPos2 = _script->readByte(); - descIndex = _script->readByte(); - - if ((stackPos2 != 0) || (descIndex != 0)) - deltaTime /= 100; - - timeVal = deltaTime; - _script->skip(1); - - startPos = _script->pos(); - WRITE_VAR(16, 0); - - var_1C = 0; - index = 0; - curEditIndex = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - offsetPos = _script->pos(); - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - offsetPos = 0; - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - - if (left != 0xFFFF) { - _vm->_draw->adjustCoords(0, &left, &top); - if (((cmd & 0x3F) < 20) && ((cmd & 0x3F) >= 3)) { - if (_vm->_draw->_needAdjust != 2) - height &= 0xFFFE; - _vm->_draw->adjustCoords(0, 0, &width); - } else - _vm->_draw->adjustCoords(0, &height, &width); - } - - cmd &= 0x7F; - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - _vm->_util->clearKeyBuf(); - var_1C = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->peekUint16() + 2); - } else - descArray[index].ptr = 0; - - if (left == 0xFFFF) { - if ((cmd & 1) == 0) { - _script->skip(_script->peekUint16(2) + 2); - } - break; - } - - if ((cmd & 1) == 0) { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, - top + height - 1, cmd, key, 0, - _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - } else - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, - top + height - 1, cmd, key, 0, 0); - - index++; - break; - - case 11: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xE000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 12: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xD000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _script->pos(), 0, offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - } - } - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_1C != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, descArray, - &_activeCollResId, &_activeCollIndex); - - WRITE_VAR(55, curEditIndex); - if (key == 0x1C0D) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - _activeCollResId = _collisionAreas[i].id; - collResId = _collisionAreas[i].id & 0x7FFF; - _activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &_activeCollResId, &_activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (_activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - - if (_activeCollResId == 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if ((adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else if (deltaTime != 0) { - if (stackPos2 != 0) { - collStackPos = 0; - - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) != 0x8000) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - _activeCollResId = collPtr->id; - _activeCollIndex = i + collAreaStart; - _vm->_inter->storeMouse(); - if (VAR(16) != 0) - break; - - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - - if (collPtr->funcLeave != 0) { - int16 collResIdBak = _activeCollResId; - int16 collIndexBak = _activeCollIndex; - - timeKey = _vm->_util->getTimeKey(); - collSub(collPtr->funcLeave); - - _activeCollResId = collResIdBak; - _activeCollIndex = collIndexBak; - - _vm->_inter->animPalette(); - - deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); - - if (deltaTime < 2) - deltaTime = 2; - if (deltaTime > timeVal) - deltaTime = timeVal; - } - - if (VAR(16) == 0) - _activeCollResId = 0; - break; - } - } else { - if (descIndex != 0) { - - counter = 0; - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) - if (++counter == descIndex) { - _activeCollResId = collPtr->id; - _activeCollIndex = i + collAreaStart; - break; - } - } - - } else { - - for (i = 0, collPtr = _collisionAreas; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) { - _activeCollResId = collPtr->id; - _activeCollIndex = i; - break; - } - } - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) - collSub(_collisionAreas[_lastCollAreaIndex].funcLeave); - _lastCollKey = 0; - } - - } - } - } - - if ((_activeCollResId == 0) || - (_collisionAreas[_activeCollIndex].funcLeave != 0)) - continue; - - _vm->_inter->storeMouse(); - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - - if (_collisionAreas[_activeCollIndex].funcEnter != 0) - collSub(_collisionAreas[_activeCollIndex].funcEnter); - - WRITE_VAR(16, 0); - _activeCollResId = 0; - } - while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if ((_activeCollResId & 0xFFF) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0xC000) == 0x8000) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' '))) - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - if (_vm->_language == 2) - while ((ptr = strchr(_tempStr, '.'))) - *ptr = ','; - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (_handleMouse == 1) - _vm->_draw->blitCursor(); - - if (!_vm->_inter->_terminate) { - _script->seek(_collisionAreas[_activeCollIndex].funcLeave); - - _vm->_inter->storeMouse(); - if (VAR(16) == 0) { - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - } - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); - - for (i = 0; i < 150; i++) { - if (((_collisionAreas[i].id & 0xF000) == 0xA000) || - ((_collisionAreas[i].id & 0xF000) == 0x9000)) - _collisionAreas[i].id |= 0x4000; - } -} - -int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc * inpDesc, int16 *collResId, int16 *collIndex, bool mono) { - Collision *collArea; - int16 descInd; - int16 key; - int16 found = -1; - int16 i; - byte *fontExtraBak = 0; - int16 needAdjust = 0; - - descInd = 0; - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - strncpy0(_tempStr, GET_VARO_STR(collArea->key), 255); - - _vm->_draw->_destSpriteX = collArea->left; - _vm->_draw->_destSpriteY = collArea->top; - _vm->_draw->_spriteRight = collArea->right - collArea->left + 1; - _vm->_draw->_spriteBottom = collArea->bottom - collArea->top + 1; - - _vm->_draw->_destSurface = 21; - - _vm->_draw->_backColor = inpDesc[descInd].backColor; - _vm->_draw->_frontColor = inpDesc[descInd].frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData = 0; - } - - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - _vm->_draw->_destSpriteY += ((collArea->bottom - collArea->top + 1) - - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData = fontExtraBak; - } - - descInd++; - } - - for (i = 0; i < 40; i++) - WRITE_VAR_OFFSET(i * 4 + 0x44, 0); - - while (1) { - descInd = 0; - - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (descInd == *pCurPos) { - found = i; - break; - } - - descInd++; - } - - assert(found != -1); - - collArea = &_collisionAreas[found]; - - key = inputArea(collArea->left, collArea->top, - collArea->right - collArea->left + 1, - collArea->bottom - collArea->top + 1, - inpDesc[*pCurPos].backColor, inpDesc[*pCurPos].frontColor, - GET_VARO_STR(collArea->key), inpDesc[*pCurPos].fontIndex, - collArea->flags, &time, collResId, collIndex, mono); - - if (_vm->_inter->_terminate) - return 0; - - switch (key) { - case 0: - if (*collResId == 0) - return 0; - - if (_mouseButtons != 0) { - for (collArea = _collisionAreas, i = 0; - collArea->left != 0xFFFF; collArea++, i++) { - if ((collArea->flags & 0xF00)) - continue; - - if ((collArea->id & 0x4000)) - continue; - - if ((collArea->left > _vm->_global->_inter_mouseX) || - (collArea->right < _vm->_global->_inter_mouseX) || - (collArea->top > _vm->_global->_inter_mouseY) || - (collArea->bottom < _vm->_global->_inter_mouseY)) - continue; - - if ((collArea->id & 0xF000)) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - *collIndex = i; - } - } - - if ((_collisionAreas[*collIndex].flags & 0x0F) < 3) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) > 10) - return 0; - - *pCurPos = 0; - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (i != *collIndex) - pCurPos[0]++; - } - break; - - case 0x3B00: - case 0x3C00: - case 0x3D00: - case 0x3E00: - case 0x3F00: - case 0x4000: - case 0x4100: - case 0x4200: - case 0x4300: - case 0x4400: - return key; - - case 0x1C0D: - - if (index == 1) - return key; - - if (*pCurPos == index - 1) { - *pCurPos = 0; - break; - } - - pCurPos[0]++; - break; - - case 0x5000: - if (index - 1 > *pCurPos) - pCurPos[0]++; - break; - - case 0x4800: - if (*pCurPos > 0) - pCurPos[0]--; - break; - } - } -} - -int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, int16 *collIndex, bool mono) { - byte handleMouse; - uint32 editSize; - Video::FontDesc *pFont; - char curSym; - int16 key; - const char *str1; - const char *str2; - int16 i; - uint32 pos; - int16 flag; - int16 savedKey; - byte *fontExtraBak = 0; - int16 needAdjust = 0; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - pos = strlen(str); - pFont = _vm->_draw->_fonts[fontIndex]; - editSize = (!mono && pFont->extraData) ? 0 : (width / pFont->itemWidth); - - while (1) { - strncpy0(_tempStr, str, 254); - strcat(_tempStr, " "); - if ((editSize != 0) && strlen(_tempStr) > editSize) - strncpy0(_tempStr, str, 255); - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _vm->_draw->_destSpriteX = xPos; - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteRight = mono ? (editSize * pFont->itemWidth) : width; - _vm->_draw->_spriteBottom = height; - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); - - _vm->_draw->_destSpriteY = yPos + (height - pFont->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if ((editSize != 0) && (pos == editSize)) - pos--; - - curSym = _tempStr[pos]; - - flag = 1; - - if (_vm->_inter->_variables) - WRITE_VAR(56, pos); - - while (1) { - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - - if (pFont->extraData) { - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteBottom = height; - _vm->_draw->_spriteRight = 1; - - _vm->_draw->_destSpriteX = xPos; - for (uint32 j = 0; j < pos; j++) - _vm->_draw->_destSpriteX += pFont->extraData[str[j] - pFont->startItem]; - - } else { - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - } - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = frontColor; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if (flag != 0) { - key = checkCollisions(handleMouse, -1, collResId, collIndex); - if (key == 0) - key = checkCollisions(handleMouse, -300, collResId, collIndex); - flag = 0; - } else - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - - if (pFont->extraData) { - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteBottom = height; - _vm->_draw->_spriteRight = 1; - - _vm->_draw->_destSpriteX = xPos; - for (uint32 j = 0; j < pos; j++) - _vm->_draw->_destSpriteX += pFont->extraData[str[j] - pFont->startItem]; - - } else { - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - } - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - _vm->_draw->_destSpriteY = yPos + (height - pFont->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if ((key != 0) || (*collResId != 0)) - break; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if ((key != 0) || (*collResId != 0) || - _vm->_inter->_terminate || _vm->shouldQuit()) - break; - - if (*pTotTime > 0) { - *pTotTime -= 600; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - } - - if ((key == 0) || (*collResId != 0) || - _vm->_inter->_terminate || _vm->shouldQuit()) - return 0; - - switch (key) { - case 0x4D00: // Right Arrow - if ((pos > strlen(str)) || (pos > (editSize - 1)) || (editSize == 0)) { - pos++; - continue; - } - return 0x5000; - - case 0x4B00: // Left Arrow - if (pos > 0) { - pos--; - continue; - } - return 0x4800; - - case 0xE08: // Backspace - if (pos > 0) { - _vm->_util->cutFromStr(str, pos - 1, 1); - pos--; - continue; - } else { - if (pos < strlen(str)) - _vm->_util->cutFromStr(str, pos, 1); - } - - case 0x5300: // Del - - if (pos >= strlen(str)) - continue; - - _vm->_util->cutFromStr(str, pos, 1); - continue; - - case 0x1C0D: // Enter - case 0x3B00: // F1 - case 0x3C00: // F2 - case 0x3D00: // F3 - case 0x3E00: // F4 - case 0x3F00: // F5 - case 0x4000: // F6 - case 0x4100: // F7 - case 0x4200: // F8 - case 0x4300: // F9 - case 0x4400: // F10 - case 0x4800: // Up arrow - case 0x5000: // Down arrow - return key; - - case 0x11B: // Escape - if (_vm->_global->_useMouse != 0) - continue; - - _forceHandleMouse = !_forceHandleMouse; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - while (_vm->_global->_pressedKeys[1] != 0) - ; - continue; - - default: - - savedKey = key; - key &= 0xFF; - - if (((inpType == 9) || (inpType == 10)) && - (key >= ' ') && (key <= 0xFF)) { - str1 = "0123456789-.,+ "; - str2 = "0123456789-,,+ "; - - if ((((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) && - ((_vm->_global->_pressedKeys[42] != 0) || - (_vm->_global->_pressedKeys[56] != 0))) - key = ((savedKey >> 8) - 1) % 10 + '0'; - - for (i = 0; str1[i] != 0; i++) { - if (key == str1[i]) { - key = str2[i]; - break; - } - } - - if (i == (int16) strlen(str1)) - key = 0; - } - - if ((key >= ' ') && (key <= 0xFF)) { - if (editSize == 0) { - int length = _vm->_draw->stringLength(str, fontIndex) + - pFont->extraData[' ' - pFont->startItem] + - pFont->extraData[key - pFont->startItem]; - - if (length > width) - continue; - - if (((int32) strlen(str)) >= (_vm->_global->_inter_animDataSize * 4 - 1)) - continue; - - } else { - if (strlen(str) > editSize) - continue; - else if (editSize == strlen(str)) - _vm->_util->cutFromStr(str, strlen(str) - 1, 1); - } - - pos++; - _tempStr[0] = key; - _tempStr[1] = 0; - - _vm->_util->insertStr(_tempStr, str, pos - 1); - } - - } - } -} - -int16 Game_v2::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (ptr->id & 0x4000) - continue; - - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((ptr->flags & 0xF) < 1) - continue; - - if ((((ptr->flags & 0xF0) >> 4) != (_mouseButtons - 1)) && - (((ptr->flags & 0xF0) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - if (((ptr->flags & 0xF) == 1) || ((ptr->flags & 0xF) == 2)) - return ptr->key; - return 0; - } - } - - if ((_mouseButtons != 1) && (all == 0)) - return 0x11B; - - return 0; -} - -} // End of namespace Gob diff --git a/engines/gob/game_v6.cpp b/engines/gob/game_v6.cpp deleted file mode 100644 index 8d40d41acc..0000000000 --- a/engines/gob/game_v6.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" -#include "common/file.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/helper.h" -#include "gob/global.h" -#include "gob/script.h" -#include "gob/resources.h" -#include "gob/inter.h" -#include "gob/draw.h" - -namespace Gob { - -Game_v6::Game_v6(GobEngine *vm) : Game_v2(vm) { - _someTimeDly = 0; -} - -// flagbits: 5 = freeInterVariables, 6 = skipPlay -void Game_v6::totSub(int8 flags, const char *newTotFile) { - int8 curBackupPos; - - if ((flags == 16) || (flags == 17)) - warning("Urban Stub: Game_v6::totSub(), flags == %d", flags); - - if (_numEnvironments >= Environments::kEnvironmentCount) - return; - - _environments->set(_numEnvironments); - - curBackupPos = _curEnvironment; - _numEnvironments++; - _curEnvironment = _numEnvironments; - - _script = new Script(_vm); - _resources = new Resources(_vm); - - if (flags & 0x80) - warning("Urban Stub: Game_v6::totSub(), flags & 0x80"); - - if (flags & 5) - _vm->_inter->_variables = 0; - - strncpy0(_curTotFile, newTotFile, 9); - strcat(_curTotFile, ".TOT"); - - if (_vm->_inter->_terminate != 0) { - clearUnusedEnvironment(); - return; - } - - pushCollisions(0); - - if (flags & 6) - playTot(-1); - else - playTot(0); - - if (_vm->_inter->_terminate < 2) - _vm->_inter->_terminate = 0; - - clearCollisions(); - popCollisions(); - - if ((flags & 5) && _vm->_inter->_variables) { - _vm->_inter->delocateVars(); - } - - clearUnusedEnvironment(); - - _numEnvironments--; - _curEnvironment = curBackupPos; - _environments->get(_numEnvironments); -} - -int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 150; i++) { - if ((_collisionAreas[i].left != 0xFFFF) && (_collisionAreas[i].id != id)) - continue; - - ptr = &_collisionAreas[i]; - - if ((ptr->id & 0xBFFF) != (id & 0xBFFF)) - ptr->id = id; - - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = _script; - - return i; - } - error("Game_v6::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v6::prepareStart(void) { - _noCd = false; - - if (Common::File::exists("cd1.itk") && Common::File::exists("cd2.itk") && - Common::File::exists("cd3.itk") && Common::File::exists("cd4.itk")) { - _noCd = true; - } - - Game_v2::prepareStart(); -} - -void Game_v6::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if ( (all == 1) || - ((all == 0) && (((uint16) srcPtr->id) >= 20)) || - ((all == 2) && (((srcPtr->id & 0xF000) == 0xD000) || - ((srcPtr->id & 0xF000) == 0x4000) || - ((srcPtr->id & 0xF000) == 0xE000)))) - size++; - } - - if (_collStackSize >= 5) - error("Game_v6::pushCollisions: _collStackSize == %d", _collStackSize); - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - - if (_vm->_inter->_terminate) - return; - - _collStackElemSizes[_collStackSize] = size; - - if (_shouldPushColls != 0) - _collStackElemSizes[_collStackSize] |= 0x8000; - - _shouldPushColls = 0; - _collLasts[_collStackSize].key = _lastCollKey; - _collLasts[_collStackSize].id = _lastCollId; - _collLasts[_collStackSize].areaIndex = _lastCollAreaIndex; - _lastCollKey = 0; - _lastCollId = 0; - _lastCollAreaIndex = 0; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if ( (all == 1) || - ((all == 0) && (((uint16) srcPtr->id) >= 20)) || - ((all == 2) && (((srcPtr->id & 0xF000) == 0xD000) || - ((srcPtr->id & 0xF000) == 0x4000) || - ((srcPtr->id & 0xF000) == 0xE000)))) { - - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -int16 Game_v6::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_lastCollKey != 0) && - ( (_collisionAreas[_lastCollAreaIndex].id != _lastCollId) || - (_collisionAreas[_lastCollAreaIndex].key != _lastCollKey))) { - - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - timeKey = _vm->_util->getTimeKey(); - _vm->_draw->blitInvalidated(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - collSubReenter(); - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - - if (handleMouse) - _vm->_draw->animateCursor(-1); - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if (key != _lastCollKey) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else - collSubReenter(); - } - - if ((deltaTime == -2) && (key == 0) && (_mouseButtons == 0)) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - - } else if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == 0)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - _vm->_util->delay(10); - } -} - -void Game_v6::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[300]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 deltaTime; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - Collision *collArea; - byte collAreaStart; - int16 activeCollResId = 0; - int16 activeCollIndex = 0; - uint32 startPos; - uint32 offsetPos; - - if (_shouldPushColls) - pushCollisions(0); - - collAreaStart = 0; - while (_collisionAreas[collAreaStart].left != 0xFFFF) - collAreaStart++; - collArea = &_collisionAreas[collAreaStart]; - - _shouldPushColls = 0; - collResId = -1; - - _script->skip(1); - count = _script->readByte(); - - _handleMouse = _script->peekByte(0); - deltaTime = 1000 * _script->peekByte(1); - stackPos2 = _script->peekByte(3); - descIndex = _script->peekByte(4); - byte var_42 = _script->peekByte(5); - - if ((stackPos2 != 0) || (descIndex != 0)) { - deltaTime /= 100; - if (_script->peekByte(1) == 100) - deltaTime = 2; - } - - timeVal = deltaTime; - _script->skip(6); - - startPos = _script->pos(); - WRITE_VAR(16, 0); - - byte var_41 = 0; - int16 var_46 = 0; - int16 var_1C = 0; - int16 index = 0; - int16 curEditIndex = 0; - int right = 0, funcLeave = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - offsetPos = _script->pos(); - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - offsetPos = 0; - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - - if (left != 0xFFFF) { - _vm->_draw->adjustCoords(0, &left, &top); - if (((cmd & 0x3F) < 20) && ((cmd & 0x3F) >= 3)) { - if (_vm->_draw->_needAdjust != 2) - height &= 0xFFFE; - _vm->_draw->adjustCoords(0, 0, &width); - } else - _vm->_draw->adjustCoords(0, &height, &width); - } - - cmd &= 0x7F; - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - _vm->_util->clearKeyBuf(); - var_1C = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->peekUint16() + 2); - } else - descArray[index].ptr = 0; - - if (left == 0xFFFF) { - if ((cmd & 1) == 0) { - _script->skip(_script->peekUint16(2) + 2); - } - break; - } - - right = left + width - 1; - if (!_vm->_draw->_fonts[descArray[index].fontIndex]->extraData) - right = left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1; - - funcLeave = 0; - if (!(cmd & 1)) - funcLeave = _script->pos(); - - addNewCollision(curCmd + 0x8000, left, top, right, - top + height - 1, cmd, key, 0, funcLeave, 0); - - if (!(cmd & 1)) { - _script->skip(_script->peekUint16(2) + 2); - } - - index++; - break; - - case 11: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xE000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 12: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xD000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _script->pos(), 0, offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - } - } - - if (var_42 != 0) - setCollisions(1); - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_1C != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, descArray, - &activeCollResId, &activeCollIndex, false); - - WRITE_VAR(55, curEditIndex); - if (key == 0x1C0D) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - activeCollResId = _collisionAreas[i].id; - collResId = _collisionAreas[i].id & 0x7FFF; - activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &activeCollResId, &activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - activeCollResId = _collisionAreas[i].id; - activeCollIndex = i; - break; - } - } - - if (activeCollResId == 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if (adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) { - activeCollResId = _collisionAreas[i].id; - activeCollIndex = i; - break; - } - } - } - } else if (deltaTime != 0) { - if (stackPos2 != 0) { - collStackPos = 0; - - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) != 0x8000) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - activeCollResId = collPtr->id; - activeCollIndex = i + collAreaStart; - _vm->_inter->storeMouse(); - if (VAR(16) != 0) - break; - - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - - if (collPtr->funcLeave != 0) { - uint32 timeKey = _vm->_util->getTimeKey(); - collSub(collPtr->funcLeave); - - if (timeVal != 2) { - deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); - - if ((deltaTime - var_46) < 3) { - var_46 -= (deltaTime - 3); - deltaTime = 3; - } else if (var_46 != 0) { - deltaTime -= var_46; - var_46 = 0; - } - - if (deltaTime > timeVal) - deltaTime = timeVal; - - } else - deltaTime = 2; - - } - - if (VAR(16) == 0) - activeCollResId = 0; - else - var_41 = 1; - - break; - } - } else { - if (descIndex != 0) { - - counter = 0; - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) - if (++counter == descIndex) { - activeCollResId = collPtr->id; - activeCollIndex = i + collAreaStart; - break; - } - } - - } else { - - for (i = 0, collPtr = _collisionAreas; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) { - activeCollResId = collPtr->id; - activeCollIndex = i; - break; - } - } - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) - collSub(_collisionAreas[_lastCollAreaIndex].funcLeave); - - _lastCollKey = 0; - } - - } - } - } - - if (var_41 != 0) - break; - - if ((activeCollResId == 0) || - (_collisionAreas[activeCollIndex].funcLeave != 0)) - continue; - - _vm->_inter->storeMouse(); - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - - if (_collisionAreas[activeCollIndex].funcEnter != 0) - collSub(_collisionAreas[activeCollIndex].funcEnter); - - WRITE_VAR(16, 0); - activeCollResId = 0; - } - while ((activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if ((activeCollResId & 0xFFF) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' '))) - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - if (_vm->_language == 2) - while ((ptr = strchr(_tempStr, '.'))) - *ptr = ','; - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (_handleMouse == 1) - _vm->_draw->blitCursor(); - - if (!_vm->_inter->_terminate && (var_41 == 0)) { - _script->seek(_collisionAreas[activeCollIndex].funcLeave); - - _vm->_inter->storeMouse(); - if (VAR(16) == 0) { - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - } - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); - - for (i = 0; i < 150; i++) { - if (((_collisionAreas[i].id & 0xF000) == 0xA000) || - ((_collisionAreas[i].id & 0xF000) == 0x9000)) - _collisionAreas[i].id |= 0x4000; - } -} - -void Game_v6::setCollisions(byte arg_0) { - for (Collision *collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) { - if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) - continue; - - if (arg_0 == 0) - if (collArea->flags & 0x80) - continue; - - Script *curScript = _script; - - _script = collArea->script; - if (!_script) - _script = curScript; - - _script->call(collArea->funcSub); - - int16 left = _script->readValExpr(); - int16 top = _script->readValExpr(); - int16 width = _script->readValExpr(); - int16 height = _script->readValExpr(); - uint16 flags = 0; - - if ((collArea->id & 0xF000) == 0xA000) - flags = _script->readValExpr(); - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && - (left != -1)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - if (_vm->_draw->_needAdjust != 2) { - _vm->_draw->adjustCoords(0, &left, &top); - if ((collArea->flags & 0x0F) < 3) - _vm->_draw->adjustCoords(2, &width, &height); - else { - height &= 0xFFFE; - _vm->_draw->adjustCoords(2, 0, &height); - } - } - - if (left < 0) { - width += left; - left = 0; - } - - if (top < 0) { - height += top; - top = 0; - } - - collArea->left = left; - collArea->top = top; - collArea->right = left + width - 1; - collArea->bottom = top + height - 1; - - if ((collArea->id & 0xF000) == 0xA000) - collArea->flags = flags; - - _script->pop(); - - _script = curScript; - } -} - -void Game_v6::collSub(uint16 offset) { - int16 collStackSize; - - uint32 savedPos = _script->pos(); - - _script->seek(offset); - - _shouldPushColls = 1; - collStackSize = _collStackSize; - - _vm->_inter->funcBlock(0); - - if (collStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->seek(savedPos); - - if ((_vm->_util->getTimeKey() - _someTimeDly) > 500) - setCollisions(0); -} - -static const byte adjustTable[] = { - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x81, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x40, 0x40, 0x40, 0x40, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -int16 Game_v6::adjustKey(int16 key) { - if (key == -1) - return -1; - - if (adjustTable[key & 0xFF] & 8) - return ((key & 0xFF) - 0x20); - - return key & 0xFF; -} - -int16 Game_v6::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (ptr->id & 0x4000) - continue; - - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((ptr->flags & 0xF) < 1) - continue; - - if ((((ptr->flags & 0x70) >> 4) != (_mouseButtons - 1)) && - (((ptr->flags & 0x70) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - if (((ptr->flags & 0xF) == 1) || ((ptr->flags & 0xF) == 2)) - return ptr->key; - return 0; - } - } - - if ((_mouseButtons != 1) && (all == 0)) - return 0x11B; - - return 0; -} - -void Game_v6::collSubReenter() { - int16 lastCollAreaIndex = _lastCollAreaIndex; - int16 lastCollId = _lastCollId; - int16 collKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (collKey == _lastCollKey) - return; - - if ((_lastCollKey != 0) && (lastCollId & 0x8000)) - collAreaSub(lastCollAreaIndex, 0); - - _lastCollKey = collKey; - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); -} - -} // End of namespace Gob diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index 4165938966..2969ed0870 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -123,6 +123,8 @@ Global::Global(GobEngine *vm) : _vm(vm) { _inter_mouseY = 0; _speedFactor = 1; + + _noCd = false; } Global::~Global() { diff --git a/engines/gob/global.h b/engines/gob/global.h index 982ce113cb..7849490107 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -141,6 +141,8 @@ public: // Can be 1, 2 or 3 for normal, double and triple speed, respectively uint8 _speedFactor; + bool _noCd; + Global(GobEngine *vm); ~Global(); diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index e534464cce..8605dfbd52 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -126,7 +126,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { Common::addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); Common::addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level"); Common::addDebugChannel(kDebugVideo, "Video", "IMD/VMD video debug level"); - Common::addDebugChannel(kDebugCollisions, "Collisions", "Collisions debug level"); + Common::addDebugChannel(kDebugHotspots, "Hotspots", "Hotspots debug level"); Common::addDebugChannel(kDebugDemo, "Demo", "Demo script debug level"); syst->getEventManager()->registerRandomSource(_rnd, "gob"); @@ -331,6 +331,7 @@ bool GobEngine::initGameParts() { _palAnim = new PalAnim(this); _vidPlayer = new VideoPlayer(this); _sound = new Sound(this); + _game = new Game(this); switch (_gameType) { case kGameTypeGeisha: @@ -341,7 +342,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v1(this); _mult = new Mult_v1(this); _draw = new Draw_v1(this); - _game = new Game_v1(this); _map = new Map_v1(this); _goblin = new Goblin_v1(this); _scenery = new Scenery_v1(this); @@ -353,7 +353,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_Fascination(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_Fascination(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); _scenery = new Scenery_v2(this); @@ -367,7 +366,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); _scenery = new Scenery_v2(this); @@ -380,7 +378,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_Bargon(this); _mult = new Mult_v2(this); _draw = new Draw_Bargon(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); _scenery = new Scenery_v2(this); @@ -394,7 +391,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v3(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v3(this); _scenery = new Scenery_v2(this); @@ -407,7 +403,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v3(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v3(this); _scenery = new Scenery_v2(this); @@ -420,7 +415,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v4(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); @@ -436,7 +430,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v5(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); @@ -445,12 +438,11 @@ bool GobEngine::initGameParts() { case kGameTypeAdibou4: case kGameTypeUrban: - _init = new Init_v3(this); + _init = new Init_v6(this); _video = new Video_v6(this); _inter = new Inter_v6(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v6(this); _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); diff --git a/engines/gob/gob.h b/engines/gob/gob.h index 5d1cb3ecf2..5047382316 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -133,7 +133,7 @@ enum { kDebugSaveLoad = 1 << 7, kDebugGraphics = 1 << 8, kDebugVideo = 1 << 9, - kDebugCollisions = 1 << 10, + kDebugHotspots = 1 << 10, kDebugDemo = 1 << 11 }; diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp new file mode 100644 index 0000000000..b717bd76df --- /dev/null +++ b/engines/gob/hotspots.cpp @@ -0,0 +1,1928 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "gob/hotspots.h" +#include "gob/global.h" +#include "gob/helper.h" +#include "gob/draw.h" +#include "gob/game.h" +#include "gob/script.h" +#include "gob/inter.h" + +namespace Gob { + +Hotspots::Hotspot::Hotspot() { + clear(); +} + +Hotspots::Hotspot::Hotspot(uint16 i, + uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k, + uint16 enter, uint16 leave, uint16 pos) { + + id = i; + left = l; + top = t; + right = r; + bottom = b; + flags = f; + key = k; + funcEnter = enter; + funcLeave = leave; + funcPos = pos; + script = 0; +} + +void Hotspots::Hotspot::clear() { + id = 0; + left = 0xFFFF; + top = 0; + right = 0; + bottom = 0; + flags = 0; + key = 0; + funcEnter = 0; + funcLeave = 0; + funcPos = 0; + script = 0; +} + +Hotspots::Type Hotspots::Hotspot::getType() const { + return (Type) (flags & 0xF); +} + +MouseButtons Hotspots::Hotspot::getButton() const { + uint8 buttonBits = ((flags & 0x70) >> 4); + + if (buttonBits == 0) + return kMouseButtonsLeft; + if (buttonBits == 1) + return kMouseButtonsRight; + if (buttonBits == 2) + return kMouseButtonsAny; + + return kMouseButtonsNone; +} + +uint8 Hotspots::Hotspot::getWindow() const { + return (flags & 0x0F00) >> 8; +} + +uint8 Hotspots::Hotspot::getCursor() const { + return (flags & 0xF000) >> 12; +} + +uint8 Hotspots::Hotspot::getState(uint16 id) { + return (id & 0xF000) >> 12; +} + +uint8 Hotspots::Hotspot::getState() const { + return getState(id); +} + +bool Hotspots::Hotspot::isEnd() const { + return (left == 0xFFFF); +} + +bool Hotspots::Hotspot::isInput() const { + if (getType() < kTypeInput1NoLeave) + return false; + + if (getType() > kTypeInputFloatLeave) + return false; + + return true; +} + +bool Hotspots::Hotspot::isActiveInput() const { + if (isEnd()) + return false; + + if (!isFilledEnabled()) + return false; + + if (!isInput()) + return false; + + return true; +} + +bool Hotspots::Hotspot::isFilled() const { + return getState() & kStateFilled; +} + +bool Hotspots::Hotspot::isFilledEnabled() const { + return (getState() & kStateFilledDisabled) == kStateFilled; +} + +bool Hotspots::Hotspot::isFilledNew() const { + return getState() == kStateFilled; +} + +bool Hotspots::Hotspot::isDisabled() const { + return getState() & kStateDisabled; +} + +bool Hotspots::Hotspot::isIn(uint16 x, uint16 y) const { + if (x < left) + return false; + if (x > right) + return false; + if (y < top) + return false; + if (y > bottom) + return false; + + return true; +} + +bool Hotspots::Hotspot::buttonMatch(MouseButtons button) const { + MouseButtons myButton = getButton(); + + if (myButton == kMouseButtonsAny) + // Any button allowed + return true; + + if (myButton == kMouseButtonsNone) + // No button allowed + return false; + + if (myButton == button) + // Exact match + return true; + + return false; +} + +void Hotspots::Hotspot::disable() { + id |= (kStateDisabled << 12); +} + +void Hotspots::Hotspot::enable() { + id &= ~(kStateDisabled << 12); +} + + +Hotspots::Hotspots(GobEngine *vm) : _vm(vm) { + _hotspots = new Hotspot[kHotspotCount]; + + _shouldPush = false; + + _currentKey = 0; + _currentIndex = 0; + _currentId = 0; +} + +Hotspots::~Hotspots() { + delete[] _hotspots; + + // Pop the whole stack and free each element's memory + while (!_stack.empty()) { + + StackEntry backup = _stack.pop(); + + delete[] backup.hotspots; + } +} + +void Hotspots::clear() { + _currentKey = 0; + + for (int i = 0; i < kHotspotCount; i++) + _hotspots[i].clear(); +} + +uint16 Hotspots::add(uint16 id, + uint16 left, uint16 top, uint16 right, uint16 bottom, + uint16 flags, uint16 key, + uint16 funcEnter, uint16 funcLeave, uint16 funcPos) { + + Hotspot hotspot(id, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + + return add(hotspot); +} + +uint16 Hotspots::add(const Hotspot &hotspot) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + // free space => add same id => update + if (! (spot.isEnd() || (spot.id == hotspot.id))) + continue; + + // When updating, keep disabled state intact + uint16 id = hotspot.id; + if ((spot.id & ~(kStateDisabled << 12)) == + (hotspot.id & ~(kStateDisabled << 12))) + id = spot.id; + + // Set + spot = hotspot; + spot.id = id; + + // Remember the current script + spot.script = _vm->_game->_script; + + debugC(1, kDebugHotspots, "Adding hotspot %03d: %3d+%3d+%3d+%3d - %04X, %04X, %04X - %5d, %5d, %5d", + i, spot.left, spot.top, spot.right, spot.bottom, + spot.id, spot.key, spot.flags, spot.funcEnter, spot.funcLeave, spot.funcPos); + + return i; + } + + error("Hotspots::add(): Hotspot array full"); + return 0xFFFF; +} + +void Hotspots::remove(uint16 id) { + for (int i = 0; i < kHotspotCount; i++) { + if (_hotspots[i].id == id) { + debugC(1, kDebugHotspots, "Removing hotspot %d: %X", i, id); + _hotspots[i].clear(); + } + } +} + +void Hotspots::removeState(uint8 state) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.getState() == state) { + debugC(1, kDebugHotspots, "Removing hotspot %d: %X (by state %X)", i, spot.id, state); + spot.clear(); + } + } +} + +void Hotspots::recalculate(bool force) { + debugC(5, kDebugHotspots, "Recalculating hotspots"); + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (!force && ((spot.flags & 0x80) != 0)) + // Not forcing a special hotspot + continue; + + if (spot.funcPos == 0) + // Simple coordinates don't need update + continue; + + // Setting the needed script + Script *curScript = _vm->_game->_script; + + _vm->_game->_script = spot.script; + if (!_vm->_game->_script) + _vm->_game->_script = curScript; + + // Calling the function that contains the positions + _vm->_game->_script->call(spot.funcPos); + + // Calculate positions + int16 left = _vm->_game->_script->readValExpr(); + int16 top = _vm->_game->_script->readValExpr(); + int16 width = _vm->_game->_script->readValExpr(); + int16 height = _vm->_game->_script->readValExpr(); + + // Re-read the flags too, if applicable + uint16 flags = 0; + if (spot.getState() == (kStateFilled | kStateType2)) + flags = _vm->_game->_script->readValExpr(); + + // Apply backDelta, if needed + if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != -1)) { + left += _vm->_draw->_backDeltaX; + top += _vm->_draw->_backDeltaY; + } + + // Clamping + if (left < 0) { + width += left; + left = 0; + } + if (top < 0) { + height += top; + top = 0; + } + + // Set the updated position + spot.left = left; + spot.top = top; + spot.right = left + width - 1; + spot.bottom = top + height - 1; + + if (spot.getState() == (kStateFilled | kStateType2)) + spot.flags = flags; + + // Return + _vm->_game->_script->pop(); + + _vm->_game->_script = curScript; + } +} + +void Hotspots::push(uint8 all, bool force) { + debugC(1, kDebugHotspots, "Pushing hotspots (%d, %d)", all, force); + + // Should we push at all? + if (!_shouldPush && !force) + return; + + // Count the hotspots + uint32 size = 0; + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + // Save all of them + if ( (all == 1) || + // Don't save the global ones + ((all == 0) && (spot.id >= 20)) || + // Only save disabled ones + ((all == 2) && ((spot.getState() == (kStateFilledDisabled | kStateType1)) || + (spot.getState() == (kStateDisabled)) || + (spot.getState() == (kStateFilledDisabled | kStateType2))))) { + size++; + } + + } + + StackEntry backup; + + backup.shouldPush = _shouldPush; + backup.size = size; + backup.key = _currentKey; + backup.id = _currentId; + backup.index = _currentIndex; + + backup.hotspots = new Hotspot[size]; + + // Copy the hotspots + Hotspot *destPtr = backup.hotspots; + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + // Save all of them + if ( (all == 1) || + // Don't save the global ones + ((all == 0) && (spot.id >= 20)) || + // Only save disabled ones + ((all == 2) && ((spot.getState() == (kStateFilledDisabled | kStateType1)) || + (spot.getState() == (kStateDisabled)) || + (spot.getState() == (kStateFilledDisabled | kStateType2))))) { + + memcpy(destPtr, &spot, sizeof(Hotspot)); + destPtr++; + + spot.clear(); + } + + } + + // Reset current state + _shouldPush = false; + _currentKey = 0; + _currentId = 0; + _currentIndex = 0; + + _stack.push(backup); +} + +void Hotspots::pop() { + debugC(1, kDebugHotspots, "Popping hotspots"); + + assert(!_stack.empty()); + + StackEntry backup = _stack.pop(); + + // Find the end of the filled hotspot space + int i; + Hotspot *destPtr = _hotspots; + for (i = 0; i < kHotspotCount; i++, destPtr++) + if (destPtr->isEnd()) + break; + + if (((uint32) (kHotspotCount - i)) < backup.size) + error("Hotspots::pop(): Not enough free space in the current Hotspot " + "array to pop %d elements (got %d)", backup.size, kHotspotCount - i); + + // Copy + memcpy(destPtr, backup.hotspots, backup.size * sizeof(Hotspot)); + + _shouldPush = backup.shouldPush; + _currentKey = backup.key; + _currentId = backup.id; + _currentIndex = backup.index; + + delete[] backup.hotspots; +} + +bool Hotspots::isValid(uint16 key, uint16 id, uint16 index) const { + if (index >= kHotspotCount) + return false; + + if (key == 0) + return false; + + if (!(Hotspot::getState(id) & kStateFilled)) + return false; + + return true; +} + +void Hotspots::call(uint16 offset) { + debugC(4, kDebugHotspots, "Calling hotspot function %d", offset); + + _vm->_game->_script->call(offset); + + _shouldPush = true; + + int16 stackSize = _stack.size(); + + _vm->_inter->funcBlock(0); + + while (stackSize != _stack.size()) + pop(); + + _shouldPush = false; + + _vm->_game->_script->pop(); + + recalculate(false); +} + +void Hotspots::enter(uint16 index) { + debugC(2, kDebugHotspots, "Entering hotspot %d", index); + + if (index >= kHotspotCount) { + warning("Hotspots::enter(): Index %d out of range", index); + return; + } + + Hotspot &spot = _hotspots[index]; + + // If requested, write the ID into a variable + if ((spot.getState() == (kStateFilled | kStateType1)) || + (spot.getState() == (kStateFilled | kStateType2))) + WRITE_VAR(17, -(spot.id & 0x0FFF)); + + if (spot.funcEnter != 0) + call(spot.funcEnter); +} + +void Hotspots::leave(uint16 index) { + debugC(2, kDebugHotspots, "Leaving hotspot %d", index); + + if (index >= kHotspotCount) { + warning("Hotspots::leave(): Index %d out of range", index); + return; + } + + Hotspot &spot = _hotspots[index]; + + // If requested, write the ID into a variable + if ((spot.getState() == (kStateFilled | kStateType1)) || + (spot.getState() == (kStateFilled | kStateType2))) + WRITE_VAR(17, spot.id & 0x0FFF); + + if (spot.funcLeave != 0) + call(spot.funcLeave); +} + +uint16 Hotspots::checkMouse(Type type, uint16 &id, uint16 &index) const { + id = 0; + index = 0; + + if (type == kTypeMove) { + // Check where the mouse was moved to + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.isDisabled()) + // Only consider enabled hotspots + continue; + + if (spot.getType() > kTypeMove) + // Only consider click and move hotspots + continue; + + if (spot.getWindow() != 0) + // Only check the main window + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + // If we're not in it, ignore it + continue; + + id = spot.id; + index = i; + + return spot.key; + } + + return 0; + + } else if (type == kTypeClick) { + // Check if something was clicked + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.isDisabled()) + // Only consider enabled hotspots + continue; + + if (spot.getWindow() != 0) + // Only check the main window + continue; + + if (spot.getType() < kTypeMove) + // Only consider hotspots that can be clicked + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + // If we're not in it, ignore it + continue; + + if (!spot.buttonMatch(_vm->_game->_mouseButtons)) + // Don't follow hotspots with button requirements we don't meet + continue; + + id = spot.id; + index = i; + + if ((spot.getType() == kTypeMove) || (spot.getType() == kTypeClick)) + // It's a move or click => return the key + return spot.key; + + // Otherwise, the key has a different meaning, so ignore it + return 0; + } + + if (_vm->_game->_mouseButtons != kMouseButtonsLeft) + // Let the right mouse button act as an escape key + return kKeyEscape; + + return 0; + + } + + return 0; +} + +bool Hotspots::checkHotspotChanged() { + uint16 key, id, index; + + // Get the current hotspot + key = checkMouse(kTypeMove, id, index); + + if (key == _currentKey) + // Nothing changed => nothing to do + return false; + + // Leave the old area + if (isValid(_currentKey, _currentId,_currentIndex)) + leave(_currentIndex); + + _currentKey = key; + _currentId = id; + _currentIndex = index; + + // Enter the new one + if (isValid(key, id, index)) + enter(index); + + return true; +} + +uint16 Hotspots::check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index) { + _vm->_game->_scrollHandleMouse = handleMouse != 0; + + if (delay >= -1) { + _currentKey = 0; + _currentId = 0; + _currentIndex = 0; + } + + id = 0; + index = 0; + + if (handleMouse) { + if ((_vm->_draw->_cursorIndex == -1) && (_currentKey == 0)) { + // Last know state: No hotspot hit. Look if that changed + + _currentKey = checkMouse(kTypeMove, _currentId, _currentIndex); + + if (isValid(_currentKey, _currentId, _currentIndex)) + enter(_currentIndex); + } + + _vm->_draw->animateCursor(-1); + } + + uint32 startTime = _vm->_util->getTimeKey(); + + // Update display + _vm->_draw->blitInvalidated(); + _vm->_video->retrace(); + + uint16 key = 0; + while (key == 0) { + + if (_vm->_inter->_terminate || _vm->shouldQuit()) { + if (handleMouse) + _vm->_draw->blitCursor(); + return 0; + } + + // Anything changed? + checkHotspotChanged(); + + // Update display + if (!_vm->_draw->_noInvalidated) { + if (handleMouse) + _vm->_draw->animateCursor(-1); + else + _vm->_draw->blitInvalidated(); + _vm->_video->waitRetrace(); + } + + // Update keyboard and mouse state + key = _vm->_game->checkKeys(&_vm->_global->_inter_mouseX, + &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, handleMouse); + + if (!handleMouse && (_vm->_game->_mouseButtons != kMouseButtonsNone)) { + // We don't want any mouse input but got one => Wait till it went away + + _vm->_util->waitMouseRelease(0); + key = 3; + } + + if (key != 0) { + // Got a key press + + if (handleMouse & 1) + _vm->_draw->blitCursor(); + + id = 0; + index = 0; + + // Leave the current hotspot + if (isValid(_currentKey, _currentId, _currentIndex)) + leave(_currentIndex); + + _currentKey = 0; + break; + } + + if (handleMouse) { + + if (_vm->_game->_mouseButtons != kMouseButtonsNone) { + // Mouse button pressed + + if (delay > 0) { + // If a delay was requested, wait the specified time + + _vm->_draw->animateCursor(2); + _vm->_util->delay(delay); + } else if (handleMouse & 1) + _vm->_util->waitMouseRelease(1); + + _vm->_draw->animateCursor(-1); + + // Which region was clicked? + key = checkMouse(kTypeClick, id, index); + + if ((key != 0) || (id != 0)) { + // Got a valid region + + if ( (handleMouse & 1) && + ((delay <= 0) || (_vm->_game->_mouseButtons == kMouseButtonsNone))) + _vm->_draw->blitCursor(); + + // If the hotspot changed, leave the old one + if (key != _currentKey) + leave(_currentIndex); + + _currentKey = 0; + break; + } + + if (handleMouse & 4) + // Nothing further than one simple check was requested => return + return 0; + + // Leave the current area + if (_currentKey != 0) + leave(_currentIndex); + + // No click, but do we have a move event? If so, enter that hotspot + _currentKey = checkMouse(kTypeMove, _currentId, _currentIndex); + if (isValid(_currentKey, _currentId, _currentIndex)) + enter(_currentIndex); + + } else + // No mouse button pressed, check whether the position changed at least + checkHotspotChanged(); + } + + if ((delay == -2) && (key == 0) && + (_vm->_game->_mouseButtons == kMouseButtonsNone)) { + // Nothing found and no further handling requested. Return. + + id = 0; + index = 0; + break; + } + + if (handleMouse) + _vm->_draw->animateCursor(-1); + + if ((delay < 0) && (key == 0) && + (_vm->_game->_mouseButtons == kMouseButtonsNone)) { + + // Look if we've maybe reached the timeout + + uint32 curTime = _vm->_util->getTimeKey(); + if ((curTime + delay) > startTime) { + // If so, return + + id = 0; + index = 0; + break; + } + + } + + // Sleep for a short amount of time + _vm->_util->delay(10); + + } + + return key; +} + +uint16 Hotspots::check(uint8 handleMouse, int16 delay) { + uint16 id, index; + + // Check and ignore the id and index + return Hotspots::check(handleMouse, delay, id, index); +} + +uint16 Hotspots::updateInput(uint16 xPos, uint16 yPos, uint16 width, uint16 height, + uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex, + Type type, int16 &duration, uint16 &id, uint16 &index) { + + if ((fontIndex >= 8) || !_vm->_draw->_fonts[fontIndex]) { + warning("Hotspots::updateInput(): Invalid font specified: %d", fontIndex); + return 0; + } + + // Check if we need to consider mouse events + bool handleMouse = false; + if ( (_vm->_game->_handleMouse != 0) && + ((_vm->_global->_useMouse != 0) || (_vm->_game->_forceHandleMouse != 0))) + handleMouse = true; + + const Video::FontDesc &font = *_vm->_draw->_fonts[fontIndex]; + + // The font doesn't specify individual character widths => monospaced + bool monoSpaced = (font.charWidths == 0); + + // Current position in the string, preset to the end + uint32 pos = strlen(str); + /* Size of input field in characters. + * If the font is not monospaced, we can't know that */ + uint32 editSize = monoSpaced ? (width / font.itemWidth) : 0; + + uint16 key = 0; + char tempStr[256]; + + while (1) { + // If we the edit field has enough space, add a space for the new character + strncpy0(tempStr, str, 254); + strcat(tempStr, " "); + if ((editSize != 0) && strlen(tempStr) > editSize) + strncpy0(tempStr, str, 255); + + // Clear input area + fillRect(xPos, yPos, + monoSpaced ? (editSize * font.itemWidth) : width, height, + backColor); + + // Print the current string, vertically centered + printText(xPos, yPos + (height - font.itemHeight) / 2, + tempStr, fontIndex, frontColor); + + // If we've reached the end of the input field, set the cursor to the last character + if ((editSize != 0) && (pos == editSize)) + pos--; + + // The character under the cursor + char curSym = tempStr[pos]; + + if (_vm->_inter->_variables) + WRITE_VAR(56, pos); + + bool first = true; + while (1) { + tempStr[0] = curSym; + tempStr[1] = 0; + + // Draw cursor + uint16 cursorX, cursorY, cursorWidth, cursorHeight; + getTextCursorPos(font, str, pos, xPos, yPos, width, height, + cursorX, cursorY, cursorWidth, cursorHeight); + fillRect(cursorX, cursorY, cursorWidth, cursorHeight, frontColor); + + if (first) { + // The first time, purge old information too + key = check(handleMouse, -1, id, index); + + if (key == 0) + // We didn't catch any input, let's try again with a real timeout + key = check(handleMouse, -300, id, index); + + first = false; + } else + // Try to catch a character + key = check(handleMouse, -300, id, index); + + tempStr[0] = curSym; + tempStr[1] = 0; + + // Clear cursor + getTextCursorPos(font, str, pos, xPos, yPos, width, height, + cursorX, cursorY, cursorWidth, cursorHeight); + fillRect(cursorX, cursorY, cursorWidth, cursorHeight, backColor); + + // Print the current string, vertically centered + printText(cursorX, yPos + (height - font.itemHeight) / 2, + tempStr, fontIndex, frontColor); + + if ((key != 0) || (id != 0)) + // We did get a key, stop looking + break; + + // Try again + key = check(handleMouse, -300, id, index); + + if ((key != 0) || (id != 0) || + _vm->_inter->_terminate || _vm->shouldQuit()) + // We did get a key, stop looking + break; + + if (duration > 0) { + // Look if we reached the time limit + duration -= 600; + if (duration <= 1) { + // If so, abort + key = 0; + id = 0; + break; + } + } + } + + if ((key == 0) || (id != 0) || + _vm->_inter->_terminate || _vm->shouldQuit()) + // Got no key, or a region ID instead, return + return 0; + + switch (key) { + case kKeyRight: + // If possible, move the cursor right + if ((pos > strlen(str)) || (pos > (editSize - 1)) || (editSize == 0)) { + pos++; + continue; + } + // Continue downwards instead + return kKeyDown; + + case kKeyLeft: + // If possible, move the cursor left + if (pos > 0) { + pos--; + continue; + } + // Continue upwards instead + return kKeyUp; + + case kKeyBackspace: + if (pos > 0) { + // Delete the character to the left + _vm->_util->cutFromStr(str, pos - 1, 1); + pos--; + continue; + } else { + if (pos < strlen(str)) + // Delete the character to the right + _vm->_util->cutFromStr(str, pos, 1); + } + + case kKeyDelete: + if (pos >= strlen(str)) + continue; + + // Delete the character to the right + _vm->_util->cutFromStr(str, pos, 1); + continue; + + case kKeyReturn: + case kKeyF1: + case kKeyF2: + case kKeyF3: + case kKeyF4: + case kKeyF5: + case kKeyF6: + case kKeyF7: + case kKeyF8: + case kKeyF9: + case kKeyF10: + case kKeyUp: + case kKeyDown: + return key; + + case kKeyEscape: + // If we got an escape event, wait until the mouse buttons have been released + if (_vm->_global->_useMouse != 0) + continue; + + _vm->_game->_forceHandleMouse = !_vm->_game->_forceHandleMouse; + + handleMouse = false; + if ( (_vm->_game->_handleMouse != 0) && + ((_vm->_global->_useMouse != 0) || (_vm->_game->_forceHandleMouse != 0))) + handleMouse = true; + + while (_vm->_global->_pressedKeys[1] != 0); + continue; + + default: + // Got a "normal" key + + uint16 savedKey = key; + + key &= 0xFF; + + if (((type == kTypeInputFloatNoLeave) || (type == kTypeInputFloatLeave)) && + (key >= ' ') && (key <= 0xFF)) { + + // Only allow character found in numerical floating values + + const char *str1 = "0123456789-.,+ "; + const char *str2 = "0123456789-,,+ "; + + if ((((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) && + ((_vm->_global->_pressedKeys[42] != 0) || + (_vm->_global->_pressedKeys[56] != 0))) + key = ((savedKey >> 8) - 1) % 10 + '0'; + + int i; + for (i = 0; str1[i] != 0; i++) { + if (key == str1[i]) { + key = str2[i]; + break; + } + } + + if (i == (int16) strlen(str1)) + key = 0; + } + + if ((key >= ' ') && (key <= 0xFF)) { + if (editSize == 0) { + // Length of the string + current character + next one + int length = _vm->_draw->stringLength(str, fontIndex) + + font.charWidths[' ' - font.startItem] + + font.charWidths[key - font.startItem]; + + if (length > width) + // We're above the limit, ignore the key + continue; + + if (((int32) strlen(str)) >= (_vm->_global->_inter_animDataSize * 4 - 1)) + // Above the limit of character allowed in a string, ignore the key + continue; + + } else { + if (strlen(str) > editSize) + // We're over the upper character limit for this field + continue; + else if (editSize == strlen(str)) + // We've reached the upper limit, overwrite the last character + _vm->_util->cutFromStr(str, strlen(str) - 1, 1); + } + + // Advance cursor + pos++; + tempStr[0] = key; + tempStr[1] = 0; + + // Add character + _vm->_util->insertStr(tempStr, str, pos - 1); + } + + } + } +} + +uint16 Hotspots::handleInputs(int16 time, uint16 inputCount, uint16 &curInput, + InputDesc *inputs, uint16 &id, uint16 &index) { + + // Redraw all texts in all inputs we currently manage + updateAllTexts(inputs); + + for (int i = 0; i < 40; i++) + WRITE_VAR(17 + i, 0); + + while (1) { + // Find the hotspot index to our current input + uint16 hotspotIndex = inputToHotspot(curInput); + + assert(hotspotIndex != 0xFFFF); + + Hotspot inputSpot = _hotspots[hotspotIndex]; + + // Handle input events from that input field + uint16 key = updateInput(inputSpot.left, inputSpot.top, + inputSpot.right - inputSpot.left + 1, + inputSpot.bottom - inputSpot.top + 1, + inputs[curInput].backColor, inputs[curInput].frontColor, + GET_VARO_STR(inputSpot.key), inputs[curInput].fontIndex, + inputSpot.getType(), time, id, index); + + if (_vm->_inter->_terminate) + return 0; + + switch (key) { + case kKeyNone: + if (id == 0) + // No key and no hotspot => return + return 0; + + if (_vm->_game->_mouseButtons != kMouseButtonsNone) + // Clicked something, get the hotspot index + index = findClickedInput(index); + + if (!_hotspots[index].isInput()) + // It's no input, return + return 0; + + // Get the associated input index + curInput = hotspotToInput(index); + break; + + case kKeyF1: + case kKeyF2: + case kKeyF3: + case kKeyF4: + case kKeyF5: + case kKeyF6: + case kKeyF7: + case kKeyF8: + case kKeyF9: + case kKeyF10: + return key; + + case kKeyReturn: + // Just one input => return + if (inputCount == 1) + return kKeyReturn; + + // End of input chain reached => wrap + if (curInput == (inputCount - 1)) { + curInput = 0; + break; + } + + // Next input + curInput++; + break; + + case kKeyDown: + // Next input + if ((inputCount - 1) > curInput) + curInput++; + break; + + case kKeyUp: + // Previous input + if (curInput > 0) + curInput--; + break; + } + } +} + +void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, + uint16 &validId, bool &hasInput, uint16 &inputCount) { + + ids[i] = 0; + + // Type and window + byte type = _vm->_game->_script->readByte(); + byte window = 0; + + if ((type & 0x40) != 0) { + // Got a window ID + + type -= 0x40; + window = _vm->_game->_script->readByte(); + } + + // Coordinates + uint16 left, top, width, height, right, bottom; + uint32 funcPos = 0; + if ((type & 0x80) != 0) { + // Complex coordinate expressions + funcPos = _vm->_game->_script->pos(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); + } else { + // Immediate values + funcPos = 0; + left = _vm->_game->_script->readUint16(); + top = _vm->_game->_script->readUint16(); + width = _vm->_game->_script->readUint16(); + height = _vm->_game->_script->readUint16(); + } + type &= 0x7F; + + // Apply global drawing offset + if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { + left += _vm->_draw->_backDeltaX; + top += _vm->_draw->_backDeltaY; + } + + right = left + width - 1; + bottom = top + height - 1; + + // Enabling the hotspots again + if ((type == kTypeEnable2) || (type == kTypeEnable1)) { + uint8 wantedState = 0; + if (type == kTypeEnable2) + wantedState = kStateFilledDisabled | kStateType2; + else + wantedState = kStateFilledDisabled | kStateType1; + + _vm->_game->_script->skip(6); + + for (int j = 0; j < kHotspotCount; j++) { + Hotspot &spot = _hotspots[j]; + + if (spot.getState() == wantedState) { + spot.enable(); + spot.funcEnter = _vm->_game->_script->pos(); + spot.funcLeave = _vm->_game->_script->pos(); + } + } + + _vm->_game->_script->skipBlock(); + + return; + } + + int16 key = 0; + int16 flags = 0; + Video::FontDesc *font = 0; + uint32 funcEnter = 0, funcLeave = 0; + + // Evaluate parameters for the new hotspot + switch (type) { + case kTypeNone: + _vm->_game->_script->skip(6); + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + key = i + ((kStateFilled | kStateType2) << 12); + flags = type + (window << 8); + break; + + case kTypeMove: + key = _vm->_game->_script->readInt16(); + ids[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16(); + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + if (key == 0) + key = i + ((kStateFilled | kStateType2) << 12); + + flags = type + (window << 8) + (flags << 4); + break; + + case kTypeInput1NoLeave: + case kTypeInput1Leave: + case kTypeInput2NoLeave: + case kTypeInput2Leave: + case kTypeInput3NoLeave: + case kTypeInput3Leave: + case kTypeInputFloatNoLeave: + case kTypeInputFloatLeave: + hasInput = true; + + _vm->_util->clearKeyBuf(); + + // Input text parameters + key = _vm->_game->_script->readVarIndex(); + inputs[inputCount].fontIndex = _vm->_game->_script->readInt16(); + inputs[inputCount].backColor = _vm->_game->_script->readByte(); + inputs[inputCount].frontColor = _vm->_game->_script->readByte(); + inputs[inputCount].length = 0; + inputs[inputCount].str = 0; + + if ((type >= kTypeInput2NoLeave) && (type <= kTypeInput3Leave)) { + uint16 length = _vm->_game->_script->readUint16(); + + inputs[inputCount].str = + (const char *) (_vm->_game->_script->getData() + _vm->_game->_script->pos()); + + _vm->_game->_script->skip(length); + } + + if (left == 0xFFFF) { + if (!(type & 1)) + // No coordinates but a leave block => skip it + _vm->_game->_script->skipBlock(); + break; + } + + font = _vm->_draw->_fonts[inputs[inputCount].fontIndex]; + if (!font->charWidths) + // Monospaced font + right = left + width * font->itemWidth - 1; + + funcEnter = 0; + funcPos = 0; + funcLeave = 0; + if (!(type & 1)) { + // Got a leave + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + } + + flags = type; + + inputCount++; + break; + + case 20: + validId = i; + // Fall through to case 2 + case kTypeClick: + key = _vm->_game->_script->readInt16(); + ids[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16(); + + funcEnter = 0; + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + flags = ((uint16) kTypeClick) + (window << 8) + (flags << 4); + break; + + case kTypeClickEnter: + key = _vm->_game->_script->readInt16(); + ids[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16() & 3; + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = 0; + + flags = ((uint16) kTypeClick) + (window << 8) + (flags << 4); + break; + } + + // Add the new hotspot + add(i | (kStateFilled << 12), left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); +} + +void Hotspots::evaluate() { + InputDesc inputs[20]; + uint16 ids[kHotspotCount]; + int16 counter; + int16 var_24; + int16 var_26; + int16 collStackPos; + + // Push all local hotspots + push(0); + + // Find the current end of the hotspot block + uint16 endIndex = 0; + while (!_hotspots[endIndex].isEnd()) + endIndex++; + + _shouldPush = false; + + _vm->_game->_script->skip(1); + + // Number of new hotspots + byte count = _vm->_game->_script->readByte(); + + // Parameters of this block + _vm->_game->_handleMouse = _vm->_game->_script->peekByte(0); + int16 duration = _vm->_game->_script->peekByte(1); + byte stackPos2 = _vm->_game->_script->peekByte(3); + byte descIndex = _vm->_game->_script->peekByte(4); + bool needRecalculation = _vm->_game->_script->peekByte(5) != 0; + + // Seconds -> Milliseconds + duration *= 1000; + + if ((stackPos2 != 0) || (descIndex != 0)) { + duration /= 100; + if (_vm->_game->_script->peekByte(1) == 100) + duration = 2; + } + + int16 timeVal = duration; + + _vm->_game->_script->skip(6); + + // Clear current ID + WRITE_VAR(16, 0); + + byte var_41 = 0; + int16 var_46 = 0; + + uint16 id = 0; + uint16 validId = 0xFFFF; + uint16 index = 0; + + bool hasInput = false; + uint16 inputCount = 0; + + // Adding new hotspots + for (uint16 i = 0; i < count; i++) + evaluateNew(i, ids, inputs, validId, hasInput, inputCount); + + // Recalculate all hotspots if requested + if (needRecalculation) + recalculate(true); + + _vm->_game->_forceHandleMouse = 0; + _vm->_util->clearKeyBuf(); + + do { + uint16 key = 0; + if (hasInput) { + // Input + + uint16 curInput = 0; + + key = handleInputs(duration, inputCount, curInput, inputs, id, index); + + // Notify the script of the current input index + WRITE_VAR(55, curInput); + if (key == kKeyReturn) { + // Return pressed, invoke input leave + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledEnabled()) + // Not filled or disabled + continue; + + if ((spot.getType() & 1) != 0) + // Not an input with a leave function + continue; + + if (spot.getType() <= kTypeClick) + // Not an input + continue; + + id = spot.id; + validId = spot.id & 0x7FFF; + index = i; + break; + } + break; + } + } else + // Normal move or click check + key = check(_vm->_game->_handleMouse, -duration, id, index); + + // Handle special number keys + if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && + ((key >> 8) > 1) && ((key >> 8) < 12)) + key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); + + if (id == 0) { + // No hotspot area + + if (key != 0) { + // But a key + + // Find the hotspot with that key associated + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledEnabled()) + // Not filled or disabled + continue; + + // Key match Catch all + if ((spot.key == key) || (spot.key == 0x7FFF)) { + id = spot.id; + index = i; + break; + } + } + + if (id == 0) { + // Didn't find such a hotspot + + // Try it again, this time case insensitively + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledEnabled()) + continue; + + if ((spot.key & 0xFF00) != 0) + continue; + + if (spot.key == 0) + continue; + + if (toupper(key & 0xFF) == toupper(spot.key)) { + id = spot.id; + index = i; + break; + } + } + } + } else if (duration != 0) { + if (stackPos2 != 0) { + collStackPos = 0; + + for (int i = endIndex; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledNew()) + continue; + + collStackPos++; + if (collStackPos != stackPos2) + // Isn't yet the one wanted + continue; + + id = spot.id; + index = i; + _vm->_inter->storeMouse(); + if (VAR(16) != 0) + // We already handle a hotspot + break; + + // Notify the scripts that we now handle this hotspot + if (Hotspot::getState(id) == kStateFilled) + WRITE_VAR(16, ids[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); + + if (spot.funcLeave != 0) { + // It has a leave function + + uint32 timeKey = _vm->_util->getTimeKey(); + call(spot.funcLeave); + + if (timeVal != 2) { + // Rest time we have left = time we had - time the leave took + duration = timeVal - (_vm->_util->getTimeKey() - timeKey); + + // Remove the buffer time + if ((duration - var_46) < 3) { + var_46 -= (duration - 3); + duration = 3; + } else if (var_46 != 0) { + duration -= var_46; + var_46 = 0; + } + + // Clamp + if (duration > timeVal) + duration = timeVal; + + } else + duration = 2; + + } + + if (VAR(16) == 0) + // Didn't find anything + id = 0; + else + var_41 = 1; + + break; + } + + } else { + if (descIndex != 0) { + + counter = 0; + // Enter the nth hotspot + for (int i = endIndex; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.isFilledNew()) { + if (++counter == descIndex) { + id = spot.id; + index = i; + break; + } + } + + } + + } else { + + // Enter the first hotspot + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.isFilledNew()) { + id = spot.id; + index = i; + break; + } + } + + // Leave the current hotspot + if ((_currentKey != 0) && (_hotspots[_currentIndex].funcLeave != 0)) + call(_hotspots[_currentIndex].funcLeave); + + _currentKey = 0; + } + + } + } + } + + if (var_41 != 0) + break; + + if ((id == 0) || (_hotspots[index].funcLeave != 0)) + // We don't have a new ID, but haven't yet handled the leave function + continue; + + _vm->_inter->storeMouse(); + + // Notify the scripts of the currently handled hotspot + if (Hotspot::getState(id) == kStateFilled) + WRITE_VAR(16, ids[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); + + // Enter it + if (_hotspots[index].funcEnter != 0) + call(_hotspots[index].funcEnter); + + WRITE_VAR(16, 0); + id = 0; + } + while ((id == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); + + char tempStr[256]; + if ((id & 0xFFF) == validId) { + collStackPos = 0; + var_24 = 0; + var_26 = 1; + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + // Looking for all enabled inputs + if (spot.isEnd()) + continue; + if (!spot.isFilledEnabled()) + continue; + if (!spot.isInput()) + continue; + + // Clean up numerical floating values + if (spot.getType() >= kTypeInputFloatNoLeave) { + // Get the string + char *ptr; + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + // Remove spaces + while ((ptr = strchr(tempStr, ' '))) + _vm->_util->cutFromStr(tempStr, (ptr - tempStr), 1); + + // Exchange decimal separator if needed + if (_vm->_global->_language == kLanguageBritish) + while ((ptr = strchr(tempStr, '.'))) + *ptr = ','; + + // Write it back + WRITE_VARO_STR(spot.key, tempStr); + } + + if ((spot.getType() >= kTypeInput2NoLeave) && (spot.getType() <= kTypeInput3Leave)) { + const char *str = inputs[var_24].str; + + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + if (spot.getType() < kTypeInput3NoLeave) + _vm->_util->cleanupStr(tempStr); + + // Look if we find a match between the wanted and the typed string + int16 pos = 0; + do { + char spotStr[256]; + + strncpy0(spotStr, str, 255); + pos += strlen(str) + 1; + + str += strlen(str) + 1; + + if (spot.getType() < kTypeInput3NoLeave) + _vm->_util->cleanupStr(spotStr); + + // Compare the entered string with the string we wanted + if (strcmp(tempStr, spotStr) == 0) { + WRITE_VAR(17, VAR(17) + 1); + WRITE_VAR(17 + var_26, 1); + break; + } + } while (inputs[var_24].length > pos); + + collStackPos++; + } else + WRITE_VAR(17 + var_26, 2); + + var_24++; + var_26++; + } + + // Notify the scripts if we reached the requested hotspot + if (collStackPos != (int16) VAR(17)) + WRITE_VAR(17, 0); + else + WRITE_VAR(17, 1); + } + + if (_vm->_game->_handleMouse == 1) + _vm->_draw->blitCursor(); + + if (!_vm->_inter->_terminate && (var_41 == 0)) { + _vm->_game->_script->seek(_hotspots[index].funcLeave); + + _vm->_inter->storeMouse(); + if (VAR(16) == 0) { + // No hotspot currently handled, now we'll handle the newly found one + + if (Hotspot::getState(id) == kStateFilled) + WRITE_VAR(16, ids[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); + } + } else + _vm->_game->_script->setFinished(true); + + for (int i = 0; i < count; i++) + // Remove all local hotspots + remove(i + (kStateFilled << 12)); + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + // Disable the ones still there + if ((spot.getState() == (kStateFilled | kStateType1)) || + (spot.getState() == (kStateFilled | kStateType2))) + spot.disable(); + } + +} + +int16 Hotspots::findCursor(uint16 x, uint16 y) const { + int16 cursor = 0; + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if ((spot.getWindow() != 0) || spot.isDisabled()) + // Ignore disabled and non-main-windowed hotspots + continue; + + if (!spot.isIn(x, y)) + // We're not in that hotspot, ignore it + continue; + + if (spot.getCursor() == 0) { + // Hotspot doesn't itself specify a cursor... + if (spot.getType() >= kTypeInput1NoLeave) { + // ...but the type has a generic one + cursor = 3; + break; + } else if ((spot.getButton() != kMouseButtonsRight) && (cursor == 0)) + // ...but there's a generic "click" cursor + cursor = 1; + } else if (cursor == 0) + // Hotspot had an attached cursor index + cursor = spot.getCursor(); + } + + return cursor; +} + +uint16 Hotspots::inputToHotspot(uint16 input) const { + uint16 inputIndex = 0; + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (!spot.isActiveInput()) + // Not an active input + continue; + + if (inputIndex == input) + // We've found our input + return i; + + // Next one + inputIndex++; + } + + // None found + return 0xFFFF; +} + +uint16 Hotspots::hotspotToInput(uint16 hotspot) const { + uint16 input = 0; + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (!spot.isActiveInput()) + // Not an active input + continue; + + if (i == hotspot) + // We've found our hotspot + break; + + // Next one + input++; + } + + return input; +} + +uint16 Hotspots::findClickedInput(uint16 index) const { + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.getWindow() != 0) + // Ignore other windows + continue; + + if (spot.isDisabled()) + // Ignore disabled hotspots + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + // This one wasn't it + continue; + + if (spot.getCursor() != 0) + // This one specifies a cursor, so we don't want it + continue; + + if (!spot.isInput()) + // It's no input + continue; + + index = i; + break; + } + + return index; +} + +void Hotspots::getTextCursorPos(const Video::FontDesc &font, const char *str, + uint32 pos, uint16 x, uint16 y, uint16 width, uint16 height, + uint16 &cursorX, uint16 &cursorY, uint16 &cursorWidth, uint16 &cursorHeight) const { + + if (font.charWidths) { + // Cursor to the right of the current character + + cursorX = x; + cursorY = y; + cursorWidth = 1; + cursorHeight = height; + + // Iterate through the string and add each character's width + for (uint32 i = 0; i < pos; i++) + cursorX += font.charWidths[str[i] - font.startItem]; + + } else { + // Cursor underlining the current character + + cursorX = x + font.itemWidth * pos; + cursorY = y + height - 1; + cursorWidth = font.itemWidth; + cursorHeight = 1; + } +} + +void Hotspots::fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 color) const { + _vm->_draw->_destSurface = 21; + _vm->_draw->_destSpriteX = x; + _vm->_draw->_destSpriteY = y; + _vm->_draw->_spriteRight = width; + _vm->_draw->_spriteBottom = height; + _vm->_draw->_backColor = color; + + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); +} + +void Hotspots::printText(uint16 x, uint16 y, const char *str, uint16 fontIndex, uint16 color) const { + _vm->_draw->_destSpriteX = x; + _vm->_draw->_destSpriteY = y; + _vm->_draw->_frontColor = color; + _vm->_draw->_fontIndex = fontIndex; + _vm->_draw->_textToPrint = str; + _vm->_draw->_transparency = 1; + + _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); +} + +void Hotspots::updateAllTexts(const InputDesc *inputs) const { + uint16 input = 0; + + for (int i = 0; i < kHotspotCount; i++) { + const Hotspot &spot = _hotspots[i]; + + if (spot.isEnd()) + // It's an end, we don't want it + continue; + + if (!spot.isFilledEnabled()) + // This one's either not used or disabled + continue; + + if (!spot.isInput()) + // Not an input + continue; + + // Get its text + char tempStr[256]; + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + // Coordinates + uint16 x = spot.left; + uint16 y = spot.top; + uint16 width = spot.right - spot.left + 1; + uint16 height = spot.bottom - spot.top + 1; + // Clear the background + fillRect(x, y, width, height, inputs[input].backColor); + + // Center the text vertically + y += (height - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->itemHeight) / 2; + + // Draw it + printText(x, y, tempStr, inputs[input].fontIndex, inputs[input].frontColor); + + input++; + } +} + +} // End of namespace Gob diff --git a/engines/gob/hotspots.h b/engines/gob/hotspots.h new file mode 100644 index 0000000000..893991bfbe --- /dev/null +++ b/engines/gob/hotspots.h @@ -0,0 +1,241 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_HOTSPOTS_H +#define GOB_HOTSPOTS_H + +#include "common/stack.h" + +#include "gob/util.h" + +namespace Gob { + +class Script; + +class Hotspots { +public: + static const int kHotspotCount = 250; + + enum Type { + kTypeNone = 0, + kTypeMove = 1, + kTypeClick = 2, + kTypeInput1NoLeave = 3, + kTypeInput1Leave = 4, + kTypeInput2NoLeave = 5, + kTypeInput2Leave = 6, + kTypeInput3NoLeave = 7, + kTypeInput3Leave = 8, + kTypeInputFloatNoLeave = 9, + kTypeInputFloatLeave = 10, + kTypeEnable2 = 11, + kTypeEnable1 = 12, + kTypeClickEnter = 21 + }; + + enum State { + kStateFilledDisabled = 0xC, + kStateFilled = 0x8, + kStateDisabled = 0x4, + kStateType2 = 0x2, + kStateType1 = 0x1 + }; + + Hotspots(GobEngine *vm); + ~Hotspots(); + + /** Remove all hotspots. */ + void clear(); + + /** Add a hotspot, returning the new index. */ + uint16 add(uint16 id, + uint16 left, uint16 top, uint16 right, uint16 bottom, + uint16 flags, uint16 key, + uint16 funcEnter, uint16 funcLeave, uint16 funcPos); + + /** Remove a specific hotspot. */ + void remove(uint16 id); + /** Remove all hotspots in this state. */ + void removeState(uint8 state); + + /** Push the current hotspots onto the stack. + * + * @param all 0: Don't push global ones; 1: Push all; 2: Push only the disabled ones + * @param force Force a push although _shouldPush is false + */ + void push(uint8 all, bool force = false); + /** Pop hotspots from the stack. */ + void pop(); + + /** Check the current hotspot. */ + uint16 check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index); + /** Check the current hotspot. */ + uint16 check(uint8 handleMouse, int16 delay); + + /** Evaluate hotspot changes. */ + void evaluate(); + + /** Return the cursor found in the hotspot to the coordinates. */ + int16 findCursor(uint16 x, uint16 y) const; + +private: + struct Hotspot { + uint16 id; + uint16 left; + uint16 top; + uint16 right; + uint16 bottom; + uint16 flags; + uint16 key; + uint16 funcEnter; + uint16 funcLeave; + uint16 funcPos; + Script *script; + + Hotspot(); + Hotspot(uint16 i, + uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k, + uint16 enter, uint16 leave, uint16 pos); + + void clear(); + + Type getType() const; + MouseButtons getButton() const; + uint8 getWindow() const; + uint8 getCursor() const; + uint8 getState() const; + + /** Is this hotspot the block end marker? */ + bool isEnd() const; + + bool isInput() const; + bool isActiveInput() const; + + bool isFilled() const; + bool isFilledEnabled() const; + bool isFilledNew() const; + bool isDisabled() const; + + /** Are the specified coordinates in the hotspot? */ + bool isIn(uint16 x, uint16 y) const; + /** Does the specified button trigger the hotspot? */ + bool buttonMatch(MouseButtons button) const; + + static uint8 getState(uint16 id); + + void disable(); + void enable(); + }; + + struct StackEntry { + bool shouldPush; + Hotspot *hotspots; + uint32 size; + uint32 key; + uint32 id; + uint32 index; + }; + + struct InputDesc { + uint16 fontIndex; + uint16 backColor; + uint16 frontColor; + uint16 length; + const char *str; + }; + + GobEngine *_vm; + + Hotspot *_hotspots; + Common::Stack<StackEntry> _stack; + + bool _shouldPush; + + uint16 _currentKey; + uint16 _currentIndex; + uint16 _currentId; + + /** Add a hotspot, returning the new index. */ + uint16 add(const Hotspot &hotspot); + + /** Recalculate all hotspot parameters + * + * @param force Force recalculation of all hotspots, including global ones. + */ + void recalculate(bool force); + + /** Is this a valid hotspot? */ + bool isValid(uint16 key, uint16 id, uint16 index) const; + + /** Call a hotspot subroutine. */ + void call(uint16 offset); + /** Handling hotspot enter events. */ + void enter(uint16 index); + /** Handling hotspot leave events. */ + void leave(uint16 index); + + /** Which hotspot is the mouse cursor currently at? */ + uint16 checkMouse(Type type, uint16 &id, uint16 &index) const; + + /** Did the current hotspot change in the meantime? */ + bool checkHotspotChanged(); + + /** Update events from a specific input. */ + uint16 updateInput(uint16 xPos, uint16 yPos, uint16 width, uint16 height, + uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex, + Type type, int16 &duration, uint16 &id, uint16 &index); + + /** Handle all inputs we currently manage. */ + uint16 handleInputs(int16 time, uint16 inputCount, uint16 &curInput, + InputDesc *inputs, uint16 &id, uint16 &index); + + /** Evaluate adding new hotspots script commands. */ + void evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, + uint16 &validId, bool &hasInput, uint16 &inputCount); + + /** Find the hotspot index that corresponds to the input index. */ + uint16 inputToHotspot(uint16 input) const; + /** Find the input index that corresponds to the hotspot index. */ + uint16 hotspotToInput(uint16 hotspot) const; + /** Find the input that was clicked on. */ + uint16 findClickedInput(uint16 index) const; + + /** Calculate the graphical cursor position. */ + void getTextCursorPos(const Video::FontDesc &font, const char *str, + uint32 pos, uint16 x, uint16 y, uint16 width, uint16 height, + uint16 &cursorX, uint16 &cursorY, uint16 &cursorWidth, uint16 &cursorHeight) const; + + /** Fill that rectangle with the color. */ + void fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 color) const; + /** Print the given text. */ + void printText(uint16 x, uint16 y, const char *str, uint16 fontIndex, uint16 color) const; + + /** Go through all inputs we manage and redraw their texts. */ + void updateAllTexts(const InputDesc *inputs) const; +}; + +} // End of namespace Gob + +#endif // GOB_HOTSPOTS_H diff --git a/engines/gob/init.h b/engines/gob/init.h index a8d4b9833e..60642d0189 100644 --- a/engines/gob/init.h +++ b/engines/gob/init.h @@ -32,7 +32,7 @@ namespace Gob { class Init { public: - void initGame(); + virtual void initGame(); virtual void initVideo() = 0; @@ -72,6 +72,14 @@ public: virtual ~Init_v3() {} }; +class Init_v6 : public Init_v3 { +public: + virtual void initGame(); + + Init_v6(GobEngine *vm); + virtual ~Init_v6() {} +}; + } // End of namespace Gob #endif // GOB_INIT_H diff --git a/engines/gob/init_v6.cpp b/engines/gob/init_v6.cpp new file mode 100644 index 0000000000..4b14c8a29c --- /dev/null +++ b/engines/gob/init_v6.cpp @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/init.h" +#include "gob/global.h" + +namespace Gob { + +Init_v6::Init_v6(GobEngine *vm) : Init_v3(vm) { +} + +void Init_v6::initGame() { + _vm->_global->_noCd = false; + + if (Common::File::exists("cd1.itk") && Common::File::exists("cd2.itk") && + Common::File::exists("cd3.itk") && Common::File::exists("cd4.itk")) { + _vm->_global->_noCd = true; + } + + Init::initGame(); +} + +} // End of namespace Gob diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index 8be07034c6..afd215a00d 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -35,6 +35,7 @@ #include "gob/game.h" #include "gob/expression.h" #include "gob/script.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -180,7 +181,7 @@ void Inter::storeMouse() { WRITE_VAR(2, x); WRITE_VAR(3, y); - WRITE_VAR(4, _vm->_game->_mouseButtons); + WRITE_VAR(4, (uint32) _vm->_game->_mouseButtons); } void Inter::storeKey(int16 key) { @@ -189,20 +190,20 @@ void Inter::storeKey(int16 key) { storeMouse(); WRITE_VAR(1, _vm->_sound->blasterPlayingSound()); - if (key == 0x4800) - key = 0x0B; - else if (key == 0x5000) - key = 0x0A; - else if (key == 0x4D00) - key = 0x09; - else if (key == 0x4B00) - key = 0x08; - else if (key == 0x011B) - key = 0x1B; - else if (key == 0x0E08) - key = 0x19; - else if (key == 0x5300) - key = 0x1A; + if (key == kKeyUp) + key = kShortKeyUp; + else if (key == kKeyDown) + key = kShortKeyDown; + else if (key == kKeyRight) + key = kShortKeyRight; + else if (key == kKeyLeft) + key = kShortKeyLeft; + else if (key == kKeyEscape) + key = kShortKeyEscape; + else if (key == kKeyBackspace) + key = kShortKeyBackspace; + else if (key == kKeyDelete) + key = kShortKeyDelete; else if ((key & 0xFF) != 0) key &= 0xFF; @@ -334,7 +335,7 @@ void Inter::callSub(int16 retFlag) { if (block == 1) funcBlock(retFlag); else if (block == 2) - _vm->_game->collisionsBlock(); + _vm->_game->_hotspots->evaluate(); else error("Unknown block type %d in Inter::callSub()", block); } diff --git a/engines/gob/inter.h b/engines/gob/inter.h index d4ed2d3240..a31860885f 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -238,7 +238,7 @@ protected: bool o1_playComposition(OpFuncParams ¶ms); bool o1_getFreeMem(OpFuncParams ¶ms); bool o1_checkData(OpFuncParams ¶ms); - bool o1_prepareStr(OpFuncParams ¶ms); + bool o1_cleanupStr(OpFuncParams ¶ms); bool o1_insertStr(OpFuncParams ¶ms); bool o1_cutStr(OpFuncParams ¶ms); bool o1_strstr(OpFuncParams ¶ms); @@ -380,8 +380,8 @@ protected: bool o2_assign(OpFuncParams ¶ms); bool o2_printText(OpFuncParams ¶ms); bool o2_animPalInit(OpFuncParams ¶ms); - bool o2_addCollision(OpFuncParams ¶ms); - bool o2_freeCollision(OpFuncParams ¶ms); + bool o2_addHotspot(OpFuncParams ¶ms); + bool o2_removeHotspot(OpFuncParams ¶ms); bool o2_goblinFunc(OpFuncParams ¶ms); bool o2_stopSound(OpFuncParams ¶ms); bool o2_loadSound(OpFuncParams ¶ms); @@ -541,7 +541,7 @@ protected: bool o6_loadCursor(OpFuncParams ¶ms); bool o6_assign(OpFuncParams ¶ms); bool o6_palLoad(OpFuncParams ¶ms); - bool o6_freeCollision(OpFuncParams ¶ms); + bool o6_removeHotspot(OpFuncParams ¶ms); bool o6_fillRect(OpFuncParams ¶ms); void probe16bitMusic(char *fileName); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 12079600c0..b955057bac 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -89,7 +89,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { int i; int16 mouseX; int16 mouseY; - int16 buttons; + MouseButtons buttons; SurfaceDescPtr surface; SoundDesc samples[4]; int16 comp[5] = { 0, 1, 2, 3, -1 }; @@ -107,13 +107,13 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { for (i = 320; i >= 0; i--) { _vm->_util->setScrollOffset(i, 0); _vm->_video->dirtyRectsAll(); - if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || + if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == kKeyEscape) || _vm->shouldQuit()) { _vm->_palAnim->fade(0, -2, 0); _vm->_video->clearSurf(*_vm->_draw->_frontSurface); memset((char *) _vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); - WRITE_VAR(0, 0x11B); + WRITE_VAR(0, kKeyEscape); WRITE_VAR(57, (uint32) -1); break; } @@ -137,7 +137,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { int16 mouseX; int16 mouseY; - int16 buttons; + MouseButtons buttons; Video::Color *palBak; SoundDesc samples[2]; int16 comp[3] = { 0, 1, -1 }; @@ -158,14 +158,14 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); _vm->_util->longDelay(_vm->_util->getRandom(200)); } - if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || + if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == kKeyEscape) || _vm->shouldQuit()) { _vm->_sound->blasterStop(10); _vm->_palAnim->fade(0, -2, 0); _vm->_video->clearSurf(*_vm->_draw->_frontSurface); memset(_vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); - WRITE_VAR(0, 0x11B); + WRITE_VAR(0, kKeyEscape); WRITE_VAR(57, (uint32) -1); break; } diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 96ecfc6b25..7c5094d175 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -37,6 +37,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/map.h" @@ -147,7 +148,7 @@ void Inter_v1::setupOpcodesFunc() { OPCODEFUNC(0x3E, o1_getFreeMem); OPCODEFUNC(0x3F, o1_checkData); - OPCODEFUNC(0x41, o1_prepareStr); + OPCODEFUNC(0x41, o1_cleanupStr); OPCODEFUNC(0x42, o1_insertStr); OPCODEFUNC(0x43, o1_cutStr); @@ -867,7 +868,16 @@ bool Inter_v1::o1_loadSpriteToPos(OpFuncParams ¶ms) { _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16(); _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); - _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + + // WORKAROUND: The EGA version of Gobliiins 1 has an invalid expression there + if (_vm->isEGA() && (_vm->_game->_script->pos() == 1398) && + !scumm_stricmp(_vm->_game->_curTotFile, "intro.tot")) { + + _vm->_draw->_destSpriteY = 0; + _vm->_game->_script->skip(1); + + } else + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); _vm->_draw->_transparency = _vm->_game->_script->peekByte() & 1; _vm->_draw->_destSurface = ((int16) (_vm->_game->_script->peekByte() >> 1)) - 1; @@ -1173,7 +1183,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { case 0: _vm->_draw->_showCursor &= ~2; _vm->_util->longDelay(1); - key = _vm->_game->checkCollisions(0, 0, 0, 0); + key = _vm->_game->_hotspots->check(0, 0); storeKey(key); _vm->_util->clearKeyBuf(); @@ -1601,11 +1611,11 @@ bool Inter_v1::o1_checkData(OpFuncParams ¶ms) { return false; } -bool Inter_v1::o1_prepareStr(OpFuncParams ¶ms) { +bool Inter_v1::o1_cleanupStr(OpFuncParams ¶ms) { int16 strVar; strVar = _vm->_game->_script->readVarIndex(); - _vm->_util->prepareStr(GET_VARO_FSTR(strVar)); + _vm->_util->cleanupStr(GET_VARO_FSTR(strVar)); return false; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 82822330b1..20f812bb88 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -39,6 +39,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" @@ -121,8 +122,8 @@ void Inter_v2::setupOpcodesFunc() { OPCODEFUNC(0x17, o2_animPalInit); - OPCODEFUNC(0x18, o2_addCollision); - OPCODEFUNC(0x19, o2_freeCollision); + OPCODEFUNC(0x18, o2_addHotspot); + OPCODEFUNC(0x19, o2_removeHotspot); OPCODEFUNC(0x25, o2_goblinFunc); @@ -1176,67 +1177,51 @@ bool Inter_v2::o2_animPalInit(OpFuncParams ¶ms) { return false; } -bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { - int16 id; - int16 left, top, width, height; - int16 flags; - int16 key; - int16 funcSub; - - id = _vm->_game->_script->readValExpr(); - funcSub = _vm->_game->_script->pos(); - left = _vm->_game->_script->readValExpr(); - top = _vm->_game->_script->readValExpr(); - width = _vm->_game->_script->readValExpr(); - height = _vm->_game->_script->readValExpr(); - flags = _vm->_game->_script->readValExpr(); - key = _vm->_game->_script->readInt16(); +bool Inter_v2::o2_addHotspot(OpFuncParams ¶ms) { + int16 id = _vm->_game->_script->readValExpr(); + uint16 funcPos = _vm->_game->_script->pos(); + int16 left = _vm->_game->_script->readValExpr(); + int16 top = _vm->_game->_script->readValExpr(); + uint16 width = _vm->_game->_script->readValExpr(); + uint16 height = _vm->_game->_script->readValExpr(); + uint16 flags = _vm->_game->_script->readValExpr(); + uint16 key = _vm->_game->_script->readInt16(); if (key == 0) key = ABS(id) + 41960; - _vm->_draw->adjustCoords(0, &left, &top); - _vm->_draw->adjustCoords(2, &width, &height); - if (left < 0) { width += left; - left = 0; + left = 0; } if (top < 0) { height += top; - top = 0; + top = 0; } int16 index; if (id < 0) - index = _vm->_game->addNewCollision(0xD000 - id, left & 0xFFFC, top & 0xFFFC, - left + width + 3, top + height + 3, flags, key, 0, 0); + index = _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC, + left + width + 3, top + height + 3, flags, key, 0, 0, funcPos); else - index = _vm->_game->addNewCollision(0xE000 + id, left, top, - left + width - 1, top + height - 1, flags, key, 0, 0); - - _vm->_game->_collisionAreas[index].funcSub = funcSub; + index = _vm->_game->_hotspots->add(0xE000 + id, left, top, + left + width - 1, top + height - 1, flags, key, 0, 0, funcPos); return false; } -bool Inter_v2::o2_freeCollision(OpFuncParams ¶ms) { - int16 id; +bool Inter_v2::o2_removeHotspot(OpFuncParams ¶ms) { + int16 id = _vm->_game->_script->readValExpr(); + uint8 stateType1 = Hotspots::kStateFilledDisabled | Hotspots::kStateType1; + uint8 stateType2 = Hotspots::kStateFilledDisabled | Hotspots::kStateType2; - id = _vm->_game->_script->readValExpr(); - if (id == -2) { - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } - } else if (id == -1) { - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } - } else - _vm->_game->freeCollision(0xE000 + id); + if (id == -2) + _vm->_game->_hotspots->removeState(stateType1); + else if (id == -1) + _vm->_game->_hotspots->removeState(stateType2); + else + _vm->_game->_hotspots->remove((stateType2 << 12) + id); return false; } diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp index 506de821d4..aa4721ff0a 100644 --- a/engines/gob/inter_v6.cpp +++ b/engines/gob/inter_v6.cpp @@ -31,10 +31,12 @@ #include "gob/inter.h" #include "gob/helper.h" #include "gob/global.h" +#include "gob/dataio.h" #include "gob/game.h" #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/draw.h" #include "gob/sound/sound.h" #include "gob/videoplayer.h" @@ -64,7 +66,7 @@ void Inter_v6::setupOpcodesFunc() { OPCODEFUNC(0x03, o6_loadCursor); OPCODEFUNC(0x09, o6_assign); OPCODEFUNC(0x13, o6_palLoad); - OPCODEFUNC(0x19, o6_freeCollision); + OPCODEFUNC(0x19, o6_removeHotspot); OPCODEFUNC(0x33, o6_fillRect); } @@ -187,7 +189,7 @@ void Inter_v6::o6_openItk() { // (it checks CD1.ITK - CD4.ITK and the first that's found determines // the CD number), while its NO_CD modus wants everything in CD1.ITK. // So we just open the other ITKs, too. - if (_vm->_game->_noCd && !scumm_stricmp(fileName, "CD1.ITK")) { + if (_vm->_global->_noCd && !scumm_stricmp(fileName, "CD1.ITK")) { _vm->_dataIO->openDataFile("CD2.ITK", true); _vm->_dataIO->openDataFile("CD3.ITK", true); _vm->_dataIO->openDataFile("CD4.ITK", true); @@ -351,36 +353,33 @@ bool Inter_v6::o6_palLoad(OpFuncParams ¶ms) { return false; } -bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { +bool Inter_v6::o6_removeHotspot(OpFuncParams ¶ms) { int16 id; + uint8 stateType1 = Hotspots::kStateFilledDisabled | Hotspots::kStateType1; + uint8 stateType2 = Hotspots::kStateFilledDisabled | Hotspots::kStateType2; + uint8 stateDisabled = Hotspots::kStateDisabled; id = _vm->_game->_script->readValExpr(); switch (id + 5) { case 0: - _vm->_game->pushCollisions(1); + _vm->_game->_hotspots->push(1); break; case 1: - _vm->_game->popCollisions(); + _vm->_game->_hotspots->pop(); break; case 2: - _vm->_game->pushCollisions(2); + _vm->_game->_hotspots->push(2); break; case 3: - for (int i = 0; i < 150; i++) { - if (((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) || - ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0x4000)) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } + _vm->_game->_hotspots->removeState(stateType1); + _vm->_game->_hotspots->removeState(stateDisabled); break; case 4: - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } + _vm->_game->_hotspots->removeState(stateType2); break; default: - _vm->_game->freeCollision(0xE000 + id); + _vm->_game->_hotspots->remove((stateType2 << 12) + id); break; } diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 695976da61..66c1b0dbaf 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -11,10 +11,6 @@ MODULE_OBJS := \ driver_vga.o \ expression.o \ game.o \ - game_v1.o \ - game_v2.o \ - game_v6.o \ - game_fascin.o \ global.o \ gob.o \ goblin.o \ @@ -22,11 +18,12 @@ MODULE_OBJS := \ goblin_v2.o \ goblin_v3.o \ goblin_v4.o \ - videoplayer.o \ + hotspots.o \ init.o \ init_v1.o \ init_v2.o \ init_v3.o \ + init_v6.o \ inter.o \ inter_v1.o \ inter_v2.o \ @@ -56,6 +53,7 @@ MODULE_OBJS := \ video_v1.o \ video_v2.o \ video_v6.o \ + videoplayer.o \ demos/demoplayer.o \ demos/scnplayer.o \ demos/batplayer.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 5aec5ff76e..d383d955c7 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -204,7 +204,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, stop = false; _vm->_util->processInput(); - if (checkEscape && (_vm->_util->checkKey() == 0x11B)) + if (checkEscape && (_vm->_util->checkKey() == kKeyEscape)) stop = true; _frame++; diff --git a/engines/gob/script.cpp b/engines/gob/script.cpp index 6162e943bf..38b1f8fa40 100644 --- a/engines/gob/script.cpp +++ b/engines/gob/script.cpp @@ -127,6 +127,10 @@ bool Script::skip(int32 offset) { return seek(offset, SEEK_CUR); } +bool Script::skipBlock() { + return seek(peekUint16(2) + 2, SEEK_CUR); +} + int32 Script::getOffset(byte *ptr) const { if (!_totData) return -1; diff --git a/engines/gob/script.h b/engines/gob/script.h index 64a04503b1..84daeaf1af 100644 --- a/engines/gob/script.h +++ b/engines/gob/script.h @@ -53,6 +53,7 @@ public: // Stream seeking bool seek(int32 offset, int whence = SEEK_SET); bool skip(int32 offset); + bool skipBlock(); // Reading data byte readByte (); diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp index d3afc9baa3..2d7ba02385 100644 --- a/engines/gob/sound/sound.cpp +++ b/engines/gob/sound/sound.cpp @@ -506,7 +506,7 @@ void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) { _blaster->endComposition(); while (_blaster->isPlaying() && !_vm->shouldQuit()) { - if (interruptible && (_vm->_util->checkKey() == 0x11B)) { + if (interruptible && (_vm->_util->checkKey() == kKeyEscape)) { WRITE_VAR(57, (uint32) -1); return; } diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index b0e7691c07..429b0269cf 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -38,14 +38,14 @@ namespace Gob { Util::Util(GobEngine *vm) : _vm(vm) { - _mouseButtons = 0; - _keyBufferHead = 0; - _keyBufferTail = 0; - _fastMode = 0; - _frameRate = 12; - _frameWaitTime = 0; + _mouseButtons = kMouseButtonsNone, + _keyBufferHead = 0; + _keyBufferTail = 0; + _fastMode = 0; + _frameRate = 12; + _frameWaitTime = 0; _startFrameTime = 0; - _frameWaitLag = 0; + _frameWaitLag = 0; } uint32 Util::getTimeKey(void) { @@ -85,7 +85,7 @@ void Util::longDelay(uint16 msecs) { } void Util::initInput(void) { - _mouseButtons = 0; + _mouseButtons = kMouseButtonsNone; _keyBufferHead = _keyBufferTail = 0; } @@ -103,16 +103,16 @@ void Util::processInput(bool scroll) { y = event.mouse.y; break; case Common::EVENT_LBUTTONDOWN: - _mouseButtons |= 1; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) | ((uint32) kMouseButtonsLeft)); break; case Common::EVENT_RBUTTONDOWN: - _mouseButtons |= 2; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) | ((uint32) kMouseButtonsRight)); break; case Common::EVENT_LBUTTONUP: - _mouseButtons &= ~1; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) & ~((uint32) kMouseButtonsLeft)); break; case Common::EVENT_RBUTTONUP: - _mouseButtons &= ~2; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) & ~((uint32) kMouseButtonsRight)); break; case Common::EVENT_KEYDOWN: if (event.kbd.flags == Common::KBD_CTRL) { @@ -179,26 +179,26 @@ int16 Util::translateKey(const Common::KeyState &key) { int16 from; int16 to; } keys[] = { - {Common::KEYCODE_INVALID, 0x0000}, - {Common::KEYCODE_BACKSPACE, 0x0E08}, - {Common::KEYCODE_SPACE, 0x3920}, - {Common::KEYCODE_RETURN, 0x1C0D}, - {Common::KEYCODE_ESCAPE, 0x011B}, - {Common::KEYCODE_DELETE, 0x5300}, - {Common::KEYCODE_UP, 0x4800}, - {Common::KEYCODE_DOWN, 0x5000}, - {Common::KEYCODE_RIGHT, 0x4D00}, - {Common::KEYCODE_LEFT, 0x4B00}, - {Common::KEYCODE_F1, 0x3B00}, - {Common::KEYCODE_F2, 0x3C00}, - {Common::KEYCODE_F3, 0x3D00}, - {Common::KEYCODE_F4, 0x3E00}, - {Common::KEYCODE_F5, 0x011B}, - {Common::KEYCODE_F6, 0x4000}, - {Common::KEYCODE_F7, 0x4100}, - {Common::KEYCODE_F8, 0x4200}, - {Common::KEYCODE_F9, 0x4300}, - {Common::KEYCODE_F10, 0x4400} + {Common::KEYCODE_INVALID, kKeyNone }, + {Common::KEYCODE_BACKSPACE, kKeyBackspace}, + {Common::KEYCODE_SPACE, kKeySpace }, + {Common::KEYCODE_RETURN, kKeyReturn }, + {Common::KEYCODE_ESCAPE, kKeyEscape }, + {Common::KEYCODE_DELETE, kKeyDelete }, + {Common::KEYCODE_UP, kKeyUp }, + {Common::KEYCODE_DOWN, kKeyDown }, + {Common::KEYCODE_RIGHT, kKeyRight }, + {Common::KEYCODE_LEFT, kKeyLeft }, + {Common::KEYCODE_F1, kKeyF1 }, + {Common::KEYCODE_F2, kKeyF2 }, + {Common::KEYCODE_F3, kKeyF3 }, + {Common::KEYCODE_F4, kKeyF4 }, + {Common::KEYCODE_F5, kKeyEscape }, + {Common::KEYCODE_F6, kKeyF6 }, + {Common::KEYCODE_F7, kKeyF7 }, + {Common::KEYCODE_F8, kKeyF8 }, + {Common::KEYCODE_F9, kKeyF9 }, + {Common::KEYCODE_F10, kKeyF10 } }; for (int i = 0; i < ARRAYSIZE(keys); i++) @@ -246,7 +246,7 @@ bool Util::checkKey(int16 &key) { return true; } -void Util::getMouseState(int16 *pX, int16 *pY, int16 *pButtons) { +void Util::getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons) { Common::Point mouse = g_system->getEventManager()->getMousePos(); *pX = mouse.x + _vm->_video->_scrollOffsetX - _vm->_video->_screenDeltaX; *pY = mouse.y + _vm->_video->_scrollOffsetY - _vm->_video->_screenDeltaY; @@ -264,15 +264,15 @@ void Util::setMousePos(int16 x, int16 y) { void Util::waitMouseUp(void) { do { processInput(); - if (_mouseButtons != 0) + if (_mouseButtons != kMouseButtonsNone) delay(10); - } while (_mouseButtons != 0); + } while (_mouseButtons != kMouseButtonsNone); } void Util::waitMouseDown(void) { int16 x; int16 y; - int16 buttons; + MouseButtons buttons; do { processInput(); @@ -283,7 +283,7 @@ void Util::waitMouseDown(void) { } void Util::waitMouseRelease(char drawMouse) { - int16 buttons; + MouseButtons buttons; int16 mouseX; int16 mouseY; @@ -300,8 +300,8 @@ void Util::forceMouseUp(bool onlyWhenSynced) { if (onlyWhenSynced && (_vm->_game->_mouseButtons != _mouseButtons)) return; - _vm->_game->_mouseButtons = 0; - _mouseButtons = 0; + _vm->_game->_mouseButtons = kMouseButtonsNone; + _mouseButtons = kMouseButtonsNone; } void Util::clearPalette(void) { @@ -403,10 +403,10 @@ Video::FontDesc *Util::loadFont(const char *path) { fontDesc->bitWidth = fontDesc->itemWidth; if (data[0] & 0x80) - fontDesc->extraData = data + 4 + fontDesc->itemSize * + fontDesc->charWidths = data + 4 + fontDesc->itemSize * (fontDesc->endItem - fontDesc->startItem + 1); else - fontDesc->extraData = 0; + fontDesc->charWidths = 0; return fontDesc; } @@ -452,7 +452,7 @@ static const char trStr2[] = " "; static const char trStr3[] = " "; -void Util::prepareStr(char *str) { +void Util::cleanupStr(char *str) { char *start, *end; char buf[300]; @@ -460,17 +460,20 @@ void Util::prepareStr(char *str) { strcat(buf, trStr2); strcat(buf, trStr3); + // Translating "wrong" characters for (size_t i = 0; i < strlen(str); i++) - str[i] = buf[str[i] - 32]; + str[i] = buf[MIN<int>(str[i] - 32, 32)]; + // Trim spaces left while (str[0] == ' ') cutFromStr(str, 0, 1); + // Trim spaces right while ((strlen(str) > 0) && (str[strlen(str) - 1] == ' ')) cutFromStr(str, strlen(str) - 1, 1); + // Merge double spaces start = strchr(str, ' '); - while (start) { if (start[1] == ' ') { cutFromStr(str, start - str, 1); diff --git a/engines/gob/util.h b/engines/gob/util.h index 0a76ee40ab..088a78a64d 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -34,6 +34,47 @@ namespace Gob { #define KEYBUFSIZE 16 +enum MouseButtons { + kMouseButtonsNone = 0, + kMouseButtonsLeft = 1, + kMouseButtonsRight = 2, + kMouseButtonsBoth = 3, + kMouseButtonsAny = 4 +}; + +enum Keys { + kKeyNone = 0x0000, + kKeyBackspace = 0x0E08, + kKeySpace = 0x3920, + kKeyReturn = 0x1C0D, + kKeyEscape = 0x011B, + kKeyDelete = 0x5300, + kKeyUp = 0x4800, + kKeyDown = 0x5000, + kKeyRight = 0x4D00, + kKeyLeft = 0x4B00, + kKeyF1 = 0x3B00, + kKeyF2 = 0x3C00, + kKeyF3 = 0x3D00, + kKeyF4 = 0x3E00, + kKeyF5 = 0x3F00, + kKeyF6 = 0x4000, + kKeyF7 = 0x4100, + kKeyF8 = 0x4200, + kKeyF9 = 0x4300, + kKeyF10 = 0x4400 +}; + +enum ShortKey { + kShortKeyUp = 0x0B, + kShortKeyDown = 0x0A, + kShortKeyRight = 0x09, + kShortKeyLeft = 0x08, + kShortKeyEscape = 0x1B, + kShortKeyBackspace = 0x19, + kShortKeyDelete = 0x1A +}; + class Util { public: struct ListNode; @@ -66,7 +107,7 @@ public: int16 checkKey(void); bool checkKey(int16 &key); - void getMouseState(int16 *pX, int16 *pY, int16 *pButtons); + void getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons); void setMousePos(int16 x, int16 y); void waitMouseUp(void); void waitMouseDown(void); @@ -84,7 +125,7 @@ public: static void insertStr(const char *str1, char *str2, int16 pos); static void cutFromStr(char *str, int16 from, int16 cutlen); - static void prepareStr(char *str); + static void cleanupStr(char *str); static void replaceChar(char *str, char c1, char c2); static void listInsertFront(List *list, void *data); @@ -95,7 +136,8 @@ public: Util(GobEngine *vm); protected: - int16 _mouseButtons; + MouseButtons _mouseButtons; + Common::KeyState _keyBuffer[KEYBUFSIZE]; int16 _keyBufferHead; int16 _keyBufferTail; diff --git a/engines/gob/video.h b/engines/gob/video.h index c71a18daa6..8716a637c2 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -78,7 +78,7 @@ public: uint8 endItem; int8 itemSize; int8 bitWidth; - byte *extraData; + uint8 *charWidths; FontDesc() : dataPtr(0), itemWidth(0), itemHeight(0), startItem(0), endItem(0), itemSize(0), bitWidth(0) {} ~FontDesc() { diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index 6c07d22333..da552d7202 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -27,7 +27,6 @@ #include "gob/videoplayer.h" #include "gob/helper.h" #include "gob/global.h" -#include "gob/util.h" #include "gob/dataio.h" #include "gob/video.h" #include "gob/draw.h" diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index 842426f90a..ead752d446 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -31,11 +31,12 @@ #include "graphics/video/coktelvideo/coktelvideo.h" -#include "gob/dataio.h" +#include "gob/util.h" namespace Gob { class GobEngine; +class DataStream; class VideoPlayer { public: @@ -60,13 +61,14 @@ public: bool primaryOpen(const char *videoFile, int16 x = -1, int16 y = -1, int32 flags = kFlagFrontSurface, Type which = kVideoTypeTry); - bool primaryPlay(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27, + bool primaryPlay(int16 startFrame = -1, int16 lastFrame = -1, + int16 breakKey = kShortKeyEscape, uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, int16 palFrame = -1, int16 endFrame = -1, bool fade = false, int16 reverseTo = -1, bool forceSeek = false); void primaryClose(); - void playFrame(int16 frame, int16 breakKey = 27, + void playFrame(int16 frame, int16 breakKey = kShortKeyEscape, uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, int16 palFrame = -1 , int16 endFrame = -1); diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 24f47351a3..cdf05e803b 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -108,7 +108,11 @@ Common::Error GroovieEngine::run() { } // Create the music player - _musicPlayer = new MusicPlayer(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); + if (_gameDescription->desc.platform == Common::kPlatformMacintosh) { + _musicPlayer = new MusicPlayerMac(this); + } else { + _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); + } // Load volume levels syncSoundSettings(); diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 30889deb44..1a1de92156 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -31,72 +31,20 @@ namespace Groovie { -MusicPlayer::MusicPlayer(GroovieEngine *vm, const Common::String >lName) : - _vm(vm), _midiParser(NULL), _data(NULL), _driver(NULL), - _backgroundFileRef(0), _gameVolume(100), _prevCDtrack(0), _isPlaying(0) { - // Create the parser - _midiParser = MidiParser::createParser_XMIDI(); - - // Create the driver - int driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = createMidi(driver); - this->open(); - - // Initialize the channel volumes and banks - for (int i = 0; i < 0x10; i++) { - _chanVolumes[i] = 0x7F; - _chanBanks[i] = 0; - } - - // Load the Global Timbre Library - if (driver == MD_ADLIB) { - // MIDI through AdLib - _musicType = MD_ADLIB; - loadTimbres(gtlName + ".ad"); - - // Setup the percussion channel - for (unsigned int i = 0; i < _timbres.size(); i++) { - if (_timbres[i].bank == 0x7F) - setTimbreAD(9, _timbres[i]); - } - } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) { - // MT-32 - _musicType = MD_MT32; - loadTimbres(gtlName + ".mt"); - } else { - // GM - _musicType = 0; - } - - // Set the parser's driver - _midiParser->setMidiDriver(this); - - // Set the timer rate - _midiParser->setTimerRate(_driver->getBaseTempo()); -} - -MusicPlayer::~MusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - - Common::StackLock lock(_mutex); - - // Unload the parser - unload(); - delete _midiParser; +// MusicPlayer - // Unload the MIDI Driver - _driver->close(); - delete _driver; - - // Unload the timbres - clearTimbres(); +MusicPlayer::MusicPlayer(GroovieEngine *vm) : + _vm(vm), _isPlaying(false), _backgroundFileRef(0), _gameVolume(100), + _prevCDtrack(0) { } void MusicPlayer::playSong(uint32 fileref) { Common::StackLock lock(_mutex); + // Set the volumes _fadingEndVolume = 100; _gameVolume = 100; + // Play the referenced file once play(fileref, false); } @@ -146,6 +94,14 @@ void MusicPlayer::playCD(uint8 track) { AudioCD.play(track - 1, 1, startms * 75 / 1000, 0); } +void MusicPlayer::startBackground() { + debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: startBackground()"); + if (!_isPlaying && _backgroundFileRef) { + debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef); + play(_backgroundFileRef, true); + } +} + void MusicPlayer::setUserVolume(uint16 volume) { Common::StackLock lock(_mutex); @@ -154,10 +110,8 @@ void MusicPlayer::setUserVolume(uint16 volume) { if (_userVolume > 0x100) _userVolume = 0x100; - // Apply it to all the channels - for (int i = 0; i < 0x10; i++) { - updateChanVolume(i); - } + // Apply it + updateVolume(); } void MusicPlayer::setGameVolume(uint16 volume, uint16 time) { @@ -176,17 +130,15 @@ void MusicPlayer::setGameVolume(uint16 volume, uint16 time) { _fadingEndVolume = 100; } -void MusicPlayer::startBackground() { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: startBackground()"); - if (!_isPlaying && _backgroundFileRef) { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef); - play(_backgroundFileRef, true); - } -} - -void MusicPlayer::endTrack() { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: endTrack()"); +bool MusicPlayer::play(uint32 fileref, bool loop) { + // Unload the previous song unload(); + + // Set the new state + _isPlaying = true; + + // Load the new file + return load(fileref, loop); } void MusicPlayer::applyFading() { @@ -212,13 +164,129 @@ void MusicPlayer::applyFading() { } } - // Apply the new volume to all the channels + // Apply it + updateVolume(); +} + +void MusicPlayer::onTimer(void *refCon) { + debugC(9, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: onTimer()"); + MusicPlayer *music = (MusicPlayer *)refCon; + Common::StackLock lock(music->_mutex); + + // Apply the game volume fading + if (music->_gameVolume != music->_fadingEndVolume) { + // Apply the next step of the fading + music->applyFading(); + } + + // Handle internal timed events + music->onTimerInternal(); +} + +void MusicPlayer::unload() { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Stopping the playback"); + + // Set the new state + _isPlaying = false; +} + + +// MusicPlayerMidi + +MusicPlayerMidi::MusicPlayerMidi(GroovieEngine *vm) : + MusicPlayer(vm), _midiParser(NULL), _data(NULL), _driver(NULL) { + // Initialize the channel volumes for (int i = 0; i < 0x10; i++) { - updateChanVolume(i); + _chanVolumes[i] = 0x7F; + } +} + +MusicPlayerMidi::~MusicPlayerMidi() { + // Stop the callback + if (_driver) + _driver->setTimerCallback(NULL, NULL); + + Common::StackLock lock(_mutex); + + // Unload the parser + unload(); + delete _midiParser; + + // Unload the MIDI Driver + if (_driver) + _driver->close(); + delete _driver; +} + +int MusicPlayerMidi::open() { + // Don't ever call open without first setting the output driver! + if (!_driver) + return 255; + + int ret = _driver->open(); + if (ret) + return ret; + + return 0; +} + +void MusicPlayerMidi::close() {} + +void MusicPlayerMidi::send(uint32 b) { + if ((b & 0xFFF0) == 0x07B0) { // Volume change + // Save the specific channel volume + byte chan = b & 0xF; + _chanVolumes[chan] = (b >> 16) & 0x7F; + + // Send the updated value + updateChanVolume(chan); + + return; + } + if (_driver) + _driver->send(b); +} + +void MusicPlayerMidi::metaEvent(byte type, byte *data, uint16 length) { + switch (type) { + case 0x2F: + // End of Track, play the background song + endTrack(); + break; + default: + if (_driver) + _driver->metaEvent(type, data, length); + break; } } -void MusicPlayer::updateChanVolume(byte channel) { +void MusicPlayerMidi::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { + if (_driver) + _driver->setTimerCallback(timer_param, timer_proc); +} + +uint32 MusicPlayerMidi::getBaseTempo(void) { + if (_driver) + return _driver->getBaseTempo(); + else + return 0; +} + +MidiChannel *MusicPlayerMidi::allocateChannel() { + if (_driver) + return _driver->allocateChannel(); + else + return 0; +} + +MidiChannel *MusicPlayerMidi::getPercussionChannel() { + if (_driver) + return _driver->getPercussionChannel(); + else + return 0; +} + +void MusicPlayerMidi::updateChanVolume(byte channel) { // Generate a MIDI Control change message for the volume uint32 b = 0x7B0; @@ -230,76 +298,119 @@ void MusicPlayer::updateChanVolume(byte channel) { val &= 0x7F; // Send it to the driver - _driver->send(b | (val << 16)); + if (_driver) + _driver->send(b | (val << 16)); } -bool MusicPlayer::play(uint32 fileref, bool loop) { - // Unload the previous song +void MusicPlayerMidi::endTrack() { + debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: endTrack()"); unload(); +} - // Set the looping option - _midiParser->property(MidiParser::mpAutoLoop, loop); +void MusicPlayerMidi::onTimerInternal() { + // TODO: We really only need to call this while music is playing. + if (_midiParser) + _midiParser->onTimer(); +} - _isPlaying = true; - // Load the new file - return load(fileref); +void MusicPlayerMidi::updateVolume() { + // Apply it to all the channels + for (int i = 0; i < 0x10; i++) { + updateChanVolume(i); + } } -bool MusicPlayer::load(uint32 fileref) { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); +void MusicPlayerMidi::unload() { + MusicPlayer::unload(); - // Open the song resource - Common::SeekableReadStream *xmidiFile = _vm->_resMan->open(fileref); - if (!xmidiFile) { - error("Groovie::Music: Couldn't find resource 0x%04X", fileref); + // Unload the parser data + if (_midiParser) + _midiParser->unloadMusic(); + + // Unload the data + delete[] _data; + _data = NULL; +} + +bool MusicPlayerMidi::loadParser(Common::SeekableReadStream *stream, bool loop) { + if (!_midiParser) return false; - } // Read the whole file to memory - int length = xmidiFile->size(); + int length = stream->size(); _data = new byte[length]; - xmidiFile->read(_data, length); - delete xmidiFile; + stream->read(_data, length); + delete stream; + + // Set the looping option + _midiParser->property(MidiParser::mpAutoLoop, loop); // Start parsing the data if (!_midiParser->loadMusic(_data, length)) { - error("Groovie::Music: Invalid XMI file"); + error("Groovie::Music: Couldn't parse the data"); return false; } // Activate the timer source - _driver->setTimerCallback(this, &onTimer); + if (_driver) + _driver->setTimerCallback(this, &onTimer); return true; } -void MusicPlayer::unload() { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Stopping the playback"); - _isPlaying = false; - // Unload the parser - _midiParser->unloadMusic(); +// MusicPlayerXMI - // Unload the xmi file - delete[] _data; - _data = NULL; -} +MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) : + MusicPlayerMidi(vm) { + // Create the parser + _midiParser = MidiParser::createParser_XMIDI(); -int MusicPlayer::open() { - // Don't ever call open without first setting the output driver! - if (!_driver) - return 255; + // Create the driver + int driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _driver = createMidi(driver); + this->open(); - int ret = _driver->open(); - if (ret) - return ret; + // Set the parser's driver + _midiParser->setMidiDriver(this); - return 0; + // Set the timer rate + _midiParser->setTimerRate(_driver->getBaseTempo()); + + // Initialize the channel banks + for (int i = 0; i < 0x10; i++) { + _chanBanks[i] = 0; + } + + // Load the Global Timbre Library + if (driver == MD_ADLIB) { + // MIDI through AdLib + _musicType = MD_ADLIB; + loadTimbres(gtlName + ".ad"); + + // Setup the percussion channel + for (unsigned int i = 0; i < _timbres.size(); i++) { + if (_timbres[i].bank == 0x7F) + setTimbreAD(9, _timbres[i]); + } + } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) { + // MT-32 + _musicType = MD_MT32; + loadTimbres(gtlName + ".mt"); + } else { + // GM + _musicType = 0; + } } -void MusicPlayer::close() {} +MusicPlayerXMI::~MusicPlayerXMI() { + //~MusicPlayer(); + + // Unload the timbres + clearTimbres(); +} -void MusicPlayer::send(uint32 b) { +void MusicPlayerXMI::send(uint32 b) { if ((b & 0xFFF0) == 0x72B0) { // XMIDI Patch Bank Select 114 // From AIL2's documentation: XMIDI Patch Bank Select controller (114) // selects a bank to be used when searching the next patches @@ -337,63 +448,24 @@ void MusicPlayer::send(uint32 b) { // If we got here we couldn't find the patch, and the // received message will be sent unchanged. } - } else if ((b & 0xFFF0) == 0x07B0) { // Volume change - // Save the specific channel volume - byte chan = b & 0xF; - _chanVolumes[chan] = (b >> 16) & 0x7F; - - // Send the updated value - updateChanVolume(chan); - - return; - } - _driver->send(b); -} - -void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { - switch (type) { - case 0x2F: - // End of Track, play the background song - endTrack(); - break; - default: - _driver->metaEvent(type, data, length); - break; } + MusicPlayerMidi::send(b); } -void MusicPlayer::onTimer(void *refCon) { - debugC(9, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: onTimer()"); - MusicPlayer *music = (MusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); +bool MusicPlayerXMI::load(uint32 fileref, bool loop) { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); - // Apply the game volume fading - if (music->_gameVolume != music->_fadingEndVolume) { - // Apply the next step of the fading - music->applyFading(); + // Open the song resource + Common::SeekableReadStream *file = _vm->_resMan->open(fileref); + if (!file) { + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); + return false; } - // TODO: We really only need to call this while music is playing. - music->_midiParser->onTimer(); -} - -void MusicPlayer::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { - _driver->setTimerCallback(timer_param, timer_proc); -} - -uint32 MusicPlayer::getBaseTempo(void) { - return _driver->getBaseTempo(); -} - -MidiChannel *MusicPlayer::allocateChannel() { - return _driver->allocateChannel(); -} - -MidiChannel *MusicPlayer::getPercussionChannel() { - return _driver->getPercussionChannel(); + return loadParser(file, loop); } -void MusicPlayer::loadTimbres(const Common::String &filename) { +void MusicPlayerXMI::loadTimbres(const Common::String &filename) { // Load the Global Timbre Library format as documented in AIL2 debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Loading the GTL file %s", filename.c_str()); @@ -451,7 +523,7 @@ void MusicPlayer::loadTimbres(const Common::String &filename) { delete gtl; } -void MusicPlayer::clearTimbres() { +void MusicPlayerXMI::clearTimbres() { // Delete the allocated data int num = _timbres.size(); for (int i = 0; i < num; i++) { @@ -462,7 +534,7 @@ void MusicPlayer::clearTimbres() { _timbres.clear(); } -void MusicPlayer::setTimbreAD(byte channel, const Timbre &timbre) { +void MusicPlayerXMI::setTimbreAD(byte channel, const Timbre &timbre) { // Verify the timbre size if (timbre.size != 12) { error("Groovie::Music: Invalid size for an AdLib timbre: %d", timbre.size); @@ -514,7 +586,7 @@ void MusicPlayer::setTimbreAD(byte channel, const Timbre &timbre) { } } -void MusicPlayer::setTimbreMT(byte channel, const Timbre &timbre) { +void MusicPlayerXMI::setTimbreMT(byte channel, const Timbre &timbre) { // Verify the timbre size if (timbre.size != 0xF6) { error("Groovie::Music: Invalid size for an MT-32 timbre: %d", timbre.size); @@ -528,4 +600,28 @@ void MusicPlayer::setTimbreMT(byte channel, const Timbre &timbre) { warning("Groovie::Music: Setting MT32 custom instruments isn't supported yet"); } + +// MusicPlayerMac + +MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : + MusicPlayerMidi(vm) { +} + +bool MusicPlayerMac::load(uint32 fileref, bool loop) { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); + debug("Groovie::Music: Starting the playback of song: %04X %d", fileref, fileref); + + // Open the song resource + /* + Common::SeekableReadStream *file = _vm->_resMan->open(fileref); + if (!file) { + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); + return false; + } + */ + + //return loadParser(file, loop); + return false; +} + } // End of Groovie namespace diff --git a/engines/groovie/music.h b/engines/groovie/music.h index 92c7afde70..db50930c37 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -34,10 +34,11 @@ namespace Groovie { -class MusicPlayer : public MidiDriver { +class MusicPlayer { public: - MusicPlayer(GroovieEngine *vm, const Common::String >lName); - ~MusicPlayer(); + MusicPlayer(GroovieEngine *vm); + virtual ~MusicPlayer() {} + void playSong(uint32 fileref); void setBackgroundSong(uint32 fileref); void playCD(uint8 track); @@ -48,25 +49,89 @@ public: void setGameVolume(uint16 volume, uint16 time); private: - // User volume - uint16 _userVolume; + // Song playback + bool play(uint32 fileref, bool loop); + bool _isPlaying; + uint32 _backgroundFileRef; + uint8 _prevCDtrack; - // Game volume - uint16 _gameVolume; + // Volume fading uint32 _fadingStartTime; uint16 _fadingStartVolume; uint16 _fadingEndVolume; uint16 _fadingDuration; - void endTrack(); void applyFading(); - // Song volumes +protected: + GroovieEngine *_vm; + + // Callback + static void onTimer(void *data); + virtual void onTimerInternal() {} + Common::Mutex _mutex; + + // User volume + uint16 _userVolume; + // Game volume + uint16 _gameVolume; + + // These are specific for each type of music + virtual void updateVolume() = 0; + virtual bool load(uint32 fileref, bool loop) = 0; + virtual void unload(); +}; + +class MusicPlayerMidi : public MusicPlayer, public MidiDriver { +public: + MusicPlayerMidi(GroovieEngine *vm); + ~MusicPlayerMidi(); + + // MidiDriver interface + int open(); + void close(); + void send(uint32 b); + void metaEvent(byte type, byte *data, uint16 length); + void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc); + uint32 getBaseTempo(void); + MidiChannel *allocateChannel(); + MidiChannel *getPercussionChannel(); + +private: + // Channel volumes byte _chanVolumes[0x10]; void updateChanVolume(byte channel); + void endTrack(); + +protected: + byte *_data; + MidiParser *_midiParser; + MidiDriver *_driver; + + void onTimerInternal(); + void updateVolume(); + void unload(); + + bool loadParser(Common::SeekableReadStream *stream, bool loop); +}; + +class MusicPlayerXMI : public MusicPlayerMidi { +public: + MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName); + ~MusicPlayerXMI(); + + void send(uint32 b); + +protected: + bool load(uint32 fileref, bool loop); + +private: // Channel banks byte _chanBanks[0x10]; + // Output music type + uint8 _musicType; + // Timbres class Timbre { public: @@ -81,35 +146,14 @@ private: void clearTimbres(); void setTimbreAD(byte channel, const Timbre &timbre); void setTimbreMT(byte channel, const Timbre &timbre); +}; +class MusicPlayerMac : public MusicPlayerMidi { public: - // MidiDriver interface - int open(); - void close(); - void send(uint32 b); - void metaEvent(byte type, byte *data, uint16 length); - void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc); - uint32 getBaseTempo(void); - MidiChannel *allocateChannel(); - MidiChannel *getPercussionChannel(); + MusicPlayerMac(GroovieEngine *vm); -private: - GroovieEngine *_vm; - Common::Mutex _mutex; - byte *_data; - MidiParser *_midiParser; - MidiDriver *_driver; - uint8 _musicType; - bool _isPlaying; - - uint32 _backgroundFileRef; - uint8 _prevCDtrack; - - static void onTimer(void *data); - - bool play(uint32 fileref, bool loop); - bool load(uint32 fileref); - void unload(); +protected: + bool load(uint32 fileref, bool loop); }; } // End of Groovie namespace diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 3491c54b36..63d15419d2 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -263,26 +263,12 @@ const KYRAGameDescription adGameDescs[] = { KYRA1_TOWNS_SJIS_FLAGS }, - { // PC-9821 (CD) version - { - "kyra1", - "CD", - { - { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 }, - { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC98, - ADGF_CD, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_FLAGS - }, + // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files, + // thus we will mark it as non CD game. { { "kyra1", - "CD", + "", { { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, @@ -290,7 +276,7 @@ const KYRAGameDescription adGameDescs[] = { }, Common::JA_JPN, Common::kPlatformPC98, - ADGF_CD, + ADGF_NO_FLAGS, Common::GUIO_NOSPEECH }, KYRA1_TOWNS_SJIS_FLAGS diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 020e1ea3ea..7c4b073f29 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -2880,7 +2880,7 @@ void LoLEngine::drinkBezelCup(int numUses, int charNum) { uint16 step = 0; do { - step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 2]); + step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 1]); increaseCharacterHitpoints(charNum, step / 256, true); gui_drawCharPortraitWithStats(charNum); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index fa54bffa98..963dc3f4d6 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -1529,6 +1529,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int _dsTmpWidth = shapeWidth; int cnt = _dsOffscreenLeft; int scaleState = (this->*_dsProcessMargin)(d, src, cnt); + if (_dsTmpWidth) { cnt += shpWidthScaled1; if (cnt > 0) { @@ -1584,7 +1585,6 @@ int Screen::drawShapeMarginScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt) while (cnt > 0) { --cnt; - if (*src++) continue; @@ -1611,7 +1611,6 @@ int Screen::drawShapeMarginScaleDownwind(uint8 *&dst, const uint8 *&src, int &cn while (cnt > 0) { --cnt; - if (*src++) continue; @@ -1640,10 +1639,11 @@ int Screen::drawShapeSkipScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt) { return 0; do { + --cnt; if (*src++) continue; cnt = cnt + 1 - (*src++); - } while (--cnt > 0); + } while (cnt > 0); return 0; } @@ -1656,16 +1656,17 @@ int Screen::drawShapeSkipScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt) return 0; do { + --cnt; if (*src++) continue; found = true; cnt = cnt + 1 - (*src++); - } while (--cnt > 0); + } while (cnt > 0); return found ? 0 : _dsOffscreenScaleVal1; } -void Screen::drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16) { +void Screen::drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16) { do { uint8 c = *src++; if (c) { @@ -1680,7 +1681,7 @@ void Screen::drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, i } while (cnt > 0); } -void Screen::drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16) { +void Screen::drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16) { do { uint8 c = *src++; if (c) { @@ -1695,7 +1696,7 @@ void Screen::drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, } while (cnt > 0); } -void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState) { +void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState) { int c = 0; do { @@ -1723,7 +1724,7 @@ void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int cnt = -1; } -void Screen::drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState) { +void Screen::drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState) { int c = 0; do { diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 390d058bb8..956bd7107e 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -421,10 +421,10 @@ protected: int drawShapeMarginScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt); int drawShapeSkipScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt); int drawShapeSkipScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt); - void drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); - void drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); - void drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); - void drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); + void drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); + void drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); + void drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); + void drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); void drawShapePlotType0(uint8 *dst, uint8 cmd); void drawShapePlotType1(uint8 *dst, uint8 cmd); @@ -446,7 +446,7 @@ protected: void drawShapePlotType52(uint8 *dst, uint8 cmd); typedef int (Screen::*DsMarginSkipFunc)(uint8 *&dst, const uint8 *&src, int &cnt); - typedef void (Screen::*DsLineFunc)(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); + typedef void (Screen::*DsLineFunc)(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); typedef void (Screen::*DsPlotFunc)(uint8 *dst, uint8 cmd); DsMarginSkipFunc _dsProcessMargin; diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index b9bf9961c5..46b243a4cf 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -44,8 +44,6 @@ Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system), _fadeFlag = 2; _curDimIndex = 0; - - _internDimX = _internDimY = _internDimW = _internDimH = _internDimDstX = _internBlockWidth = _internDimDstY = _internBlockHeight = _internDimU5 = _internDimU6 = _internBlockWidth2 = _internDimU8 = 0; } Screen_LoL::~Screen_LoL() { @@ -588,44 +586,25 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in va_end(args); } - // _internDimH: h0 -// _internDimW: w0 -// _internDimDstX: x1 -// _internDimDstY: y1 -// _internBlockWidth: w1 -// _internBlockHeight: h1 -// _internDimU5: x2 -// _internDimU6: y2 -// _internBlockWidth2: w2 - - _internDimX = _internDimY = 0; - _internDimW = w1; - _internDimH = h1; - calcBoundariesIntern(x1, y1, w3, h3); - if (_internBlockWidth == -1) + int na = 0, nb = 0, nc = w3; + if (!calcBounds(w1, h1, x1, y1, w3, h3, na, nb, nc)) return; - int iu5_1 = _internDimU5; - int iu6_1 = _internDimU6; - int ibw_1 = _internBlockWidth; - int ibh_1 = _internBlockHeight; - int dx_1 = _internDimDstX; - int dy_1 = _internDimDstY; - - _internDimX = _internDimY = 0; - _internDimW = w2; - _internDimH = h2; + int iu5_1 = na; + int iu6_1 = nb; + int ibw_1 = w3; + int dx_1 = x1; + int dy_1 = y1; - calcBoundariesIntern(x2, y2, ibw_1, ibh_1); - if (_internBlockWidth == -1) + if (!calcBounds(w2, h2, x2, y2, w3, h3, na, nb, nc)) return; - int iu5_2 = _internDimU5; - int iu6_2 = _internDimU6; - int ibw_2 = _internBlockWidth; - int ibh_2 = _internBlockHeight; - int dx_2 = _internDimDstX; - int dy_2 = _internDimDstY; + int iu5_2 = na; + int iu6_2 = nb; + int ibw_2 = w3; + int ibh_2 = h3; + int dx_2 = x2; + int dy_2 = y2; uint8 *src = getPagePtr(page1) + (dy_1 + iu6_2) * w1; uint8 *dst = getPagePtr(page2) + (dy_2 + iu6_1) * w2; @@ -670,7 +649,7 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in } if (!page2) - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + addDirtyRect(x2, y2, w2, h2); } void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) { @@ -678,23 +657,23 @@ void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, return; const ScreenDim *cdim = getScreenDim(dim); - _internDimX = cdim->sx << 3; - _internDimY = cdim->sy; - _internDimW = cdim->w << 3; - _internDimH = cdim->h; + int ix = cdim->sx << 3; + int iy = cdim->sy; + int iw = cdim->w << 3; + int ih = cdim->h; - calcBoundariesIntern(x2, y2, w, h); - if (_internBlockWidth == -1) + int na = 0, nb = 0, nc = w; + if (!calcBounds(iw, ih, x2, y2, w, h, na, nb, nc)) return; uint8 *src = getPagePtr(page1) + y1 * 320 + x1; - uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320; + uint8 *dst = getPagePtr(page2) + (y2 + iy) * 320; - for (int i = 0; i < _internBlockHeight; i++) { - uint8 *s = src + _internDimU5; - uint8 *d = dst + (_internDimDstX + _internDimX); + for (int i = 0; i < h; i++) { + uint8 *s = src + na; + uint8 *d = dst + (x2 + ix); - for (int ii = 0; ii < _internBlockWidth; ii++) { + for (int ii = 0; ii < w; ii++) { uint8 p = ovl[*s++]; if (p) *d = p; @@ -706,7 +685,7 @@ void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, } if (!page2) - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + addDirtyRect(x2 + ix, y2 + iy, w, h); } void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl) { @@ -714,26 +693,26 @@ void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x return; const ScreenDim *cdim = getScreenDim(dim); - _internDimX = cdim->sx << 3; - _internDimY = cdim->sy; - _internDimW = cdim->w << 3; - _internDimH = cdim->h; + int ix = cdim->sx << 3; + int iy = cdim->sy; + int iw = cdim->w << 3; + int ih = cdim->h; - calcBoundariesIntern(x2, y2, w, h); - if (_internBlockWidth == -1) + int na = 0, nb = 0, nc = w; + if (!calcBounds(iw, ih, x2, y2, w, h, na, nb, nc)) return; uint8 *src = getPagePtr(page1) + y1 * 320 + x1; - uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320; + uint8 *dst = getPagePtr(page2) + (y2 + iy) * 320; - for (int i = 0; i < _internBlockHeight; i++) { - uint8 *s = src + _internDimU5; - uint8 *d = dst + (_internDimDstX + _internDimX); + for (int i = 0; i < h; i++) { + uint8 *s = src + na; + uint8 *d = dst + (x2 + ix); if (flag) d += (i >> 1); - for (int ii = 0; ii < _internBlockWidth; ii++) { + for (int ii = 0; ii < w; ii++) { if (*s++) *d = ovl[*d]; d++; @@ -744,7 +723,7 @@ void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x } if (!page2) - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + addDirtyRect(x2 + ix, y2 + iy, w, h); } void Screen_LoL::copyBlockAndApplyOverlayOutro(int srcPage, int dstPage, const uint8 *ovl) { @@ -778,59 +757,6 @@ void Screen_LoL::copyBlockAndApplyOverlayOutro(int srcPage, int dstPage, const u } } -void Screen_LoL::calcBoundariesIntern(int dstX, int dstY, int width, int height) { - _internBlockWidth = _internBlockWidth2 = width; - _internBlockHeight = height; - _internDimDstX = dstX; - _internDimDstY = dstY; - - _internDimU5 = _internDimU6 = _internDimU8 = 0; - - int t = _internDimDstX + _internBlockWidth; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internDimDstX) { - _internDimU5 = _internBlockWidth - t; - _internBlockWidth = t; - _internDimDstX = 0; - } - - t = _internDimW - _internDimDstX; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internBlockWidth) - _internBlockWidth = t; - - _internBlockWidth2 -= _internBlockWidth; - - t = _internDimDstY + _internBlockHeight; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internDimDstY) { - _internDimU6 = _internBlockHeight - t; - _internBlockHeight = t; - _internDimDstY = 0; - } - - t = _internDimH - _internDimDstY; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internBlockHeight) - _internBlockHeight = t; -} - void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) { Screen::fadeToBlack(delay, upFunc); _fadeFlag = 2; diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 2545064b58..f9cd7133de 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -112,22 +112,6 @@ private: static const uint8 _paletteConvTable[256]; void mergeOverlay(int x, int y, int w, int h); void postProcessCursor(uint8 *data, int width, int height, int pitch); - - // magic atlas - void calcBoundariesIntern(int dstX, int dstY, int c, int d); - - int _internDimX; - int _internDimY; - int _internDimW; - int _internDimH; - int _internDimDstX; - int _internBlockWidth; - int _internDimDstY; - int _internBlockHeight; - int _internDimU5; - int _internDimU6; - int _internBlockWidth2; - int _internDimU8; }; } // end of namespace Kyra diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index bf919c3a25..d978915741 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -67,6 +67,7 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { // Kernel // DCmd_Register("classes", WRAP_METHOD(Console, cmdClasses)); // TODO DCmd_Register("opcodes", WRAP_METHOD(Console, cmdOpcodes)); + DCmd_Register("selector", WRAP_METHOD(Console, cmdSelector)); DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors)); DCmd_Register("functions", WRAP_METHOD(Console, cmdKernelFunctions)); DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable)); @@ -239,6 +240,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("Kernel:\n"); DebugPrintf(" opcodes - Lists the opcode names\n"); DebugPrintf(" selectors - Lists the selector names\n"); + DebugPrintf(" selector - Attempts to find the requested selector by name\n"); DebugPrintf(" functions - Lists the kernel functions\n"); DebugPrintf(" class_table - Shows the available classes\n"); DebugPrintf("\n"); @@ -392,6 +394,25 @@ bool Console::cmdOpcodes(int argc, const char **argv) { return true; } +bool Console::cmdSelector(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Attempts to find the requested selector by name.\n"); + DebugPrintf("Usage: %s <selector name>\n", argv[0]); + return true; + } + + for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getSelectorNamesSize(); seeker++) { + if (!scumm_stricmp(_vm->_gamestate->_kernel->getSelectorName(seeker).c_str(), argv[1])) { + DebugPrintf("Selector %s found at %03x\n", _vm->_gamestate->_kernel->getSelectorName(seeker).c_str(), seeker); + return true; + } + } + + DebugPrintf("Selector %s wasn't found\n", argv[1]); + + return true; +} + bool Console::cmdSelectors(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getSelectorNamesSize(); seeker++) { @@ -546,11 +567,6 @@ bool Console::cmdHexDump(int argc, const char **argv) { } int resNum = atoi(argv[2]); - if (resNum == 0) { - DebugPrintf("The resource number specified is not a number"); - return true; - } - ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) @@ -607,11 +623,6 @@ bool Console::cmdResourceSize(int argc, const char **argv) { } int resNum = atoi(argv[2]); - if (resNum == 0) { - DebugPrintf("The resource number specified is not a number"); - return true; - } - ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) diff --git a/engines/sci/console.h b/engines/sci/console.h index 84a8d2f942..bc07ddb530 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -52,6 +52,7 @@ private: // Kernel // bool cmdClasses(int argc, const char **argv); // TODO bool cmdOpcodes(int argc, const char **argv); + bool cmdSelector(int argc, const char **argv); bool cmdSelectors(int argc, const char **argv); bool cmdKernelFunctions(int argc, const char **argv); bool cmdClassTable(int argc, const char **argv); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index f04c390944..79088c86ff 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -34,10 +34,6 @@ namespace Sci { #define GF_FOR_SCI0_BEFORE_395 (GF_SCI0_OLD | GF_SCI0_OLDGETTIME) #define GF_FOR_SCI0_BEFORE_629 GF_SCI0_OLDGETTIME -// SCI1 -#define GF_FOR_SCI1_200_OR_LATER GF_SCI1_LOFSABSOLUTE -#define GF_FOR_SCI1_510_OR_LATER (GF_SCI1_LOFSABSOLUTE | GF_SCI1_NEWDOSOUND) - // Titles of the games static const PlainGameDescriptor SciGameTitles[] = { {"sci", "Sierra SCI Game"}, @@ -147,7 +143,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "d226d7d3b4f77c4a566913fc310487fc", 792380}, {"resource.003", 0, "d226d7d3b4f77c4a566913fc310487fc", 464348}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -162,7 +158,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 826309}, {"resource.003", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 493638}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -188,7 +184,19 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d2f5a1be74ed963fa849a76892be5290", 794832}, {"resource.002", 0, "c0c29c51af66d65cb53f49e785a2d978", 1280907}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1 + }, + + // Castle of Dr. Brain - English DOS Floppy 1.1 + {{"castlebrain", "", { + {"resource.map", 0, "f77728304c70017c54793eb6ca648174", 2745}, + {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 347071}, + {"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776}, + {"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -200,7 +208,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 1197694}, {"resource.001", 0, "735be4e58957180cfc807d5e18fdffcd", 1433302}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -382,7 +390,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "1c3804e56b114028c5873a35c2f06d13", 653002}, {"resource.006", 0, "f9487732289a4f4966b4e34eea413325", 842817}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -399,7 +407,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1154950}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1042966}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -416,7 +424,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1261462}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284720}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -432,7 +440,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1260237}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284609}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -449,7 +457,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243}, {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + GF_SCI1_EGA, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -477,7 +485,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1176914}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1123585}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -514,7 +522,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "28fe9b4f0567e71feb198bc9f3a2c605", 1241816}, {"resource.003", 0, "f3146df0ad4297f5ce35aa8c4753bf6c", 586832}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -528,7 +536,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "323b3b12f43d53f27d259beb225f0aa7", 1129316}, {"resource.003", 0, "83ac03e4bddb2c1ac2d36d2a587d0536", 1145616}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -542,7 +550,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "02d7d0411f7903aacb3bc8b0f8ca8a9a", 1202581}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1175835}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -557,7 +565,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "2d21a1d2dcbffa551552e3e0725d2284", 1186033}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1174993}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -874,7 +882,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "595b6039ea1356e7f96a52c58eedcf22", 355791}, {"resource.001", 0, "143df8aef214a2db34c2d48190742012", 632273}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -887,7 +895,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "0d06cacc87dc21a08cd017e73036f905", 735}, {"resource.001", 0, "24db2bccda0a3c43ac4a7b5edb116c7e", 797678}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -900,7 +908,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 541845}, {"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 845795}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1111,7 +1119,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368}, {"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1482,7 +1490,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "5790ac0505f7ca98d4567132b875eb1e", 681041}, {"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1495,7 +1503,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "ec20246209d7b19f38989261e5c8f5b8", 1111226}, {"resource.002", 0, "85d6935ef77e6b0e16bc307640a0d913", 1088312}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1508,7 +1516,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d34cadb11e1aefbb497cf91bc1d3baa7", 1114688}, {"resource.002", 0, "85b030bb66d5342b0a068f1208c431a8", 1078443}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1535,7 +1543,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "3fe2a3aec0ed53c7d6db1845a67e3aa2", 1095908}, {"resource.003", 0, "ac175df0ea9a2cba57f0248651856d27", 376556}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1549,7 +1557,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "bc8ca10c807515d959cbd91f9ba47735", 1123759}, {"resource.002", 0, "b7409ab32bc3bee2d6cce887cd33f2b6", 1092160}, {NULL, 0, NULL, 0}}, Common::RU_RUS, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1716,7 +1724,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "f8b2d1137bb767e5d232056b99dd69eb", 623621}, {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 715598}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1735,7 +1743,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 754966}, {"resource.007", 0, "59eba83ad465b08d763b44f86afa86f6", 683135}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1764,7 +1772,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1024810}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 1030656}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1782,7 +1790,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1021774}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 993408}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1801,7 +1809,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 946540}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 958842}, {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1820,7 +1828,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1015136}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 987222}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1831,7 +1839,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a99776df795127f387cb35dae872d4e4", 5919}, {"resource.000", 0, "a8989a5a89e7d4f702b26b378c7a357a", 7001981}, {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2157,7 +2165,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5b457cbe5042f557e5b610148171f6c0", 1158}, {"resource.001", 0, "453ea81ef66a50cbe33ce06302afe47f", 229737}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2328,7 +2336,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "630bfa65beb05f743552704ac2899dae", 759891}, {"resource.004", 0, "7b229fbdf30d670d0728cede3e984a7e", 838663}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2345,7 +2353,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6258d5dd85898d8e218eb8113ebc9059", 722738}, {"resource.005", 0, "6258d5dd85898d8e218eb8113ebc9059", 704485}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2361,7 +2369,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "8791b9eef53edf77c2dac950142221d3", 1159791}, {"resource.004", 0, "1b91e891a3c60a941dac0eecdf83375b", 1143606}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2374,7 +2382,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "277f97771f7a6d89677141f02da313d6", 65150}, {"resource.001", 0, "5c5a551b6c86cce2ee75becb90e0b586", 624411}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2390,7 +2398,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "4836f460f4cfc8de61e2df4c45775504", 1180956}, {"resource.004", 0, "0c3eb84b9755852d9e795e0d5c9373c7", 1171760}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2567,7 +2575,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "ecace1a2771846b1a8aa1afdd44111a0", 6570147}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, - SCI_VERSION_AUTODETECT, + SCI_VERSION_1, SCI_VERSION_1_1 }, @@ -2578,7 +2586,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "ec6f5cf369054dd3e5392995e9975b9e", 768218}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, 0, - SCI_VERSION_AUTODETECT, + SCI_VERSION_1, SCI_VERSION_1_1 }, @@ -2854,7 +2862,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b25a1539c71701f7715f738c5037e9a6", 775515}, {"resource.005", 0, "640ffe1a9acde392cc33cc1b1a528328", 806324}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2870,7 +2878,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "c47600e50c6fc591957ae0c5020ee7b8", 1213262}, {"resource.004", 0, "e19ea4ad131472f9238590f2e1d40289", 1203051}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2898,7 +2906,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9b78228ad4f9f335fedf74f1812dcfca", 513325}, {"resource.005", 0, "7d4ebcb745c0bf8fc42e4013f52ecd49", 1101812}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2928,7 +2936,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 545053}, {"resource.005", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 687507}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_0, SCI_VERSION_0 }, @@ -3013,7 +3021,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "3540d1cc84d674cf4b2c898b88a3b563", 790296}, {"resource.006", 0, "ade814bc4d56244c156d9e9bcfebbc11", 664085}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3030,7 +3038,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "10ee1709e6559c724676d058199b75b5", 818745}, {"resource.006", 0, "67fb188b191d88efe8414af6ea297b93", 672675}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3042,7 +3050,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a18088c8aceb06025dbc945f29e02935", 5124}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 5502009}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3054,7 +3062,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "71ccf4f82ac4efb588731acfb7bf2603", 5646}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 933928}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3071,7 +3079,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "ff9c87da3bc53473fdee8b9d3edbc93c", 1200631}, {"resource.005", 0, "e33019ac19f755ae33fbf49b4fc9066c", 1053294}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3088,7 +3096,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "47ee647b5b12232d27e63cc627c25899", 1156765}, {"resource.006", 0, "dfb023e4e2a1e7a00fa18f9ede72a91b", 924059}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3104,7 +3112,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "4277c61bed40a50dadc4b5a344520af2", 1251000}, {"resource.005", 0, "5f885abd335978e2fd4e5f886d7676c8", 1102880}, {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3117,7 +3125,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + GF_SCI1_EGA, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3130,7 +3138,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + GF_SCI1_EGA, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3158,7 +3166,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "776fba81c110d1908776232cbe190e20", 1253752}, {"resource.005", 0, "55fae26c2a92f16ef72c1e216e827c0f", 1098328}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3173,7 +3181,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "74c62fa2146ff3b3b2ea2b3fb95b9af9", 1140801}, {"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1088408}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3190,7 +3198,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368}, {"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3413,7 +3421,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { FANMADE("The Legend of the Lost Jewel", "ba1bca315e3818c5626eda51bcfbcccf", 636, "9b0736d69924af0cff32a0f78db96855", 300398), // FIXME: The vga demo does not have a resource.000/001 file. - //FANMADE_V("SCI VGA Demo", "00b1abd87bad356b90fcdfcb6132c26f", 8, "", 0, GF_FOR_SCI1_510_OR_LATER), + //FANMADE_V("SCI VGA Demo", "00b1abd87bad356b90fcdfcb6132c26f", 8, "", 0, 0), {AD_TABLE_END_MARKER, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0} }; diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index a1e2c24955..a1e7569967 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -377,7 +377,7 @@ int script_init_engine(EngineState *s) { s->bp_list = NULL; // No breakpoints defined s->have_bp = 0; - if ((s->_flags & GF_SCI1_LOFSABSOLUTE) && s->_version < SCI_VERSION_1_1) + if (s->_kernel->hasLofsAbsolute()) s->seg_manager->setExportWidth(1); else s->seg_manager->setExportWidth(0); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index b03a073d8f..8ac629d87b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -356,35 +356,54 @@ static const char *argtype_description[] = { Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) { memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t - loadKernelNames(); - + loadSelectorNames(isOldSci0); + mapSelectors(); // Map a few special selectors for later use loadOpcodes(); + loadKernelNames(); + mapFunctions(); // Map the kernel functions - if (!loadSelectorNames(isOldSci0)) { - error("Kernel: Could not retrieve selector names"); - } - - // Map the kernel functions - mapFunctions(); + // SCI0 games using old graphics functions (before version 0.000.502) did not have a + // motionCue selector + _oldGfxFunctions = (_selectorMap.motionCue == -1 && _resmgr->_sciVersion == SCI_VERSION_0); - // Map a few special selectors for later use - mapSelectors(); + // SCI1 games which use absolute lofs have the egoMoveSpeed selector + _hasLofsAbsolute = (_selectorMap.egoMoveSpeed != -1 && _resmgr->_sciVersion < SCI_VERSION_1_1); - // SCI0 games using old graphics functions (before version 0.000.502) have the TimesSin - // kernel function, whereas newer games have the SinMult kernel function in its place - _oldGfxFunctions = !hasKernelFunction("SinMult"); + printAutoDetectedFeatures(); } Kernel::~Kernel() { } -bool Kernel::loadSelectorNames(bool isOldSci0) { +void Kernel::printAutoDetectedFeatures() { + if (_oldGfxFunctions) + printf("Kernel auto-detection: game found to be using old graphics functions\n"); + else + printf("Kernel auto-detection: game found to be using newer graphics functions\n"); + + if (_hasLofsAbsolute) + printf("Kernel auto-detection: game found to be using absolute parameters for lofs\n"); + else + printf("Kernel auto-detection: game found to be using relative parameters for lofs\n"); + + if (_selectorMap.setVol != -1) + printf("Kernel auto-detection: using SCI1 sound functions\n"); + else if (_selectorMap.nodePtr != -1) + printf("Kernel auto-detection: using SCI01 sound functions\n"); + else + printf("Kernel auto-detection: using SCI0 sound functions\n"); + + if (_resmgr->_sciVersion == SCI_VERSION_0 && _selectorMap.sightAngle != -1) + printf("Kernel auto-detection: found SCI0 game using a SCI1 kernel table\n"); +} + +void Kernel::loadSelectorNames(bool isOldSci0) { int count; Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); if (!r) // No such resource? - return false; + error("Kernel: Could not retrieve selector names"); count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off @@ -394,14 +413,13 @@ bool Kernel::loadSelectorNames(bool isOldSci0) { Common::String tmp((const char *)r->data + offset + 2, len); _selectorNames.push_back(tmp); + //printf("%s\n", tmp.c_str()); // debug // Early SCI versions used the LSB in the selector ID as a read/write // toggle. To compensate for that, we add every selector name twice. if (isOldSci0) _selectorNames.push_back(tmp); } - - return true; } bool Kernel::loadOpcodes() { @@ -732,46 +750,39 @@ reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t)); } -void setDefaultKernelNames(Common::StringList &names) { - names.resize(SCI_KNAMES_DEFAULT_ENTRIES_NR); - for (int i = 0; i < SCI_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci_default_knames[i]; -} - -static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) { - int count, i, index = 2, empty_to_add = 1; - Resource *r = resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES), 0); - - if (!r) { // No kernel name table found? Fall back to default table - setDefaultKernelNames(names); - return; - } - - count = READ_LE_UINT16(r->data); - - if (count > 1023) { - // Newer kernel name table, found in KQ1. We can use the default table here - setDefaultKernelNames(names); - return; - } - - if (count < SCI0_KNAMES_WELL_DEFINED) { - empty_to_add = SCI0_KNAMES_WELL_DEFINED - count; - sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add); - } +void Kernel::setDefaultKernelNames() { + bool isSci0 = (_resmgr->_sciVersion == SCI_VERSION_0); + int offset = 0; + + // Check if we have a SCI01 game which uses a SCI1 kernel table (e.g. the KQ1 demo + // and full version). We do this by checking if the sightAngle selector exists, as no + // SCI0 game seems to have it + if (_selectorMap.sightAngle != -1 && isSci0) + isSci0 = false; + + _kernelNames.resize(SCI_KNAMES_DEFAULT_ENTRIES_NR + (isSci0 ? 4 : 0)); + for (int i = 0; i < SCI_KNAMES_DEFAULT_ENTRIES_NR; i++) { + // In SCI0, Platform was DoAvoider + if (!strcmp(sci_default_knames[i], "Platform") && isSci0) { + _kernelNames[i + offset] = "DoAvoider"; + continue; + } - names.resize(count + 1 + empty_to_add); + _kernelNames[i + offset] = sci_default_knames[i]; - for (i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + index); - int len = READ_LE_UINT16(r->data + offset); - //fprintf(stderr,"Getting name %d of %d...\n", i, count); - index += 2; - names[i] = Common::String((const char *)r->data + offset + 2, len); + // SCI0 has 4 extra functions between SetCursor (0x28) and Savegame + if (!strcmp(sci_default_knames[i], "SetCursor") && isSci0) { + _kernelNames[i + 1] = "FOpen"; + _kernelNames[i + 2] = "FPuts"; + _kernelNames[i + 3] = "FGets"; + _kernelNames[i + 4] = "FClose"; + offset = 4; + } } - for (i = 0; i < empty_to_add; i++) { - names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING; + if (_resmgr->_sciVersion == SCI_VERSION_1_1) { + // KQ6CD calls unimplemented function 0x26 + _kernelNames[0x26] = "Dummy"; } } @@ -810,16 +821,9 @@ bool Kernel::loadKernelNames() { case SCI_VERSION_01: case SCI_VERSION_01_VGA: case SCI_VERSION_01_VGA_ODD: - vocab_get_knames0(_resmgr, _kernelNames); - break; - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: + case SCI_VERSION_1: case SCI_VERSION_1_1: - setDefaultKernelNames(_kernelNames); - if (_resmgr->_sciVersion == SCI_VERSION_1_1) { - // KQ6CD calls unimplemented function 0x26 - _kernelNames[0x26] = "Dummy"; - } + setDefaultKernelNames(); break; #ifdef ENABLE_SCI32 case SCI_VERSION_32: diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index e3ecddca26..da3d255329 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -83,14 +83,22 @@ public: */ bool hasKernelFunction(const char *functionName) const; - /* Applies to all versions before 0.000.502 - ** Old SCI versions used to interpret the third DrawPic() parameter inversely, - ** with the opposite default value (obviously). - ** Also, they used 15 priority zones from 42 to 200 instead of 14 priority - ** zones from 42 to 190. - */ + /** + * Applies to all versions before 0.000.502 + * Old SCI versions used to interpret the third DrawPic() parameter inversely, + * with the opposite default value (obviously). + * Also, they used 15 priority zones from 42 to 200 instead of 14 priority + * zones from 42 to 190. + */ bool usesOldGfxFunctions() const { return _oldGfxFunctions; } + /** + * Applies to all SCI1 versions after 1.000.200 + * In late SCI1 versions, the argument of lofs[as] instructions + * is absolute rather than relative. + */ + bool hasLofsAbsolute() const { return _hasLofsAbsolute; } + // Script dissection/dumping functions void dissectScript(int scriptNumber, Vocabulary *vocab); void dumpScriptObject(char *data, int seeker, int objsize); @@ -112,10 +120,19 @@ private: bool loadKernelNames(); /** - * Loads the kernel selector names. - * @return True upon success, false otherwise. - */ - bool loadSelectorNames(bool isOldSci0); + * Sets the default kernel function names, based on the SCI version used + */ + void setDefaultKernelNames(); + + /** + * Loads the kernel selector names. + */ + void loadSelectorNames(bool isOldSci0); + + /** + * Prints auto-detected features from selectors + */ + void printAutoDetectedFeatures(); /** * Maps special selectors @@ -135,6 +152,7 @@ private: ResourceManager *_resmgr; bool _oldGfxFunctions; + bool _hasLofsAbsolute; // Kernel-related lists /** diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 6e737597d6..9d19f3f0c9 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -304,7 +304,9 @@ static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argc) { case 1 : - if (s->_version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1) { + GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16())); + } else if (s->_version == SCI_VERSION_1) { if (argv[0].toSint16() <= 1) { // Newer (SCI1.1) semantics: show/hide cursor CursorMan.showMouse(argv[0].toSint16() != 0); @@ -312,13 +314,16 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { // Pre-SCI1.1: set cursor according to the first parameter GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16())); } - } else { + } else if (s->_version >= SCI_VERSION_1_1) { // SCI1.1: Show/hide cursor CursorMan.showMouse(argv[0].toSint16() != 0); } break; case 2 : - if (s->_version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1) { + GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, + argv[1].toSint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16())); + } else if (s->_version == SCI_VERSION_1) { // Pre-SCI1.1: set cursor according to the first parameter, and toggle its // visibility based on the second parameter // Some late SCI1 games actually use the SCI1.1 version of this call (EcoQuest 1 @@ -337,7 +342,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, Common::Point(argv[0].toUint16(), argv[1].toUint16()))); } - } else { + } else if (s->_version >= SCI_VERSION_1_1) { // SCI1.1 and newer: set pointer position GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, Common::Point(argv[0].toUint16(), argv[1].toUint16()))); diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index bb27589d84..fa64ab4086 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -964,9 +964,9 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) { - if (s->_version >= SCI_VERSION_1_1 || s->_flags & GF_SCI1_NEWDOSOUND) + if (s->_kernel->_selectorMap.setVol != -1) return kDoSound_SCI1(s, funct_nr, argc, argv); - else if (s->_version >= SCI_VERSION_01) + else if (s->_kernel->_selectorMap.nodePtr != -1) return kDoSound_SCI01(s, funct_nr, argc, argv); else return kDoSound_SCI0(s, funct_nr, argc, argv); diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index fb094e00f6..d4bd094b4a 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -97,8 +97,7 @@ void script_adjust_opcode_formats(int res_version) { break; case SCI_VERSION_01_VGA: case SCI_VERSION_01_VGA_ODD: - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: + case SCI_VERSION_1: case SCI_VERSION_1_1: g_opcode_formats[op_lofsa][0] = Script_Offset; g_opcode_formats[op_lofss][0] = Script_Offset; @@ -203,6 +202,10 @@ void Kernel::mapSelectors() { FIND_SELECTOR(printLang); FIND_SELECTOR(subtitleLang); FIND_SELECTOR(parseLang); + FIND_SELECTOR(motionCue); + FIND_SELECTOR(sightAngle); + FIND_SELECTOR(setVol); + FIND_SELECTOR(egoMoveSpeed); } void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 92f890512a..a31af68323 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1193,7 +1193,7 @@ void run_vm(EngineState *s, int restoring) { if (s->_version >= SCI_VERSION_1_1) { s->r_acc.offset = opparams[0] + local_script->script_size; } else { - if (s->_flags & GF_SCI1_LOFSABSOLUTE) + if (s->_kernel->hasLofsAbsolute()) s->r_acc.offset = opparams[0]; else s->r_acc.offset = xs->addr.pc.offset + opparams[0]; @@ -1210,7 +1210,7 @@ void run_vm(EngineState *s, int restoring) { case 0x3a: // lofss r_temp.segment = xs->addr.pc.segment; - if (s->_flags & GF_SCI1_LOFSABSOLUTE) + if (s->_kernel->hasLofsAbsolute()) r_temp.offset = opparams[0]; else r_temp.offset = xs->addr.pc.offset + opparams[0]; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index a3fabbe44b..adaa064a6c 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -203,6 +203,10 @@ struct selector_map_t { Selector printLang; /**< Used for i18n */ Selector subtitleLang; Selector parseLang; + Selector motionCue; // Used to detect newer graphics functions semantics. + Selector sightAngle; // Used to detect some SCI0/SCI01 games which need a SCI1 table + Selector setVol; // Used to detect newer sound semantics + Selector egoMoveSpeed; // Used to detect SCI1 games which use absolute values in lofs }; // A reference to an object's variable. diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index 04ee5a9a4b..9457727b33 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -289,15 +289,14 @@ int GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) { } else { byte *cursorData = createCursor(pointer); - // FIXME: The palette size check is a workaround for cursors using non-palette colour GFX_CURSOR_TRANSPARENT - // Note that some cursors don't have a palette in SQ5 + // FIXME: The palette size check is a workaround for cursors using non-palette color GFX_CURSOR_TRANSPARENT + // Note that some cursors don't have a palette (e.g. in SQ5 and QFG3) byte color_key = GFX_CURSOR_TRANSPARENT; if ((pointer->color_key != GFX_PIXMAP_COLOR_KEY_NONE) && (pointer->palette && (unsigned int)pointer->color_key < pointer->palette->size())) color_key = pointer->palette->getColor(pointer->color_key).parent_index; - // Some cursors in SQ5 don't have a palette. The cursor palette seems to use 64 colors, so setting the color key to 63 works - // TODO: Is this correct? + // Some cursors don't have a palette, so we set the color key directly if (!pointer->palette) - color_key = 63; + color_key = pointer->color_key; CursorMan.replaceCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); CursorMan.showMouse(true); diff --git a/engines/sci/gfx/gfx_resmgr.cpp b/engines/sci/gfx/gfx_resmgr.cpp index 1b76c65ff4..282931d004 100644 --- a/engines/sci/gfx/gfx_resmgr.cpp +++ b/engines/sci/gfx/gfx_resmgr.cpp @@ -535,7 +535,7 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { view = gfxr_draw_view0(resid, viewRes->data, viewRes->size, -1); else if (_version == SCI_VERSION_01 || !_isVGA) view = gfxr_draw_view0(resid, viewRes->data, viewRes->size, palette); - else if (_version >= SCI_VERSION_01_VGA && _version <= SCI_VERSION_1_LATE) + else if (_version >= SCI_VERSION_01_VGA && _version <= SCI_VERSION_1) view = gfxr_draw_view1(resid, viewRes->data, viewRes->size, _staticPalette, false); else if (_version >= SCI_VERSION_1_1) view = gfxr_draw_view1(resid, viewRes->data, viewRes->size, 0, true); diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 52c079e829..7138a918a1 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -48,8 +48,7 @@ const char *sci_version_types[] = { "SCI version 0.xxx w/ 1.000 compression", "SCI version 1.000 w/ 0.xxx resource.map", "SCI version 1.000 w/ special resource.map", - "SCI version 1.000 (early)", - "SCI version 1.000 (late)", + "SCI version 1.000", "SCI version 1.001", "SCI WIN/32" }; @@ -509,16 +508,9 @@ ResourceManager::ResourceManager(int version, int maxMemory) { case SCI_VERSION_01_VGA_ODD: version = _mapVersion; break; - case SCI_VERSION_1: { - Resource *res = testResource(ResourceId(kResourceTypeScript, 0)); - - _sciVersion = version = SCI_VERSION_1_EARLY; - loadResource(res); - - if (res->status == kResStatusNoMalloc) - version = SCI_VERSION_1_LATE; + case SCI_VERSION_1: + _sciVersion = version = SCI_VERSION_1; break; - } case SCI_VERSION_1_1: // No need to handle SCI 1.1 here - it was done in resource_map.cpp version = SCI_VERSION_1_1; @@ -542,11 +534,8 @@ ResourceManager::ResourceManager(int version, int maxMemory) { case SCI_VERSION_01_VGA_ODD: debug("Resmgr: Detected SCI01VGA - Jones/CD or similar"); break; - case SCI_VERSION_1_EARLY: - debug("Resmgr: Detected SCI1 Early"); - break; - case SCI_VERSION_1_LATE: - debug("Resmgr: Detected SCI1 Late"); + case SCI_VERSION_1: + debug("Resmgr: Detected SCI1"); break; case SCI_VERSION_1_1: debug("Resmgr: Detected SCI1.1"); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 77c92840ee..8ef42b171d 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -66,8 +66,6 @@ enum { /* the first critical error number */ }; -#define SCI_VERSION_1 SCI_VERSION_1_EARLY - #define MAX_OPENED_VOLUMES 5 // Max number of simultaneously opened volumes enum ResSourceType { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index c5bf3f5a32..822542839b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -43,14 +43,13 @@ namespace Sci { class GfxDriver; -const char *versionNames[9] = { +const char *versionNames[8] = { "Autodetected", "SCI0", "SCI01 EGA", "SCI01 VGA", "SCI01 VGA ODD", - "SCI1 early", - "SCI1 late", + "SCI1", "SCI1.1", "SCI32" }; @@ -154,14 +153,12 @@ Common::Error SciEngine::run() { _gamestate = new EngineState(_resmgr, version, flags); // Verify that we haven't got an invalid game detection entry - if (version < SCI_VERSION_1_EARLY) { + if (version < SCI_VERSION_1) { // SCI0/SCI01 - if (flags & GF_SCI1_EGA || - flags & GF_SCI1_LOFSABSOLUTE || - flags & GF_SCI1_NEWDOSOUND) { + if (flags & GF_SCI1_EGA) { error("This game entry is erroneous. It's marked as SCI0/SCI01, but it has SCI1 flags set"); } - } else if (version >= SCI_VERSION_1_EARLY && version <= SCI_VERSION_1_LATE) { + } else if (version == SCI_VERSION_1) { // SCI1 if (flags & GF_SCI0_OLD || @@ -169,9 +166,7 @@ Common::Error SciEngine::run() { error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set"); } } else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) { - if (flags & GF_SCI1_EGA || - flags & GF_SCI1_LOFSABSOLUTE || - flags & GF_SCI1_NEWDOSOUND) { + if (flags & GF_SCI1_EGA) { error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI1 flags set"); } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index ea50976df4..9b5d1de689 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -49,16 +49,15 @@ enum kDebugLevels { kDebugLevelGfxDriver = 1 << 8, kDebugLevelBaseSetter = 1 << 9, kDebugLevelParser = 1 << 10, - // FIXME: seems that debug level 11 is special (check debugC in common/debug.cpp) - kDebugLevelMenu = 1 << 12, - kDebugLevelSaid = 1 << 13, - kDebugLevelFile = 1 << 14, - kDebugLevelTime = 1 << 15, - kDebugLevelRoom = 1 << 16, - kDebugLevelAvoidPath = 1 << 17, - kDebugLevelDclInflate = 1 << 18, - kDebugLevelVM = 1 << 19, - kDebugLevelScripts = 1 << 20 + kDebugLevelMenu = 1 << 11, + kDebugLevelSaid = 1 << 12, + kDebugLevelFile = 1 << 13, + kDebugLevelTime = 1 << 14, + kDebugLevelRoom = 1 << 15, + kDebugLevelAvoidPath = 1 << 16, + kDebugLevelDclInflate = 1 << 17, + kDebugLevelVM = 1 << 18, + kDebugLevelScripts = 1 << 19 }; struct SciGameDescription { @@ -74,54 +73,38 @@ enum SciGameVersions { SCI_VERSION_01 = 2, SCI_VERSION_01_VGA = 3, SCI_VERSION_01_VGA_ODD = 4, - SCI_VERSION_1_EARLY = 5, - SCI_VERSION_1_LATE = 6, + SCI_VERSION_1 = 5, SCI_VERSION_1_1 = 7, SCI_VERSION_32 = 8 }; -extern const char *versionNames[9]; +extern const char *versionNames[8]; enum SciGameFlags { - /* - ** SCI0 flags - */ + // SCI0 flags /* Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2) - ** Old SCI versions used two word header for script blocks (first word equal - ** to 0x82, meaning of the second one unknown). New SCI versions used one - ** word header. - ** Also, old SCI versions assign 120 degrees to left & right, and 60 to up - ** and down. Later versions use an even 90 degree distribution. - */ + * Old SCI versions used two word header for script blocks (first word equal + * to 0x82, meaning of the second one unknown). New SCI versions used one + * word header. + * Also, old SCI versions assign 120 degrees to left & right, and 60 to up + * and down. Later versions use an even 90 degree distribution. + */ GF_SCI0_OLD = (1 << 0), /* Applies to all versions before 0.000.629 - ** Older SCI versions had simpler code for GetTime() - */ + * Older SCI versions had simpler code for GetTime() + */ GF_SCI0_OLDGETTIME = (1 << 1), // ---------------------------------------------------------------------------- - /* - ** SCI1 flags - */ + // SCI1 flags /* - ** Used to distinguish SCI1 EGA games - */ - GF_SCI1_EGA = (1 << 2), - - /* Applies to all SCI1 versions after 1.000.200 - ** In late SCI1 versions, the argument of lofs[as] instructions - ** is absolute rather than relative. - */ - GF_SCI1_LOFSABSOLUTE = (1 << 3), - - /* Applies to all versions from 1.000.510 onwards - ** kDoSound() is different than in earlier SCI1 versions. - */ - GF_SCI1_NEWDOSOUND = (1 << 4) + * Used to distinguish SCI1 EGA games + */ + GF_SCI1_EGA = (1 << 2) }; class SciEngine : public Engine { diff --git a/engines/sci/sfx/iterator.cpp b/engines/sci/sfx/iterator.cpp index ad33bc8dfb..c1acda7f6c 100644 --- a/engines/sci/sfx/iterator.cpp +++ b/engines/sci/sfx/iterator.cpp @@ -1269,6 +1269,14 @@ static void song_iterator_remove_death_listener(SongIterator *it, TeeSongIterato } } +static void song_iterator_transfer_death_listeners(SongIterator *it, SongIterator *it_from) { + for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { + if (it_from->_deathListeners[i]) + song_iterator_add_death_listener(it, it_from->_deathListeners[i]); + it_from->_deathListeners[i] = 0; + } +} + static void songit_tee_death_notification(TeeSongIterator *self, SongIterator *corpse) { if (corpse == self->_children[TEE_LEFT].it) { self->_status &= ~TEE_LEFT_ACTIVE; @@ -1505,12 +1513,16 @@ SongIterator *TeeSongIterator::handleMessage(Message msg) { delete _children[TEE_LEFT].it; _children[TEE_LEFT].it = 0; old_it = _children[TEE_RIGHT].it; + song_iterator_remove_death_listener(old_it, this); + song_iterator_transfer_death_listeners(old_it, this); delete this; return old_it; } else if (!(_status & TEE_RIGHT_ACTIVE)) { delete _children[TEE_RIGHT].it; _children[TEE_RIGHT].it = 0; old_it = _children[TEE_LEFT].it; + song_iterator_remove_death_listener(old_it, this); + song_iterator_transfer_death_listeners(old_it, this); delete this; return old_it; } @@ -1582,9 +1594,11 @@ int songit_next(SongIterator **it, byte *buf, int *result, int mask) { ** cleanup iterator */ int channel_mask = (*it)->channel_mask; - if (mask & IT_READER_MAY_FREE) - delete *it; + SongIterator *old_it = *it; *it = new CleanupSongIterator(channel_mask); + song_iterator_transfer_death_listeners(*it, old_it); + if (mask & IT_READER_MAY_FREE) + delete old_it; retval = -9999; /* Continue */ } } while (!( /* Until one of the following holds */ diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 022dbc0eb3..ce29bf0319 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -474,7 +474,7 @@ bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *n int need_size = (int)((byte *)offset - memory + size); debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x", - need_size, total_size, (byte *)offset - memory, size); + need_size, total_size, (uint)((byte *)offset - memory), size); if (need_size < 0 || need_size > total_size) { error("%s: premature end", name); diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index c70c819b69..78f7fb0453 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -462,7 +462,7 @@ void ScummEngine::executeScript() { vm.slot[_currentScript].didexec = true; debugC(DEBUG_OPCODES, "Script %d, offset 0x%x: [%X] %s()", vm.slot[_currentScript].number, - _scriptPointer - _scriptOrgPointer, + (uint)(_scriptPointer - _scriptOrgPointer), _opcode, getOpcodeDesc(_opcode)); if (_hexdumpScripts == true) { |