diff options
Diffstat (limited to 'engines')
560 files changed, 18694 insertions, 4449 deletions
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index b1d1008b60..fd0c8dc2da 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -29,7 +29,7 @@ #include "common/system.h" #include "common/textconsole.h" #include "common/translation.h" - +#include "gui/EventRecorder.h" #include "engines/advancedDetector.h" #include "engines/obsolete.h" @@ -301,6 +301,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) return Common::kUserCanceled; debug(2, "Running %s", gameDescriptor.description().c_str()); + initSubSystems(agdDesc); if (!createInstance(syst, engine, agdDesc)) return Common::kNoGameDataFoundError; else @@ -606,3 +607,11 @@ AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, con _maxScanDepth = 1; _directoryGlobs = NULL; } + +void AdvancedMetaEngine::initSubSystems(const ADGameDescription *gameDesc) const { +#ifdef ENABLE_EVENTRECORDER + if (gameDesc) { + g_eventRec.processGameDescription(gameDesc); + } +#endif +} diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index 3eec33abe5..71d2c4a446 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -280,6 +280,9 @@ protected: return 0; } +private: + void initSubSystems(const ADGameDescription *gameDesc) const; + protected: /** * Detect games in specified directory. diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 1c342183cd..57561c00ee 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -598,8 +598,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _console = NULL; _egoHoldKey = false; - - + + } void AgiEngine::initialize() { diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp index b7d2801076..17d980dfd8 100644 --- a/engines/agi/preagi_troll.cpp +++ b/engines/agi/preagi_troll.cpp @@ -190,6 +190,7 @@ void TrollEngine::inventory() { break; case IDI_TRO_MAX_TREASURE: drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2); + break; default: sprintf(tmp, IDS_TRO_TREASURE_4, _treasuresLeft); drawStr(20, 10, kColorDefault, tmp); @@ -219,6 +220,7 @@ void TrollEngine::waitAnyKeyIntro() { switch (iMsg) { case 200: iMsg = 0; + // fall through case 0: drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2); _gfx->doUpdate(); diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index bbe9ddd0c6..1be385be37 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -985,6 +985,7 @@ void WinnieEngine::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) { } break; } + break; default: if (!event.kbd.flags) { // if the control/alt/shift keys are not pressed keyHelp(); diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 9176412e0e..40c9d1d049 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -272,7 +272,7 @@ void MoviePlayerDXA::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { if (!surface) return; - byte *src = (byte *)surface->pixels; + const byte *src = (const byte *)surface->getPixels(); dst += y * pitch + x; do { @@ -344,7 +344,7 @@ void MoviePlayerDXA::handleNextFrame() { bool MoviePlayerDXA::processFrame() { Graphics::Surface *screen = _vm->_system->lockScreen(); - copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch); + copyFrameToBuffer((byte *)screen->getPixels(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch); _vm->_system->unlockScreen(); uint32 soundTime = _mixer->getSoundElapsedTime(_bgSound); @@ -443,7 +443,7 @@ void MoviePlayerSMK::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) { if (!surface) return; - byte *src = (byte *)surface->pixels; + const byte *src = (const byte *)surface->getPixels(); dst += y * pitch + x; do { @@ -495,7 +495,7 @@ void MoviePlayerSMK::nextFrame() { bool MoviePlayerSMK::processFrame() { Graphics::Surface *screen = _vm->_system->lockScreen(); - copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch); + copyFrameToBuffer((byte *)screen->getPixels(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, screen->pitch); _vm->_system->unlockScreen(); uint32 waitTime = getTimeToNextFrame(); diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp index 262ae44f01..b6b90eefcc 100644 --- a/engines/agos/charset-fontdata.cpp +++ b/engines/agos/charset-fontdata.cpp @@ -2924,7 +2924,7 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { Graphics::Surface *screen = _system->lockScreen(); if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dstPitch = screen->pitch; h = 8; w = 6; @@ -2961,7 +2961,7 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { error("windowDrawChar: Unknown language %d", _language); } } else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dstPitch = screen->pitch; h = 8; w = 6; @@ -2986,14 +2986,14 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { error("windowDrawChar: Unknown language %d", _language); } } else if (getGameType() == GType_ELVIRA1) { - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dstPitch = screen->pitch; h = 8; w = 6; src = english_elvira1Font + (chr - 32) * 8; } else { - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dstPitch = screen->pitch; h = 8; w = 8; diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp index f58f4397b5..eca9728643 100644 --- a/engines/agos/charset.cpp +++ b/engines/agos/charset.cpp @@ -362,7 +362,7 @@ void AGOSEngine::windowScroll(WindowBlock *window) { w = window->width * 8; h = (window->height -1) * 8; - dst = (byte *)screen->pixels + window->y * screen->pitch + window->x * 8; + dst = (byte *)screen->getBasePtr(window->x * 8, window->y); src = dst + 8 * screen->pitch; do { diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp index cf3a12ceb8..d27aed29db 100644 --- a/engines/agos/draw.cpp +++ b/engines/agos/draw.cpp @@ -32,15 +32,15 @@ namespace AGOS { byte *AGOSEngine::getBackBuf() { - return (byte *)_backBuf->pixels; + return (byte *)_backBuf->getPixels(); } byte *AGOSEngine::getBackGround() { - return (byte *)_backGroundBuf->pixels; + return (byte *)_backGroundBuf->getPixels(); } byte *AGOSEngine::getScaleBuf() { - return (byte *)_scaleBuf->pixels; + return (byte *)_scaleBuf->getPixels(); } #ifdef ENABLE_AGOS2 @@ -226,7 +226,7 @@ void AGOSEngine::animateSprites() { debug(0, "Using special wall"); uint8 color, h, len; - byte *dst = (byte *)_window4BackScn->pixels; + byte *dst = (byte *)_window4BackScn->getPixels(); color = (_variableArray[293] & 1) ? 13 : 15; _wallOn = 2; @@ -256,7 +256,7 @@ void AGOSEngine::animateSprites() { } else if (getGameType() == GType_ELVIRA2 && _variableArray[71] & 2) { // Used by the Unholy Barrier spell uint8 color, h, len; - byte *dst = (byte *)_window4BackScn->pixels; + byte *dst = (byte *)_window4BackScn->getPixels(); color = 1; _wallOn = 2; @@ -491,7 +491,7 @@ void AGOSEngine::saveBackGround(VgaSprite *vsp) { int16 y = vsp->y - _scrollY; if (_window3Flag == 1) { - animTable->srcPtr = (const byte *)_window4BackScn->pixels; + animTable->srcPtr = (const byte *)_window4BackScn->getPixels(); } else { int xoffs = (_videoWindows[vsp->windowNum * 4 + 0] * 2 + x) * 8; int yoffs = (_videoWindows[vsp->windowNum * 4 + 1] + y); @@ -565,7 +565,7 @@ void AGOSEngine::displayBoxStars() { if (x_ >= 311) continue; - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dst += (((screen->pitch / 4) * y_) * 4) + x_; @@ -673,7 +673,7 @@ void AGOSEngine::scrollScreen() { if (getGameType() == GType_SIMON2) { src = getBackGround(); - dst = (byte *)_window4BackScn->pixels; + dst = (byte *)_window4BackScn->getPixels(); for (int i = 0; i < _scrollHeight; i++) { memcpy(dst, src, _screenWidth); src += _backGroundBuf->pitch; @@ -725,7 +725,7 @@ void AGOSEngine::fillBackFromBackGround(uint16 height, uint16 width) { void AGOSEngine::fillBackFromFront() { Graphics::Surface *screen = _system->lockScreen(); - byte *src = (byte *)screen->pixels; + byte *src = (byte *)screen->getPixels(); byte *dst = getBackBuf(); for (int i = 0; i < _screenHeight; i++) { @@ -748,7 +748,7 @@ void AGOSEngine::fillBackGroundFromBack() { void AGOSEngine::fillBackGroundFromFront() { Graphics::Surface *screen = _system->lockScreen(); - byte *src = (byte *)screen->pixels; + byte *src = (byte *)screen->getPixels(); byte *dst = getBackGround(); for (int i = 0; i < _screenHeight; i++) { @@ -785,7 +785,7 @@ void AGOSEngine::displayScreen() { Graphics::Surface *screen = _system->lockScreen(); if (getGameType() == GType_PP || getGameType() == GType_FF) { byte *src = getBackBuf(); - byte *dst = (byte *)screen->pixels; + byte *dst = (byte *)screen->getPixels(); for (int i = 0; i < _screenHeight; i++) { memcpy(dst, src, _screenWidth); src += _backBuf->pitch; @@ -798,9 +798,9 @@ void AGOSEngine::displayScreen() { _window4Flag = 0; uint16 srcWidth, width, height; - byte *dst = (byte *)screen->pixels; + byte *dst = (byte *)screen->getPixels(); - const byte *src = (const byte *)_window4BackScn->pixels; + const byte *src = (const byte *)_window4BackScn->getPixels(); if (_window3Flag == 1) { src = getBackGround(); } @@ -831,8 +831,8 @@ void AGOSEngine::displayScreen() { if (_window6Flag == 2) { _window6Flag = 0; - byte *src = (byte *)_window6BackScn->pixels; - byte *dst = (byte *)screen->pixels + 51 * screen->pitch; + byte *src = (byte *)_window6BackScn->getPixels(); + byte *dst = (byte *)screen->getBasePtr(0, 51); for (int i = 0; i < 80; i++) { memcpy(dst, src, _window6BackScn->w); dst += screen->pitch; diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp index cc1c40c207..65c7f7fd77 100644 --- a/engines/agos/event.cpp +++ b/engines/agos/event.cpp @@ -365,7 +365,7 @@ void AGOSEngine::drawStuff(const byte *src, uint xoffs) { const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 135; Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + y * screen->pitch + xoffs; + byte *dst = (byte *)screen->getBasePtr(xoffs, y); for (uint h = 0; h < 6; h++) { memcpy(dst, src, 4); diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index db0817250b..266fcc9796 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -649,7 +649,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->surf2_addr = getBackGround(); state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_addr = (byte *)_window4BackScn->getPixels(); state->surf_pitch = _window4BackScn->pitch; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -666,7 +666,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->surf2_addr = getBackGround(); state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_addr = (byte *)_window4BackScn->getPixels(); state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -678,7 +678,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { _window4Flag = 1; } else { - state->surf_addr = (byte *)screen->pixels; + state->surf_addr = (byte *)screen->getPixels(); state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -696,7 +696,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->surf2_addr = getBackGround(); state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_addr = (byte *)_window4BackScn->getPixels(); state->surf_pitch = _window4BackScn->pitch; } @@ -712,7 +712,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->surf2_addr = getBackGround(); state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = (byte *)screen->pixels; + state->surf_addr = (byte *)screen->getPixels(); state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -861,7 +861,7 @@ void AGOSEngine::drawImage(VC10_state *state) { uint16 xoffs = 0, yoffs = 0; if (getGameType() == GType_WW) { if (_windowNum == 4 || (_windowNum >= 10 && _windowNum <= 27)) { - state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_addr = (byte *)_window4BackScn->getPixels(); state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -873,7 +873,7 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } else { - state->surf_addr = (byte *)screen->pixels; + state->surf_addr = (byte *)screen->getPixels(); state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -881,7 +881,7 @@ void AGOSEngine::drawImage(VC10_state *state) { } } else if (getGameType() == GType_ELVIRA2) { if (_windowNum == 4 || _windowNum >= 10) { - state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_addr = (byte *)_window4BackScn->getPixels(); state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -893,7 +893,7 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } else { - state->surf_addr = (byte *)screen->pixels; + state->surf_addr = (byte *)screen->getPixels(); state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -901,19 +901,19 @@ void AGOSEngine::drawImage(VC10_state *state) { } } else if (getGameType() == GType_ELVIRA1) { if (_windowNum == 6) { - state->surf_addr = (byte *)_window6BackScn->pixels; + state->surf_addr = (byte *)_window6BackScn->getPixels(); state->surf_pitch = _window6BackScn->pitch; xoffs = state->x * 8; yoffs = state->y; } else if (_windowNum == 2 || _windowNum == 3) { - state->surf_addr = (byte *)screen->pixels; + state->surf_addr = (byte *)screen->getPixels(); state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; } else { - state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_addr = (byte *)_window4BackScn->getPixels(); state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -926,7 +926,7 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } } else { - state->surf_addr = (byte *)screen->pixels; + state->surf_addr = (byte *)screen->getPixels(); state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; @@ -973,7 +973,7 @@ void AGOSEngine::horizontalScroll(VC10_state *state) { vcWriteVar(251, _scrollX); if (getGameType() == GType_SIMON2) { - dst = (byte *)_window4BackScn->pixels; + dst = (byte *)_window4BackScn->getPixels(); dstPitch = _window4BackScn->pitch; } else { dst = getBackBuf(); @@ -1375,10 +1375,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } else if (getGameType() == GType_SIMON1 && (getFeatures() & GF_DEMO)) { // The DOS Floppy demo was based off Waxworks engine if (updateWindow == 4 || updateWindow >= 10) { - src = (byte *)_window4BackScn->pixels; + src = (byte *)_window4BackScn->getPixels(); srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3 || updateWindow == 9) { - src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + src = (byte *)screen->getBasePtr(xoffs, yoffs); srcWidth = screen->pitch; } else { _system->unlockScreen(); @@ -1387,13 +1387,13 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } } else if (getGameType() == GType_SIMON1) { if (updateWindow == 4) { - src = (byte *)_window4BackScn->pixels; + src = (byte *)_window4BackScn->getPixels(); srcWidth = _videoWindows[18] * 16; } else if (updateWindow >= 10) { - src = (byte *)_window4BackScn->pixels + xoffs + yoffs * 320; + src = (byte *)_window4BackScn->getBasePtr(xoffs, yoffs); srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 0) { - src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + src = (byte *)screen->getBasePtr(xoffs, yoffs); srcWidth = screen->pitch; } else { _system->unlockScreen(); @@ -1402,10 +1402,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } } else if (getGameType() == GType_WW) { if (updateWindow == 4 || updateWindow >= 10) { - src = (byte *)_window4BackScn->pixels; + src = (byte *)_window4BackScn->getPixels(); srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3 || updateWindow == 9) { - src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + src = (byte *)screen->getBasePtr(xoffs, yoffs); srcWidth = screen->pitch; } else { _system->unlockScreen(); @@ -1414,10 +1414,10 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } } else if (getGameType() == GType_ELVIRA2) { if (updateWindow == 4 || updateWindow >= 10) { - src = (byte *)_window4BackScn->pixels; + src = (byte *)_window4BackScn->getPixels(); srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3) { - src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + src = (byte *)screen->getBasePtr(xoffs, yoffs); srcWidth = screen->pitch; } else { _system->unlockScreen(); @@ -1427,17 +1427,17 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } else if (getGameType() == GType_ELVIRA1) { if (updateWindow == 6) { _window6Flag = 1; - src = (byte *)_window6BackScn->pixels; + src = (byte *)_window6BackScn->getPixels(); srcWidth = 48; } else if (updateWindow == 2 || updateWindow == 3) { - src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + src = (byte *)screen->getBasePtr(xoffs, yoffs); srcWidth = screen->pitch; } else { - src = (byte *)_window4BackScn->pixels; + src = (byte *)_window4BackScn->getPixels(); srcWidth = _videoWindows[18] * 16; } } else { - src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + src = (byte *)screen->getBasePtr(xoffs, yoffs); srcWidth = screen->pitch; } @@ -1451,13 +1451,13 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas if (getGameType() == GType_PN && !_wiped && !specialCase) { uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15; - dst = (byte *)screen->pixels + 48; + dst = (byte *)screen->getBasePtr(48, 0); memset(dst, color, 224); - dst = (byte *)screen->pixels + 132 * screen->pitch + 48; + dst = (byte *)screen->getBasePtr(48, 132); memset(dst, color, 224); } else if (getGameType() == GType_ELVIRA1 && updateWindow == 3 && _bottomPalette) { - dst = (byte *)screen->pixels + 133 * screen->pitch; + dst = (byte *)screen->getBasePtr(0, 133); for (int h = 0; h < 67; h++) { for (int w = 0; w < _screenWidth; w++) @@ -1479,7 +1479,7 @@ void AGOSEngine::drawEdging() { Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels + 136 * screen->pitch; + dst = (byte *)screen->getBasePtr(0, 136); uint8 len = 52; while (len--) { @@ -1488,7 +1488,7 @@ void AGOSEngine::drawEdging() { dst += screen->pitch; } - dst = (byte *)screen->pixels + 187 * screen->pitch; + dst = (byte *)screen->getBasePtr(0, 187); memset(dst, color, _screenWidth); _system->unlockScreen(); diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp index 0ee1d62fde..6d4192da2a 100644 --- a/engines/agos/icons.cpp +++ b/engines/agos/icons.cpp @@ -202,7 +202,7 @@ void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dst += 110; dst += x; @@ -228,7 +228,7 @@ void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dst += (x + window->x) * 8; dst += (y * 25 + window->y) * screen->pitch; @@ -256,7 +256,7 @@ void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dst += (x + window->x) * 8; dst += (y * 20 + window->y) * screen->pitch; @@ -284,7 +284,7 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dst += (x + window->x) * 8; dst += (y * 8 + window->y) * screen->pitch; @@ -312,7 +312,7 @@ void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); dst += (x + window->x) * 8; dst += (y * 8 + window->y) * screen->pitch; @@ -339,7 +339,7 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) { _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels + y * screen->pitch + x * 8; + dst = (byte *)screen->getBasePtr(x * 8, y); src = _iconFilePtr + icon * 146; if (icon == 0xFF) { @@ -951,7 +951,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) { } Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + y * screen->pitch + x * 8; + byte *dst = (byte *)screen->getBasePtr(x * 8, y); for (h = 0; h < 19; h++) { for (w = 0; w < 16; w++) { @@ -1042,7 +1042,7 @@ static const byte hitBarData[12 * 7] = { // Personal Nightmare specific void AGOSEngine_PN::drawIconHitBar() { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + 3 * screen->pitch + 6 * 8; + byte *dst = (byte *)screen->getBasePtr(6 * 8, 3); const byte *src = hitBarData; uint8 color = (getPlatform() == Common::kPlatformDOS) ? 7 : 15; diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp index a0d2bdcaa0..85c50e421b 100644 --- a/engines/agos/menus.cpp +++ b/engines/agos/menus.cpp @@ -164,7 +164,7 @@ void AGOSEngine::unlightMenuStrip() { mouseOff(); Graphics::Surface *screen = _system->lockScreen(); - src = (byte *)screen->pixels + 8 * screen->pitch + 272; + src = (byte *)screen->getBasePtr(272, 8); w = 48; h = 82; @@ -192,7 +192,7 @@ void AGOSEngine::lightMenuBox(uint hitarea) { mouseOff(); Graphics::Surface *screen = _system->lockScreen(); - src = (byte *)screen->pixels + ha->y * screen->pitch + ha->x; + src = (byte *)screen->getBasePtr(ha->x, ha->y); w = ha->width; h = ha->height; diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp index 93077ed83e..f5b57a01c8 100644 --- a/engines/agos/verb.cpp +++ b/engines/agos/verb.cpp @@ -973,7 +973,7 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) { _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - src = (byte *)screen->pixels + ha->y * screen->pitch + ha->x; + src = (byte *)screen->getBasePtr(ha->x, ha->y); // WORKAROUND: Hitareas for saved game names aren't adjusted for scrolling locations if (getGameType() == GType_SIMON2 && ha->id >= 208 && ha->id <= 213) { diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index 8541f579d6..cc5ede5f2c 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -1179,7 +1179,7 @@ void AGOSEngine::vc32_saveScreen() { if (getGameType() == GType_PN) { Graphics::Surface *screen = _system->lockScreen(); byte *dst = getBackGround(); - byte *src = (byte *)screen->pixels; + byte *src = (byte *)screen->getPixels(); for (int i = 0; i < _screenHeight; i++) { memcpy(dst, src, _screenWidth); dst += _backGroundBuf->pitch; @@ -1193,7 +1193,7 @@ void AGOSEngine::vc32_saveScreen() { uint16 height = _videoWindows[4 * 4 + 3]; byte *dst = (byte *)_backGroundBuf->getBasePtr(xoffs, yoffs); - byte *src = (byte *)_window4BackScn->pixels; + byte *src = (byte *)_window4BackScn->getPixels(); uint16 srcWidth = _videoWindows[4 * 4 + 2] * 16; for (; height > 0; height--) { memcpy(dst, src, width); @@ -1247,7 +1247,7 @@ void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) { if (getGameType() == GType_ELVIRA1 && num == 3) { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels; + byte *dst = (byte *)screen->getPixels(); for (int i = 0; i < _screenHeight; i++) { memset(dst, color, _screenWidth); dst += screen->pitch; @@ -1258,7 +1258,10 @@ void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) { uint16 xoffs = (vlut[0] - _videoWindows[16]) * 16; uint16 yoffs = (vlut[1] - _videoWindows[17]); uint16 dstWidth = _videoWindows[18] * 16; - byte *dst = (byte *)_window4BackScn->pixels + xoffs + yoffs * dstWidth; + // TODO: Is there any known connection between dstWidth and the pitch + // of the _window4BackScn Surface? If so, we might be able to pass + // yoffs as proper y parameter to getBasePtr. + byte *dst = (byte *)_window4BackScn->getBasePtr(xoffs, 0) + yoffs * dstWidth; setMoveRect(0, 0, vlut[2] * 16, vlut[3]); diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp index d4aafd3d7b..4eb337c687 100644 --- a/engines/agos/vga_e2.cpp +++ b/engines/agos/vga_e2.cpp @@ -76,7 +76,7 @@ void AGOSEngine::vc45_setWindowPalette() { uint8 height = vlut[3]; if (num == 4) { - byte *dst = (byte *)_window4BackScn->pixels; + byte *dst = (byte *)_window4BackScn->getPixels(); for (uint8 h = 0; h < height; h++) { for (uint8 w = 0; w < width; w++) { @@ -223,11 +223,11 @@ void AGOSEngine::vc53_dissolveIn() { uint16 count = dissolveCheck * 2; while (count--) { Graphics::Surface *screen = _system->lockScreen(); - byte *dstPtr = (byte *)screen->pixels + x + y * screen->pitch; + byte *dstPtr = (byte *)screen->getBasePtr(x, y); yoffs = _rnd.getRandomNumber(dissolveY); dst = dstPtr + yoffs * screen->pitch; - src = (byte *)_window4BackScn->pixels + yoffs * _window4BackScn->pitch; + src = (byte *)_window4BackScn->getBasePtr(0, yoffs); xoffs = _rnd.getRandomNumber(dissolveX); dst += xoffs; @@ -296,7 +296,7 @@ void AGOSEngine::vc54_dissolveOut() { uint16 count = dissolveCheck * 2; while (count--) { Graphics::Surface *screen = _system->lockScreen(); - byte *dstPtr = (byte *)screen->pixels + x + y * screen->pitch; + byte *dstPtr = (byte *)screen->getBasePtr(x, y); color |= dstPtr[0] & 0xF0; yoffs = _rnd.getRandomNumber(dissolveY); @@ -378,7 +378,7 @@ void AGOSEngine::fullFade() { void AGOSEngine::vc56_fullScreen() { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels; + byte *dst = (byte *)screen->getPixels(); byte *src = _curVgaFile2 + 800; for (int i = 0; i < _screenHeight; i++) { diff --git a/engines/agos/vga_pn.cpp b/engines/agos/vga_pn.cpp index 1e7b2ba060..b7f80ebf91 100644 --- a/engines/agos/vga_pn.cpp +++ b/engines/agos/vga_pn.cpp @@ -155,7 +155,7 @@ void AGOSEngine::vc48_specialEffect() { if (getPlatform() == Common::kPlatformDOS) { if (num == 1) { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels; + byte *dst = (byte *)screen->getPixels(); for (uint h = 0; h < _screenHeight; h++) { for (uint w = 0; w < _screenWidth; w++) { @@ -205,7 +205,7 @@ void AGOSEngine_PN::clearVideoWindow(uint16 num, uint16 color) { uint16 yoffs = vlut[1]; Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + xoffs + yoffs * screen->pitch; + byte *dst = (byte *)screen->getBasePtr(xoffs, yoffs); for (uint h = 0; h < vlut[3]; h++) { memset(dst, color, vlut[2] * 16); dst += screen->pitch; diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp index 9b9ed4e297..e0780b491a 100644 --- a/engines/agos/vga_s2.cpp +++ b/engines/agos/vga_s2.cpp @@ -213,7 +213,10 @@ void AGOSEngine_Simon2::clearVideoWindow(uint16 num, uint16 color) { uint16 xoffs = vlut[0] * 16; uint16 yoffs = vlut[1]; uint16 dstWidth = _videoWindows[18] * 16; - byte *dst = (byte *)_window4BackScn->pixels + xoffs + yoffs * dstWidth; + // TODO: Is there any known connection between dstWidth and the pitch + // of the _window4BackScn Surface? If so, we might be able to pass + // yoffs as proper y parameter to getBasePtr. + byte *dst = (byte *)_window4BackScn->getBasePtr(xoffs, 0) + yoffs * dstWidth; setMoveRect(0, 0, vlut[2] * 16, vlut[3]); diff --git a/engines/agos/vga_ww.cpp b/engines/agos/vga_ww.cpp index c74f0cf52b..ca93fa9fec 100644 --- a/engines/agos/vga_ww.cpp +++ b/engines/agos/vga_ww.cpp @@ -143,7 +143,7 @@ void AGOSEngine::vc61() { uint h, tmp; Graphics::Surface *screen = _system->lockScreen(); - dstPtr = (byte *)screen->pixels; + dstPtr = (byte *)screen->getPixels(); if (a == 6) { src = _curVgaFile2 + 800; diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp index 0365c736d8..892df92554 100644 --- a/engines/agos/window.cpp +++ b/engines/agos/window.cpp @@ -170,7 +170,7 @@ void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, u _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + y * screen->pitch + x; + byte *dst = (byte *)screen->getBasePtr(x, y); uint8 color = window->fillColor; if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) @@ -232,7 +232,7 @@ void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) { uint i; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels; + dst = (byte *)screen->getPixels(); src = getBackGround(); dst += y * screen->pitch; diff --git a/engines/cge/cge.cpp b/engines/cge/cge.cpp index 6cc0c45963..af7e91f7eb 100644 --- a/engines/cge/cge.cpp +++ b/engines/cge/cge.cpp @@ -25,7 +25,6 @@ #include "common/debug.h" #include "common/debug-channels.h" #include "common/error.h" -#include "common/EventRecorder.h" #include "common/file.h" #include "common/fs.h" #include "engines/advancedDetector.h" diff --git a/engines/cge/cge_main.cpp b/engines/cge/cge_main.cpp index f4f1cd3e0b..ae4dee6090 100644 --- a/engines/cge/cge_main.cpp +++ b/engines/cge/cge_main.cpp @@ -358,7 +358,7 @@ void CGEEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &he // Create a thumbnail and save it Graphics::Surface *thumb = new Graphics::Surface(); Graphics::Surface *s = _vga->_page[0]; - ::createThumbnail(thumb, (const byte *)s->pixels, kScrWidth, kScrHeight, thumbPalette); + ::createThumbnail(thumb, (const byte *)s->getPixels(), kScrWidth, kScrHeight, thumbPalette); Graphics::saveThumbnail(*out, *thumb); thumb->free(); delete thumb; diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp index d29c1224fd..3b01421903 100644 --- a/engines/cge/detection.cpp +++ b/engines/cge/detection.cpp @@ -121,7 +121,7 @@ static const CgeGameDescription gameDescriptions[] = { "sfinx", "Sfinx Freeware", { {"vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024}, - {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844}, + {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844}, AD_LISTEND }, Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0() diff --git a/engines/cge/snail.cpp b/engines/cge/snail.cpp index edb8972040..b9030efb4d 100644 --- a/engines/cge/snail.cpp +++ b/engines/cge/snail.cpp @@ -494,7 +494,7 @@ void CGEEngine::snGame(Sprite *spr, int num) { _sprK3->step(newRandom(6)); // check the ALT key as it's the solution of the puzzle - // the test has been restricted to some specific OSes + // the test has been restricted to some specific OSes // in order to avoid some obvious issues (like Android, iOS, NDS, N64...) // Not perfect, but at least better than nothing. #if defined(WIN32) || defined(UNIX) || defined(MACOSX) || defined(MOTOEZX) || defined(LINUPY) || defined(LINUXMOTO_SDL) diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp index 56a0754527..c0407cab42 100644 --- a/engines/cge/vga13h.cpp +++ b/engines/cge/vga13h.cpp @@ -826,7 +826,7 @@ void Vga::update() { } } - g_system->copyRectToScreen(Vga::_page[0]->getBasePtr(0, 0), kScrWidth, 0, 0, kScrWidth, kScrHeight); + g_system->copyRectToScreen(Vga::_page[0]->getPixels(), kScrWidth, 0, 0, kScrWidth, kScrHeight); g_system->updateScreen(); } @@ -845,7 +845,7 @@ void Bitmap::xShow(int16 x, int16 y) { debugC(4, kCGEDebugBitmap, "Bitmap::xShow(%d, %d)", x, y); const byte *srcP = (const byte *)_v; - byte *destEndP = (byte *)_vm->_vga->_page[1]->pixels + (kScrWidth * kScrHeight); + byte *destEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight); byte *lookupTable = _m; // Loop through processing data for each plane. The game originally ran in plane mapped mode, where a @@ -898,7 +898,7 @@ void Bitmap::show(int16 x, int16 y) { debugC(5, kCGEDebugBitmap, "Bitmap::show(%d, %d)", x, y); const byte *srcP = (const byte *)_v; - byte *destEndP = (byte *)_vm->_vga->_page[1]->pixels + (kScrWidth * kScrHeight); + byte *destEndP = (byte *)_vm->_vga->_page[1]->getBasePtr(0, kScrHeight); // Loop through processing data for each plane. The game originally ran in plane mapped mode, where a // given plane holds each fourth pixel sequentially. So to handle an entire picture, each plane's data diff --git a/engines/composer/composer.h b/engines/composer/composer.h index 33a5356b3a..7d8022455a 100644 --- a/engines/composer/composer.h +++ b/engines/composer/composer.h @@ -23,7 +23,7 @@ #ifndef COMPOSER_H #define COMPOSER_H -#include "common/config-file.h" +#include "common/ini-file.h" #include "common/random.h" #include "common/system.h" #include "common/debug.h" @@ -174,7 +174,7 @@ private: Common::List<Sprite> _sprites; uint _directoriesToStrip; - Common::ConfigFile _bookIni; + Common::INIFile _bookIni; Common::String _bookGroup; Common::List<Library> _libraries; Common::Array<PendingPageChange> _pendingPageChanges; diff --git a/engines/composer/graphics.cpp b/engines/composer/graphics.cpp index 2b68fac233..caf3ba3a40 100644 --- a/engines/composer/graphics.cpp +++ b/engines/composer/graphics.cpp @@ -39,7 +39,7 @@ bool Sprite::contains(const Common::Point &pos) const { return false; if (adjustedPos.y < 0 || adjustedPos.y >= _surface.h) return false; - byte *pixels = (byte *)_surface.pixels; + const byte *pixels = (const byte *)_surface.getPixels(); return (pixels[(_surface.h - adjustedPos.y - 1) * _surface.w + adjustedPos.x] != 0); } @@ -541,7 +541,7 @@ void ComposerEngine::redraw() { for (uint i = 0; i < _dirtyRects.size(); i++) { const Common::Rect &rect = _dirtyRects[i]; - byte *pixels = (byte *)_screen.pixels + (rect.top * _screen.pitch) + rect.left; + byte *pixels = (byte *)_screen.getBasePtr(rect.left, rect.top); _system->copyRectToScreen(pixels, _screen.pitch, rect.left, rect.top, rect.width(), rect.height()); } _system->updateScreen(); @@ -794,7 +794,7 @@ bool ComposerEngine::initSprite(Sprite &sprite) { if (width > 0 && height > 0) { sprite._surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - decompressBitmap(type, stream, (byte *)sprite._surface.pixels, size, width, height); + decompressBitmap(type, stream, (byte *)sprite._surface.getPixels(), size, width, height); } else { // there are some sprites (e.g. a -998x-998 one in Gregory's title screen) // which have an invalid size, but the original engine doesn't notice for @@ -814,13 +814,13 @@ void ComposerEngine::drawSprite(const Sprite &sprite) { int y = sprite._pos.y; // incoming data is BMP-style (bottom-up), so flip it - byte *pixels = (byte *)_screen.pixels; + byte *pixels = (byte *)_screen.getPixels(); for (int j = 0; j < sprite._surface.h; j++) { if (j + y < 0) continue; if (j + y >= _screen.h) break; - byte *in = (byte *)sprite._surface.pixels + (sprite._surface.h - j - 1) * sprite._surface.w; + const byte *in = (const byte *)sprite._surface.getBasePtr(0, sprite._surface.h - j - 1); byte *out = pixels + ((j + y) * _screen.w) + x; for (int i = 0; i < sprite._surface.w; i++) if ((x + i >= 0) && (x + i < _screen.w) && in[i]) diff --git a/engines/configure.engines b/engines/configure.engines index 0f059e6c61..7004f4111f 100644 --- a/engines/configure.engines +++ b/engines/configure.engines @@ -26,6 +26,7 @@ add_engine lastexpress "The Last Express" no "" "" "16bit" add_engine lure "Lure of the Temptress" yes add_engine made "MADE" yes add_engine mohawk "Mohawk" yes "cstime myst riven" "Living Books" +add_engine mortevielle "Mortevielle" no add_engine cstime "Where in Time is Carmen Sandiego?" no add_engine riven "Riven: The Sequel to Myst" no "" "" "16bit" add_engine myst "Myst" no "" "" "16bit" diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h index 9782df8f09..3e49e77770 100644 --- a/engines/cruise/cruise.h +++ b/engines/cruise/cruise.h @@ -43,10 +43,6 @@ */ namespace Cruise { -enum CruiseGameType { - GType_CRUISE = 1 -}; - #define GAME_FRAME_DELAY_1 50 #define GAME_FRAME_DELAY_2 100 diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index b632e4ea7a..bce3f184db 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -20,8 +20,6 @@ * */ - - #include "base/plugins.h" #include "common/savefile.h" #include "common/system.h" @@ -34,21 +32,12 @@ namespace Cruise { struct CRUISEGameDescription { ADGameDescription desc; - - int gameType; - uint32 features; }; const char *CruiseEngine::getGameId() const { return _gameDescription->desc.gameid; } -int CruiseEngine::getGameType() const { - return _gameDescription->gameType; -} -uint32 CruiseEngine::getFeatures() const { - return _gameDescription->features; -} Common::Language CruiseEngine::getLanguage() const { return _gameDescription->desc.language; } @@ -77,8 +66,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -90,8 +77,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -103,8 +88,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -116,8 +99,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -129,8 +110,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -142,8 +121,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -155,8 +132,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { // Amiga English US GOLD edition. { @@ -168,8 +143,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { // Amiga Italian US GOLD edition. { @@ -181,8 +154,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { // AtariST English KixxXL edition. { @@ -194,8 +165,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -207,8 +176,6 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, { { @@ -220,10 +187,8 @@ static const CRUISEGameDescription gameDescriptions[] = { ADGF_NO_FLAGS, GUIO0() }, - GType_CRUISE, - 0, }, - {AD_TABLE_END_MARKER, 0, 0} + {AD_TABLE_END_MARKER} }; } diff --git a/engines/draci/screen.cpp b/engines/draci/screen.cpp index 8c1a0c40f7..e43e367300 100644 --- a/engines/draci/screen.cpp +++ b/engines/draci/screen.cpp @@ -110,7 +110,7 @@ void Screen::copyToScreen() { // If a full update is needed, update the whole screen if (_surface->needsFullUpdate()) { - byte *ptr = (byte *)_surface->getBasePtr(0, 0); + byte *ptr = (byte *)_surface->getPixels(); _vm->_system->copyRectToScreen(ptr, kScreenWidth, 0, 0, kScreenWidth, kScreenHeight); @@ -138,7 +138,7 @@ void Screen::copyToScreen() { * Clears the screen and marks the whole screen dirty. */ void Screen::clearScreen() { - byte *ptr = (byte *)_surface->getBasePtr(0, 0); + byte *ptr = (byte *)_surface->getPixels(); _surface->markDirty(); diff --git a/engines/draci/surface.cpp b/engines/draci/surface.cpp index 8380f8777b..3676c6edac 100644 --- a/engines/draci/surface.cpp +++ b/engines/draci/surface.cpp @@ -80,7 +80,7 @@ void Surface::markClean() { * @brief Fills the surface with the specified color */ void Surface::fill(uint color) { - byte *ptr = (byte *)getBasePtr(0, 0); + byte *ptr = (byte *)getPixels(); memset(ptr, color, w * h); } diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index e547503bee..c4d1c4c761 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -661,7 +661,7 @@ public: void animation_3_1(); // John talks with the bartender to book a room void animation_4_1(); // John talks with the pianist // - void animation_2_2(); // John enters the chapel via the window + void animation_2_2(); // John enters the chapel via the window void animation_4_2(); // John talks with the blind man (closeup) void animation_5_2(); // John breaks the chapel window with the pike void animation_6_2(); // The blind man (closeup) thanks John for giving him money and hands him the sickle diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 3bdf724670..31d03a94a7 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -132,7 +132,7 @@ void DrasculaEngine::showFrame(Common::SeekableReadStream *stream, bool firstFra byte *prevFrame = (byte *)malloc(64000); Graphics::Surface *screenSurf = _system->lockScreen(); - byte *screenBuffer = (byte *)screenSurf->pixels; + byte *screenBuffer = (byte *)screenSurf->getPixels(); uint16 screenPitch = screenSurf->pitch; for (int y = 0; y < 200; y++) { memcpy(prevFrame+y*320, screenBuffer+y*screenPitch, 320); @@ -449,7 +449,7 @@ void DrasculaEngine::screenSaver() { int x1_, y1_, off1, off2; Graphics::Surface *screenSurf = _system->lockScreen(); - byte *screenBuffer = (byte *)screenSurf->pixels; + byte *screenBuffer = (byte *)screenSurf->getPixels(); uint16 screenPitch = screenSurf->pitch; for (int i = 0; i < 200; i++) { for (int j = 0; j < 320; j++) { @@ -538,7 +538,7 @@ int DrasculaEngine::playFrameSSN(Common::SeekableReadStream *stream) { waitFrameSSN(); Graphics::Surface *screenSurf = _system->lockScreen(); - byte *screenBuffer = (byte *)screenSurf->pixels; + byte *screenBuffer = (byte *)screenSurf->getPixels(); uint16 screenPitch = screenSurf->pitch; if (FrameSSN) mixVideo(screenBuffer, screenSurface, screenPitch); @@ -557,7 +557,7 @@ int DrasculaEngine::playFrameSSN(Common::SeekableReadStream *stream) { free(BufferSSN); waitFrameSSN(); Graphics::Surface *screenSurf = _system->lockScreen(); - byte *screenBuffer = (byte *)screenSurf->pixels; + byte *screenBuffer = (byte *)screenSurf->getPixels(); uint16 screenPitch = screenSurf->pitch; if (FrameSSN) mixVideo(screenBuffer, screenSurface, screenPitch); diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp index c3ede46df2..08838a784a 100644 --- a/engines/dreamweb/dreamweb.cpp +++ b/engines/dreamweb/dreamweb.cpp @@ -23,7 +23,6 @@ #include "common/config-manager.h" #include "common/debug-channels.h" #include "common/events.h" -#include "common/EventRecorder.h" #include "common/file.h" #include "common/func.h" #include "common/system.h" diff --git a/engines/dreamweb/monitor.cpp b/engines/dreamweb/monitor.cpp index 1f9fa8d24f..108f9d2b60 100644 --- a/engines/dreamweb/monitor.cpp +++ b/engines/dreamweb/monitor.cpp @@ -104,7 +104,7 @@ void DreamWebEngine::useMon() { redrawMainScrn(); workToScreenM(); } - + int DreamWebEngine::findCommand(const char *const cmdList[]) { // Loop over all commands in the list and see if we get a match int cmd = 0; @@ -135,7 +135,7 @@ bool DreamWebEngine::execCommand() { "KEYS", NULL }; - + static const char *const comlistFR[] = { "SORTIR", "AIDE", @@ -145,7 +145,7 @@ bool DreamWebEngine::execCommand() { "TOUCHES", // should be CLES but it is translated as TOUCHES in the game... NULL }; - + static const char *const comlistDE[] = { "ENDE", "HILF", @@ -155,7 +155,7 @@ bool DreamWebEngine::execCommand() { "DATEN", NULL }; - + static const char *const comlistIT[] = { "ESCI", "AIUTO", @@ -165,7 +165,7 @@ bool DreamWebEngine::execCommand() { "CHIAVI", NULL }; - + static const char *const comlistES[] = { "SALIR", "AYUDA", diff --git a/engines/dreamweb/print.cpp b/engines/dreamweb/print.cpp index bc75b97e71..bec58322d5 100644 --- a/engines/dreamweb/print.cpp +++ b/engines/dreamweb/print.cpp @@ -67,7 +67,7 @@ void DreamWebEngine::printChar(const GraphicsFile &charSet, uint16* x, uint16 y, // characters (0 - 31). if (c < 32 || c == 255) return; - + uint8 dummyWidth, dummyHeight; if (width == NULL) width = &dummyWidth; diff --git a/engines/engines.mk b/engines/engines.mk index 4f38629dad..3401df37e5 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -140,6 +140,11 @@ DEFINES += -DENABLE_NEVERHOOD=$(ENABLE_NEVERHOOD) MODULES += engines/neverhood endif +ifdef ENABLE_MORTEVIELLE +DEFINES += -DENABLE_MORTEVIELLE=$(ENABLE_MORTEVIELLE) +MODULES += engines/mortevielle +endif + ifdef ENABLE_PARALLACTION DEFINES += -DENABLE_PARALLACTION=$(ENABLE_PARALLACTION) MODULES += engines/parallaction diff --git a/engines/gob/iniconfig.cpp b/engines/gob/iniconfig.cpp index bba531723c..032231bd4d 100644 --- a/engines/gob/iniconfig.cpp +++ b/engines/gob/iniconfig.cpp @@ -73,7 +73,7 @@ bool INIConfig::getConfig(const Common::String &file, Config &config) { } bool INIConfig::openConfig(const Common::String &file, Config &config) { - config.config = new Common::ConfigFile(); + config.config = new Common::INIFile(); config.created = false; if (!config.config->loadFromFile(file)) { @@ -89,7 +89,7 @@ bool INIConfig::openConfig(const Common::String &file, Config &config) { } bool INIConfig::createConfig(const Common::String &file, Config &config) { - config.config = new Common::ConfigFile(); + config.config = new Common::INIFile(); config.created = true; _configs.setVal(file, config); diff --git a/engines/gob/iniconfig.h b/engines/gob/iniconfig.h index bf60f2d125..c1890170dc 100644 --- a/engines/gob/iniconfig.h +++ b/engines/gob/iniconfig.h @@ -24,7 +24,7 @@ #define GOB_INICONFIG_H #include "common/str.h" -#include "common/config-file.h" +#include "common/ini-file.h" #include "common/hashmap.h" namespace Gob { @@ -43,7 +43,7 @@ public: private: struct Config { - Common::ConfigFile *config; + Common::INIFile *config; bool created; }; diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp index 6b65eb6ab9..870b0f15b3 100644 --- a/engines/gob/surface.cpp +++ b/engines/gob/surface.cpp @@ -45,7 +45,7 @@ static void plotPixel(int x, int y, int color, void *data) { Pixel::Pixel(byte *vidMem, uint8 bpp, byte *min, byte *max) : _vidMem(vidMem), _bpp(bpp), _min(min), _max(max) { - assert((_bpp == 1) || (_bpp == 2)); + assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4)); assert(_vidMem >= _min); assert(_vidMem < _max); } @@ -91,6 +91,8 @@ uint32 Pixel::get() const { return *((byte *) _vidMem); if (_bpp == 2) return *((uint16 *) _vidMem); + if (_bpp == 4) + return *((uint32 *) _vidMem); return 0; } @@ -103,6 +105,8 @@ void Pixel::set(uint32 p) { *((byte *) _vidMem) = (byte) p; if (_bpp == 2) *((uint16 *) _vidMem) = (uint16) p; + if (_bpp == 4) + *((uint32 *) _vidMem) = (uint32) p; } bool Pixel::isValid() const { @@ -113,7 +117,7 @@ bool Pixel::isValid() const { ConstPixel::ConstPixel(const byte *vidMem, uint8 bpp, const byte *min, const byte *max) : _vidMem(vidMem), _bpp(bpp), _min(min), _max(max) { - assert((_bpp == 1) || (_bpp == 2)); + assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4)); assert(_vidMem >= _min); assert(_vidMem < _max); } @@ -159,6 +163,8 @@ uint32 ConstPixel::get() const { return *((const byte *) _vidMem); if (_bpp == 2) return *((const uint16 *) _vidMem); + if (_bpp == 4) + return *((const uint32 *) _vidMem); return 0; } @@ -172,7 +178,7 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem) : _width(width), _height(height), _bpp(bpp), _vidMem(vidMem) { assert((_width > 0) && (_height > 0)); - assert((_bpp == 1) || (_bpp == 2)); + assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4)); if (!_vidMem) { _vidMem = new byte[_bpp * _width * _height]; @@ -187,7 +193,7 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, const byte *vidMem) : _width(width), _height(height), _bpp(bpp), _vidMem(0) { assert((_width > 0) && (_height > 0)); - assert((_bpp == 1) || (_bpp == 2)); + assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4)); _vidMem = new byte[_bpp * _width * _height]; _ownVidMem = true; @@ -504,7 +510,7 @@ void Surface::fillRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uin return; } - assert(_bpp == 2); + assert((_bpp == 2) || (_bpp == 4)); // Otherwise, we have to fill by pixel @@ -815,7 +821,7 @@ bool Surface::loadIFF(Common::SeekableReadStream &stream) { return false; resize(decoder.getSurface()->w, decoder.getSurface()->h); - memcpy(_vidMem, decoder.getSurface()->pixels, decoder.getSurface()->w * decoder.getSurface()->h); + memcpy(_vidMem, decoder.getSurface()->getPixels(), decoder.getSurface()->w * decoder.getSurface()->h); return true; } diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index a478492ccc..155989ccee 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -734,7 +734,11 @@ bool VideoPlayer::copyFrame(int slot, Surface &dest, if (!surface) return false; - Surface src(surface->w, surface->h, surface->format.bytesPerPixel, (byte *)surface->pixels); + // FIXME? This currently casts away const from the pixel data. However, it + // is only used read-only in this case (as far as I can tell). Not casting + // the const qualifier away will lead to an additional allocation and copy + // of the frame data which is undesirable. + Surface src(surface->w, surface->h, surface->format.bytesPerPixel, (byte *)const_cast<void *>(surface->getPixels())); dest.blit(src, left, top, left + width - 1, top + height - 1, x, y, transp); return true; diff --git a/engines/groovie/graphics.cpp b/engines/groovie/graphics.cpp index 73eb574dec..a4d8a4330c 100644 --- a/engines/groovie/graphics.cpp +++ b/engines/groovie/graphics.cpp @@ -82,8 +82,8 @@ void GraphicsMan::mergeFgAndBg() { uint32 i; byte *countf, *countb; - countf = (byte *)_foreground.getBasePtr(0, 0); - countb = (byte *)_background.getBasePtr(0, 0); + countf = (byte *)_foreground.getPixels(); + countb = (byte *)_background.getPixels(); for (i = 640 * 320; i; i--) { if (255 == *(countf)) { *(countf) = *(countb); @@ -94,7 +94,7 @@ void GraphicsMan::mergeFgAndBg() { } void GraphicsMan::updateScreen(Graphics::Surface *source) { - _vm->_system->copyRectToScreen(source->getBasePtr(0, 0), 640, 0, 80, 640, 320); + _vm->_system->copyRectToScreen(source->getPixels(), 640, 0, 80, 640, 320); change(); } diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp index 72a61fefb2..f9a938bfd4 100644 --- a/engines/groovie/roq.cpp +++ b/engines/groovie/roq.cpp @@ -160,7 +160,7 @@ bool ROQPlayer::playFrameInternal() { if (_dirty) { // Update the screen - _syst->copyRectToScreen(_bg->getBasePtr(0, 0), _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h); + _syst->copyRectToScreen(_bg->getPixels(), _bg->pitch, 0, (_syst->getHeight() - _bg->h) / 2, _bg->w, _bg->h); _syst->updateScreen(); // Clear the dirty flag @@ -291,8 +291,8 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) { } // Clear the buffers with black YUV values - byte *ptr1 = (byte *)_currBuf->getBasePtr(0, 0); - byte *ptr2 = (byte *)_prevBuf->getBasePtr(0, 0); + byte *ptr1 = (byte *)_currBuf->getPixels(); + byte *ptr2 = (byte *)_prevBuf->getPixels(); for (int i = 0; i < width * height; i++) { *ptr1++ = 0; *ptr1++ = 128; @@ -436,11 +436,11 @@ bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) { Graphics::JPEGDecoder *jpg = new Graphics::JPEGDecoder(); jpg->loadStream(*_file); - const byte *y = (const byte *)jpg->getComponent(1)->getBasePtr(0, 0); - const byte *u = (const byte *)jpg->getComponent(2)->getBasePtr(0, 0); - const byte *v = (const byte *)jpg->getComponent(3)->getBasePtr(0, 0); + const byte *y = (const byte *)jpg->getComponent(1)->getPixels(); + const byte *u = (const byte *)jpg->getComponent(2)->getPixels(); + const byte *v = (const byte *)jpg->getComponent(3)->getPixels(); - byte *ptr = (byte *)_currBuf->getBasePtr(0, 0); + byte *ptr = (byte *)_currBuf->getPixels(); for (int i = 0; i < _currBuf->w * _currBuf->h; i++) { *ptr++ = *y++; *ptr++ = *u++; diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index cbbdecc3e7..8e3bef9945 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -373,7 +373,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) { DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) { rect.translate(0, -80); _vm->_graphicsMan->_foreground.frameRect(rect, 250); - _vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getBasePtr(0, 0), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320); + _vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320); _vm->_system->updateScreen(); } @@ -983,7 +983,7 @@ void Script::o_strcmpnejmp_var() { // 0x21 void Script::o_copybgtofg() { // 0x22 debugScript(1, true, "COPY_BG_TO_FG"); - memcpy(_vm->_graphicsMan->_foreground.getBasePtr(0, 0), _vm->_graphicsMan->_background.getBasePtr(0, 0), 640 * 320); + memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * 320); } void Script::o_strcmpeqjmp() { // 0x23 diff --git a/engines/groovie/stuffit.cpp b/engines/groovie/stuffit.cpp index 37f12585e7..60a57a0129 100644 --- a/engines/groovie/stuffit.cpp +++ b/engines/groovie/stuffit.cpp @@ -249,7 +249,7 @@ void StuffItArchive::update14(uint16 first, uint16 last, byte *code, uint16 *fre do { while (++i < last && code[first] > code[i]) ; - + while (--j > first && code[first] < code[j]) ; diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp index 8786e75488..59d966a22f 100644 --- a/engines/groovie/vdx.cpp +++ b/engines/groovie/vdx.cpp @@ -358,7 +358,7 @@ void VDXPlayer::getStill(Common::ReadStream *in) { byte *buf; if (_flagOne) { // Paint to the foreground - buf = (byte *)_fg->getBasePtr(0, 0); + buf = (byte *)_fg->getPixels(); if (_flag2Byte) { mask = 0xff; } else { @@ -370,7 +370,7 @@ void VDXPlayer::getStill(Common::ReadStream *in) { _flagFirstFrame = true; } else { // Paint to the background - buf = (byte *)_bg->getBasePtr(0, 0); + buf = (byte *)_bg->getPixels(); } // Read the palette @@ -486,9 +486,9 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth) // TODO: Verify just the else block is required //if (_flagOne) { // Paint to the foreground - //dest = (byte *)_fg->getBasePtr(0, 0) + offset; + //dest = (byte *)_fg->getPixels() + offset; //} else { - dest = (byte *)_bg->getBasePtr(0, 0) + offset; + dest = (byte *)_bg->getPixels() + offset; //} // Move the pointers to the beginning of the current block @@ -496,8 +496,8 @@ void VDXPlayer::decodeBlockDelta(uint32 offset, byte *colors, uint16 imageWidth) dest += blockOff; byte *fgBuf = 0; if (_flagSeven) { - fgBuf = (byte *)_fg->getBasePtr(0, 0) + offset + blockOff; - //byte *bgBuf = (byte *)_bg->getBasePtr(0, 0) + offset + blockOff; + fgBuf = (byte *)_fg->getPixels() + offset + blockOff; + //byte *bgBuf = (byte *)_bg->getPixels() + offset + blockOff; } for (int y = TILE_SIZE; y; y--) { @@ -550,7 +550,7 @@ void VDXPlayer::fadeIn(uint8 *targetpal) { // TODO: Is it required? If so, move to an appropiate place // Copy the foreground to the background - memcpy((byte *)_vm->_graphicsMan->_foreground.getBasePtr(0, 0), (byte *)_vm->_graphicsMan->_background.getBasePtr(0, 0), 640 * 320); + memcpy((byte *)_vm->_graphicsMan->_foreground.getPixels(), (byte *)_vm->_graphicsMan->_background.getPixels(), 640 * 320); // Start a fadein _vm->_graphicsMan->fadeIn(targetpal); diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp index f7b923badf..c09d748b97 100644 --- a/engines/hopkins/computer.cpp +++ b/engines/hopkins/computer.cpp @@ -58,7 +58,7 @@ ComputerManager::ComputerManager(HopkinsEngine *vm) { _minBreakoutMoveSpeed = 0; _maxBreakoutMoveSpeed = 0; _lastBreakoutMoveSpeed = 0; - _breakoutHiscore = 0; + _lowestHiScore = 0; } /** @@ -579,26 +579,32 @@ void ComputerManager::displayGamesSubMenu() { */ void ComputerManager::loadHiscore() { byte *ptr = _vm->_globals->allocMemory(100); - _vm->_saveLoad->load("HISCORE.DAT", ptr); + memset(ptr, 0, 100); + + if (_vm->_saveLoad->saveExists(_vm->getTargetName() + "-highscore.dat")) + _vm->_saveLoad->load(_vm->getTargetName() + "-highscore.dat", ptr); for (int scoreIndex = 0; scoreIndex < 6; ++scoreIndex) { - for (int i = 0; i < 5; ++i) { + _score[scoreIndex]._name = " "; + _score[scoreIndex]._score = " "; + + for (int i = 0; i < 6; ++i) { char nextChar = ptr[(16 * scoreIndex) + i]; if (!nextChar) nextChar = ' '; - _score[scoreIndex]._name += nextChar; + _score[scoreIndex]._name.setChar(nextChar, i); } for (int i = 0; i < 9; ++i) { char nextChar = ptr[(scoreIndex * 16) + 6 + i]; if (!nextChar) nextChar = '0'; - _score[scoreIndex]._score += nextChar; + _score[scoreIndex]._score.setChar(nextChar, i); } } + _lowestHiScore = atol(_score[5]._score.c_str()); _vm->_globals->freeMemory(ptr); - _breakoutHiscore = atol(_score[5]._score.c_str()); } /** @@ -779,7 +785,7 @@ void ComputerManager::playBreakout() { _vm->_events->mouseOn(); _vm->_objectsMan->removeSprite(0); _vm->_objectsMan->removeSprite(1); - if (_breakoutScore > _breakoutHiscore) + if (_breakoutScore > _lowestHiScore) getScoreName(); if (displayHiscores() != 1) break; @@ -823,11 +829,11 @@ int ComputerManager::displayHiscores() { yp += 46; // Display the characters of the name - for (int i = 0; i <= 5; i++) + for (int i = 0; i < 6; i++) displayHiscoreLine(ptr, 9 * i + 69, yp, _score[scoreIndex]._name[i]); // Display the digits of the score - for (int i = 0; i <= 8; i++) + for (int i = 0; i < 9; i++) displayHiscoreLine(ptr, 9 * i + 199, yp, _score[scoreIndex]._score[i]); } @@ -864,6 +870,19 @@ void ComputerManager::getScoreName() { _vm->_graphicsMan->setColorPercentage(254, 0, 0, 0); byte *ptr = _vm->_fileIO->loadFile("ALPHA.SPR"); _vm->_graphicsMan->fadeInBreakout(); + + // Figure out the line to put the new high score on + int scoreLine = 0; + while (scoreLine < 5 && _breakoutScore < atol(_score[scoreLine]._score.c_str())) + ++scoreLine; + + // If it's not the lasat line, move the lines down + for (int line = 5; line > scoreLine; --line) { + _score[line]._name = _score[line - 1]._name; + _score[line]._score = _score[line - 1]._score; + } + + // Get the name for the new high score for (int strPos = 0; strPos <= 4; strPos++) { displayHiscoreLine(ptr, 9 * strPos + 140, 78, 1); @@ -873,13 +892,15 @@ void ComputerManager::getScoreName() { if ((curChar > '9') && (curChar < 'A')) curChar = ' '; - _score[5]._name.setChar(curChar, strPos); + _score[scoreLine]._name.setChar(curChar, strPos); displayHiscoreLine(ptr, 9 * strPos + 140, 78, curChar); for (int idx = 0; idx < 12; ++idx) _vm->_events->refreshScreenAndEvents(); } - _score[5]._score = " "; + + // Set up the new score + _score[scoreLine]._score = " "; char score[16]; sprintf(score, "%d", _breakoutScore); @@ -888,8 +909,8 @@ void ComputerManager::getScoreName() { ++scoreLen; while (score[scoreLen]); - for (int i = scoreLen, scorePos = 8; i >= 0; i--) { - _score[5]._score.setChar(score[i], scorePos--); + for (int i = scoreLen - 1, scorePos = 8; i >= 0; i--) { + _score[scoreLine]._score.setChar(score[i], scorePos--); } _vm->_graphicsMan->fadeOutBreakout(); _vm->_globals->freeMemory(ptr); @@ -970,10 +991,10 @@ void ComputerManager::saveScore() { } byte *ptr = _vm->_globals->allocMemory(100); - memset(ptr, 0, 99); + memset(ptr, 0, 100); for (int scorePlaceIdx = 0; scorePlaceIdx <= 5; scorePlaceIdx++) { int curBufPtr = 16 * scorePlaceIdx; - for (int namePos = 0; namePos <= 4; namePos++) { + for (int namePos = 0; namePos < 6; namePos++) { char curChar = _score[scorePlace[scorePlaceIdx]]._name[namePos]; if (!curChar) curChar = ' '; @@ -991,7 +1012,7 @@ void ComputerManager::saveScore() { ptr[curBufPtr + 15] = 0; } - _vm->_saveLoad->saveFile("HISCORE.DAT", ptr, 100); + _vm->_saveLoad->saveFile(_vm->getTargetName() + "-highscore.dat", ptr, 100); _vm->_globals->freeMemory(ptr); } diff --git a/engines/hopkins/computer.h b/engines/hopkins/computer.h index cdd653f793..1771bba7d6 100644 --- a/engines/hopkins/computer.h +++ b/engines/hopkins/computer.h @@ -63,7 +63,7 @@ private: bool _ballUpFl; int _breakoutLevelNbr; int _padPositionX; - int _breakoutHiscore; + int _lowestHiScore; int _minBreakoutMoveSpeed; int _maxBreakoutMoveSpeed; int _lastBreakoutMoveSpeed; diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp index 9d16b0ab51..c617a5aacf 100644 --- a/engines/hopkins/detection.cpp +++ b/engines/hopkins/detection.cpp @@ -56,6 +56,10 @@ bool HopkinsEngine::getIsDemo() const { return _gameDescription->desc.flags & ADGF_DEMO; } +const Common::String &HopkinsEngine::getTargetName() const { + return _targetName; +} + } // End of namespace Hopkins static const PlainGameDescriptor hopkinsGames[] = { diff --git a/engines/hopkins/dialogs.cpp b/engines/hopkins/dialogs.cpp index 6cdfbf47d1..3b8fedf0ee 100644 --- a/engines/hopkins/dialogs.cpp +++ b/engines/hopkins/dialogs.cpp @@ -505,7 +505,7 @@ void DialogsManager::inventAnim() { return; if (_vm->_objectsMan->_eraseVisibleCounter && !_vm->_objectsMan->_visibleFl) { - _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _oldInventX, 27, 48, 38, + _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _oldInventX, 27, 48, 38, _vm->_graphicsMan->_frontBuffer, _oldInventX, 27); _vm->_graphicsMan->addDirtyRect(_oldInventX, 27, _oldInventX + 48, 65); --_vm->_objectsMan->_eraseVisibleCounter; @@ -691,7 +691,7 @@ void DialogsManager::showSaveLoad(SaveLoadMode mode) { Graphics::Surface thumb8; _vm->_saveLoad->convertThumb16To8(header._thumbnail, &thumb8); - byte *thumb = (byte *)thumb8.pixels; + byte *thumb = (byte *)thumb8.getPixels(); int16 startPosX_ = _vm->_events->_startPos.x; switch (slotNumber) { diff --git a/engines/hopkins/globals.cpp b/engines/hopkins/globals.cpp index 28f22ed99e..a9a0a81f08 100644 --- a/engines/hopkins/globals.cpp +++ b/engines/hopkins/globals.cpp @@ -134,7 +134,7 @@ Globals::~Globals() { void Globals::setConfig() { // CHECKME: Should be in Globals() but it doesn't work // The Polish version is a translation of the English version. The filenames are the same. - // The Russian version looks like a translation of the English version, based on the filenames. + // The Russian version looks like a translation of the English version, based on the filenames. switch (_vm->getLanguage()) { case Common::EN_ANY: case Common::PL_POL: diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp index ebc5cfa8da..de9f043763 100644 --- a/engines/hopkins/graphics.cpp +++ b/engines/hopkins/graphics.cpp @@ -325,7 +325,7 @@ void GraphicsManager::loadPCX640(byte *surface, const Common::String &file, byte // Copy out the dimensions and pixels of the decoded surface _largeScreenFl = s->w > SCREEN_WIDTH; - Common::copy((byte *)s->pixels, (byte *)s->pixels + (s->pitch * s->h), surface); + Common::copy((const byte *)s->getPixels(), (const byte *)s->getBasePtr(0, s->h), surface); // Copy out the palette const byte *palSrc = pcxDecoder.getPalette(); @@ -1179,7 +1179,7 @@ void GraphicsManager::displayZones() { Common::Rect r(_vm->_objectsMan->_bob[bobId]._oldX, _vm->_objectsMan->_bob[bobId]._oldY, _vm->_objectsMan->_bob[bobId]._oldX + _vm->_objectsMan->_bob[bobId]._oldWidth, _vm->_objectsMan->_bob[bobId]._oldY + _vm->_objectsMan->_bob[bobId]._oldHeight); - + displayDebugRect(screenSurface, r, 0xff0000); } } @@ -1202,15 +1202,13 @@ void GraphicsManager::displayZones() { void GraphicsManager::displayLines() { Graphics::Surface *screenSurface = g_system->lockScreen(); - uint16* pixels = (uint16*)screenSurface->pixels; - - for (int lineIndex = 0; lineIndex < _vm->_linesMan->_linesNumb; lineIndex++) { + for (int lineIndex = 0; lineIndex < _vm->_linesMan->_linesNumb; lineIndex++) { int i = 0; do { int x = _vm->_linesMan->_lineItem[lineIndex]._lineData[i] - _scrollPosX; int y = _vm->_linesMan->_lineItem[lineIndex]._lineData[i+1]; if (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT) { - pixels[ y * screenSurface->w + x ] = 0xffff; + WRITE_UINT16(screenSurface->getBasePtr(x, y), 0xffff); } i += 2; } @@ -1230,7 +1228,7 @@ void GraphicsManager::displayDebugRect(Graphics::Surface *surface, const Common: r.top = MAX(r.top, (int16)0); r.right = MIN(r.right, (int16)SCREEN_WIDTH); r.bottom = MIN(r.bottom, (int16)SCREEN_HEIGHT); - + // If there's an on-screen portion, display it if (r.isValidRect()) surface->frameRect(r, color); diff --git a/engines/hopkins/graphics.h b/engines/hopkins/graphics.h index 268db7fc2b..8767f5ec4d 100644 --- a/engines/hopkins/graphics.h +++ b/engines/hopkins/graphics.h @@ -125,7 +125,7 @@ public: public: GraphicsManager(HopkinsEngine *vm); ~GraphicsManager(); - + void clearPalette(); void clearScreen(); void clearVesaScreen(); diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp index 407f264116..96131f2968 100644 --- a/engines/hopkins/hopkins.cpp +++ b/engines/hopkins/hopkins.cpp @@ -35,12 +35,9 @@ namespace Hopkins { -HopkinsEngine *g_vm; - HopkinsEngine::HopkinsEngine(OSystem *syst, const HopkinsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Hopkins") { DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); - g_vm = this; _animMan = new AnimationManager(this); _computer = new ComputerManager(this); _dialog = new DialogsManager(this); @@ -95,7 +92,7 @@ bool HopkinsEngine::canLoadGameStateCurrently() { * Returns true if it is currently okay to save the game */ bool HopkinsEngine::canSaveGameStateCurrently() { - return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl + return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl && _globals->_curRoomNum != 0 && !isUnderwaterSubScene(); } @@ -114,8 +111,6 @@ Common::Error HopkinsEngine::saveGameState(int slot, const Common::String &desc) } Common::Error HopkinsEngine::run() { - _saveLoad->initSaves(); - _globals->setConfig(); _fileIO->initCensorship(); initializeSystem(); @@ -164,7 +159,7 @@ bool HopkinsEngine::runWin95Demo() { _globals->_speed = 3; if (_startGameSlot == -1) - _graphicsMan->fadeOutLong(); + _graphicsMan->fadeOutShort(); _globals->_eventMode = EVENTMODE_IGNORE; _globals->_characterSpriteBuf = _fileIO->loadFile("PERSO.SPR"); @@ -201,12 +196,15 @@ bool HopkinsEngine::runWin95Demo() { switch (_globals->_exitId) { case 1: + // Handles room: Apartment _linesMan->setMaxLineIdx(40); _globals->_characterMaxPosY = 435; _objectsMan->sceneControl2("IM01", "IM01", "ANIM01", "IM01", 2, true); break; case 3: + // - Displays bank attack when leaving the apartment + // - Handles room: bottom of the apartment if (!_globals->_saveData->_data[svBankAttackAnimPlayedFl]) { _soundMan->playSound(3); if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS) @@ -235,7 +233,7 @@ bool HopkinsEngine::runWin95Demo() { _soundMan->removeSample(2); _soundMan->removeSample(3); _soundMan->removeSample(4); - _graphicsMan->fadeOutLong(); + _graphicsMan->fadeOutShort(); _globals->_saveData->_data[svBankAttackAnimPlayedFl] = 1; } _linesMan->setMaxLineIdx(5); @@ -244,12 +242,14 @@ bool HopkinsEngine::runWin95Demo() { break; case 4: + // Handle room: City map _globals->_disableInventFl = true; _objectsMan->handleCityMap(); _globals->_disableInventFl = false; break; case 5: + // Handle room: Outside the bank _linesMan->setMaxLineIdx(5); _globals->_characterMaxPosY = 455; @@ -793,14 +793,14 @@ bool HopkinsEngine::runFull() { if (_startGameSlot == -1) { if (getPlatform() == Common::kPlatformLinux) { - _graphicsMan->loadImage("H2"); - _graphicsMan->fadeInLong(); - _events->delay(500); - _graphicsMan->fadeOutLong(); - _globals->_speed = 2; - _globals->_eventMode = EVENTMODE_IGNORE; - _graphicsMan->_fadingFl = true; - _animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200); + _graphicsMan->loadImage("H2"); + _graphicsMan->fadeInLong(); + _events->delay(500); + _graphicsMan->fadeOutLong(); + _globals->_speed = 2; + _globals->_eventMode = EVENTMODE_IGNORE; + _graphicsMan->_fadingFl = true; + _animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200); } else { _animMan->playAnim("MP.ANM", "MP.ANM", 10, 16, 200); _graphicsMan->fadeOutLong(); @@ -1133,12 +1133,14 @@ bool HopkinsEngine::runFull() { break; case 30: + // Shooting _linesMan->setMaxLineIdx(15); _globals->_characterMaxPosY = 440; _objectsMan->sceneControl2("IM30", "IM30", "ANIM30", "IM30", 24, false); break; case 31: + // Shooting target _objectsMan->sceneControl("IM31", "IM31", "ANIM31", "IM31", 10, true); break; @@ -1153,6 +1155,7 @@ bool HopkinsEngine::runFull() { break; case 34: + // In the airport, before the flight cut-scene _objectsMan->sceneControl("IM34", "IM34", "ANIM34", "IM34", 2, false); break; @@ -1183,6 +1186,7 @@ bool HopkinsEngine::runFull() { } case 50: + // Flight cut scene playPlaneCutscene(); _globals->_exitId = 51; break; @@ -1904,10 +1908,7 @@ void HopkinsEngine::bombExplosion() { } void HopkinsEngine::restoreSystem() { - // If the game isn't alerady trying to quit, flag that quitting is needed - if (!shouldQuit()) - quitGame(); - + quitGame(); _events->refreshEvents(); } @@ -2232,6 +2233,8 @@ void HopkinsEngine::playPlaneCutscene() { if (!_events->_escKeyFl) { _graphicsMan->_fadingFl = true; _animMan->playAnim("PARA00A.ANM", "PARA00.ANM", 9, 9, 9); + } else { + _graphicsMan->fadeOutShort(); } _events->_escKeyFl = false; diff --git a/engines/hopkins/hopkins.h b/engines/hopkins/hopkins.h index 777fd1c335..d8c30e5004 100644 --- a/engines/hopkins/hopkins.h +++ b/engines/hopkins/hopkins.h @@ -164,6 +164,7 @@ public: Common::Platform getPlatform() const; uint16 getVersion() const; bool getIsDemo() const; + const Common::String &getTargetName() const; int getRandomNumber(int maxNumber); Common::String generateSaveName(int slotNumber); @@ -183,9 +184,6 @@ public: virtual void syncSoundSettings(); }; -// Global reference to the HopkinsEngine object -extern HopkinsEngine *g_vm; - } // End of namespace Hopkins #endif /* HOPKINS_HOPKINS_H */ diff --git a/engines/hopkins/saveload.cpp b/engines/hopkins/saveload.cpp index 45b4885c90..b0dea7e6d1 100644 --- a/engines/hopkins/saveload.cpp +++ b/engines/hopkins/saveload.cpp @@ -43,39 +43,38 @@ SaveLoadManager::SaveLoadManager(HopkinsEngine *vm) { } bool SaveLoadManager::save(const Common::String &file, const void *buf, size_t n) { - Common::OutSaveFile *f = g_system->getSavefileManager()->openForSaving(file); + Common::OutSaveFile *savefile = g_system->getSavefileManager()->openForSaving(file); - if (f) { - size_t bytesWritten = f->write(buf, n); - f->finalize(); - delete f; + if (savefile) { + size_t bytesWritten = savefile->write(buf, n); + savefile->finalize(); + delete savefile; return bytesWritten == n; } else return false; } +bool SaveLoadManager::saveExists(const Common::String &file) { + Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file); + bool result = savefile != NULL; + delete savefile; + return result; +} + // Save File bool SaveLoadManager::saveFile(const Common::String &file, const void *buf, size_t n) { return save(file, buf, n); } -void SaveLoadManager::initSaves() { - Common::String dataFilename = "HISCORE.DAT"; - byte data[100]; - Common::fill(&data[0], &data[100], 0); - - saveFile(dataFilename, data, 100); -} - void SaveLoadManager::load(const Common::String &file, byte *buf) { - Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(file); - if (f == NULL) - error("Error openinig file - %s", file.c_str()); + Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file); + if (savefile == NULL) + error("Error opening file - %s", file.c_str()); - int32 filesize = f->size(); - f->read(buf, filesize); - delete f; + int32 filesize = savefile->size(); + savefile->read(buf, filesize); + delete savefile; } bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header) { @@ -215,13 +214,13 @@ Common::Error SaveLoadManager::loadGame(int slot) { bool SaveLoadManager::readSavegameHeader(int slot, hopkinsSavegameHeader &header) { // Try and open the save file for reading - Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading( - g_vm->generateSaveName(slot)); - if (!saveFile) + Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading( + _vm->generateSaveName(slot)); + if (!savefile) return false; - bool result = readSavegameHeader(saveFile, header); - delete saveFile; + bool result = readSavegameHeader(savefile, header); + delete savefile; return result; } @@ -234,14 +233,14 @@ void SaveLoadManager::createThumbnail(Graphics::Surface *s) { Graphics::Surface thumb8; thumb8.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - _vm->_graphicsMan->reduceScreenPart(_vm->_graphicsMan->_frontBuffer, (byte *)thumb8.pixels, + _vm->_graphicsMan->reduceScreenPart(_vm->_graphicsMan->_frontBuffer, (byte *)thumb8.getPixels(), _vm->_events->_startPos.x, 20, SCREEN_WIDTH, SCREEN_HEIGHT - 40, 80); // Convert the 8-bit pixel to 16 bit surface s->create(w, h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); - const byte *srcP = (const byte *)thumb8.pixels; - uint16 *destP = (uint16 *)s->pixels; + const byte *srcP = (const byte *)thumb8.getPixels(); + uint16 *destP = (uint16 *)s->getPixels(); for (int yp = 0; yp < h; ++yp) { // Copy over the line, using the source pixels as lookups into the pixels palette @@ -259,6 +258,10 @@ void SaveLoadManager::createThumbnail(Graphics::Surface *s) { } void SaveLoadManager::syncSavegameData(Common::Serializer &s, int version) { + // The brief version 3 had the highscores embedded. They're in a separate file now, so skip + if (version == 3 && s.isLoading()) + s.skip(100); + s.syncBytes(&_vm->_globals->_saveData->_data[0], 2050); syncCharacterLocation(s, _vm->_globals->_saveData->_cloneHopkins); syncCharacterLocation(s, _vm->_globals->_saveData->_realHopkins); @@ -296,8 +299,8 @@ void SaveLoadManager::convertThumb16To8(Graphics::Surface *thumb16, Graphics::Su pixelFormat16.colorToRGB(p, paletteR[palIndex], paletteG[palIndex], paletteB[palIndex]); } - const uint16 *srcP = (const uint16 *)thumb16->pixels; - byte *destP = (byte *)thumb8->pixels; + const uint16 *srcP = (const uint16 *)thumb16->getPixels(); + byte *destP = (byte *)thumb8->getPixels(); for (int yp = 0; yp < thumb16->h; ++yp) { const uint16 *lineSrcP = srcP; diff --git a/engines/hopkins/saveload.h b/engines/hopkins/saveload.h index 221a445fd2..5b77c11f12 100644 --- a/engines/hopkins/saveload.h +++ b/engines/hopkins/saveload.h @@ -35,7 +35,7 @@ namespace Hopkins { class HopkinsEngine; -#define HOPKINS_SAVEGAME_VERSION 2 +#define HOPKINS_SAVEGAME_VERSION 4 struct hopkinsSavegameHeader { uint8 _version; @@ -56,14 +56,14 @@ private: public: SaveLoadManager(HopkinsEngine *vm); - void initSaves(); + bool saveExists(const Common::String &file); bool save(const Common::String &file, const void *buf, size_t n); bool saveFile(const Common::String &file, const void *buf, size_t n); void load(const Common::String &file, byte *buf); static bool readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header); void writeSavegameHeader(Common::OutSaveFile *out, hopkinsSavegameHeader &header); - static bool readSavegameHeader(int slot, hopkinsSavegameHeader &header); + bool readSavegameHeader(int slot, hopkinsSavegameHeader &header); Common::Error saveGame(int slot, const Common::String &saveName); Common::Error loadGame(int slot); diff --git a/engines/hopkins/script.cpp b/engines/hopkins/script.cpp index c39273203d..7e150624b8 100644 --- a/engines/hopkins/script.cpp +++ b/engines/hopkins/script.cpp @@ -536,6 +536,7 @@ int ScriptManager::handleOpcode(const byte *dataP) { break; case 12: + // Bank - negotiations between Hopkins and one of the killers _vm->_fontMan->hideText(9); _vm->_events->refreshScreenAndEvents(); _vm->_events->refreshScreenAndEvents(); @@ -543,6 +544,7 @@ int ScriptManager::handleOpcode(const byte *dataP) { break; case 13: + // Bank - after negotiations, Hopkins enters the bank _vm->_events->_mouseButton = _vm->_events->_curMouseButton; _vm->_globals->_disableInventFl = true; _vm->_graphicsMan->fadeOutLong(); @@ -553,9 +555,7 @@ int ScriptManager::handleOpcode(const byte *dataP) { _vm->_graphicsMan->endDisplayBob(); _vm->_objectsMan->clearScreen(); - if ((_vm->getPlatform() == Common::kPlatformWindows) && _vm->getIsDemo()) { - _vm->_graphicsMan->fadeOutLong(); - } else { + if ((_vm->getPlatform() != Common::kPlatformWindows) || !_vm->getIsDemo()) { _vm->_soundMan->playSoundFile("SOUND17.WAV"); _vm->_graphicsMan->_fadingFl = true; _vm->_animMan->playSequence2("HELICO.SEQ", 10, 4, 10); @@ -615,10 +615,6 @@ int ScriptManager::handleOpcode(const byte *dataP) { _vm->_graphicsMan->_fadingFl = true; _vm->_animMan->playSequence2("ASSOM.SEQ", 10, 4, 500); _vm->_soundMan->_specialSoundNum = 0; - - if ((_vm->getPlatform() == Common::kPlatformWindows) && _vm->getIsDemo()) - _vm->_graphicsMan->fadeOutLong(); - _vm->_globals->_disableInventFl = false; _vm->_objectsMan->_helicopterFl = true; break; @@ -1221,6 +1217,7 @@ int ScriptManager::handleOpcode(const byte *dataP) { break; case 88: + // Shooting target - Shooting at target if (_vm->_globals->_saveData->_data[svField183] == 1) { _vm->_objectsMan->setBobAnimDataIdx(1, 0); _vm->_objectsMan->setBobAnimDataIdx(2, 0); @@ -1298,6 +1295,7 @@ int ScriptManager::handleOpcode(const byte *dataP) { break; case 90: + // Shooting target - Using the level _vm->_soundMan->playSoundFile("SOUND52.WAV"); if (!_vm->_globals->_saveData->_data[svField186]) { _vm->_animMan->playSequence("CIB5A.SEQ", 1, 12, 1, false, false); @@ -1984,6 +1982,7 @@ int ScriptManager::handleOpcode(const byte *dataP) { break; case 216: + // Discuss with pilot just before Flight cutscene _vm->_globals->_introSpeechOffFl = true; _vm->_talkMan->startAnimatedCharacterDialogue("aviat1.pe2"); _vm->_globals->_introSpeechOffFl = false; diff --git a/engines/hugo/dialogs.cpp b/engines/hugo/dialogs.cpp index 0f07d52aee..5dcee3ae94 100644 --- a/engines/hugo/dialogs.cpp +++ b/engines/hugo/dialogs.cpp @@ -140,8 +140,8 @@ void TopMenu::loadBmpArr(Common::SeekableReadStream &in) { _arrayBmp[i * 2] = bitmapSrc->convertTo(g_system->getOverlayFormat()); _arrayBmp[i * 2 + 1] = new Graphics::Surface(); _arrayBmp[i * 2 + 1]->create(_arrayBmp[i * 2]->w * 2, _arrayBmp[i * 2]->h * 2, g_system->getOverlayFormat()); - byte *src = (byte *)_arrayBmp[i * 2]->pixels; - byte *dst = (byte *)_arrayBmp[i * 2 + 1]->pixels; + byte *src = (byte *)_arrayBmp[i * 2]->getPixels(); + byte *dst = (byte *)_arrayBmp[i * 2 + 1]->getPixels(); for (int j = 0; j < _arrayBmp[i * 2]->h; j++) { src = (byte *)_arrayBmp[i * 2]->getBasePtr(0, j); diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index bcf06055f8..b140cfdba2 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -66,7 +66,7 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy _console = new HugoConsole(this); _rnd = 0; - + _screen = NULL; _mouse = NULL; _inventory = NULL; diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp index 505e356049..6f314c8774 100644 --- a/engines/hugo/intro.cpp +++ b/engines/hugo/intro.cpp @@ -89,11 +89,7 @@ void intro_v1d::preNewGame() { void intro_v1d::introInit() { _introState = 0; _introTicks = 0; - _surf.w = 320; - _surf.h = 200; - _surf.pixels = _vm->_screen->getFrontBuffer(); - _surf.pitch = 320; - _surf.format = Graphics::PixelFormat::createFormatCLUT8(); + _surf.init(320, 200, 320, _vm->_screen->getFrontBuffer(), Graphics::PixelFormat::createFormatCLUT8()); _vm->_screen->displayList(kDisplayInit); } @@ -243,11 +239,7 @@ void intro_v2d::preNewGame() { void intro_v2d::introInit() { _vm->_screen->displayList(kDisplayInit); _vm->_file->readBackground(_vm->_numScreens - 1); // display splash screen - _surf.w = 320; - _surf.h = 200; - _surf.pixels = _vm->_screen->getFrontBuffer(); - _surf.pitch = 320; - _surf.format = Graphics::PixelFormat::createFormatCLUT8(); + _surf.init(320, 200, 320, _vm->_screen->getFrontBuffer(), Graphics::PixelFormat::createFormatCLUT8()); char buffer[128]; @@ -289,11 +281,7 @@ void intro_v3d::preNewGame() { void intro_v3d::introInit() { _vm->_screen->displayList(kDisplayInit); _vm->_file->readBackground(_vm->_numScreens - 1); // display splash screen - _surf.w = 320; - _surf.h = 200; - _surf.pixels = _vm->_screen->getFrontBuffer(); - _surf.pitch = 320; - _surf.format = Graphics::PixelFormat::createFormatCLUT8(); + _surf.init(320, 200, 320, _vm->_screen->getFrontBuffer(), Graphics::PixelFormat::createFormatCLUT8()); char buffer[128]; if (_vm->_boot._registered) diff --git a/engines/kyra/gui_mr.cpp b/engines/kyra/gui_mr.cpp index bcbfe27b69..ee0303c8c3 100644 --- a/engines/kyra/gui_mr.cpp +++ b/engines/kyra/gui_mr.cpp @@ -737,7 +737,7 @@ void KyraEngine_MR::loadAlbumPageWSA() { if (_album.curPage != 14) { filename = Common::String::format("PAGE%x.WSA", _album.curPage+1); _album.rightPage.wsa->open(filename.c_str(), 1, 0); - _album.rightPage.maxFrame = _album.leftPage.wsa->frames()-1; + _album.rightPage.maxFrame = _album.rightPage.wsa->frames()-1; } } diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp index f8eb7d00cd..4f7adcc6e5 100644 --- a/engines/kyra/kyra_rpg.cpp +++ b/engines/kyra/kyra_rpg.cpp @@ -213,7 +213,7 @@ void KyraRpgEngine::drawDialogueButtons() { screen()->printText(_dialogueButtonString[i], (x + 37 - (screen()->getTextWidth(_dialogueButtonString[i])) / 2) & ~3, ((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xC1 : 0xE1, 0); } else { - int sjisYOffset = (_flags.lang == Common::JA_JPN && _dialogueButtonString[i][0] < 0) ? 2 : 0; + int sjisYOffset = (_flags.lang == Common::JA_JPN && (_dialogueButtonString[i][0] & 0x80)) ? 2 : 0; gui_drawBox(x, (_dialogueButtonYoffs + _dialogueButtonPosY[i]), _dialogueButtonWidth, guiSettings()->buttons.height, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill); screen()->printText(_dialogueButtonString[i], x + (_dialogueButtonWidth >> 1) - (screen()->getTextWidth(_dialogueButtonString[i])) / 2, (_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2 - sjisYOffset, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0); diff --git a/engines/kyra/scene_mr.cpp b/engines/kyra/scene_mr.cpp index c9486d9c45..d2b4907b6a 100644 --- a/engines/kyra/scene_mr.cpp +++ b/engines/kyra/scene_mr.cpp @@ -577,6 +577,7 @@ void KyraEngine_MR::initSceneScreen(int unk1) { } updateCharPal(0); + _screen->updateScreen(); if (!_menuDirectlyToLoad) { _emc->start(&_sceneScriptState, 3); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 419b630714..8c97e46a8f 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -718,6 +718,13 @@ void Screen::fadePalette(const Palette &pal, int delay, const UpdateFunctor *upF _vm->delay((delayAcc >> 8) * 1000 / 60); delayAcc &= 0xFF; } + + // In case we should quit we setup the final palette here. This avoids + // ugly palette glitches when quitting while fading. This can for example + // be noticed when quitting while viewing the family album in Kyra3. + if (_vm->shouldQuit()) { + setScreenPalette(pal); + } } void Screen::getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff) { @@ -1256,7 +1263,7 @@ int Screen::getTextWidth(const char *str) { while (1) { if (_sjisMixedFontMode) - setFont(*str < 0 ? FID_SJIS_FNT : curFont); + setFont((*str & 0x80) ? FID_SJIS_FNT : curFont); uint c = fetchChar(str); @@ -1296,7 +1303,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 while (1) { if (_sjisMixedFontMode) - setFont(*str < 0 ? FID_SJIS_FNT : curFont); + setFont((*str & 0x80) ? FID_SJIS_FNT : curFont); uint8 charHeightFnt = getFontHeight(); diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp index 7618259e69..832bcc2e26 100644 --- a/engines/lastexpress/data/animation.cpp +++ b/engines/lastexpress/data/animation.cpp @@ -270,7 +270,7 @@ void Animation::play() { draw(s); // XXX: Update the screen - g_system->copyRectToScreen(s->pixels, s->pitch, 0, 0, s->w, s->h); + g_system->copyRectToScreen(s->getPixels(), s->pitch, 0, 0, s->w, s->h); // Free the temporary surface s->free(); diff --git a/engines/lastexpress/data/sequence.cpp b/engines/lastexpress/data/sequence.cpp index a5bcba84cd..c7073b560c 100644 --- a/engines/lastexpress/data/sequence.cpp +++ b/engines/lastexpress/data/sequence.cpp @@ -128,8 +128,8 @@ AnimFrame::~AnimFrame() { } Common::Rect AnimFrame::draw(Graphics::Surface *s) { - byte *inp = (byte *)_image.pixels; - uint16 *outp = (uint16 *)s->pixels; + byte *inp = (byte *)_image.getPixels(); + uint16 *outp = (uint16 *)s->getPixels(); for (int i = 0; i < 640 * 480; i++, inp++, outp++) { if (*inp) *outp = _palette[*inp]; @@ -155,7 +155,7 @@ void AnimFrame::decomp4(Common::SeekableReadStream *in, const FrameInfo &f) { } void AnimFrame::decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byte mask, byte shift) { - byte *p = (byte *)_image.getBasePtr(0, 0); + byte *p = (byte *)_image.getPixels(); uint32 skip = f.initialSkip / 2; uint32 size = f.decompressedEndOffset / 2; @@ -200,7 +200,7 @@ void AnimFrame::decomp34(Common::SeekableReadStream *in, const FrameInfo &f, byt } void AnimFrame::decomp5(Common::SeekableReadStream *in, const FrameInfo &f) { - byte *p = (byte *)_image.getBasePtr(0, 0); + byte *p = (byte *)_image.getPixels(); uint32 skip = f.initialSkip / 2; uint32 size = f.decompressedEndOffset / 2; @@ -235,7 +235,7 @@ void AnimFrame::decomp5(Common::SeekableReadStream *in, const FrameInfo &f) { } void AnimFrame::decomp7(Common::SeekableReadStream *in, const FrameInfo &f) { - byte *p = (byte *)_image.getBasePtr(0, 0); + byte *p = (byte *)_image.getPixels(); uint32 skip = f.initialSkip / 2; uint32 size = f.decompressedEndOffset / 2; @@ -288,7 +288,7 @@ void AnimFrame::decomp7(Common::SeekableReadStream *in, const FrameInfo &f) { } void AnimFrame::decompFF(Common::SeekableReadStream *in, const FrameInfo &f) { - byte *p = (byte *)_image.getBasePtr(0, 0); + byte *p = (byte *)_image.getPixels(); uint32 skip = f.initialSkip / 2; uint32 size = f.decompressedEndOffset / 2; diff --git a/engines/lastexpress/graphics.cpp b/engines/lastexpress/graphics.cpp index 753c3a39e4..9ced38a2e1 100644 --- a/engines/lastexpress/graphics.cpp +++ b/engines/lastexpress/graphics.cpp @@ -131,11 +131,11 @@ void GraphicsManager::mergePlanes() { // Clear screen surface _screen.fillRect(Common::Rect(640, 480), 0); - uint16 *screen = (uint16 *)_screen.pixels; - uint16 *inventory = (uint16 *)_inventory.pixels; - uint16 *overlay = (uint16 *)_overlay.pixels; - uint16 *backgroundC = (uint16 *)_backgroundC.pixels; - uint16 *backgroundA = (uint16 *)_backgroundA.pixels; + uint16 *screen = (uint16 *)_screen.getPixels(); + uint16 *inventory = (uint16 *)_inventory.getPixels(); + uint16 *overlay = (uint16 *)_overlay.getPixels(); + uint16 *backgroundC = (uint16 *)_backgroundC.getPixels(); + uint16 *backgroundA = (uint16 *)_backgroundA.getPixels(); for (int i = 0; i < 640 * 480; i++) { @@ -160,7 +160,7 @@ void GraphicsManager::mergePlanes() { void GraphicsManager::updateScreen() { g_system->fillScreen(0); - g_system->copyRectToScreen(_screen.getBasePtr(0, 0), 640 * 2, 0, 0, 640, 480); + g_system->copyRectToScreen(_screen.getPixels(), 640 * 2, 0, 0, 640, 480); } } // End of namespace LastExpress diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index 7fab4521f7..d0b439677d 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -260,8 +260,10 @@ void Hotspot::setAnimation(HotspotAnimData *newRecord) { _anim = NULL; _numFrames = 0; _frameNumber = 0; - if (!newRecord) return; - if (!disk.exists(newRecord->animId)) return; + if (!newRecord) + return; + if (!disk.exists(newRecord->animId)) + return; // Scan for any size overrides - some animations get their size set after decoding, but // we want it in advance so we can decode the animation straight to a graphic surface @@ -516,7 +518,8 @@ void Hotspot::endAction() { } void Hotspot::setDirection(Direction dir) { - if ((_numFrames == 0) || (_direction == dir)) return; + if ((_numFrames == 0) || (_direction == dir)) + return; uint8 newFrameNumber = 0; switch (dir) { @@ -634,7 +637,8 @@ void Hotspot::setOccupied(bool occupiedFlag) { if (xp < 0) { xp = -xp; widthVal -= xp; - if (widthVal <= 0) return; + if (widthVal <= 0) + return; xp = 0; } @@ -642,7 +646,8 @@ void Hotspot::setOccupied(bool occupiedFlag) { int x2 = xp + widthVal - ROOM_PATHS_WIDTH - 1; if (x2 >= 0) { widthVal -= (x2 + 1); - if (widthVal <= 0) return; + if (widthVal <= 0) + return; } RoomPathsData &paths = Resources::getReference().getRoom(_roomNumber)->paths; @@ -656,14 +661,16 @@ void Hotspot::setOccupied(bool occupiedFlag) { // walks the character a single step in a sequence defined by the walking list bool Hotspot::walkingStep() { - if (_pathFinder.isEmpty()) return true; + if (_pathFinder.isEmpty()) + return true; // Check to see if the end of the next straight walking slice if (_pathFinder.stepCtr() >= _pathFinder.top().numSteps()) { // Move to next slice in walking sequence _pathFinder.stepCtr() = 0; _pathFinder.pop(); - if (_pathFinder.isEmpty()) return true; + if (_pathFinder.isEmpty()) + return true; } if (_pathFinder.stepCtr() == 0) @@ -782,13 +789,15 @@ void Hotspot::showMessage(uint16 messageId, uint16 destCharacterId) { uint16 *v = (uint16 *) (msgData + READ_LE_UINT16(msgData + idx + sizeof(uint16))); while ((idVal = READ_LE_UINT16(v)) != 0xffff) { ++v; - if (READ_LE_UINT16(v) == messageId) break; + if (READ_LE_UINT16(v) == messageId) + break; ++v; } // default response if a specific response not found - if (idVal == 0xffff) idVal = 0x8c4; + if (idVal == 0xffff) + idVal = 0x8c4; debugC(ERROR_DETAILED, kLureDebugStrings, "Hotspot::showMessage idVal=%xh", idVal); if (idVal == 0x76) { @@ -826,7 +835,8 @@ void Hotspot::handleTalkDialog() { Room &room = Room::getReference(); // Return if no talk dialog is necessary - if (_data->talkCountdown == 0) return; + if (_data->talkCountdown == 0) + return; debugC(ERROR_DETAILED, kLureDebugAnimations, "Talk countdown = %d", _data->talkCountdown); if (_data->talkCountdown == CONVERSE_COUNTDOWN_SIZE) { @@ -933,7 +943,8 @@ static const uint16 validRoomExitHotspots[] = {0x2711, 0x2712, 0x2714, 0x2715, 0 bool Hotspot::isRoomExit(uint16 id) { for (const uint16 *p = &validRoomExitHotspots[0]; *p != 0; ++p) - if (*p == id) return true; + if (*p == id) + return true; return false; } @@ -1043,7 +1054,7 @@ BarPlaceResult Hotspot::getBarPlace() { index = -1; while (++index < NUM_SERVE_CUSTOMERS) { if (barEntry.customers[index].hotspotId == 0) - break; + break; } if (index == NUM_SERVE_CUSTOMERS) @@ -1391,7 +1402,8 @@ void Hotspot::doGet(HotspotData *hotspot) { Resources &res = Resources::getReference(); HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1409,7 +1421,8 @@ void Hotspot::doGet(HotspotData *hotspot) { if (sequenceOffset != 0) { uint16 execResult = Script::execute(sequenceOffset); - if (execResult == 1) return; + if (execResult == 1) + return; else if (execResult != 0) { showMessage(execResult); return; @@ -1432,7 +1445,8 @@ void Hotspot::doOperate(HotspotData *hotspot) { Action action = currentActions().top().supportData().action(); HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1467,7 +1481,8 @@ void Hotspot::doOpen(HotspotData *hotspot) { } HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1487,7 +1502,8 @@ void Hotspot::doOpen(HotspotData *hotspot) { if (sequenceOffset != 0) { sequenceOffset = Script::execute(sequenceOffset); - if (sequenceOffset == 1) return; + if (sequenceOffset == 1) + return; if (sequenceOffset != 0) { if (_exitCtr != 0) _exitCtr = 4; @@ -1522,7 +1538,8 @@ void Hotspot::doClose(HotspotData *hotspot) { } HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1575,7 +1592,8 @@ void Hotspot::doUse(HotspotData *hotspot) { } HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1616,7 +1634,8 @@ void Hotspot::doGive(HotspotData *hotspot) { } HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1662,7 +1681,8 @@ void Hotspot::doTalkTo(HotspotData *hotspot) { (hotspot->hotspotId != BLACKSMITH_ID))) { HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1706,7 +1726,8 @@ void Hotspot::doTell(HotspotData *hotspot) { assert(character); HotspotPrecheckResult hsResult = actionPrecheck(hotspot); - if (hsResult == PC_WAIT) return; + if (hsResult == PC_WAIT) + return; else if (hsResult != PC_EXECUTE) { endAction(); return; @@ -1800,7 +1821,8 @@ void Hotspot::doAsk(HotspotData *hotspot) { _data->useHotspotId = usedId; HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1886,14 +1908,17 @@ void Hotspot::doStatus(HotspotData *hotspot) { HotspotData const &rec = **i; if (rec.roomNumber == PLAYER_ID) { - if (numItems++ == 0) strcat(buffer, ": "); - else strcat(buffer, ", "); + if (numItems++ == 0) + strcat(buffer, ": "); + else + strcat(buffer, ", "); strings.getString(rec.nameId, buffer + strlen(buffer)); } } // If there were no items, add in the word 'nothing' - if (numItems == 0) strcat(buffer, stringList.getString(S_INV_NOTHING)); + if (numItems == 0) + strcat(buffer, stringList.getString(S_INV_NOTHING)); // If the player has money, add it in uint16 numGroats = res.fieldList().numGroats(); @@ -1943,7 +1968,8 @@ void Hotspot::doBribe(HotspotData *hotspot) { fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId); HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -1968,7 +1994,8 @@ void Hotspot::doBribe(HotspotData *hotspot) { sequenceOffset = res.getHotspotAction(hotspot->actionsOffset, BRIBE); if (sequenceOffset != 0) { sequenceOffset = Script::execute(sequenceOffset); - if (sequenceOffset != 0) return; + if (sequenceOffset != 0) + return; } uint16 talkIndex = res.fieldList().getField(TALK_INDEX); @@ -2004,7 +2031,8 @@ void Hotspot::doLockUnlock(HotspotData *hotspot) { fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId); HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -2156,7 +2184,8 @@ void Hotspot::npcTalkNpcToNpc(HotspotData *hotspot) { fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId); HotspotPrecheckResult result = actionPrecheck(hotspot); - if (result == PC_WAIT) return; + if (result == PC_WAIT) + return; else if (result != PC_EXECUTE) { endAction(); return; @@ -2594,7 +2623,8 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) { if (h.characterMode() == CHARMODE_PLAYER_WAIT) { h.updateMovement(); - if (bumpedPlayer) return; + if (bumpedPlayer) + return; } else { // All other character modes if (h.delayCtr() > 0) { @@ -2691,7 +2721,8 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) { res.pausedList().scan(h); pfResult = pathFinder.process(); - if (pfResult == PF_UNFINISHED) break; + if (pfResult == PF_UNFINISHED) + break; debugC(ERROR_DETAILED, kLureDebugAnimations, "pathFinder done: result = %d", pfResult); @@ -2863,7 +2894,8 @@ void HotspotTickHandlers::roomExitAnimHandler(Hotspot &h) { Room &room = Room::getReference(); RoomExitJoinData *rec = res.getExitJoin(h.hotspotId()); - if (!rec) return; + if (!rec) + return; RoomExitJoinStruct &rs = (rec->hotspots[0].hotspotId == h.hotspotId()) ? rec->hotspots[0] : rec->hotspots[1]; @@ -3036,7 +3068,8 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) { res.pausedList().scan(h); pfResult = pathFinder.process(); - if (pfResult == PF_UNFINISHED) break; + if (pfResult == PF_UNFINISHED) + break; // Pathfinding is now complete buffer = pathFinder.getDebugInfo(); @@ -3474,7 +3507,8 @@ void HotspotTickHandlers::talkAnimHandler(Hotspot &h) { showSelections |= (entry->descId & 0x3fff) != TALK_MAGIC_ID; } - if ((entry->preSequenceId & 0x8000) != 0) break; + if ((entry->preSequenceId & 0x8000) != 0) + break; } if (showSelections && (numLines > 1)) { @@ -3584,7 +3618,8 @@ void HotspotTickHandlers::talkAnimHandler(Hotspot &h) { debugC(ERROR_DETAILED, kLureDebugAnimations, "Character response pre id = %xh", _talkResponse->preSequenceId); - if (!_talkResponse->preSequenceId) break; + if (!_talkResponse->preSequenceId) + break; responseNumber = Script::execute(_talkResponse->preSequenceId); debugC(ERROR_DETAILED, kLureDebugAnimations, "Character response new response = %d", responseNumber); @@ -3680,9 +3715,12 @@ void HotspotTickHandlers::grubAnimHandler(Hotspot &h) { character = ratpouch; } - if (character->x() < 72) frameNumber = 0; - else if (character->x() < 172) frameNumber = 1; - else frameNumber = 2; + if (character->x() < 72) + frameNumber = 0; + else if (character->x() < 172) + frameNumber = 1; + else + frameNumber = 2; h.setActionCtr(frameNumber); h.setFrameNumber(frameNumber); @@ -3782,7 +3820,8 @@ void HotspotTickHandlers::barmanAnimHandler(Hotspot &h) { // Moving right h.setPosition(h.x() + 2, h.y()); h.setActionCtr(h.actionCtr() + 1); - if (h.actionCtr() >= 6) h.setActionCtr(0); + if (h.actionCtr() >= 6) + h.setActionCtr(0); } } else { // Stop the barman moving @@ -4006,6 +4045,7 @@ void HotspotTickHandlers::rackSerfAnimHandler(Hotspot &h) { h.setActionCtr(4); h.setLayer(2); + // Deliberate fall-through case 4: if (HotspotScript::execute(&h)) { h.setLayer(255); @@ -4230,7 +4270,8 @@ PathFinderResult PathFinder::process() { while (1) { // Loop through to process cells in the given area - if (!returnFlag) _yCtr = 0; + if (!returnFlag) + _yCtr = 0; while (returnFlag || (_yCtr < ROOM_PATHS_HEIGHT)) { if (!returnFlag) _xCtr = 0; @@ -4238,7 +4279,8 @@ PathFinderResult PathFinder::process() { if (!returnFlag) { processCell(&_layer[(_yChangeStart + _yCtr * _yChangeInc) * DECODED_PATHS_WIDTH + (_xChangeStart + _xCtr * _xChangeInc)]); - if (breakFlag && (_countdownCtr <= 0)) return PF_UNFINISHED; + if (breakFlag && (_countdownCtr <= 0)) + return PF_UNFINISHED; } else { returnFlag = false; } @@ -4248,7 +4290,8 @@ PathFinderResult PathFinder::process() { } // If the destination cell has been filled in, then break out of loop - if (*_pDest != 0) break; + if (*_pDest != 0) + break; if (_cellPopulated) { // At least one cell populated, so go repeat loop @@ -4306,27 +4349,37 @@ PathFinderResult PathFinder::process() { currDirection = NO_DIRECTION; while (1) { v = *pCurrent - 1; - if (v == 0) break; + if (v == 0) + break; newDirection = NO_DIRECTION; if (!altFlag && (currDirection != LEFT) && (currDirection != RIGHT)) { // Standard order direction checking - if (*(pCurrent - DECODED_PATHS_WIDTH) == v) newDirection = DOWN; - else if (*(pCurrent + DECODED_PATHS_WIDTH) == v) newDirection = UP; - else if (*(pCurrent + 1) == v) newDirection = LEFT; - else if (*(pCurrent - 1) == v) newDirection = RIGHT; + if (*(pCurrent - DECODED_PATHS_WIDTH) == v) + newDirection = DOWN; + else if (*(pCurrent + DECODED_PATHS_WIDTH) == v) + newDirection = UP; + else if (*(pCurrent + 1) == v) + newDirection = LEFT; + else if (*(pCurrent - 1) == v) + newDirection = RIGHT; } else { // Alternate order direction checking - if (*(pCurrent + 1) == v) newDirection = LEFT; - else if (*(pCurrent - 1) == v) newDirection = RIGHT; - else if (*(pCurrent - DECODED_PATHS_WIDTH) == v) newDirection = DOWN; - else if (*(pCurrent + DECODED_PATHS_WIDTH) == v) newDirection = UP; + if (*(pCurrent + 1) == v) + newDirection = LEFT; + else if (*(pCurrent - 1) == v) + newDirection = RIGHT; + else if (*(pCurrent - DECODED_PATHS_WIDTH) == v) + newDirection = DOWN; + else if (*(pCurrent + DECODED_PATHS_WIDTH) == v) + newDirection = UP; } if (newDirection == NO_DIRECTION) error("Path finding process failed"); // Process for the specified direction - if (newDirection != currDirection) add(newDirection, 0); + if (newDirection != currDirection) + add(newDirection, 0); switch (newDirection) { case UP: @@ -4373,8 +4426,10 @@ PathFinderResult PathFinder::process() { } // Final Step - if (_xPos < 0) add(RIGHT, -_xPos); - else if (_xPos > 0) add(LEFT, _xPos); + if (_xPos < 0) + add(RIGHT, -_xPos); + else if (_xPos > 0) + add(LEFT, _xPos); return result; } @@ -4401,16 +4456,20 @@ void PathFinder::processCell(uint16 *p) { // Check the surrounding cells (up,down,left,right) for values // Up vTemp = *(p - DECODED_PATHS_WIDTH); - if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp; + if ((vTemp != 0) && (vTemp < vMax)) + vMax = vTemp; // Down vTemp = *(p + DECODED_PATHS_WIDTH); - if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp; + if ((vTemp != 0) && (vTemp < vMax)) + vMax = vTemp; // Left vTemp = *(p - 1); - if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp; + if ((vTemp != 0) && (vTemp < vMax)) + vMax = vTemp; // Right vTemp = *(p + 1); - if ((vTemp != 0) && (vTemp < vMax)) vMax = vTemp; + if ((vTemp != 0) && (vTemp < vMax)) + vMax = vTemp; if (vMax != 0xffff) { // A surrounding cell with a value was found @@ -4432,7 +4491,8 @@ void PathFinder::scanLine(int numScans, int changeAmount, uint16 *&pEnd, int &v) for (int ctr = 1; ctr <= numScans; ++ctr) { pTemp += changeAmount; if ((*pTemp != 0) && (*pTemp != 0xffff)) { - if ((v < ctr) || ((v == ctr) && (*pTemp >= *pEnd))) return; + if ((v < ctr) || ((v == ctr) && (*pTemp >= *pEnd))) + return; pEnd = pTemp; v = ctr; break; @@ -4447,11 +4507,15 @@ void PathFinder::initVars() { _destX = _hotspot->destX(); _destY = _hotspot->destY(); - if (_destX < 10) _destX -= 50; - if (_destX >= FULL_SCREEN_WIDTH-10) _destX += 50; + if (_destX < 10) + _destX -= 50; + if (_destX >= FULL_SCREEN_WIDTH-10) + _destX += 50; - _xPos = 0; _yPos = 0; - _xDestPos = 0; _yDestPos = 0; + _xPos = 0; + _yPos = 0; + _xDestPos = 0; + _yDestPos = 0; _xCurrent = _hotspot->x(); if (_xCurrent < 0) { @@ -4621,7 +4685,8 @@ void Support::characterChangeRoom(Hotspot &h, uint16 roomNumber, if (h.hotspotId() == PLAYER_ID) { // Room change code for the player - if (room.cursorState() != CS_NONE) return; + if (room.cursorState() != CS_NONE) + return; PlayerNewPosition &p = fields.playerNewPos(); if (checkForIntersectingCharacter(h, newX, newY - 48, roomNumber)) { @@ -4678,7 +4743,8 @@ bool Support::charactersIntersecting(HotspotData *hotspot1, HotspotData *hotspot bool Support::isCharacterInList(uint16 *lst, int numEntries, uint16 charId) { while (numEntries-- > 0) - if (*lst++ == charId) return true; + if (*lst++ == charId) + return true; return false; } diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp index 4d3fc7116a..a8e33774f6 100644 --- a/engines/made/graphics.cpp +++ b/engines/made/graphics.cpp @@ -83,7 +83,7 @@ void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, u if ((maskFlags != 0) && (maskFlags != 2) && (pixelFlags != 0) && (pixelFlags != 2) && (cmdFlags != 0)) error("decompressImage() Unsupported flags: cmdFlags = %02X; maskFlags = %02X, pixelFlags = %02X", cmdFlags, maskFlags, pixelFlags); - byte *destPtr = (byte *)surface.getBasePtr(0, 0); + byte *destPtr = (byte *)surface.getPixels(); byte lineBuf[640 * 4]; byte bitBuf[40]; @@ -196,7 +196,7 @@ void decompressMovieImage(byte *source, Graphics::Surface &surface, uint16 cmdOf byte *maskBuffer = source + maskOffs; byte *pixelBuffer = source + pixelOffs; - byte *destPtr = (byte *)surface.getBasePtr(0, 0); + byte *destPtr = (byte *)surface.getPixels(); byte bitBuf[40]; diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index cf450f7e25..573ff7faf1 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -248,7 +248,7 @@ void PmvPlayer::handleEvents() { } void PmvPlayer::updateScreen() { - _vm->_system->copyRectToScreen(_surface->pixels, _surface->pitch, + _vm->_system->copyRectToScreen(_surface->getPixels(), _surface->pitch, (320 - _surface->w) / 2, (200 - _surface->h) / 2, _surface->w, _surface->h); _vm->_system->updateScreen(); } diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index ea7d57f82d..30848e8ec1 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -344,12 +344,12 @@ void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask void Screen::updateSprites() { // TODO: This needs some more work, dirty rectangles are currently not used - memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); + memcpy(_workScreen->getPixels(), _backgroundScreen->getPixels(), 64000); drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); drawSpriteChannels(_workScreenDrawCtx, 1, 2); - _vm->_system->copyRectToScreen(_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); + _vm->_system->copyRectToScreen(_workScreen->getPixels(), _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); _vm->_screen->updateScreenAndWait(10); } @@ -593,7 +593,7 @@ void Screen::show() { return; drawSpriteChannels(_backgroundScreenDrawCtx, 3, 0); - memcpy(_workScreen->pixels, _backgroundScreen->pixels, 64000); + memcpy(_workScreen->getPixels(), _backgroundScreen->getPixels(), 64000); drawSpriteChannels(_workScreenDrawCtx, 1, 2); _fx->run(_visualEffectNum, _workScreen, _palette, _newPalette, _paletteColorCount); @@ -775,7 +775,7 @@ void Screen::unlockScreen() { } void Screen::showWorkScreen() { - _vm->_system->copyRectToScreen(_workScreen->pixels, _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); + _vm->_system->copyRectToScreen(_workScreen->getPixels(), _workScreen->pitch, 0, 0, _workScreen->w, _workScreen->h); } void Screen::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) { diff --git a/engines/made/screenfx.cpp b/engines/made/screenfx.cpp index ad71f1fb49..d069308a4b 100644 --- a/engines/made/screenfx.cpp +++ b/engines/made/screenfx.cpp @@ -368,7 +368,7 @@ void ScreenEffects::vfx07(Graphics::Surface *surface, byte *palette, byte *newPa // "Screen slide in" right to left void ScreenEffects::vfx08(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { for (int x = 8; x <= 320; x += 8) { - _screen->copyRectToScreen(surface->getBasePtr(0, 0), surface->pitch, 320 - x, 0, x, 200); + _screen->copyRectToScreen(surface->getPixels(), surface->pitch, 320 - x, 0, x, 200); _screen->updateScreenAndWait(25); } setPalette(palette); @@ -529,7 +529,7 @@ void ScreenEffects::vfx19(Graphics::Surface *surface, byte *palette, byte *newPa // "Screen slide in" bottom to top void ScreenEffects::vfx20(Graphics::Surface *surface, byte *palette, byte *newPalette, int colorCount) { for (int y = 4; y <= 200; y += 4) { - _screen->copyRectToScreen(surface->getBasePtr(0, 0), surface->pitch, 0, 200 - y, 320, y); + _screen->copyRectToScreen(surface->getPixels(), surface->pitch, 0, 200 - y, 320, y); _screen->updateScreenAndWait(25); } diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index c57778fb71..0e3b50aa98 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -574,7 +574,7 @@ int16 ScriptFunctions::sfLoadMouseCursor(int16 argc, int16 *argv) { PictureResource *flex = _vm->_res->getPicture(argv[2]); if (flex) { Graphics::Surface *surf = flex->getPicture(); - CursorMan.replaceCursor(surf->pixels, surf->w, surf->h, argv[1], argv[0], 0); + CursorMan.replaceCursor(surf->getPixels(), surf->w, surf->h, argv[1], argv[0], 0); _vm->_res->freeResource(flex); } return 0; diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp index bc19fe2d3e..b321e043d9 100644 --- a/engines/mohawk/bitmap.cpp +++ b/engines/mohawk/bitmap.cpp @@ -580,7 +580,7 @@ void MohawkBitmap::drawRaw(Graphics::Surface *surface) { _data->skip(_header.bytesPerRow - _header.width * 3); } else { - _data->read((byte *)surface->pixels + y * _header.width, _header.width); + _data->read((byte *)surface->getBasePtr(0, y), _header.width); _data->skip(_header.bytesPerRow - _header.width); } } @@ -599,7 +599,7 @@ void MohawkBitmap::drawRLE8(Graphics::Surface *surface, bool isLE) { for (uint16 i = 0; i < _header.height; i++) { uint16 rowByteCount = isLE ? _data->readUint16LE() : _data->readUint16BE(); int32 startPos = _data->pos(); - byte *dst = (byte *)surface->pixels + i * _header.width; + byte *dst = (byte *)surface->getBasePtr(0, i); int16 remaining = _header.width; while (remaining > 0) { @@ -779,7 +779,7 @@ MohawkSurface *DOSBitmap::decodeImage(Common::SeekableReadStream *stream) { } Graphics::Surface *surface = createSurface(_header.width, _header.height); - memset(surface->pixels, 0, _header.width * _header.height); + memset(surface->getPixels(), 0, _header.width * _header.height); // Expand the <8bpp data to one byte per pixel switch (getBitsPerPixel()) { @@ -801,7 +801,7 @@ MohawkSurface *DOSBitmap::decodeImage(Common::SeekableReadStream *stream) { void DOSBitmap::expandMonochromePlane(Graphics::Surface *surface, Common::SeekableReadStream *rawStream) { assert(surface->format.bytesPerPixel == 1); - byte *dst = (byte *)surface->pixels; + byte *dst = (byte *)surface->getPixels(); // Expand the 8 pixels in a byte into a full byte per pixel @@ -830,7 +830,7 @@ void DOSBitmap::expandEGAPlanes(Graphics::Surface *surface, Common::SeekableRead // Note that the image is in EGA planar form and not just standard 4bpp // This seems to contradict the PoP specs which seem to do something else - byte *dst = (byte *)surface->pixels; + byte *dst = (byte *)surface->getPixels(); for (uint32 i = 0; i < surface->h; i++) { uint x = 0; diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index c7bd03678f..f70efde5fb 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -121,11 +121,11 @@ void MystCursorManager::setCursor(uint16 id) { // Myst ME stores some cursors as 24bpp images instead of 8bpp if (surface->format.bytesPerPixel == 1) { - CursorMan.replaceCursor(surface->pixels, surface->w, surface->h, hotspotX, hotspotY, 0); + CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, 0); CursorMan.replaceCursorPalette(mhkSurface->getPalette(), 0, 256); } else { Graphics::PixelFormat pixelFormat = g_system->getScreenFormat(); - CursorMan.replaceCursor(surface->pixels, surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat); + CursorMan.replaceCursor(surface->getPixels(), surface->w, surface->h, hotspotX, hotspotY, pixelFormat.RGBToColor(255, 255, 255), false, &pixelFormat); } _vm->_needsUpdate = true; diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp index efa0dd3fd3..634ff441b6 100644 --- a/engines/mohawk/livingbooks.cpp +++ b/engines/mohawk/livingbooks.cpp @@ -311,8 +311,8 @@ void MohawkEngine_LivingBooks::loadBookInfo(const Common::String &filename) { // - fDebugWindow (always 0?) if (_bookInfoFile.hasSection("Globals")) { - const Common::ConfigFile::SectionKeyList globals = _bookInfoFile.getKeys("Globals"); - for (Common::ConfigFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) { + const Common::INIFile::SectionKeyList globals = _bookInfoFile.getKeys("Globals"); + for (Common::INIFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) { Common::String command = Common::String::format("%s = %s", i->key.c_str(), i->value.c_str()); LBCode tempCode(this, 0); uint offset = tempCode.parseCode(command); diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h index 76da7d8219..615fcd0e16 100644 --- a/engines/mohawk/livingbooks.h +++ b/engines/mohawk/livingbooks.h @@ -28,7 +28,7 @@ #include "mohawk/livingbooks_graphics.h" #include "mohawk/sound.h" -#include "common/config-file.h" +#include "common/ini-file.h" #include "common/rect.h" #include "common/queue.h" #include "common/random.h" @@ -759,7 +759,7 @@ public: private: LivingBooksConsole *_console; - Common::ConfigFile _bookInfoFile; + Common::INIFile _bookInfoFile; Common::String getBookInfoFileName() const; void loadBookInfo(const Common::String &filename); diff --git a/engines/mohawk/livingbooks_lbx.cpp b/engines/mohawk/livingbooks_lbx.cpp index 2b8b22ec81..dcf8caa4a5 100644 --- a/engines/mohawk/livingbooks_lbx.cpp +++ b/engines/mohawk/livingbooks_lbx.cpp @@ -33,7 +33,7 @@ public: bool call(uint callId, const Common::Array<LBValue> ¶ms, LBValue &result); protected: - Common::ConfigFile _dataFile; + Common::INIFile _dataFile; Common::String _curSection; void open(const Common::String &filename); @@ -77,8 +77,8 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> ¶ms, LBValu case kLBXDataFileGetSectionList: { Common::SharedPtr<LBList> list = Common::SharedPtr<LBList>(new LBList); - Common::ConfigFile::SectionList sections = _dataFile.getSections(); - for (Common::List<Common::ConfigFile::Section>::const_iterator i = sections.begin(); i != sections.end(); ++i) + Common::INIFile::SectionList sections = _dataFile.getSections(); + for (Common::List<Common::INIFile::Section>::const_iterator i = sections.begin(); i != sections.end(); ++i) list->array.push_back(LBValue(i->name)); result = LBValue(list); } @@ -103,8 +103,8 @@ bool LBXDataFile::call(uint callId, const Common::Array<LBValue> ¶ms, LBValu error("incorrect number of parameters (%d) to LBXDataFile::loadCurSectionVars", params.size()); { - const Common::ConfigFile::SectionKeyList globals = _dataFile.getKeys(_curSection); - for (Common::ConfigFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) { + const Common::INIFile::SectionKeyList globals = _dataFile.getKeys(_curSection); + for (Common::INIFile::SectionKeyList::const_iterator i = globals.begin(); i != globals.end(); i++) { Common::String command = Common::String::format("%s = %s", i->key.c_str(), i->value.c_str()); LBCode tempCode(_vm, 0); uint offset = tempCode.parseCode(command); diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp index 05e66a3924..cd15960b85 100644 --- a/engines/mohawk/riven_graphics.cpp +++ b/engines/mohawk/riven_graphics.cpp @@ -255,7 +255,7 @@ void RivenGraphics::runScheduledTransition() { } // For now, just copy the image to screen without doing any transition. - _vm->_system->copyRectToScreen(_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h); + _vm->_system->copyRectToScreen(_mainScreen->getPixels(), _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h); _vm->_system->updateScreen(); _scheduledTransition = -1; // Clear scheduled transition @@ -345,7 +345,7 @@ void RivenGraphics::drawInventoryImage(uint16 id, const Common::Rect *rect) { mhkSurface->convertToTrueColor(); Graphics::Surface *surface = mhkSurface->getSurface(); - _vm->_system->copyRectToScreen(surface->pixels, surface->pitch, rect->left, rect->top, surface->w, surface->h); + _vm->_system->copyRectToScreen(surface->getPixels(), surface->pitch, rect->left, rect->top, surface->w, surface->h); delete mhkSurface; } @@ -420,7 +420,7 @@ void RivenGraphics::updateCredits() { } else { // Otheriwse, we're scrolling // Move the screen up one row - memmove(_mainScreen->pixels, _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1)); + memmove(_mainScreen->getPixels(), _mainScreen->getBasePtr(0, 1), _mainScreen->pitch * (_mainScreen->h - 1)); // Only update as long as we're not before the last frame // Otherwise, we're just moving up a row (which we already did) @@ -437,7 +437,7 @@ void RivenGraphics::updateCredits() { } // Now flush the new screen - _vm->_system->copyRectToScreen(_mainScreen->pixels, _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h); + _vm->_system->copyRectToScreen(_mainScreen->getPixels(), _mainScreen->pitch, 0, 0, _mainScreen->w, _mainScreen->h); _vm->_system->updateScreen(); } } diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index 8b0130d711..b7e06a2b9f 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -245,7 +245,7 @@ bool VideoManager::updateMovies() { // Clip the width/height to make sure we stay on the screen (Myst does this a few times) uint16 width = MIN<int32>(_videoStreams[i]->getWidth(), _vm->_system->getWidth() - _videoStreams[i].x); uint16 height = MIN<int32>(_videoStreams[i]->getHeight(), _vm->_system->getHeight() - _videoStreams[i].y); - _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height); + _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, _videoStreams[i].x, _videoStreams[i].y, width, height); // We've drawn something to the screen, make sure we update it updateScreen = true; diff --git a/engines/mortevielle/actions.cpp b/engines/mortevielle/actions.cpp new file mode 100644 index 0000000000..c06f19dadc --- /dev/null +++ b/engines/mortevielle/actions.cpp @@ -0,0 +1,1633 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/dialogs.h" +#include "mortevielle/menu.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" + +#include "common/scummsys.h" + +namespace Mortevielle { + +/** + * Engine function - Move + * @remarks Originally called 'taller' + */ +void MortevielleEngine::fctMove() { + int oldMenu = (_menu._moveMenu[6]._menuId << 8) | _menu._moveMenu[6]._actionId; + if ((_coreVar._currPlace == ROOM26) && (_currAction == oldMenu)) { + _coreVar._currPlace = LANDING; + _caff = _coreVar._currPlace; + drawPictureWithText(); + handleDescriptionText(2, _coreVar._currPlace); + } + if ((_coreVar._currPlace == LANDING) && (_currAction == oldMenu)) { + if (!_syn) + displayTextInVerbBar(getEngineString(S_GO_TO)); + displayStatusArrow(); + + if (_keyPressedEsc) + _destinationOk = false; + + if ((_anyone) || (_keyPressedEsc)) + return; + + setCoordinates(1); + + if (_num == 0) + return; + + if (_num == 1) { + _coreVar._currPlace = OWN_ROOM; + _menu.setDestinationText(OWN_ROOM); + } else if (_num == 7) { + _coreVar._currPlace = ATTIC; + _menu.setDestinationText(ATTIC); + } else if (_num != 6) + _coreVar._currPlace = ROOM26; + + if ((_num > 1) && (_num < 6)) + _roomDoorId = _num - 1; + else if (_num > 7) + _roomDoorId = _num - 3; + + if (_num != 6) + prepareDisplayText(); + else + showMoveMenuAlert(); + return; + } + exitRoom(); + int menuChoice = 1; + oldMenu = (_menu._moveMenu[menuChoice]._menuId << 8) | _menu._moveMenu[menuChoice]._actionId; + while (oldMenu != _currAction) { + ++menuChoice; + oldMenu = (_menu._moveMenu[menuChoice]._menuId << 8) | _menu._moveMenu[menuChoice]._actionId; + } + + if (_coreVar._currPlace == MOUNTAIN) { + if (menuChoice == 1) + gotoManorFront(); + else if (menuChoice == 2) + checkManorDistance(); + _menu.setDestinationText(_coreVar._currPlace); + return; + } else if (_coreVar._currPlace == INSIDE_WELL) { + if (menuChoice == 1) + floodedInWell(); + else if (menuChoice == 2) + gotoManorBack(); + _menu.setDestinationText(_coreVar._currPlace); + return; + } else if ((_coreVar._currPlace == BUREAU) && (menuChoice == 1)) + menuChoice = 6; + else if (_coreVar._currPlace == KITCHEN) { + if (menuChoice == 2) + menuChoice = 6; + else if (menuChoice == 5) + menuChoice = 16; + } else if ((_coreVar._currPlace == CELLAR) && (menuChoice == 3)) + menuChoice = 6; + else if (((_coreVar._currPlace == LANDING) || (_coreVar._currPlace == ROOM26)) && (menuChoice == 4)) + menuChoice = 6; + + if ((_coreVar._currPlace > MOUNTAIN) && (_coreVar._currPlace != ROOM26)) + menuChoice += 10; + + if ((_coreVar._currPlace == CHAPEL) && (menuChoice == 13)) + menuChoice = 16; + else if (_coreVar._currPlace == MANOR_FRONT) { + if (menuChoice == 12) + menuChoice = 16; + else if (menuChoice > 13) + menuChoice = 15; + } else if ((_coreVar._currPlace == MANOR_BACK) && (menuChoice > 14)) + menuChoice = 15; + else if ((_coreVar._currPlace == WELL) && (menuChoice > 13) && (menuChoice != 17)) + menuChoice = 15; + + if (menuChoice == 1) + _coreVar._currPlace = BUREAU; + else if (menuChoice == 2) + _coreVar._currPlace = KITCHEN; + else if (menuChoice == 3) + _coreVar._currPlace = CELLAR; + else if (menuChoice == 4) + _coreVar._currPlace = LANDING; + else if (menuChoice == 5) + menuChoice = 12; + else if (menuChoice == 6) + menuChoice = 11; + + if (menuChoice == 11) + gotoDiningRoom(); + else if (menuChoice == 12) + gotoManorFront(); + else if (menuChoice == 13) + _coreVar._currPlace = CHAPEL; + else if (menuChoice == 14) + _coreVar._currPlace = WELL; + else if (menuChoice == 15) + checkManorDistance(); + else if (menuChoice == 16) + gotoManorBack(); + else if (menuChoice == 17) { + if ((_coreVar._wellObjectId != 120) && (_coreVar._wellObjectId != 140)) + _crep = 997; + else if (_coreVar._wellObjectId == 120) + _crep = 181; + else if (_coreVar._faithScore > 80) { + _crep = 1505; + loseGame(); + } else { + _coreVar._currPlace = INSIDE_WELL; + prepareDisplayText(); + } + } + if ((menuChoice < 5) || (menuChoice == 13) || (menuChoice == 14)) + prepareDisplayText(); + resetRoomVariables(_coreVar._currPlace); + _menu.setDestinationText(_coreVar._currPlace); +} + +/** + * Engine function - Take + * @remarks Originally called 'tprendre' + */ +void MortevielleEngine::fctTake() { + if (_caff > 99) { + int cx = _caff; + putInHand(cx); + if (_crep != 139) { + if (_currBitIndex > 0) + _coreVar._faithScore += 3; + if (_obpart) { + if (_coreVar._currPlace == PURPLE_ROOM) + _coreVar._purpleRoomObjectId = 0; + if (_coreVar._currPlace == ATTIC) { + if (_coreVar._atticBallHoleObjectId == _caff) + _coreVar._atticBallHoleObjectId = 0; + if (_coreVar._atticRodHoleObjectId == _caff) + _coreVar._atticRodHoleObjectId = 0; + } + if (_coreVar._currPlace == CELLAR) + _coreVar._cellarObjectId = 0; + if (_coreVar._currPlace == CRYPT) + _coreVar._cryptObjectId = 0; + if (_coreVar._currPlace == SECRET_PASSAGE) + _coreVar._secretPassageObjectId = 0; + if (_coreVar._currPlace == WELL) + _coreVar._wellObjectId = 0; + _menu.unsetSearchMenu(); + _obpart = false; + prepareDisplayText(); + } else { + _tabdon[kAcha + ((_curSearchObjId - 1) * 10) + _searchCount - 1] = 0; + prepareNextObject(); + ++_takeObjCount; + if (_takeObjCount > 6) { + _coreVar._faithScore += 2; + _takeObjCount = 0; + } + } + } + return; + } + if (!_syn) + displayTextInVerbBar(getEngineString(S_TAKE)); + displayStatusArrow(); + if ((_anyone) || (_keyPressedEsc)) + return; + if (_caff == 3) { + setCoordinates(2); + if (_num == 1) { + _crep = 152; + return; + } + } + setCoordinates(5); + if ((_num == 0) || ((_num == 1) && (_coreVar._currPlace == CRYPT))) { + setCoordinates(8); + if (_num != 0) { + if (_currBitIndex > 0) + _coreVar._faithScore += 3; + _crep = 997; + if ((_coreVar._currPlace == PURPLE_ROOM) && (_coreVar._purpleRoomObjectId != 0)) + putInHand(_coreVar._purpleRoomObjectId); + if ((_coreVar._currPlace == ATTIC) && (_num == 1) && (_coreVar._atticBallHoleObjectId != 0)) { + putInHand(_coreVar._atticBallHoleObjectId); + if ((_crep != 997) && (_crep != 139)) + displayAnimFrame(2, 7); + } + if ((_coreVar._currPlace == ATTIC) && (_num == 2) && (_coreVar._atticRodHoleObjectId != 0)) { + putInHand(_coreVar._atticRodHoleObjectId); + if ((_crep != 997) && (_crep != 139)) + displayAnimFrame(2, 6); + } + if ((_coreVar._currPlace == CELLAR) && (_coreVar._cellarObjectId != 0)) { + putInHand(_coreVar._cellarObjectId); + if ((_crep != 997) && (_crep != 139)) + displayAnimFrame(2, 2); + } + if ((_coreVar._currPlace == CRYPT) && (_coreVar._cryptObjectId != 0)) + putInHand(_coreVar._cryptObjectId); + + if ((_coreVar._currPlace == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId != 0)) { + putInHand(_coreVar._secretPassageObjectId); + if ((_crep != 997) && (_crep != 139)) { + _crep = 182; + displayAnimFrame(2, 1); + } + } + if ((_coreVar._currPlace == WELL) && (_coreVar._wellObjectId != 0)) { + putInHand(_coreVar._wellObjectId); + if ((_crep != 997) && (_crep != 139)) + displayAnimFrame(2, 1); + } + if ((_crep != 997) && (_crep != 182) && (_crep != 139)) + _crep = 999; + } + } else { + if ( ((_coreVar._currPlace == OWN_ROOM) && (_num == 3)) + || ((_coreVar._currPlace == GREEN_ROOM) && (_num == 4)) + || ((_coreVar._currPlace == PURPLE_ROOM) && (_num == 1)) + || ((_coreVar._currPlace == DARKBLUE_ROOM) && (_num == 3)) + || ((_coreVar._currPlace == BLUE_ROOM) && (_num == 6)) + || ((_coreVar._currPlace == RED_ROOM) && (_num == 2)) + || ((_coreVar._currPlace == BATHROOM) && (_num == 6)) + || ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 4)) + || ((_coreVar._currPlace == JULIA_ROOM) && (_num == 4)) + || ((_coreVar._currPlace == DINING_ROOM) && (_num > 2)) + || ((_coreVar._currPlace == BUREAU) && (_num == 7)) + || ((_coreVar._currPlace == KITCHEN) && (_num == 6)) + || ((_coreVar._currPlace == ATTIC) && (_num > 4)) + || ((_coreVar._currPlace > ATTIC) && (_coreVar._currPlace != INSIDE_WELL)) ) + _crep = 997; + else if (_coreVar._currPlace == INSIDE_WELL) { + _crep = 1504; + loseGame(); + } else + _crep = 120; + } +} +/** + * Engine function - Inventory / Take + * @remarks Originally called 'tsprendre' + */ +void MortevielleEngine::fctInventoryTake() { + int inventIndex = 0; + int oldMenu = 0; + do { + ++inventIndex; + oldMenu = (_menu._inventoryMenu[inventIndex]._menuId << 8) | _menu._inventoryMenu[inventIndex]._actionId; + } while (oldMenu != _currAction); + int cz = 0; + int cy = 0; + do { + ++cy; + if (_coreVar._inventory[cy] != 0) + ++cz; + } while (cz != inventIndex); + cz = _coreVar._inventory[cy]; + _coreVar._inventory[cy] = 0; + _menu.setInventoryText(); + putInHand(cz); + _crep = 998; + clearDescriptionBar(); +} + +/** + * Engine function - Lift + * @remarks Originally called 'tsoulever' + */ +void MortevielleEngine::fctLift() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_LIFT)); + displayStatusArrow(); + if ((_anyone) || (_keyPressedEsc)) + return; + setCoordinates(3); + if (_num == 0) { + setCoordinates(8); + if (_num != 0) { + if (_currBitIndex > 0) + ++_coreVar._faithScore; + _crep = 997; + if ((_coreVar._currPlace == PURPLE_ROOM) && (_coreVar._purpleRoomObjectId != 0)) + displayLookScreen(_coreVar._purpleRoomObjectId); + } + return; + } + if (_currBitIndex > 0) + ++_coreVar._faithScore; + int tmpPlace = _coreVar._currPlace; + if (_coreVar._currPlace == CRYPT) + tmpPlace = 14; + else if (_coreVar._currPlace == MOUNTAIN) + tmpPlace = 15; + _crep = _tabdon[kAsoul + (tmpPlace << 3) + (_num - 1)]; + if (_crep == 255) + _crep = 997; +} + +/** + * Engine function - Read + * @remarks Originally called 'tlire' + */ +void MortevielleEngine::fctRead() { + if (_caff > 99) + getReadDescription(_caff); + else { + if (!_syn) + displayTextInVerbBar(getEngineString(S_READ)); + displayStatusArrow(); + if (!(_anyone) && !(_keyPressedEsc)) { + setCoordinates(4); + if (_num != 0) + _crep = 107; + } + } +} + +/** + * Engine function - Self / Read + * @remarks Originally called 'tslire' + */ +void MortevielleEngine::fctSelfRead() { + if (_coreVar._selectedObjectId == 0) + _crep = 186; + else + getReadDescription(_coreVar._selectedObjectId); +} + +/** + * Engine function - Look + * @remarks Originally called 'tregarder' + */ +void MortevielleEngine::fctLook() { + if (_caff > 99) { + _crep = 103; + return; + } + if (!_syn) + displayTextInVerbBar(getEngineString(S_LOOK)); + displayStatusArrow(); + if ((_anyone) || (_keyPressedEsc)) + return; + setCoordinates(5); + if (_num == 0) { + setCoordinates(8); + _crep = 131; + if (_num != 0) { + if (_coreVar._currPlace == ATTIC) { + if (_num == 1) { + _crep = 164; + if (_coreVar._atticRodHoleObjectId != 0) + displayLookScreen(_coreVar._atticRodHoleObjectId); + else if (_coreVar._atticBallHoleObjectId != 0) + displayLookScreen(_coreVar._atticBallHoleObjectId); + } else { + _crep = 193; + if (_coreVar._atticRodHoleObjectId != 0) + displayLookScreen(_coreVar._atticRodHoleObjectId); + } + } + if (_coreVar._currPlace == CELLAR) { + _crep = 164; + if (_coreVar._cellarObjectId != 0) + displayLookScreen(_coreVar._cellarObjectId); + } + if (_coreVar._currPlace == SECRET_PASSAGE) { + _crep = 174; + if (_coreVar._secretPassageObjectId != 0) + displayLookScreen(_coreVar._secretPassageObjectId); + } + if (_coreVar._currPlace == WELL) { + _crep = 131; + if (_coreVar._wellObjectId != 0) + displayLookScreen(_coreVar._wellObjectId); + } + } + return; + } + int cx = _coreVar._currPlace; + if (_coreVar._currPlace == CHAPEL) + cx = 17; + if ((_coreVar._currPlace > MANOR_FRONT) && (_coreVar._currPlace < DOOR)) + cx -= 4; + if (_coreVar._currPlace == ROOM26) + cx = 21; + _crep = _tabdon[kArega + (cx * 7) + _num - 1]; + if ((_coreVar._currPlace == ATTIC) && (_num == 8)) + _crep = 126; + if (_coreVar._currPlace == MOUNTAIN) + _crep = 103; + if (_crep == 255) + _crep = 131; + if ((_coreVar._currPlace == GREEN_ROOM) && (_num == 1)) + displayLookScreen(144); + if ((_coreVar._currPlace == BLUE_ROOM) && (_num == 3)) + displayLookScreen(147); + if ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 3)) + displayLookScreen(149); + if ((_coreVar._currPlace == JULIA_ROOM) && (_num == 2)) + displayLookScreen(30); + if ((_coreVar._currPlace == DINING_ROOM) && (_num == 3)) + displayLookScreen(31); +} + +/** + * Engine function - Self / Look + * @remarks Originally called 'tsregarder' + */ +void MortevielleEngine::fctSelftLook() { + if (_coreVar._selectedObjectId != 0) + displayLookScreen(_coreVar._selectedObjectId); + else + _crep = 186; +} + +/** + * Engine function - Search + * @remarks Originally called 'tfouiller' + */ +void MortevielleEngine::fctSearch() { + static const byte answerArr[14] = {123, 104, 123, 131, 131, 123, 104, 131, 123, 123, 106, 123, 123, 107}; + + if (_caff > 99) { + getSearchDescription(_caff); + return; + } + + if (!_syn) + displayTextInVerbBar(getEngineString(S_SEARCH)); + + displayStatusArrow(); + if (_anyone || _keyPressedEsc) + return; + + if (_coreVar._currPlace == INSIDE_WELL) { + _crep = 1504; + loseGame(); + return; + } + + setCoordinates(6); + if (_num == 0) { + setCoordinates(7); + if (_num != 0) { + int i; + for (i = 1; (i <= 6) && (_num != _openObjects[i]); i++) + ; + if (_num == _openObjects[i]) { + if (_currBitIndex > 0) + _coreVar._faithScore += 3; + + _curSearchObjId = getFirstObject(); + if (_curSearchObjId != 0) { + _searchCount = 0; + _heroSearching = true; + _menu.setSearchMenu(); + prepareNextObject(); + } else + _crep = 997; + } else + _crep = 187; + } else { + setCoordinates(8); + _crep = 997; + if (_num != 0) { + if (_currBitIndex > 0) + _coreVar._faithScore += 3; + if ((_coreVar._currPlace != WELL) && (_coreVar._currPlace != SECRET_PASSAGE) && (_coreVar._currPlace != ATTIC)) { + if (_coreVar._currPlace == PURPLE_ROOM) { + _crep = 123; + if (_coreVar._purpleRoomObjectId != 0) + displayLookScreen(_coreVar._purpleRoomObjectId); + } + if (_coreVar._currPlace == CRYPT) { + _crep = 123; + if (_coreVar._cryptObjectId != 0) + displayLookScreen(_coreVar._cryptObjectId); + } + } + } + } + } else { + if (_currBitIndex > 0) + _coreVar._faithScore += 3; + _crep = 997; + if (_coreVar._currPlace < CELLAR) + _crep = answerArr[_coreVar._currPlace]; + + if ((_coreVar._currPlace == TOILETS) && (_num == 2)) + _crep = 162; + + if (_coreVar._currPlace == KITCHEN) { + if ((_num == 3) || (_num == 4)) + _crep = 162; + else if (_num == 5) + _crep = 159; + } + + if (_coreVar._currPlace == MOUNTAIN) + _crep = 104; + else if (_coreVar._currPlace == CRYPT) + _crep = 155; + } +} + +/** + * Engine function - Self / Search + * @remarks Originally called 'tsfouiller' + */ +void MortevielleEngine::fctSelfSearch() { + if (_coreVar._selectedObjectId != 0) + getSearchDescription(_coreVar._selectedObjectId); + else + _crep = 186; +} + +/** + * Engine function - Open + * @remarks Originally called 'touvrir' + */ +void MortevielleEngine::fctOpen() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_OPEN)); + + if (_caff == ROOM26) { + if (_roomDoorId != OWN_ROOM) { + _currAction = _menu._opcodeEnter; + _syn = true; + } else + _crep = 997; + return; + } + + if (_caff == LANDING) { + showMoveMenuAlert(); + return; + } + + displayStatusArrow(); + if ((_anyone) || (_keyPressedEsc)) + return; + + setCoordinates(7); + if (_num != 0) { + if (_currBitIndex > 0) + _coreVar._faithScore += 2; + ++_openObjCount; + int i; + for (i = 1; (i <= 6) && (_openObjects[i] != 0) && (_openObjects[i] != _num); i++) + ; + if (_openObjects[i] != _num) { + if (!( ((_num == 3) && ((_coreVar._currPlace == OWN_ROOM) + || (_coreVar._currPlace == JULIA_ROOM) + || (_coreVar._currPlace == BLUE_ROOM) + || (_coreVar._currPlace == BATHROOM))) + || ((_num == 4) && ((_coreVar._currPlace == GREEN_ROOM) + || (_coreVar._currPlace == PURPLE_ROOM) + || (_coreVar._currPlace == RED_ROOM))) + || ((_coreVar._currPlace == DARKBLUE_ROOM) && (_num == 5)) + || ((_num == 6) && ((_coreVar._currPlace == BATHROOM) + || (_coreVar._currPlace == DINING_ROOM) + || (_coreVar._currPlace == GREEN_ROOM2) + || (_coreVar._currPlace == ATTIC))) + || ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 2)) + || ((_coreVar._currPlace == KITCHEN) && (_num == 7))) ) { + if ( ((_coreVar._currPlace > DINING_ROOM) && (_coreVar._currPlace < CELLAR)) + || ((_coreVar._currPlace > RED_ROOM) && (_coreVar._currPlace < DINING_ROOM)) + || (_coreVar._currPlace == OWN_ROOM) + || (_coreVar._currPlace == PURPLE_ROOM) + || (_coreVar._currPlace == BLUE_ROOM)) { + if (getRandomNumber(1, 4) == 3) + _soundManager.startSpeech(7, 9, 1); + } + _openObjects[i] = _num; + displayAnimFrame(1, _num); + _soundManager.waitSpeech(); + } + int tmpPlace = _coreVar._currPlace; + if (_coreVar._currPlace == CRYPT) + tmpPlace = CELLAR; + _crep = _tabdon[kAouvr + (tmpPlace * 7) + _num - 1]; + if (_crep == 254) + _crep = 999; + } else + // display "Already Opened" + _crep = 18; + } +} + +/** + * Engine function - Place + * @remarks Originally called 'tmettre' + */ +void MortevielleEngine::fctPlace() { + if (_coreVar._selectedObjectId == 0) { + _crep = 186; + return; + } + + if (!_syn) + displayTextInVerbBar(getEngineString(S_PUT)); + + displayStatusArrow(); + if (_keyPressedEsc) + _crep = 998; + + if ((_anyone) || (_keyPressedEsc)) + return; + + setCoordinates(8); + if (_num != 0) { + _crep = 999; + if (_caff == ATTIC) { + if (_num == 1) { + if (_coreVar._atticBallHoleObjectId != 0) { + _crep = 188; + } else { + _coreVar._atticBallHoleObjectId = _coreVar._selectedObjectId; + if (_coreVar._selectedObjectId == 141) + displayAnimFrame(1, 7); + } + } else if (_coreVar._atticRodHoleObjectId != 0) { + _crep = 188; + } else { + _coreVar._atticRodHoleObjectId = _coreVar._selectedObjectId; + if (_coreVar._selectedObjectId == 159) + displayAnimFrame(1, 6); + } + } + + if (_caff == CELLAR) { + if (_coreVar._cellarObjectId != 0) { + _crep = 188; + } else { + _coreVar._cellarObjectId = _coreVar._selectedObjectId; + if (_coreVar._selectedObjectId == 151) { + // Open hidden passage + displayAnimFrame(1, 2); + displayAnimFrame(1, 1); + handleDescriptionText(2, 165); + displayEmptyHand(); + _soundManager.startSpeech(6, -9, 1); + + // Do you want to enter the hidden passage? + int answer = _dialogManager.show(getEngineString(S_YES_NO), 1); + if (answer == 1) { + Common::String alertTxt = getString(582); + _dialogManager.show(alertTxt, 1); + + bool enterPassageFl = _dialogManager.showKnowledgeCheck(); + _mouse.hideMouse(); + clearScreen(); + drawRightFrame(); + clearDescriptionBar(); + clearVerbBar(); + _mouse.showMouse(); + prepareRoom(); + drawClock(); + if (_currBitIndex != 0) + showPeoplePresent(_currBitIndex); + else + displayAloneText(); + + _menu.displayMenu(); + if (enterPassageFl) { + _coreVar._currPlace = SECRET_PASSAGE; + _menu.setDestinationText(SECRET_PASSAGE); + } else { + _menu.setDestinationText(_coreVar._currPlace); + setPal(14); + drawPicture(); + displayAnimFrame(1, 2); + displayAnimFrame(1, 1); + alertTxt = getString(577); + _dialogManager.show(alertTxt, 1); + displayAnimFrame(2, 1); + _crep = 166; + } + prepareDisplayText(); + } else { + displayAnimFrame(2, 1); + _crep = 166; + } + return; + } + } + } + + if (_caff == CRYPT) { + if (_coreVar._cryptObjectId == 0) + _coreVar._cryptObjectId = _coreVar._selectedObjectId; + else + _crep = 188; + } + + if (_caff == SECRET_PASSAGE) { + if (_coreVar._secretPassageObjectId != 0) { + _crep = 188; + } else if (_coreVar._selectedObjectId == 143) { + _coreVar._secretPassageObjectId = 143; + displayAnimFrame(1, 1); + } else { + _crep = 1512; + loseGame(); + } + } + + if (_caff == WELL) { + if (_coreVar._wellObjectId != 0) { + _crep = 188; + } else if ((_coreVar._selectedObjectId == 140) || (_coreVar._selectedObjectId == 120)) { + _coreVar._wellObjectId = _coreVar._selectedObjectId; + displayAnimFrame(1, 1); + } else { + _crep = 185; + } + } + + if (_crep != 188) + displayEmptyHand(); + } +} + +/** + * Engine function - Turn + * @remarks Originally called 'ttourner' + */ +void MortevielleEngine::fctTurn() { + if (_caff > 99) { + _crep = 149; + return; + } + if (!_syn) + displayTextInVerbBar(getEngineString(S_TURN)); + displayStatusArrow(); + if ((_anyone) || (_keyPressedEsc)) + return; + setCoordinates(9); + if (_num != 0) { + _crep = 997; + if ((_coreVar._currPlace == ATTIC) && (_coreVar._atticRodHoleObjectId == 159) && (_coreVar._atticBallHoleObjectId == 141)) { + handleDescriptionText(2, 167); + _soundManager.startSpeech(7, 9, 1); + int answer = _dialogManager.show(getEngineString(S_YES_NO), 1); + if (answer == 1) + _endGame = true; + else + _crep = 168; + } + if ((_coreVar._currPlace == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId == 143)) { + handleDescriptionText(2, 175); + clearVerbBar(); + _soundManager.startSpeech(6, -9, 1); + int answer = _dialogManager.show(getEngineString(S_YES_NO), 1); + if (answer == 1) { + _coreVar._currPlace = CRYPT; + prepareDisplayText(); + } else + _crep = 176; + } + } +} + +/** + * Engine function - Hide Self + * @remarks Originally called 'tcacher' + */ +void MortevielleEngine::fctSelfHide() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_HIDE_SELF)); + displayStatusArrow(); + if (!(_anyone) && !(_keyPressedEsc)) { + setCoordinates(10); + if (_num == 0) + _hiddenHero = false; + else { + _hiddenHero = true; + _crep = 999; + } + } +} + +/** + * Engine function - Attach + * @remarks Originally called 'tattacher' + */ +void MortevielleEngine::fctAttach() { + if (_coreVar._selectedObjectId == 0) + _crep = 186; + else { + if (!_syn) + displayTextInVerbBar(getEngineString(S_TIE)); + displayStatusArrow(); + if (!(_anyone) && !(_keyPressedEsc)) { + setCoordinates(8); + _crep = 997; + if ((_num != 0) && (_coreVar._currPlace == WELL)) { + _crep = 999; + if ((_coreVar._selectedObjectId == 120) || (_coreVar._selectedObjectId == 140)) { + _coreVar._wellObjectId = _coreVar._selectedObjectId; + displayAnimFrame(1, 1); + } else + _crep = 185; + displayEmptyHand(); + } + } + } +} + +/** + * Engine function - Close + * @remarks Originally called 'tfermer' + */ +void MortevielleEngine::fctClose() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_CLOSE)); + + if (_caff < ROOM26) { + displayStatusArrow(); + if (_keyPressedEsc) + _crep = 998; + if ((_anyone) || (_keyPressedEsc)) + return; + setCoordinates(7); + if (_num != 0) { + int i; + for (i = 1; (i <= 6) && (_num != _openObjects[i]); ++i) + ; + if (_num == _openObjects[i]) { + displayAnimFrame(2, _num); + _crep = 998; + _openObjects[i] = 0; + --_openObjCount; + if (_openObjCount < 0) + _openObjCount = 0; + int objId = getFirstObject(); + if (_curSearchObjId == objId) + _curSearchObjId = 0; + } else { + _crep = 187; + } + } + } + if (_caff == ROOM26) + _crep = 999; +} + +/** + * Engine function - Knock + * @remarks Originally called 'tfrapper' + */ +void MortevielleEngine::fctKnock() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_HIT)); + + if (_coreVar._currPlace == LANDING) { + _dialogManager.show(getEngineString(S_BEFORE_USE_DEP_MENU), 1); + return; + } + + if (_coreVar._currPlace < DOOR) { + displayStatusArrow(); + if (!(_anyone) && !(_keyPressedEsc)) { + if ((_coreVar._currPlace < MOUNTAIN) && (_coreVar._currPlace != LANDING)) + _crep = 133; + else + _crep = 997; + } + + return; + } + + if (_coreVar._currPlace == ROOM26) { + int rand = (getRandomNumber(0, 8)) - 4; + _soundManager.startSpeech(11, rand, 1); + int pres = getPresenceStats(rand, _coreVar._faithScore, _roomDoorId); + if (_roomDoorId != OWN_ROOM) { + if (pres != -500) { + if (rand > pres) + _crep = 190; + else { + setPresenceFlags(_roomDoorId); + getKnockAnswer(); + } + } else + getKnockAnswer(); + } + + if (_roomDoorId == GREEN_ROOM2) + _crep = 190; + } +} + +/** + * Engine function - Self / Put + * @remarks Originally called 'tposer' + */ +void MortevielleEngine::fctSelfPut() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_POSE)); + if (_coreVar._selectedObjectId == 0) + _crep = 186; + else { + if (_caff > 99) { + _crep = 999; + putObject(); + if (_crep != 192) + displayEmptyHand(); + return; + } + displayStatusArrow(); + if ((_anyone) || (_keyPressedEsc)) + return; + setCoordinates(7); + _crep = 124; + if (_num != 0) { + int objId = getFirstObject(); + if (objId == 0) + _crep = 997; + else { + int i; + for (i = 1; (i <= 6) && (_num != _openObjects[i]); i++) + ; + if (_num == _openObjects[i]) { + _curSearchObjId = objId; + _crep = 999; + } else + _crep = 187; + } + } else { + setCoordinates(8); + if (_num != 0) { + _crep = 998; + if (_caff == PURPLE_ROOM) { + if (_coreVar._purpleRoomObjectId != 0) + _crep = 188; + else + _coreVar._purpleRoomObjectId = _coreVar._selectedObjectId; + } + + if (_caff == ATTIC) { + if (_num == 1) { + if (_coreVar._atticBallHoleObjectId != 0) + _crep = 188; + else + _coreVar._atticBallHoleObjectId = _coreVar._selectedObjectId; + } else if (_coreVar._atticRodHoleObjectId != 0) { + _crep = 188; + } else { + _coreVar._atticRodHoleObjectId = _coreVar._selectedObjectId; + } + } + + if (_caff == CRYPT) { + if (_coreVar._cryptObjectId != 0) + _crep = 188; + else + _coreVar._cryptObjectId = _coreVar._selectedObjectId; + } + + if (_caff == WELL) + _crep = 185; + if ((_caff == CELLAR) || (_caff == SECRET_PASSAGE)) + _crep = 124; + } else { + _crep = 124; + if (_caff == WELL) { + setCoordinates(5); + if (_num != 0) + _crep = 185; + } + } + } + if (_caff == INSIDE_WELL) + _crep = 185; + if ((_crep == 999) || (_crep == 185) || (_crep == 998)) { + if (_crep == 999) + putObject(); + if (_crep != 192) + displayEmptyHand(); + } + } +} + +/** + * Engine function - Listen + * @remarks Originally called 'tecouter' + */ +void MortevielleEngine::fctListen() { + if (_coreVar._currPlace != ROOM26) + _crep = 101; + else { + if (_currBitIndex != 0) + ++_coreVar._faithScore; + int rand; + int pres = getPresenceStats(rand, _coreVar._faithScore, _roomDoorId); + if (_roomDoorId != OWN_ROOM) { + if (pres != -500) { + if (rand > pres) + _crep = 101; + else { + setPresenceFlags(_roomDoorId); + int day, hour, minute; + updateHour(day, hour, minute); + rand = getRandomNumber(1, 100); + if ((hour >= 0) && (hour < 8)) { + if (rand > 30) + _crep = 101; + else + _crep = 178; + } else if (rand > 70) + _crep = 101; + else + _crep = 178; + } + } else + _crep = 178; + } + } +} + +/** + * Engine function - Eat + * @remarks Originally called 'tmanger' + */ +void MortevielleEngine::fctEat() { + if ((_coreVar._currPlace > LANDING) && (_coreVar._currPlace < ROOM26)) { + _crep = 148; + } else { + exitRoom(); + _coreVar._currPlace = DINING_ROOM; + _caff = DINING_ROOM; + resetRoomVariables(_coreVar._currPlace); + _menu.setDestinationText(_coreVar._currPlace); + + int day, hour, minute; + updateHour(day, hour, minute); + if ((hour == 12) || (hour == 13) || (hour == 19)) { + _coreVar._faithScore -= (_coreVar._faithScore / 7); + if (hour == 12) { + if (minute == 0) + hour = 4; + else + hour = 3; + } + + if ((hour == 13) || (hour == 19)) { + if (minute == 0) + hour = 2; + else + hour = 1; + } + + _currentHourCount += hour; + _crep = 135; + prepareRoom(); + } else { + _crep = 134; + } + } +} + +/** + * Engine function - Enter + * @remarks Originally called 'tentrer' + */ +void MortevielleEngine::fctEnter() { + if ((_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK)) { + gotoDiningRoom(); + _menu.setDestinationText(_coreVar._currPlace); + } else if (_coreVar._currPlace == LANDING) + showMoveMenuAlert(); + else if (_roomDoorId == OWN_ROOM) + _crep = 997; + else if ((_roomDoorId == JULIA_ROOM) && (_coreVar._selectedObjectId != 136)) { + _crep = 189; + _coreVar._availableQuestion[8] = '*'; + } else { + int pres = 0; + if (!_blo) + pres = getPresence(_roomDoorId); + if (pres != 0) { + if ((_roomDoorId == TOILETS) || (_roomDoorId == BATHROOM)) + _crep = 179; + else { + int randVal = (getRandomNumber(0, 10)) - 5; + _soundManager.startSpeech(7, randVal, 1); + displayAnimFrame(1, 1); + _soundManager.waitSpeech(); + + int charIndex = convertBitIndexToCharacterIndex(pres); + ++_coreVar._faithScore; + _coreVar._currPlace = LANDING; + _currMenu = MENU_DISCUSS; + _currAction = (_menu._discussMenu[charIndex]._menuId << 8) | _menu._discussMenu[charIndex]._actionId; + _syn = true; + if (_roomDoorId == JULIA_ROOM) { + _col = true; + _caff = 70; + drawPictureWithText(); + handleDescriptionText(2, _caff); + } else + _col = false; + resetRoomVariables(_roomDoorId); + _roomDoorId = OWN_ROOM; + } + } else { + int randVal = (getRandomNumber(0, 10)) - 5; + _soundManager.startSpeech(7, randVal, 1); + displayAnimFrame(1, 1); + _soundManager.waitSpeech(); + + _coreVar._currPlace = _roomDoorId; + prepareDisplayText(); + resetRoomVariables(_coreVar._currPlace); + _menu.setDestinationText(_coreVar._currPlace); + _roomDoorId = OWN_ROOM; + _savedBitIndex = 0; + _currBitIndex = 0; + } + } +} + +/** + * Engine function - Sleep + * @remarks Originally called 'tdormir' + */ +void MortevielleEngine::fctSleep() { + if ((_coreVar._currPlace > LANDING) && (_coreVar._currPlace < ROOM26)) { + _crep = 148; + return; + } + if (_coreVar._currPlace != OWN_ROOM) { + exitRoom(); + _coreVar._currPlace = OWN_ROOM; + prepareDisplayText(); + drawPictureWithText(); + resetRoomVariables(_coreVar._currPlace); + _menu.setDestinationText(_coreVar._currPlace); + } + clearVerbBar(); + clearDescriptionBar(); + prepareScreenType2(); + displayTextBlock(getEngineString(S_WANT_TO_WAKE_UP)); + int day, hour, minute; + updateHour(day, hour, minute); + + int answer; + do { + if (hour < 8) { + _coreVar._faithScore -= (_coreVar._faithScore / 20); + int z = (7 - hour) * 2; + if (minute == 30) + --z; + _currentHourCount += z; + hour = 7; + } + _currentHourCount += 2; + ++hour; + if (hour > 23) + hour = 0; + prepareRoom(); + answer = _dialogManager.show(getEngineString(S_YES_NO), 1); + _anyone = false; + } while (answer != 1); + _crep = 998; + _num = 0; +} + +/** + * Engine function - Force + * @remarks Originally called 'tdefoncer' + */ +void MortevielleEngine::fctForce() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_SMASH)); + if (_caff < DOOR) + displayStatusArrow(); + + if ((!_anyone) && (!_keyPressedEsc)) { + if (_coreVar._currPlace != ROOM26) + _crep = 997; + else { + _crep = 143; + _coreVar._faithScore += 2; + } + } +} + +/** + * Engine function - Leave + * @remarks Originally called 'tsortir' + */ +void MortevielleEngine::fctLeave() { + exitRoom(); + _crep = 0; + if ((_coreVar._currPlace == MOUNTAIN) || (_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK) || (_coreVar._currPlace == WELL)) + _crep = 997; + else { + int nextPlace = OWN_ROOM; + + if ((_coreVar._currPlace < CRYPT) || (_coreVar._currPlace == ROOM26)) + nextPlace = DINING_ROOM; + else if ((_coreVar._currPlace == DINING_ROOM) || (_coreVar._currPlace == CHAPEL)) + nextPlace = MANOR_FRONT; + else if ((_coreVar._currPlace < DINING_ROOM) || (_coreVar._currPlace == ATTIC)) + nextPlace = LANDING; + else if (_coreVar._currPlace == CRYPT) { + nextPlace = SECRET_PASSAGE; + _crep = 176; + } else if (_coreVar._currPlace == SECRET_PASSAGE) + nextPlace = checkLeaveSecretPassage(); + else if (_coreVar._currPlace == INSIDE_WELL) + nextPlace = WELL; + + if (_crep != 997) + _coreVar._currPlace = nextPlace; + + _caff = nextPlace; + if (_crep == 0) + _crep = nextPlace; + resetRoomVariables(nextPlace); + _menu.setDestinationText(nextPlace); + } +} + +/** + * Engine function - Wait + * @remarks Originally called 'tattendre' + */ +void MortevielleEngine::fctWait() { + _savedBitIndex = 0; + clearVerbBar(); + + int answer; + do { + ++_currentHourCount; + prepareRoom(); + if (!_blo) + getPresence(_coreVar._currPlace); + if ((_currBitIndex != 0) && (_savedBitIndex == 0)) { + _crep = 998; + if ((_coreVar._currPlace == ATTIC) || (_coreVar._currPlace == CELLAR)) + initCaveOrCellar(); + if ((_coreVar._currPlace > OWN_ROOM) && (_coreVar._currPlace < DINING_ROOM)) + _anyone = true; + _savedBitIndex = _currBitIndex; + if (!_anyone) + prepareRoom(); + return; + } + handleDescriptionText(2, 102); + answer = _dialogManager.show(getEngineString(S_YES_NO), 1); + } while (answer != 2); + _crep = 998; + if (!_anyone) + prepareRoom(); +} + +/** + * Engine function - Sound + * @remarks Originally called 'tsonder' + */ +void MortevielleEngine::fctSound() { + if (!_syn) + displayTextInVerbBar(getEngineString(S_PROBE2)); + if (_caff < 27) { + displayStatusArrow(); + if (!(_anyone) && (!_keyPressedEsc)) + _crep = 145; + _num = 0; + } +} + +/** + * Engine function - Discuss + * @remarks Originally called 'tparler' + */ +void MortevielleEngine::fctDiscuss() { + bool questionAsked[47]; + int cy, cx; + int x, y; + Common::String lib[47]; + + int choice; + int displId; + + endSearch(); + if (_col) + displId = 128; + else { + cx = 0; + int oldMenu; + do { + ++cx; + oldMenu = (_menu._discussMenu[cx]._menuId << 8) | _menu._discussMenu[cx]._actionId; + } while (oldMenu != _currAction); + _caff = 69 + cx; + drawPictureWithText(); + handleDescriptionText(2, _caff); + displId = _caff + 60; + } + testKey(false); + menuUp(); + _mouse.hideMouse(); + clearScreen(); + drawDiscussionBox(); + startDialog(displId); + clearScreen(); + for (int ix = 1; ix <= 46; ++ix) + questionAsked[ix] = false; + for (int ix = 1; ix <= 45; ++ix) { + lib[ix] = getString(ix + kQuestionStringIndex); + for (int i = lib[ix].size(); i <= 40; ++i) + lib[ix] = lib[ix] + ' '; + } + lib[46] = lib[45]; + lib[45] = ' '; + _mouse.showMouse(); + do { + choice = 0; + int posX = 0; + int posY = 0; + for (int icm = 1; icm < 43; icm++) { + _screenSurface.putxy(posX, posY); + if (_coreVar._availableQuestion[icm] == '*') { + // If question already asked, write it in reverse video + if (questionAsked[icm]) + displayQuestionText(lib[icm], 1); + else + displayQuestionText(lib[icm], 0); + } + + if (icm == 23) { + posY = 0; + posX = 320; + } else + posY += 8; + } + _screenSurface.putxy(320, 176); + displayQuestionText(lib[46], 0); + char retKey = '\0'; + bool click; + do { + bool dummyFl; + _mouse.moveMouse(dummyFl, retKey); + if (shouldQuit()) + return; + + _mouse.getMousePosition(x, y, click); + x *= (3 - kResolutionScaler); + if (x > 319) + cx = 41; + else + cx = 1; + cy = ((uint)y >> 3) + 1; // 0-199 => 1-25 + if ((cy > 23) || ((cx == 41) && ((cy >= 20) && (cy <= 22)))) { + if (choice != 0) { + posY = ((choice - 1) % 23) << 3; + if (choice > 23) + posX = 320; + else + posX = 0; + _screenSurface.putxy(posX, posY); + if (questionAsked[choice]) + displayQuestionText(lib[choice], 0); + else + displayQuestionText(lib[choice], 1); + questionAsked[choice] = !questionAsked[choice]; + choice = 0; + } + } else { + int ix = cy; + if (cx == 41) + ix += 23; + if (ix != choice) { + if (choice != 0) { + posY = ((choice - 1) % 23) << 3; + if (choice > 23) + posX = 320; + else + posX = 0; + _screenSurface.putxy(posX, posY); + if (questionAsked[choice]) + displayQuestionText(lib[choice], 0); + else + displayQuestionText(lib[choice], 1); + questionAsked[choice] = ! questionAsked[choice]; + } + if ((ix == 46) || (_coreVar._availableQuestion[ix] == '*')) { + posY = ((ix - 1) % 23) << 3; + if (ix > 23) + posX = 320; + else + posX = 0; + _screenSurface.putxy(posX, posY); + if (questionAsked[ix]) + displayQuestionText(lib[ix], 0); + else + displayQuestionText(lib[ix], 1); + questionAsked[ix] = ! questionAsked[ix]; + choice = ix; + } else + choice = 0; + } + } + } while (!((retKey == '\15') || (((click != 0) || getMouseClick()) && (choice != 0)))); + setMouseClick(false); + + // If choice is not "End of Conversation" + if (choice != 46) { + int ix = choice - 1; + if (_col) { + _col = false; + _coreVar._currPlace = 15; + int maxRandVal; + if (_openObjCount > 0) + maxRandVal = 8; + else + maxRandVal = 4; + if (getRandomNumber(1, maxRandVal) == 2) + displId = 129; + else { + displId = 138; + _coreVar._faithScore += (3 * (_coreVar._faithScore / 10)); + } + } else if (_charAnswerCount[_caff - 69] < _charAnswerMax[_caff - 69]) { + displId = _tabdon[kArep + (ix << 3) + (_caff - 70)]; + _coreVar._faithScore += _tabdon[kArcf + ix]; + ++_charAnswerCount[_caff - 69]; + } else { + _coreVar._faithScore += 3; + displId = 139; + } + _mouse.hideMouse(); + clearScreen(); + drawDiscussionBox(); + startDialog(displId); + _mouse.showMouse(); + if ((displId == 84) || (displId == 86)) { + _coreVar._pctHintFound[5] = '*'; + _coreVar._availableQuestion[7] = '*'; + } + if ((displId == 106) || (displId == 108) || (displId == 94)) { + for (int indx = 29; indx <= 31; ++indx) + _coreVar._availableQuestion[indx] = '*'; + _coreVar._pctHintFound[7] = '*'; + } + if (displId == 70) { + _coreVar._pctHintFound[8] = '*'; + _coreVar._availableQuestion[32] = '*'; + } + _mouse.hideMouse(); + clearScreen(); + _mouse.showMouse(); + } + } while ((choice != 46) && (displId != 138)); + if (_col) { + _coreVar._faithScore += (3 * (_coreVar._faithScore / 10)); + _mouse.hideMouse(); + clearScreen(); + drawDiscussionBox(); + startDialog(138); + _mouse.showMouse(); + _col = false; + _coreVar._currPlace = LANDING; + } + _controlMenu = 0; + _mouse.hideMouse(); + clearScreen(); + drawRightFrame(); + _mouse.showMouse(); + showPeoplePresent(_currBitIndex); + prepareRoom(); + drawClock(); + prepareDisplayText(); + /* chech;*/ + _menu.setDestinationText(_coreVar._currPlace); + clearVerbBar(); +} + +/** + * Engine function - Smell + * @remarks Originally called 'tsentir' + */ +void MortevielleEngine::fctSmell() { + _crep = 119; + if (_caff < ROOM26) { + if (!_syn) + displayTextInVerbBar(getEngineString(S_SMELL)); + displayStatusArrow(); + if (!(_anyone) && !(_keyPressedEsc)) + if (_caff == CRYPT) + _crep = 153; + } else if (_caff == 123) + _crep = 110; + _num = 0; +} + +/** + * Engine function - Scratch + * @remarks Originally called 'tgratter' + */ +void MortevielleEngine::fctScratch() { + _crep = 155; + if (_caff < 27) { + if (!_syn) + displayTextInVerbBar(getEngineString(S_SCRATCH)); + displayStatusArrow(); + } + _num = 0; +} + +/** + * The game is over + * @remarks Originally called 'tmaj1' + */ +void MortevielleEngine::endGame() { + _quitGame = true; + displayNarrativePicture(13, 152); + displayEmptyHand(); + clearUpperLeftPart(); + clearDescriptionBar(); + clearVerbBar(); + handleDescriptionText(9, 1509); + testKey(false); + _mouse.hideMouse(); + _caff = 70; + _text.taffich(); + clearScreen(); + drawDiscussionBox(); + startDialog(141); + _mouse.showMouse(); + clearUpperLeftPart(); + handleDescriptionText(9, 1509); + handleDescriptionText(2, 142); + testKey(false); + _caff = 32; + drawPictureWithText(); + handleDescriptionText(6, 34); + handleDescriptionText(2, 35); + startMusicOrSpeech(0); + testKey(false); + // A wait message was displayed. + // testKey (aka tkey1) was called before and after. + // This double call is useless, thus removed + resetVariables(); +} + +/** + * You lost! + * @remarks Originally called 'tencore' + */ +void MortevielleEngine::askRestart() { + clearDescriptionBar(); + startMusicOrSpeech(0); + testKey(false); + displayEmptyHand(); + resetVariables(); + initGame(); + _currHour = 10; + _currHalfHour = 0; + _currDay = 0; + _minute = 0; + _hour = 10; + _day = 0; + handleDescriptionText(2, 180); + + int answer = _dialogManager.show(getEngineString(S_YES_NO), 1); + _quitGame = (answer != 1); +} + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/debugger.cpp b/engines/mortevielle/debugger.cpp new file mode 100644 index 0000000000..4ef5151c81 --- /dev/null +++ b/engines/mortevielle/debugger.cpp @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/debugger.h" + +namespace Mortevielle { + +Debugger::Debugger() : GUI::Debugger() { + DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); + DCmd_Register("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions)); + DCmd_Register("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano)); +} + +bool Debugger::Cmd_showAllQuestions(int argc, const char **argv) { + for (int i = 1; i <= 10; ++i) + _vm->_coreVar._pctHintFound[i] = '*'; + + for (int i = 1; i <= 42; ++i) + _vm->_coreVar._availableQuestion[i] = '*'; + + for (int i = 0; i < 9; i++) { + _vm->_charAnswerCount[i] = 0; + _vm->_charAnswerMax[i] = 999; + } + + return true; +} + +bool Debugger::Cmd_resetParano(int argc, const char **argv) { + _vm->_coreVar._faithScore = 0; + + return true; +} + +void Debugger::setParent(MortevielleEngine *vm) { + _vm = vm; +} + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/debugger.h b/engines/mortevielle/debugger.h new file mode 100644 index 0000000000..9041d90110 --- /dev/null +++ b/engines/mortevielle/debugger.h @@ -0,0 +1,49 @@ +/* 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. + * + */ + +#ifndef MORTEVIELLE_DEBUGGER_H +#define MORTEVIELLE_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace Mortevielle { + +class MortevielleEngine; + +class Debugger : public GUI::Debugger { +private: + MortevielleEngine *_vm; + +protected: + bool Cmd_showAllQuestions(int argc, const char **argv); + bool Cmd_resetParano(int argc, const char **argv); + +public: + Debugger(); + virtual ~Debugger() {} + void setParent(MortevielleEngine *vm); +}; + +} // End of namespace Mortevielle + +#endif diff --git a/engines/mortevielle/detection.cpp b/engines/mortevielle/detection.cpp new file mode 100644 index 0000000000..8e2eab52b8 --- /dev/null +++ b/engines/mortevielle/detection.cpp @@ -0,0 +1,109 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "base/plugins.h" +#include "engines/advancedDetector.h" + +#include "mortevielle/mortevielle.h" +#include "mortevielle/saveload.h" + +namespace Mortevielle { +struct MortevielleGameDescription { + ADGameDescription desc; + Common::Language originalLanguage; +}; + +uint32 MortevielleEngine::getGameFlags() const { return _gameDescription->desc.flags; } + +Common::Language MortevielleEngine::getLanguage() const { return _gameDescription->desc.language; } + +Common::Language MortevielleEngine::getOriginalLanguage() const { return _gameDescription->originalLanguage; } + +} + +static const PlainGameDescriptor MortevielleGame[] = { + {"mortevielle", "Mortville Manor"}, + {0, 0} +}; + +#include "mortevielle/detection_tables.h" + +class MortevielleMetaEngine : public AdvancedMetaEngine { +public: + MortevielleMetaEngine() : AdvancedMetaEngine(Mortevielle::MortevielleGameDescriptions, sizeof(Mortevielle::MortevielleGameDescription), + MortevielleGame) { + _md5Bytes = 512; + _singleid = "mortevielle"; + } + virtual const char *getName() const { + return "Mortevielle"; + } + + virtual const char *getOriginalCopyright() const { + return "Mortville Manor (C) 1987-89 Lankhor"; + } + + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual bool hasFeature(MetaEngineFeature f) const; + virtual int getMaximumSaveSlot() const; + virtual SaveStateList listSaves(const char *target) const; + virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; + +bool MortevielleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + if (desc) { + *engine = new Mortevielle::MortevielleEngine(syst, (const Mortevielle::MortevielleGameDescription *)desc); + } + return desc != 0; +} + +bool MortevielleMetaEngine::hasFeature(MetaEngineFeature f) const { + switch (f) { + case kSupportsListSaves: + case kSupportsDeleteSave: + case kSupportsLoadingDuringStartup: + case kSavesSupportMetaInfo: + case kSavesSupportThumbnail: + case kSavesSupportCreationDate: + return true; + default: + return false; + } +} + +int MortevielleMetaEngine::getMaximumSaveSlot() const { return 99; } + +SaveStateList MortevielleMetaEngine::listSaves(const char *target) const { + return Mortevielle::SavegameManager::listSaves(target); +} + +SaveStateDescriptor MortevielleMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Mortevielle::MortevielleEngine::generateSaveFilename(target, slot); + return Mortevielle::SavegameManager::querySaveMetaInfos(filename); +} + + +#if PLUGIN_ENABLED_DYNAMIC(MORTEVIELLE) + REGISTER_PLUGIN_DYNAMIC(MORTEVIELLE, PLUGIN_TYPE_ENGINE, MortevielleMetaEngine); +#else + REGISTER_PLUGIN_STATIC(MORTEVIELLE, PLUGIN_TYPE_ENGINE, MortevielleMetaEngine); +#endif diff --git a/engines/mortevielle/detection_tables.h b/engines/mortevielle/detection_tables.h new file mode 100644 index 0000000000..9bb5fbea87 --- /dev/null +++ b/engines/mortevielle/detection_tables.h @@ -0,0 +1,99 @@ +/* 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. + * + */ + +namespace Mortevielle { + +static const MortevielleGameDescription MortevielleGameDescriptions[] = { + // French + { + { + "mortevielle", + "", + { + {"menufr.mor", 0, "e413f36b9e14eef16130adc347a9391f", 144}, + {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744}, + AD_LISTEND + }, + Common::FR_FRA, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO0() + }, Common::FR_FRA + }, + // German + { + { + "mortevielle", + "", + { + {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144}, + {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744}, + AD_LISTEND + }, + Common::DE_DEU, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO0() + }, Common::DE_DEU + }, + + // DOS English version doesn't exist. Technically, they are French or German versions, + // using English strings stored mort.dat + + // English on top of French version + { + { + "mortevielle", + "", + { + {"menufr.mor", 0, "e413f36b9e14eef16130adc347a9391f", 144}, + {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO0() + }, Common::FR_FRA + }, + + // English on top of German version + { + { + "mortevielle", + "", + { + {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144}, + {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO0() + }, Common::DE_DEU + }, + + { AD_TABLE_END_MARKER , Common::EN_ANY} +}; + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp new file mode 100644 index 0000000000..a7bd381603 --- /dev/null +++ b/engines/mortevielle/dialogs.cpp @@ -0,0 +1,472 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" + +#include "mortevielle/dialogs.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" + +#include "common/str.h" + +namespace Mortevielle { + +/** + * Alert function - Show + * @remarks Originally called 'do_alert' + */ +int DialogManager::show(const Common::String &msg, int n) { + // Make a copy of the current screen surface for later restore + _vm->_backgroundSurface.copyFrom(_vm->_screenSurface); + + _vm->_mouse.hideMouse(); + while (_vm->keyPressed()) + _vm->getChar(); + + _vm->setMouseClick(false); + + int colNumb = 0; + int lignNumb = 0; + int caseNumb = 0; + Common::String alertStr = ""; + Common::String caseStr; + + decodeAlertDetails(msg, caseNumb, lignNumb, colNumb, alertStr, caseStr); + + Common::Point curPos; + if (alertStr == "") { + drawAlertBox(10, 5, colNumb); + } else { + drawAlertBox(8, 7, colNumb); + int i = 0; + _vm->_screenSurface._textPos.y = 70; + do { + curPos.x = 320; + Common::String displayStr = ""; + while ((alertStr[i + 1] != '\174') && (alertStr[i + 1] != '\135')) { + ++i; + displayStr += alertStr[i]; + curPos.x -= 3; + } + _vm->_screenSurface.putxy(curPos.x, _vm->_screenSurface._textPos.y); + _vm->_screenSurface._textPos.y += 6; + _vm->_screenSurface.drawString(displayStr, 4); + ++i; + } while (alertStr[i] != ']'); + } + int esp; + if (caseNumb == 1) + esp = colNumb - 40; + else + esp = (uint)(colNumb - caseNumb * 40) / 2; + + int coldep = 320 - ((uint)colNumb / 2) + ((uint)esp / 2); + Common::String buttonStr[3]; + setButtonText(caseStr, coldep, caseNumb, &buttonStr[0], esp); + + int limit[3][3]; + memset(&limit[0][0], 0, sizeof(int) * 3 * 3); + + limit[1][1] = ((uint)(coldep) / 2) * kResolutionScaler; + limit[1][2] = limit[1][1] + 40; + if (caseNumb == 1) { + limit[2][1] = limit[2][2]; + } else { + limit[2][1] = ((uint)(320 + ((uint)esp >> 1)) / 2) * kResolutionScaler; + limit[2][2] = (limit[2][1]) + 40; + } + _vm->_mouse.showMouse(); + int id = 0; + bool dummyFl = false; + bool test3; + do { + char dummyKey = '\377'; + _vm->_mouse.moveMouse(dummyFl, dummyKey); + if (_vm->shouldQuit()) + return 0; + + curPos = _vm->_mouse._pos; + bool newaff = false; + if ((curPos.y > 95) && (curPos.y < 105)) { + bool test1 = (curPos.x > limit[1][1]) && (curPos.x < limit[1][2]); + bool test2 = test1; + if (caseNumb > 1) + test2 |= ((curPos.x > limit[2][1]) && (curPos.x < limit[2][2])); + if (test2) { + newaff = true; + + int ix; + if (test1) + ix = 1; + else + ix = 2; + if (ix != id) { + _vm->_mouse.hideMouse(); + if (id != 0) { + setPosition(id, coldep, esp); + + Common::String tmpStr(" "); + tmpStr += buttonStr[id]; + tmpStr += " "; + _vm->_screenSurface.drawString(tmpStr, 0); + } + setPosition(ix, coldep, esp); + + Common::String tmp2 = " "; + tmp2 += buttonStr[ix]; + tmp2 += " "; + _vm->_screenSurface.drawString(tmp2, 1); + + id = ix; + _vm->_mouse.showMouse(); + } + } + } + if ((id != 0) && !newaff) { + _vm->_mouse.hideMouse(); + setPosition(id, coldep, esp); + + Common::String tmp3(" "); + tmp3 += buttonStr[id]; + tmp3 += " "; + _vm->_screenSurface.drawString(tmp3, 0); + + id = 0; + _vm->_mouse.showMouse(); + } + test3 = (curPos.y > 95) && (curPos.y < 105) && (((curPos.x > limit[1][1]) && (curPos.x < limit[1][2])) + || ((curPos.x > limit[2][1]) && (curPos.x < limit[2][2]))); + } while (!_vm->getMouseClick()); + _vm->setMouseClick(false); + _vm->_mouse.hideMouse(); + if (!test3) { + id = n; + setPosition(n, coldep, esp); + Common::String tmp4(" "); + tmp4 += buttonStr[n]; + tmp4 += " "; + _vm->_screenSurface.drawString(tmp4, 1); + } + _vm->_mouse.showMouse(); + + /* Restore the background area */ + _vm->_screenSurface.copyFrom(_vm->_backgroundSurface, 0, 0); + + return id; +} + +/** + * Alert function - Decode Alert Details + * @remarks Originally called 'decod' + */ +void DialogManager::decodeAlertDetails(Common::String inputStr, int &choiceNumb, int &lineNumb, int &col, Common::String &choiceStr, Common::String &choiceListStr) { + // The second character of the string contains the number of choices + choiceNumb = atoi(inputStr.c_str() + 1); + + choiceStr = ""; + col = 0; + lineNumb = 0; + + // Originally set to 5, decreased to 4 because strings are 0 based, and not 1 based as in Pascal + int i = 4; + int k = 0; + bool empty = true; + + for (; inputStr[i] != ']'; ++i) { + choiceStr += inputStr[i]; + if ((inputStr[i] == '|') || (inputStr[i + 1] == ']')) { + if (k > col) + col = k; + k = 0; + ++lineNumb; + } else if (inputStr[i] != ' ') + empty = false; + ++k; + } + + if (empty) { + choiceStr = ""; + col = 20; + } else { + choiceStr += ']'; + col += 6; + } + + choiceListStr = Common::String(inputStr.c_str() + i); + col *= 6; +} + +void DialogManager::setPosition(int ji, int coldep, int esp) { + _vm->_screenSurface.putxy(coldep + (40 + esp) * (ji - 1), 98); +} + +/** + * Alert function - Draw Alert Box + * @remarks Originally called 'fait_boite' + */ +void DialogManager::drawAlertBox(int firstLine, int lineNum, int width) { + if (width > 640) + width = 640; + int x = 320 - ((uint)width / 2); + int y = (firstLine - 1) * 8; + int xx = x + width; + int yy = y + (lineNum * 8); + _vm->_screenSurface.fillRect(15, Common::Rect(x, y, xx, yy)); + _vm->_screenSurface.fillRect(0, Common::Rect(x, y + 2, xx, y + 4)); + _vm->_screenSurface.fillRect(0, Common::Rect(x, yy - 4, xx, yy - 2)); +} + +/** + * Alert function - Set Button Text + * @remarks Originally called 'fait_choix' + */ +void DialogManager::setButtonText(Common::String c, int coldep, int nbcase, Common::String *str, int esp) { + int i = 1; + int x = coldep; + for (int l = 1; l <= nbcase; ++l) { + str[l] = ""; + do { + ++i; + char ch = c[i]; + str[l] += ch; + } while (c[i + 1] != ']'); + i += 2; + + while (str[l].size() < 3) + str[l] += ' '; + + _vm->_screenSurface.putxy(x, 98); + + Common::String tmp(" "); + tmp += str[l]; + tmp += " "; + + _vm->_screenSurface.drawString(tmp, 0); + x += esp + 40; + } +} + +/*------------------------------------------------------------------------*/ + +/** + * Questions asked before entering the hidden passage + */ +bool DialogManager::showKnowledgeCheck() { + const int textIndexArr[10] = {511, 516, 524, 531, 545, 552, 559, 563, 570, 576}; + const int correctAnswerArr[10] = {4, 7, 1, 6, 4, 4, 2, 5, 3, 1 }; + + Hotspot coor[kMaxHotspots+1]; + + for (int i = 0; i <= kMaxHotspots; ++i) { + coor[i]._rect = Common::Rect(); + coor[i]._enabled = false; + } + + Common::String choiceArray[15]; + + int currChoice, prevChoice; + int correctCount = 0; + + for (int indx = 0; indx < 10; ++indx) { + _vm->_mouse.hideMouse(); + _vm->clearScreen(); + _vm->_mouse.showMouse(); + int dialogHeight = 23; + _vm->_screenSurface.fillRect(15, Common::Rect(0, 14, 630, dialogHeight)); + Common::String tmpStr = _vm->getString(textIndexArr[indx]); + _vm->_text.displayStr(tmpStr, 20, 15, 100, 2, 0); + + int firstOption; + int lastOption; + + if (indx != 9) { + firstOption = textIndexArr[indx] + 1; + lastOption = textIndexArr[indx + 1] - 1; + } else { + firstOption = 503; + lastOption = 510; + } + int optionPosY = 35; + int maxLength = 0; + + prevChoice = 1; + for (int j = firstOption; j <= lastOption; ++j, ++prevChoice) { + tmpStr = _vm->getString(j); + if ((int) tmpStr.size() > maxLength) + maxLength = tmpStr.size(); + _vm->_text.displayStr(tmpStr, 100, optionPosY, 100, 1, 0); + choiceArray[prevChoice] = tmpStr; + optionPosY += 8; + } + + for (int j = 1; j <= lastOption - firstOption + 1; ++j) { + coor[j]._rect = Common::Rect(45 * kResolutionScaler, 27 + j * 8, (maxLength * 3 + 55) * kResolutionScaler, 34 + j * 8); + coor[j]._enabled = true; + + while ((int)choiceArray[j].size() < maxLength) { + choiceArray[j] += ' '; + } + } + coor[lastOption - firstOption + 2]._enabled = false; + int rep = 6; + _vm->_screenSurface.drawBox(80, 33, 40 + (maxLength * rep), (lastOption - firstOption) * 8 + 16, 15); + rep = 0; + + prevChoice = 0; + warning("Expected answer: %d", correctAnswerArr[indx]); + do { + _vm->setMouseClick(false); + bool flag; + char key; + _vm->_mouse.moveMouse(flag, key); + if (_vm->shouldQuit()) + return false; + + currChoice = 1; + while (coor[currChoice]._enabled && !_vm->_mouse.isMouseIn(coor[currChoice]._rect)) + ++currChoice; + if (coor[currChoice]._enabled) { + if ((prevChoice != 0) && (prevChoice != currChoice)) { + tmpStr = choiceArray[prevChoice] + '$'; + _vm->_text.displayStr(tmpStr, 100, 27 + (prevChoice * 8), 100, 1, 0); + } + if (prevChoice != currChoice) { + tmpStr = choiceArray[currChoice] + '$'; + _vm->_text.displayStr(tmpStr, 100, 27 + (currChoice * 8), 100, 1, 1); + prevChoice = currChoice; + } + } else if (prevChoice != 0) { + tmpStr = choiceArray[prevChoice] + '$'; + _vm->_text.displayStr(tmpStr, 100, 27 + (prevChoice * 8), 100, 1, 0); + prevChoice = 0; + } + } while (!((prevChoice != 0) && _vm->getMouseClick())); + + if (prevChoice == correctAnswerArr[indx]) + // Answer is correct + ++correctCount; + else { + // Skip questions that may give hints on previous wrong answer + if (indx == 4) + ++indx; + else if ((indx == 6) || (indx == 7)) + indx = 9; + } + } + + return (correctCount == 10); +} + +/*------------------------------------------------------------------------*/ + +/** + * Draw the F3/F8 dialog + */ +void DialogManager::drawF3F8() { + Common::String f3 = _vm->getEngineString(S_F3); + Common::String f8 = _vm->getEngineString(S_F8); + + // Write the F3 and F8 text strings + _vm->_screenSurface.putxy(3, 44); + _vm->_screenSurface.drawString(f3, 5); + _vm->_screenSurface._textPos.y = 51; + _vm->_screenSurface.drawString(f8, 5); + + // Get the width of the written text strings + int f3Width = _vm->_screenSurface.getStringWidth(f3); + int f8Width = _vm->_screenSurface.getStringWidth(f8); + + // Write out the bounding box + _vm->_screenSurface.drawBox(0, 42, MAX(f3Width, f8Width) + 6, 18, 7); +} + +/** + * Alert function - Loop until F8 is pressed, update + * Graphical Device if modified + * @remarks Originally called 'diver' + */ +void DialogManager::checkForF8(int SpeechNum, bool drawFrame2Fl) { + _vm->testKeyboard(); + do { + _vm->_soundManager.startSpeech(SpeechNum, 0, 0); + _vm->_key = waitForF3F8(); + if (_vm->shouldQuit()) + return; + } while (_vm->_key != 66); // keycode for F8 +} + +/** + * Alert function - Loop until F3 or F8 is pressed + * @remarks Originally called 'atf3f8' + */ +int DialogManager::waitForF3F8() { + int key; + + do { + key = _vm->gettKeyPressed(); + if (_vm->shouldQuit()) + return key; + } while ((key != 61) && (key != 66)); + + return key; +} + +/** + * Intro function - display intro screen + * @remarks Originally called 'aff50' + */ +void DialogManager::displayIntroScreen(bool drawFrame2Fl) { + _vm->_caff = 50; + _vm->_maff = 0; + _vm->_text.taffich(); + _vm->draw(63, 12); + if (drawFrame2Fl) + displayIntroFrame2(); + else + _vm->handleDescriptionText(2, kDialogStringIndex + 142); + + // Draw the f3/f8 dialog + drawF3F8(); +} + +/** + * Intro function - display 2nd frame of intro + * @remarks Originally called 'ani50' + */ +void DialogManager::displayIntroFrame2() { + _vm->_crep = _vm->getAnimOffset(1, 1); + _vm->displayPicture(&_vm->_curAnim[_vm->_crep], 63, 12); + _vm->_crep = _vm->getAnimOffset(2, 1); + _vm->displayPicture(&_vm->_curAnim[_vm->_crep], 63, 12); + _vm->_largestClearScreen = false; + _vm->handleDescriptionText(2, kDialogStringIndex + 143); +} + +void DialogManager::setParent(MortevielleEngine *vm) { + _vm = vm; +} +} // End of namespace Mortevielle diff --git a/engines/mortevielle/dialogs.h b/engines/mortevielle/dialogs.h new file mode 100644 index 0000000000..ee210a62b2 --- /dev/null +++ b/engines/mortevielle/dialogs.h @@ -0,0 +1,65 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_ALERT_H +#define MORTEVIELLE_ALERT_H + +#include "common/rect.h" +#include "common/str.h" + +namespace Mortevielle { +class MortevielleEngine; + +static const int NUM_LINES = 7; +const int kMaxHotspots = 14; + +struct Hotspot { + Common::Rect _rect; + bool _enabled; +}; + +class DialogManager { +private: + MortevielleEngine *_vm; + + void decodeAlertDetails(Common::String inputStr, int &choiceNumb, int &lineNumb, int &col, Common::String &choiceStr, Common::String &choiceListStr); + void setPosition(int ji, int coldep, int esp); + void drawAlertBox(int firstLine, int lineNum, int width); + void setButtonText(Common::String c, int coldep, int nbcase, Common::String *str, int esp); +public: + void setParent(MortevielleEngine *vm); + int show(const Common::String &msg, int n); + void drawF3F8(); + void checkForF8(int SpeechNum, bool drawFrame2Fl); + int waitForF3F8(); + void displayIntroScreen(bool drawFrame2Fl); + void displayIntroFrame2(); + bool showKnowledgeCheck(); +}; + +} // End of namespace Mortevielle +#endif diff --git a/engines/mortevielle/graphics.cpp b/engines/mortevielle/graphics.cpp new file mode 100644 index 0000000000..daf7926438 --- /dev/null +++ b/engines/mortevielle/graphics.cpp @@ -0,0 +1,1167 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/graphics.h" +#include "mortevielle/mouse.h" + +#include "common/endian.h" +#include "common/system.h" +#include "graphics/palette.h" + +namespace Mortevielle { + +/*-------------------------------------------------------------------------* + * Palette Manager + * + *-------------------------------------------------------------------------*/ + +/** + * Set palette entries from the 64 color available EGA palette + */ +void PaletteManager::setPalette(const int *palette, uint idx, uint size) { + assert((idx + size) <= 16); + + // Build up the EGA palette + byte egaPalette[64 * 3]; + + byte *p = &egaPalette[0]; + for (int i = 0; i < 64; ++i) { + *p++ = (i >> 2 & 1) * 0xaa + (i >> 5 & 1) * 0x55; + *p++ = (i >> 1 & 1) * 0xaa + (i >> 4 & 1) * 0x55; + *p++ = (i & 1) * 0xaa + (i >> 3 & 1) * 0x55; + } + + // Loop through setting palette colors based on the passed indexes + for (; size > 0; --size, ++idx) { + int palIndex = palette[idx]; + assert(palIndex < 64); + + const byte *pRgb = (const byte *)&egaPalette[palIndex * 3]; + g_system->getPaletteManager()->setPalette(pRgb, idx, 1); + } +} + +/** + * Set the default EGA palette + */ +void PaletteManager::setDefaultPalette() { + const int defaultPalette[16] = { 0, 1, 2, 3, 4, 5, 20, 7, 56, 57, 58, 59, 60, 61, 62, 63 }; + setPalette(defaultPalette, 0, 16); +} + +/*-------------------------------------------------------------------------* + * Image decoding + * + * The code in this section is responsible for decoding image resources. + * Images are broken down into rectangular sections, which can use one + * of 18 different encoding methods. + *-------------------------------------------------------------------------*/ + +#define INCR_XSIZE { if (_xSize & 1) ++_xSize; } +#define DEFAULT_WIDTH (SCREEN_WIDTH / 2) +#define BUFFER_SIZE 40000 + +void GfxSurface::decode(const byte *pSrc) { + w = h = 0; + // If no transparency, use invalid (for EGA) palette index of 16. Otherwise get index to use + _transparency = (*pSrc == 0) ? 16 : *(pSrc + 2); + bool offsetFlag = *pSrc++ == 0; + int entryCount = *pSrc++; + pSrc += 2; + + if (offsetFlag) + pSrc += 30; + + // First run through the data to calculate starting offsets + const byte *p = pSrc; + _offset.x = _offset.y = 999; + + assert(entryCount > 0); + for (int idx = 0; idx < entryCount; ++idx) { + _xp = READ_BE_UINT16(p + 4); + if (_xp < _offset.x) + _offset.x = _xp; + + _yp = READ_BE_UINT16(p + 6); + if (_yp < _offset.y) + _offset.y = _yp; + + // Move to next entry + int size = READ_BE_UINT16(p) + READ_BE_UINT16(p + 2); + if ((size % 2) == 1) + ++size; + + p += size + 14; + } + + // Temporary output buffer + byte *outputBuffer = (byte *)malloc(sizeof(byte) * 65536); + memset(outputBuffer, _transparency, 65536); + + byte *pDest = &outputBuffer[0]; + const byte *pSrcStart = pSrc; + const byte *pLookup = NULL; + + byte *lookupTable = (byte *)malloc(sizeof(byte) * BUFFER_SIZE); + byte *srcBuffer = (byte *)malloc(sizeof(byte) * BUFFER_SIZE); + + // Main processing loop + for (int entryIndex = 0; entryIndex < entryCount; ++entryIndex) { + int lookupBytes = READ_BE_UINT16(pSrc); + int srcSize = READ_BE_UINT16(pSrc + 2); + _xp = READ_BE_UINT16(pSrc + 4) - _offset.x; + _yp = READ_BE_UINT16(pSrc + 6) - _offset.y; + assert((_xp >= 0) && (_yp >= 0) && (_xp < SCREEN_WIDTH) && (_yp < SCREEN_ORIG_HEIGHT)); + pSrc += 8; + + int decomCode = READ_BE_UINT16(pSrc); + _xSize = READ_BE_UINT16(pSrc + 2) + 1; + _ySize = READ_BE_UINT16(pSrc + 4) + 1; + majTtxTty(); + + pSrc += 6; + pDest = &outputBuffer[0]; + + _lookupIndex = 0; + _nibbleFlag = false; + + int decomIndex = 0; + if (decomCode >> 8) { + // Build up reference table + int tableOffset = 0; + + if (decomCode & 1) { + // Handle decompression of the pattern lookup table + do { + int outerCount = desanalyse(pSrc); + int innerCount = desanalyse(pSrc); + + const byte *pSrcSaved = pSrc; + bool savedNibbleFlag = _nibbleFlag; + int savedLookupIndex = _lookupIndex; + + do { + pSrc = pSrcSaved; + _nibbleFlag = savedNibbleFlag; + _lookupIndex = savedLookupIndex; + + for (int idx = 0; idx < innerCount; ++idx, ++tableOffset) { + assert(tableOffset < BUFFER_SIZE); + lookupTable[tableOffset] = nextNibble(pSrc); + } + } while (--outerCount > 0); + } while (_lookupIndex < (lookupBytes - 1)); + + } else { + assert(lookupBytes < BUFFER_SIZE); + for (int idx = 0; idx < (lookupBytes * 2); ++idx) + lookupTable[idx] = nextNibble(pSrc); + } + + if (_nibbleFlag) { + ++pSrc; + _nibbleFlag = false; + } + if ((lookupBytes + srcSize) & 1) + ++pSrc; + + tableOffset = 0; + _lookupIndex = 0; + + if (decomCode & 2) { + // Handle decompression of the temporary source buffer + do { + int outerCount = desanalyse(pSrc); + int innerCount = desanalyse(pSrc); + _lookupIndex += innerCount; + + if (_nibbleFlag) { + ++pSrc; + ++_lookupIndex; + _nibbleFlag = false; + } + + const byte *pStart = pSrc; + do { + pSrc = pStart; + for (int idx = 0; idx < innerCount; ++idx) { + assert(tableOffset < BUFFER_SIZE); + srcBuffer[tableOffset++] = *pSrc++; + } + } while (--outerCount > 0); + } while (_lookupIndex < (srcSize - 1)); + } else { + assert(srcSize < BUFFER_SIZE); + for (int idx = 0; idx < srcSize; ++idx) + srcBuffer[idx] = *pSrc++; + } + + if (_nibbleFlag) + ++pSrc; + + // Switch over to using the decompressed source and lookup buffers + pSrcStart = pSrc; + pDest = &outputBuffer[_yp * DEFAULT_WIDTH + _xp]; + pSrc = &srcBuffer[0]; + pLookup = &lookupTable[0] - 1; + + _lookupValue = _lookupIndex = 0; + _nibbleFlag = false; + decomIndex = decomCode >> 8; + } + + // Main decompression switch + switch (decomIndex) { + case 0: + // Draw rect at pos + pDest = &outputBuffer[_yp * DEFAULT_WIDTH + _xp]; + pSrcStart = pSrc; + INCR_XSIZE; + + for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDest += DEFAULT_WIDTH) { + byte *pDestLine = pDest; + for (int xCtr = 0; xCtr < _xSize; ++xCtr) { + *pDestLine++ = nextNibble(pSrc); + } + } + + pSrcStart += lookupBytes + ((lookupBytes & 1) ? 1 : 0); + break; + + case 1: + // Draw rect using horizontal lines alternating left to right, then right to left + INCR_XSIZE; + for (int yCtr = 0; yCtr < _ySize; ++yCtr) { + if ((yCtr % 2) == 0) { + for (int xCtr = 0; xCtr < _xSize; ++xCtr) { + *pDest++ = nextByte(pSrc, pLookup); + } + } else { + for (int xCtr = 0; xCtr < _xSize; ++xCtr) { + *--pDest = nextByte(pSrc, pLookup); + } + } + pDest += DEFAULT_WIDTH; + } + break; + + case 2: + // Draw rect alternating top to bottom, bottom to top + for (int xCtr = 0; xCtr < _xSize; ++xCtr) { + if ((xCtr % 2) == 0) { + for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDest += DEFAULT_WIDTH) { + *pDest = nextByte(pSrc, pLookup); + } + } else { + for (int yCtr = 0; yCtr < _ySize; ++yCtr) { + pDest -= DEFAULT_WIDTH; + *pDest = nextByte(pSrc, pLookup); + } + } + ++pDest; + } + break; + + case 3: + // Draw horizontal area? + _thickness = 2; + horizontal(pSrc, pDest, pLookup); + break; + + case 4: + // Draw vertical area? + _thickness = 2; + vertical(pSrc, pDest, pLookup); + break; + + case 5: + _thickness = 3; + horizontal(pSrc, pDest, pLookup); + break; + + case 6: + _thickness = 4; + vertical(pSrc, pDest, pLookup); + break; + + case 7: + // Draw rect using horizontal lines left to right + INCR_XSIZE; + for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDest += DEFAULT_WIDTH) { + byte *pDestLine = pDest; + for (int xCtr = 0; xCtr < _xSize; ++xCtr) + *pDestLine++ = nextByte(pSrc, pLookup); + } + break; + + case 8: + // Draw box + for (int xCtr = 0; xCtr < _xSize; ++xCtr, ++pDest) { + byte *pDestLine = pDest; + for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDestLine += DEFAULT_WIDTH) + *pDestLine = nextByte(pSrc, pLookup); + } + break; + + case 9: + _thickness = 4; + horizontal(pSrc, pDest, pLookup); + break; + + case 10: + _thickness = 6; + horizontal(pSrc, pDest, pLookup); + break; + + case 11: + decom11(pSrc, pDest, pLookup); + break; + + case 12: + INCR_XSIZE; + _thickness = _xInc = 1; + _yInc = DEFAULT_WIDTH; + _yEnd = _ySize; + _xEnd = _xSize; + diag(pSrc, pDest, pLookup); + break; + + case 13: + INCR_XSIZE; + _thickness = _xSize; + _yInc = 1; + _yEnd = _xSize; + _xInc = DEFAULT_WIDTH; + _xEnd = _ySize; + diag(pSrc, pDest, pLookup); + break; + + case 14: + _thickness = _yInc = 1; + _yEnd = _xSize; + _xInc = DEFAULT_WIDTH; + _xEnd = _ySize; + diag(pSrc, pDest, pLookup); + break; + + case 15: + INCR_XSIZE; + _thickness = 2; + _yInc = DEFAULT_WIDTH; + _yEnd = _ySize; + _xInc = 1; + _xEnd = _xSize; + diag(pSrc, pDest, pLookup); + break; + + case 16: + _thickness = 3; + _yInc = 1; + _yEnd = _xSize; + _xInc = DEFAULT_WIDTH; + _xEnd = _ySize; + diag(pSrc, pDest, pLookup); + break; + + case 17: + INCR_XSIZE; + _thickness = 3; + _yInc = DEFAULT_WIDTH; + _yEnd = _ySize; + _xInc = 1; + _xEnd = _xSize; + diag(pSrc, pDest, pLookup); + break; + + case 18: + INCR_XSIZE; + _thickness = 5; + _yInc = DEFAULT_WIDTH; + _yEnd = _ySize; + _xInc = 1; + _xEnd = _xSize; + diag(pSrc, pDest, pLookup); + break; + + default: + error("Unknown decompression block type %d", decomIndex); + } + + pSrc = pSrcStart; + debugC(2, kMortevielleGraphics, "Decoding image block %d position %d,%d size %d,%d method %d", + entryIndex + 1, _xp, _yp, w, h, decomIndex); + } + + // At this point, the outputBuffer has the data for the image. Initialize the surface + // with the calculated size, and copy the lines to the surface + create(w, h, Graphics::PixelFormat::createFormatCLUT8()); + + for (int yCtr = 0; yCtr < h; ++yCtr) { + const byte *copySrc = &outputBuffer[yCtr * DEFAULT_WIDTH]; + byte *copyDest = (byte *)getBasePtr(0, yCtr); + + Common::copy(copySrc, copySrc + w, copyDest); + } + + ::free(outputBuffer); + ::free(lookupTable); + ::free(srcBuffer); +} + +void GfxSurface::majTtxTty() { + if (!_yp) + w += _xSize; + + if (!_xp) + h += _ySize; +} + +/** + * Decompression Function - get next nibble + * @remarks Originally called 'suiv' + */ +byte GfxSurface::nextNibble(const byte *&pSrc) { + int v = *pSrc; + if (_nibbleFlag) { + ++pSrc; + ++_lookupIndex; + _nibbleFlag = false; + return v & 0xf; + } else { + _nibbleFlag = !_nibbleFlag; + return v >> 4; + } +} + +/** + * Decompression Function - get next byte + * @remarks Originally called 'csuiv' + */ +byte GfxSurface::nextByte(const byte *&pSrc, const byte *&pLookup) { + assert(pLookup); + + while (!_lookupValue) { + int v; + do { + v = nextNibble(pSrc) & 0xff; + _lookupValue += v; + } while (v == 0xf); + ++pLookup; + } + + --_lookupValue; + return *pLookup; +} + +int GfxSurface::desanalyse(const byte *&pSrc) { + int total = 0; + int v = nextNibble(pSrc); + if (v == 0xf) { + int v2; + do { + v2 = nextNibble(pSrc); + total += v2; + } while (v2 == 0xf); + + total *= 15; + v = nextNibble(pSrc); + } + + total += v; + return total; +} + +void GfxSurface::horizontal(const byte *&pSrc, byte *&pDest, const byte *&pLookup) { + INCR_XSIZE; + byte *pDestEnd = pDest + (_ySize - 1) * DEFAULT_WIDTH + _xSize; + + for (;;) { + // If position is past end point, then skip this line + if (((_thickness - 1) * DEFAULT_WIDTH) + pDest >= pDestEnd) { + if (--_thickness == 0) + break; + continue; + } + + bool continueFlag = false; + do { + for (int xIndex = 0; xIndex < _xSize; ++xIndex) { + if ((xIndex % 2) == 0) { + if (xIndex != 0) + ++pDest; + + // Write out vertical slice top to bottom + for (int yIndex = 0; yIndex < _thickness; ++yIndex, pDest += DEFAULT_WIDTH) + *pDest = nextByte(pSrc, pLookup); + + ++pDest; + } else { + // Write out vertical slice bottom to top + for (int yIndex = 0; yIndex < _thickness; ++yIndex) { + pDest -= DEFAULT_WIDTH; + *pDest = nextByte(pSrc, pLookup); + } + } + } + + if ((_xSize % 2) == 0) { + int blockSize = _thickness * DEFAULT_WIDTH; + pDest += blockSize; + blockSize -= DEFAULT_WIDTH; + + if (pDestEnd < (pDest + blockSize)) { + do { + if (--_thickness == 0) + return; + } while ((pDest + (_thickness - 1) * DEFAULT_WIDTH) >= pDestEnd); + } + } else { + while ((pDest + (_thickness - 1) * DEFAULT_WIDTH) >= pDestEnd) { + if (--_thickness == 0) + return; + } + } + + for (int xIndex = 0; xIndex < _xSize; ++xIndex, --pDest) { + if ((xIndex % 2) == 0) { + // Write out vertical slice top to bottom + for (int yIndex = 0; yIndex < _thickness; ++yIndex, pDest += DEFAULT_WIDTH) + *pDest = nextByte(pSrc, pLookup); + } else { + // Write out vertical slice top to bottom + for (int yIndex = 0; yIndex < _thickness; ++yIndex) { + pDest -= DEFAULT_WIDTH; + *pDest = nextByte(pSrc, pLookup); + } + } + } + + if ((_xSize % 2) == 1) { + ++pDest; + + if ((pDest + (_thickness - 1) * DEFAULT_WIDTH) < pDestEnd) { + continueFlag = true; + break; + } + } else { + pDest += _thickness * DEFAULT_WIDTH + 1; + continueFlag = true; + break; + } + + ++pDest; + } while (((_thickness - 1) * DEFAULT_WIDTH + pDest) < pDestEnd); + + if (continueFlag) + continue; + + // Move to next line + if (--_thickness == 0) + break; + } +} + +void GfxSurface::vertical(const byte *&pSrc, byte *&pDest, const byte *&pLookup) { + int drawIndex = 0; + + for (;;) { + // Reduce thickness as necessary + while ((drawIndex + _thickness) > _xSize) { + if (--_thickness == 0) + return; + } + + // Loop + for (int yCtr = 0; yCtr < _ySize; ++yCtr) { + if ((yCtr % 2) == 0) { + if (yCtr > 0) + pDest += DEFAULT_WIDTH; + + drawIndex += _thickness; + for (int xCtr = 0; xCtr < _thickness; ++xCtr) + *pDest++ = nextByte(pSrc, pLookup); + } else { + pDest += DEFAULT_WIDTH; + drawIndex -= _thickness; + for (int xCtr = 0; xCtr < _thickness; ++xCtr) + *--pDest = nextByte(pSrc, pLookup); + } + } + if ((_ySize % 2) == 0) { + pDest += _thickness; + drawIndex += _thickness; + } + + while (_xSize < (drawIndex + _thickness)) { + if (--_thickness == 0) + return; + } + + // Loop + for (int yCtr = 0; yCtr < _ySize; ++yCtr) { + if ((yCtr % 2) == 0) { + if (yCtr > 0) + pDest -= DEFAULT_WIDTH; + + drawIndex += _thickness; + + for (int xCtr = 0; xCtr < _thickness; ++xCtr) + *pDest++ = nextByte(pSrc, pLookup); + } else { + pDest -= DEFAULT_WIDTH; + drawIndex -= _thickness; + + for (int xCtr = 0; xCtr < _thickness; ++xCtr) + *--pDest = nextByte(pSrc, pLookup); + } + } + if ((_ySize % 2) == 0) { + pDest += _thickness; + drawIndex += _thickness; + } + } +} + +void GfxSurface::decom11(const byte *&pSrc, byte *&pDest, const byte *&pLookup) { + int yPos = 0, drawIndex = 0; + _yInc = DEFAULT_WIDTH; + _xInc = -1; + --_xSize; + --_ySize; + + int areaNum = 0; + while (areaNum != -1) { + switch (areaNum) { + case 0: + *pDest = nextByte(pSrc, pLookup); + areaNum = 1; + break; + + case 1: + nextDecompPtr(pDest); + + if (!drawIndex) { + negXInc(); + negYInc(); + + if (yPos == _ySize) { + nextDecompPtr(pDest); + ++drawIndex; + } else { + ++yPos; + } + + *++pDest = nextByte(pSrc, pLookup); + areaNum = 2; + } else if (yPos != _ySize) { + ++yPos; + --drawIndex; + areaNum = 0; + } else { + negXInc(); + negYInc(); + nextDecompPtr(pDest); + ++drawIndex; + + *++pDest = nextByte(pSrc, pLookup); + + if (drawIndex == _xSize) { + areaNum = -1; + } else { + areaNum = 2; + } + } + break; + + case 2: + nextDecompPtr(pDest); + + if (!yPos) { + negXInc(); + negYInc(); + + if (drawIndex == _xSize) { + nextDecompPtr(pDest); + ++yPos; + } else { + ++drawIndex; + } + + pDest += DEFAULT_WIDTH; + areaNum = 0; + } else if (drawIndex != _xSize) { + ++drawIndex; + --yPos; + + *pDest = nextByte(pSrc, pLookup); + areaNum = 2; + } else { + pDest += DEFAULT_WIDTH; + ++yPos; + negXInc(); + negYInc(); + nextDecompPtr(pDest); + + *pDest = nextByte(pSrc, pLookup); + + if (yPos == _ySize) + areaNum = -1; + else + areaNum = 1; + } + break; + } + } +} + +void GfxSurface::diag(const byte *&pSrc, byte *&pDest, const byte *&pLookup) { + int diagIndex = 0, drawIndex = 0; + --_xEnd; + + while (!TFP(diagIndex)) { + for (;;) { + negXInc(); + for (int idx = 0; idx <= _thickness; ++idx) { + *pDest = nextByte(pSrc, pLookup); + negXInc(); + nextDecompPtr(pDest); + } + + negYInc(); + pDest += _yInc; + + for (int idx = 0; idx <= _thickness; ++idx) { + *pDest = nextByte(pSrc, pLookup); + negXInc(); + nextDecompPtr(pDest); + } + + negXInc(); + negYInc(); + nextDecompPtr(pDest); + + ++drawIndex; + if (_xEnd < (drawIndex + 1)) { + TF1(pDest, diagIndex); + break; + } + + pDest += _xInc; + ++drawIndex; + if (_xEnd < (drawIndex + 1)) { + TF2(pSrc, pDest, pLookup, diagIndex); + break; + } + } + + if (TFP(diagIndex)) + break; + + for (;;) { + for (int idx = 0; idx <= _thickness; ++idx) { + *pDest = nextByte(pSrc, pLookup); + negXInc(); + nextDecompPtr(pDest); + } + + negYInc(); + pDest += _yInc; + + for (int idx = 0; idx <= _thickness; ++idx) { + *pDest = nextByte(pSrc, pLookup); + negXInc(); + nextDecompPtr(pDest); + } + + negXInc(); + negYInc(); + nextDecompPtr(pDest); + + if (--drawIndex == 0) { + TF1(pDest, diagIndex); + negXInc(); + break; + } else { + pDest += _xInc; + + if (--drawIndex == 0) { + TF2(pSrc, pDest, pLookup, diagIndex); + negXInc(); + break; + } + } + + negXInc(); + } + } +} + +/** + * Decompression Function - Move pDest ptr to next value to uncompress + * @remarks Originally called 'increments' + */ +void GfxSurface::nextDecompPtr(byte *&pDest) { + pDest += _xInc + _yInc; +} + +/** + * Decompression Function - set xInc to its opposite value + * @remarks Originally called 'NIH' + */ +void GfxSurface::negXInc() { + _xInc = -_xInc; +} + +/** + * Decompression Function - set yInc to its opposite value + * @remarks Originally called 'NIV' + */ +void GfxSurface::negYInc() { + _yInc = -_yInc; +} + +bool GfxSurface::TFP(int v) { + int diff = _yEnd - v; + if (!diff) + // Time to finish loop in outer method + return true; + + if (diff < (_thickness + 1)) + _thickness = diff - 1; + + return false; +} + +void GfxSurface::TF1(byte *&pDest, int &v) { + v += _thickness + 1; + pDest += (_thickness + 1) * _yInc; +} + +void GfxSurface::TF2(const byte *&pSrc, byte *&pDest, const byte *&pLookup, int &v) { + v += _thickness + 1; + + for (int idx = 0; idx <= _thickness; ++idx) { + *pDest = nextByte(pSrc, pLookup); + pDest += _yInc; + } +} + +/*-------------------------------------------------------------------------*/ + +GfxSurface::~GfxSurface() { + free(); +} + +/*-------------------------------------------------------------------------* + * Screen surface + *-------------------------------------------------------------------------*/ + +/** + * Called to populate the font data from the passed file + */ +void ScreenSurface::readFontData(Common::File &f, int dataSize) { + assert(dataSize == (FONT_NUM_CHARS * FONT_HEIGHT)); + f.read(_fontData, FONT_NUM_CHARS * FONT_HEIGHT); +} + +/** + * Returns a graphics surface representing a subset of the screen. The affected area + * is also marked as dirty + */ +Graphics::Surface ScreenSurface::lockArea(const Common::Rect &bounds) { + _dirtyRects.push_back(bounds); + + Graphics::Surface s; + s.init(bounds.width(), bounds.height(), pitch, getBasePtr(bounds.left, bounds.top), format); + return s; +} + +/** + * Updates the affected areas of the surface to the underlying physical screen + */ +void ScreenSurface::updateScreen() { + // Iterate through copying dirty areas to the screen + for (Common::List<Common::Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) { + Common::Rect r = *i; + g_system->copyRectToScreen((const byte *)getBasePtr(r.left, r.top), pitch, + r.left, r.top, r.width(), r.height()); + } + _dirtyRects.clear(); + + // Update the screen + g_system->updateScreen(); +} + +/** + * Draws a decoded picture on the screen + * @remarks - Because the ScummVM surface is using a double height 640x400 surface to + * simulate the original 640x400 surface, all Y values have to be doubled. + * - Image resources are stored at 320x200, so when drawn onto the screen a single pixel + * from the source image is drawn using the two pixels at the given index in the palette map + * - Because the original game supported 320 width resolutions, the X coordinate + * also needs to be doubled for EGA mode + */ +void ScreenSurface::drawPicture(GfxSurface &surface, int x, int y) { + // Adjust the draw position by the draw offset + x += surface._offset.x; + y += surface._offset.y; + + // Lock the affected area of the surface to write to + Graphics::Surface destSurface = lockArea(Common::Rect(x * 2, y * 2, + (x + surface.w) * 2, (y + surface.h) * 2)); + + // Get a lookup for the palette mapping + const byte *paletteMap = &_vm->_curPict[2]; + + // Loop through writing + for (int yp = 0; yp < surface.h; ++yp) { + if (((y + yp) < 0) || ((y + yp) >= 200)) + continue; + + const byte *pSrc = (const byte *)surface.getBasePtr(0, yp); + byte *pDest = (byte *)destSurface.getBasePtr(0, yp * 2); + + for (int xp = 0; xp < surface.w; ++xp, ++pSrc) { + if (*pSrc == surface._transparency) { + // Transparent point, so skip pixels + pDest += 2; + } else { + // Draw the pixel using the specified index in the palette map + *pDest = paletteMap[*pSrc * 2]; + *(pDest + SCREEN_WIDTH) = paletteMap[*pSrc * 2]; + ++pDest; + + // Use the secondary mapping value to draw the secondary column pixel + *pDest = paletteMap[*pSrc * 2 + 1]; + *(pDest + SCREEN_WIDTH) = paletteMap[*pSrc * 2 + 1]; + ++pDest; + } + } + } +} + +/** + * Copys a given surface to the given position + */ +void ScreenSurface::copyFrom(Graphics::Surface &src, int x, int y) { + lockArea(Common::Rect(x, y, x + src.w, y + src.h)); + + // Loop through writing + for (int yp = 0; yp < src.h; ++yp) { + if (((y + yp) < 0) || ((y + yp) >= SCREEN_HEIGHT)) + continue; + + const byte *pSrc = (const byte *)src.getBasePtr(0, yp); + byte *pDest = (byte *)getBasePtr(0, yp); + Common::copy(pSrc, pSrc + src.w, pDest); + } +} + +/** + * Draws a character at the specified co-ordinates + * @remarks Because the ScummVM surface is using a double height 640x400 surface to + * simulate the original 640x400 surface, all Y values have to be doubled + */ +void ScreenSurface::writeCharacter(const Common::Point &pt, unsigned char ch, int palIndex) { + Graphics::Surface destSurface = lockArea(Common::Rect(pt.x, pt.y * 2, + pt.x + FONT_WIDTH, (pt.y + FONT_HEIGHT) * 2)); + + // Get the start of the character to use + assert((ch >= ' ') && (ch <= (unsigned char)(32 + FONT_NUM_CHARS))); + const byte *charData = &_fontData[((int)ch - 32) * FONT_HEIGHT]; + + // Loop through decoding each character's data + for (int yp = 0; yp < FONT_HEIGHT; ++yp) { + byte *lineP = (byte *)destSurface.getBasePtr(0, yp * 2); + byte byteVal = *charData++; + + for (int xp = 0; xp < FONT_WIDTH; ++xp, ++lineP, byteVal <<= 1) { + if (byteVal & 0x80) { + *lineP = palIndex; + *(lineP + SCREEN_WIDTH) = palIndex; + } + } + } +} + +/** + * Draws a box at the specified position and size + * @remarks Because the ScummVM surface is using a double height 640x400 surface to + * simulate the original 640x400 surface, all Y values have to be doubled + */ +void ScreenSurface::drawBox(int x, int y, int dx, int dy, int col) { + Graphics::Surface destSurface = lockArea(Common::Rect(x, y * 2, x + dx, (y + dy) * 2)); + + destSurface.hLine(0, 0, dx, col); + destSurface.hLine(0, 1, dx, col); + destSurface.hLine(0, destSurface.h - 1, dx, col); + destSurface.hLine(0, destSurface.h - 2, dx, col); + destSurface.vLine(0, 2, destSurface.h - 3, col); + destSurface.vLine(1, 2, destSurface.h - 3, col); + destSurface.vLine(dx - 1, 2, destSurface.h - 3, col); + destSurface.vLine(dx - 2, 2, destSurface.h - 3, col); +} + +/** + * Fills an area with the specified color + * @remarks Because the ScummVM surface is using a double height 640x400 surface to + * simulate the original 640x400 surface, all Y values have to be doubled + */ +void ScreenSurface::fillRect(int color, const Common::Rect &bounds) { + Graphics::Surface destSurface = lockArea(Common::Rect(bounds.left, bounds.top * 2, + bounds.right, bounds.bottom * 2)); + + // Fill the area + destSurface.fillRect(Common::Rect(0, 0, destSurface.w, destSurface.h), color); +} + +/** + * Clears the screen + */ +void ScreenSurface::clearScreen() { + Graphics::Surface destSurface = lockArea(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + destSurface.fillRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0); +} + +/** + * Sets a single pixel at the specified co-ordinates + * @remarks Because the ScummVM surface is using a double height 640x400 surface to + * simulate the original 640x400 surface, all Y values have to be doubled + */ +void ScreenSurface::setPixel(const Common::Point &pt, int palIndex) { + assert((pt.x >= 0) && (pt.y >= 0) && (pt.x <= SCREEN_WIDTH) && (pt.y <= SCREEN_ORIG_HEIGHT)); + Graphics::Surface destSurface = lockArea(Common::Rect(pt.x, pt.y * 2, pt.x + 1, (pt.y + 1) * 2)); + + byte *destP = (byte *)destSurface.getPixels(); + *destP = palIndex; + *(destP + SCREEN_WIDTH) = palIndex; +} + +/** + * Write out a string + * @remarks Originally called 'writeg' + */ +void ScreenSurface::drawString(const Common::String &l, int command) { + if (l == "") + return; + + _vm->_mouse.hideMouse(); + Common::Point pt = _textPos; + + int charWidth = 6; + + int x = pt.x + charWidth * l.size(); + int color = 0; + + switch (command) { + case 0: + case 2: + color = 15; + _vm->_screenSurface.fillRect(0, Common::Rect(pt.x, pt.y, x, pt.y + 7)); + break; + case 1: + case 3: + _vm->_screenSurface.fillRect(15, Common::Rect(pt.x, pt.y, x, pt.y + 7)); + break; + case 5: + color = 15; + break; + default: + // Default: Color set to zero (already done) + break; + } + + pt.x += 1; + pt.y += 1; + for (x = 1; (x <= (int)l.size()) && (l[x - 1] != 0); ++x) { + _vm->_screenSurface.writeCharacter(Common::Point(pt.x, pt.y), l[x - 1], color); + pt.x += charWidth; + } + _vm->_mouse.showMouse(); +} + +/** + * Gets the width in pixels of the specified string + */ +int ScreenSurface::getStringWidth(const Common::String &s) { + int charWidth = 6; + + return s.size() * charWidth; +} + +void ScreenSurface::drawLine(int x, int y, int xx, int yy, int coul) { + int step, i; + float a, b; + float xr, yr, xro, yro; + + xr = x; + yr = y; + xro = xx; + yro = yy; + + if (abs(y - yy) > abs(x - xx)) { + a = (float)((x - xx)) / (y - yy); + b = (yr * xro - yro * xr) / (y - yy); + i = y; + if (y > yy) + step = -1; + else + step = 1; + do { + _vm->_screenSurface.setPixel(Common::Point(abs((int)(a * i + b)), i), coul); + i += step; + } while (i != yy); + } else { + a = (float)((y - yy)) / (x - xx); + b = ((yro * xr) - (yr * xro)) / (x - xx); + i = x; + if (x > xx) + step = -1; + else + step = 1; + do { + _vm->_screenSurface.setPixel(Common::Point(i, abs((int)(a * i + b))), coul); + i = i + step; + } while (i != xx); + } +} + +/** + * Draw plain rectangle + * @remarks Originally called 'paint_rect' + */ +void ScreenSurface::drawRectangle(int x, int y, int dx, int dy) { + _vm->_screenSurface.fillRect(11, Common::Rect(x, y, x + dx, y + dy)); +} + +void ScreenSurface::setParent(MortevielleEngine *vm) { + _vm = vm; +} + + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/graphics.h b/engines/mortevielle/graphics.h new file mode 100644 index 0000000000..e31f5da29a --- /dev/null +++ b/engines/mortevielle/graphics.h @@ -0,0 +1,117 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_GRAPHICS_H +#define MORTEVIELLE_GRAPHICS_H + +#include "common/file.h" +#include "common/list.h" +#include "common/rect.h" +#include "graphics/surface.h" + +namespace Mortevielle { +class MortevielleEngine; + +class PaletteManager { +private: + void setPalette(const int *palette, uint idx, uint size); + +public: + void setDefaultPalette(); +}; + +#define FONT_WIDTH 8 +#define FONT_HEIGHT 6 +#define FONT_NUM_CHARS 121 + +class GfxSurface : public Graphics::Surface { +private: + int _xp, _yp; + int _xSize, _ySize; + int _lookupIndex, _lookupValue; + bool _nibbleFlag; + int _thickness; + int _yInc, _yEnd, _xInc, _xEnd; + + byte nextNibble(const byte *&pSrc); + byte nextByte(const byte *&pSrc, const byte *&pLookup); + + void majTtxTty(); + int desanalyse(const byte *&pSrc); + void horizontal(const byte *&pSrc, byte *&pDest, const byte *&pLookup); + void vertical(const byte *&pSrc, byte *&pDest, const byte *&pLookup); + void decom11(const byte *&pSrc, byte *&pDest, const byte *&pLookup); + void diag(const byte *&pSrc, byte *&pDest, const byte *&pLookup); + void nextDecompPtr(byte *&pDest); + void negXInc(); + void negYInc(); + bool TFP(int v); + void TF1(byte *&pDest, int &v); + void TF2(const byte *&pSrc, byte *&pDest, const byte *&pLookup, int &v); +public: + // Specifies offset when drawing the image + Common::Point _offset; + // Transparency palette index + int _transparency; + + ~GfxSurface(); + + void decode(const byte *pSrc); +}; + +class ScreenSurface: public Graphics::Surface { +private: + MortevielleEngine *_vm; + + Common::List<Common::Rect> _dirtyRects; + byte _fontData[FONT_NUM_CHARS * FONT_HEIGHT]; + +public: + Common::Point _textPos; // Original called xwhere/ywhere + void readFontData(Common::File &f, int dataSize); + Graphics::Surface lockArea(const Common::Rect &bounds); + void updateScreen(); + void drawPicture(GfxSurface &surface, int x, int y); + void copyFrom(Graphics::Surface &src, int x, int y); + void writeCharacter(const Common::Point &pt, unsigned char ch, int palIndex); + void drawBox(int x, int y, int dx, int dy, int col); + void fillRect(int color, const Common::Rect &bounds); + void clearScreen(); + void putxy(int x, int y) { _textPos = Common::Point(x, y); } + void drawString(const Common::String &l, int command); + int getStringWidth(const Common::String &s); + void drawLine(int x, int y, int xx, int yy, int coul); + void drawRectangle(int x, int y, int dx, int dy); + void setParent(MortevielleEngine *vm); + + // TODO: Refactor code to remove this method, for increased performance + void setPixel(const Common::Point &pt, int palIndex); +}; + +} // End of namespace Mortevielle + +#endif diff --git a/engines/mortevielle/menu.cpp b/engines/mortevielle/menu.cpp new file mode 100644 index 0000000000..1077f66fc2 --- /dev/null +++ b/engines/mortevielle/menu.cpp @@ -0,0 +1,756 @@ +/* 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 re_distribute 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" + +#include "mortevielle/menu.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/textconsole.h" + +namespace Mortevielle { + +const byte menuConstants[8][4] = { + { 7, 37, 23, 8}, + {19, 33, 23, 7}, + {31, 89, 10, 21}, + {43, 25, 11, 5}, + {55, 37, 5, 8}, + {64, 13, 11, 2}, + {62, 42, 13, 9}, + {62, 46, 13, 10} +}; + +Menu::Menu() { + _opcodeAttach = _opcodeWait = _opcodeForce = _opcodeSleep = OPCODE_NONE; + _opcodeListen = _opcodeEnter = _opcodeClose = _opcodeSearch = OPCODE_NONE; + _opcodeKnock = _opcodeScratch = _opcodeRead = _opcodeEat = OPCODE_NONE; + _opcodePlace = _opcodeOpen = _opcodeTake = _opcodeLook = OPCODE_NONE; + _opcodeSmell = _opcodeSound = _opcodeLeave = _opcodeLift = OPCODE_NONE; + _opcodeTurn = _opcodeSHide = _opcodeSSearch = _opcodeSRead = OPCODE_NONE; + _opcodeSPut = _opcodeSLook = OPCODE_NONE; +} + +void Menu::readVerbNums(Common::File &f, int dataSize) { + // Figure out what language Id is needed + byte desiredLanguageId; + switch(_vm->getLanguage()) { + case Common::EN_ANY: + desiredLanguageId = MORTDAT_LANG_ENGLISH; + break; + case Common::FR_FRA: + desiredLanguageId = MORTDAT_LANG_FRENCH; + break; + case Common::DE_DEU: + desiredLanguageId = MORTDAT_LANG_GERMAN; + break; + default: + warning("Language not supported, switching to English"); + desiredLanguageId = MORTDAT_LANG_ENGLISH; + break; + } + // Read in the language + byte languageId = f.readByte(); + --dataSize; + + // If the language isn't correct, then skip the entire block + if (languageId != desiredLanguageId) { + f.skip(dataSize); + return; + } + + assert(dataSize == 52); + _opcodeAttach = f.readUint16LE(); + _opcodeWait = f.readUint16LE(); + _opcodeForce = f.readUint16LE(); + _opcodeSleep = f.readUint16LE(); + _opcodeListen = f.readUint16LE(); + _opcodeEnter = f.readUint16LE(); + _opcodeClose = f.readUint16LE(); + _opcodeSearch = f.readUint16LE(); + _opcodeKnock = f.readUint16LE(); + _opcodeScratch = f.readUint16LE(); + _opcodeRead = f.readUint16LE(); + _opcodeEat = f.readUint16LE(); + _opcodePlace = f.readUint16LE(); + _opcodeOpen = f.readUint16LE(); + _opcodeTake = f.readUint16LE(); + _opcodeLook = f.readUint16LE(); + _opcodeSmell = f.readUint16LE(); + _opcodeSound = f.readUint16LE(); + _opcodeLeave = f.readUint16LE(); + _opcodeLift = f.readUint16LE(); + _opcodeTurn = f.readUint16LE(); + _opcodeSHide = f.readUint16LE(); + _opcodeSSearch = f.readUint16LE(); + _opcodeSRead = f.readUint16LE(); + _opcodeSPut = f.readUint16LE(); + _opcodeSLook = f.readUint16LE(); + + _actionMenu[0]._menuId = OPCODE_NONE >> 8; + _actionMenu[0]._actionId = OPCODE_NONE & 0xFF; + + _actionMenu[1]._menuId = _opcodeSHide >> 8; + _actionMenu[1]._actionId = _opcodeSHide & 0xFF; + + _actionMenu[2]._menuId = _opcodeAttach >> 8; + _actionMenu[2]._actionId = _opcodeAttach & 0xFF; + + _actionMenu[3]._menuId = _opcodeForce >> 8; + _actionMenu[3]._actionId = _opcodeForce & 0xFF; + + _actionMenu[4]._menuId = _opcodeSleep >> 8; + _actionMenu[4]._actionId = _opcodeSleep & 0xFF; + + _actionMenu[5]._menuId = _opcodeEnter >> 8; + _actionMenu[5]._actionId = _opcodeEnter & 0xFF; + + _actionMenu[6]._menuId = _opcodeClose >> 8; + _actionMenu[6]._actionId = _opcodeClose & 0xFF; + + _actionMenu[7]._menuId = _opcodeKnock >> 8; + _actionMenu[7]._actionId = _opcodeKnock & 0xFF; + + _actionMenu[8]._menuId = _opcodeEat >> 8; + _actionMenu[8]._actionId = _opcodeEat & 0xFF; + + _actionMenu[9]._menuId = _opcodePlace >> 8; + _actionMenu[9]._actionId = _opcodePlace & 0xFF; + + _actionMenu[10]._menuId = _opcodeOpen >> 8; + _actionMenu[10]._actionId = _opcodeOpen & 0xFF; + + _actionMenu[11]._menuId = _opcodeLeave >> 8; + _actionMenu[11]._actionId = _opcodeLeave & 0xFF; +} + +/** + * Setup a menu's contents + * @remarks Originally called 'menut' + */ +void Menu::setText(MenuItem item, Common::String name) { + Common::String s = name; + + switch (item._menuId) { + case MENU_INVENTORY: + if (item._actionId != 7) { + while (s.size() < 22) + s += ' '; + + _inventoryStringArray[item._actionId] = s; + _inventoryStringArray[item._actionId].insertChar(' ', 0); + } + break; + case MENU_MOVE: + while (s.size() < 22) + s += ' '; + + _moveStringArray[item._actionId] = s; + break; + case MENU_ACTION: { + // If the first character isn't '*' or ' ' then it's missing a heading space + char c = s[0]; + if (c != '*' && c != ' ') + s = ' ' + s; + + while (s.size() < 10) + s += ' '; + + _actionStringArray[item._actionId] = s; + } + break; + case MENU_SELF: { + // If the first character isn't '*' or ' ' then it's missing a heading space + char c = s[0]; + if (c != '*' && c != ' ') + s = ' ' + s; + + while (s.size() < 10) + s += ' '; + + _selfStringArray[item._actionId] = s; + } + break; + case MENU_DISCUSS: + _discussStringArray[item._actionId] = s; + break; + default: + break; + } +} + +/** + * Init destination menu + * @remarks Originally called 'tmlieu' + */ +void Menu::setDestinationText(int roomId) { + Common::String nomp; + + if (roomId == ROOM26) + roomId = LANDING; + + int destinationId = 0; + for (; (destinationId < 7) && (_vm->_destinationArray[destinationId][roomId]); ++destinationId) { + nomp = _vm->getString(_vm->_destinationArray[destinationId][roomId] + kMenuPlaceStringIndex); + while (nomp.size() < 20) + nomp += ' '; + setText(_moveMenu[destinationId + 1], nomp); + } + nomp = "* "; + for (int i = 7; i >= destinationId + 1; --i) + setText(_moveMenu[i], nomp); +} + +/** + * _disable a menu item + * @param menuId Menu number + * @param actionId Item index + */ +void Menu::disableMenuItem(MenuItem item) { + switch (item._menuId) { + case MENU_INVENTORY: + if (item._actionId > 6) { + _inventoryStringArray[item._actionId].setChar('<', 0); + _inventoryStringArray[item._actionId].setChar('>', 21); + } else + _inventoryStringArray[item._actionId].setChar('*', 0); + break; + case MENU_MOVE: + _moveStringArray[item._actionId].setChar('*', 0); + break; + case MENU_ACTION: + _actionStringArray[item._actionId].setChar('*', 0); + break; + case MENU_SELF: + _selfStringArray[item._actionId].setChar('*', 0); + break; + case MENU_DISCUSS: + _discussStringArray[item._actionId].setChar('*', 0); + break; + default: + break; + } +} + +/** + * Enable a menu item + * @param menuId Menu number + * @param actionId Item index + * @remarks Originally called menu_enable + */ +void Menu::enableMenuItem(MenuItem item) { + switch (item._menuId) { + case MENU_INVENTORY: + _inventoryStringArray[item._actionId].setChar(' ', 0); + _inventoryStringArray[item._actionId].setChar(' ', 21); + break; + case MENU_MOVE: + _moveStringArray[item._actionId].setChar(' ', 0); + break; + case MENU_ACTION: + _actionStringArray[item._actionId].setChar(' ', 0); + break; + case MENU_SELF: + _selfStringArray[item._actionId].setChar(' ', 0); + break; + case MENU_DISCUSS: + _discussStringArray[item._actionId].setChar(' ', 0); + break; + default: + break; + } +} + +void Menu::displayMenu() { + _vm->_mouse.hideMouse(); + _vm->_screenSurface.fillRect(7, Common::Rect(0, 0, 639, 10)); + + int col = 28 * kResolutionScaler; + for (int charNum = 0; charNum < 6; charNum++) { + // One character after the other + int idx = 0; + for (int y = 1; y < 9; ++y) { + // One column after the other + int x = col; + for (int k = 0; k < 3; ++k) { + // One line after the other + uint msk = 0x80; + for (int pt = 0; pt <= 7; ++pt) { + if ((_charArr[charNum][idx] & msk) != 0) { + _vm->_screenSurface.setPixel(Common::Point(x + 1, y + 1), 0); + _vm->_screenSurface.setPixel(Common::Point(x, y + 1), 0); + _vm->_screenSurface.setPixel(Common::Point(x, y), 9); + } + msk >>= 1; + ++x; + } + ++idx; + } + } + col += 48 * kResolutionScaler; + } + _vm->_mouse.showMouse(); +} + +/** + * Show the menu + */ +void Menu::drawMenu() { + displayMenu(); + _menuActive = true; + _msg4 = OPCODE_NONE; + _msg3 = OPCODE_NONE; + _menuSelected = false; + _vm->setMouseClick(false); + _multiTitle = false; +} + +/** + * Menu function - Invert a menu entry + * @remarks Originally called 'invers' + */ +void Menu::invert(int indx) { + if (_msg4 == OPCODE_NONE) + return; + + int menuIndex = _msg4 & 0xFF; + + _vm->_screenSurface.putxy(menuConstants[_msg3 - 1][0] << 3, (menuIndex + 1) << 3); + + Common::String str; + switch (_msg3) { + case MENU_INVENTORY: + str = _inventoryStringArray[menuIndex]; + break; + case MENU_MOVE: + str = _moveStringArray[menuIndex]; + break; + case MENU_ACTION: + str = _actionStringArray[menuIndex]; + break; + case MENU_SELF: + str = _selfStringArray[menuIndex]; + break; + case MENU_DISCUSS: + str = _discussStringArray[menuIndex]; + break; + case MENU_FILE: + str = _vm->getEngineString(S_SAVE_LOAD + menuIndex); + break; + case MENU_SAVE: + str = _vm->getEngineString(S_SAVE_LOAD + 1); + str += ' '; + str += (char)(48 + menuIndex); + break; + case MENU_LOAD: + if (menuIndex == 1) { + str = _vm->getEngineString(S_RESTART); + } else { + str = _vm->getEngineString(S_SAVE_LOAD + 2); + str += ' '; + str += (char)(47 + menuIndex); + } + break; + default: + break; + } + if ((str[0] != '*') && (str[0] != '<')) + _vm->_screenSurface.drawString(str, indx); + else + _msg4 = OPCODE_NONE; +} + +void Menu::util(Common::Point pos) { + + int ymx = (menuConstants[_msg3 - 1][3] << 3) + 16; + int dxcar = menuConstants[_msg3 - 1][2]; + int xmn = (menuConstants[_msg3 - 1][0] << 2) * kResolutionScaler; + + int charWidth = 6; + int xmx = dxcar * charWidth + xmn + 2; + if ((pos.x > xmn) && (pos.x < xmx) && (pos.y < ymx) && (pos.y > 15)) { + int ix = (((uint)pos.y >> 3) - 1) + (_msg3 << 8); + if (ix != _msg4) { + invert(1); + _msg4 = ix; + invert(0); + } + } else if (_msg4 != OPCODE_NONE) { + invert(1); + _msg4 = OPCODE_NONE; + } +} + +/** + * Draw a menu + */ +void Menu::menuDown(int ii) { + // Make a copy of the current screen surface for later restore + _vm->_backgroundSurface.copyFrom(_vm->_screenSurface); + + // Draw the menu + int minX = menuConstants[ii - 1][0] << 3; + int lineNum = menuConstants[ii - 1][3]; + _vm->_mouse.hideMouse(); + int deltaX = 6; + int maxX = minX + (menuConstants[ii - 1][2] * deltaX) + 6; + if ((ii == 4) && (_vm->getLanguage() == Common::EN_ANY)) + // Extra width needed for Self menu in English version + maxX = 435; + + _vm->_screenSurface.fillRect(15, Common::Rect(minX, 12, maxX, 10 + (menuConstants[ii - 1][1] << 1))); + _vm->_screenSurface.fillRect(0, Common::Rect(maxX, 12, maxX + 4, 10 + (menuConstants[ii - 1][1] << 1))); + _vm->_screenSurface.fillRect(0, Common::Rect(minX, 8 + (menuConstants[ii - 1][1] << 1), maxX + 4, 12 + (menuConstants[ii - 1][1] << 1))); + _vm->_screenSurface.putxy(minX, 16); + for (int i = 1; i <= lineNum; i++) { + switch (ii) { + case 1: + if (_inventoryStringArray[i][0] != '*') + _vm->_screenSurface.drawString(_inventoryStringArray[i], 4); + break; + case 2: + if (_moveStringArray[i][0] != '*') + _vm->_screenSurface.drawString(_moveStringArray[i], 4); + break; + case 3: + if (_actionStringArray[i][0] != '*') + _vm->_screenSurface.drawString(_actionStringArray[i], 4); + break; + case 4: + if (_selfStringArray[i][0] != '*') + _vm->_screenSurface.drawString(_selfStringArray[i], 4); + break; + case 5: + if (_discussStringArray[i][0] != '*') + _vm->_screenSurface.drawString(_discussStringArray[i], 4); + break; + case 6: + _vm->_screenSurface.drawString(_vm->getEngineString(S_SAVE_LOAD + i), 4); + break; + case 7: { + Common::String s = _vm->getEngineString(S_SAVE_LOAD + 1); + s += ' '; + s += (char)(48 + i); + _vm->_screenSurface.drawString(s, 4); + } + break; + case 8: + if (i == 1) + _vm->_screenSurface.drawString(_vm->getEngineString(S_RESTART), 4); + else { + Common::String s = _vm->getEngineString(S_SAVE_LOAD + 2); + s += ' '; + s += (char)(47 + i); + _vm->_screenSurface.drawString(s, 4); + } + break; + default: + break; + } + _vm->_screenSurface.putxy(minX, _vm->_screenSurface._textPos.y + 8); + } + _multiTitle = true; + _vm->_mouse.showMouse(); +} + +/** + * Menu is being removed, so restore the previous background area. + */ +void Menu::menuUp(int msgId) { + if (_multiTitle) { + /* Restore the background area */ + assert(_vm->_screenSurface.pitch == _vm->_backgroundSurface.pitch); + + // Get a pointer to the source and destination of the area to restore + const byte *pSrc = (const byte *)_vm->_backgroundSurface.getBasePtr(0, 10); + Graphics::Surface destArea = _vm->_screenSurface.lockArea(Common::Rect(0, 10, SCREEN_WIDTH, SCREEN_HEIGHT)); + byte *pDest = (byte *)destArea.getPixels(); + + // Copy the data + Common::copy(pSrc, pSrc + (400 - 10) * SCREEN_WIDTH, pDest); + + _multiTitle = false; + } +} + +/** + * Erase the menu + */ +void Menu::eraseMenu() { + _menuActive = false; + _vm->setMouseClick(false); + menuUp(_msg3); +} + +/** + * Handle updates to the menu + * @remarks Originally called 'mdn' + */ +void Menu::updateMenu() { + if (!_menuActive) + return; + + Common::Point curPos = _vm->_mouse._pos; + if (!_vm->getMouseClick()) { + if (curPos == _vm->_prevPos) + return; + else + _vm->_prevPos = curPos; + + bool tes = (curPos.y < 11) + && ((curPos.x >= (28 * kResolutionScaler) && curPos.x <= (28 * kResolutionScaler + 24)) + || (curPos.x >= (76 * kResolutionScaler) && curPos.x <= (76 * kResolutionScaler + 24)) + || ((curPos.x > 124 * kResolutionScaler) && (curPos.x < 124 * kResolutionScaler + 24)) + || ((curPos.x > 172 * kResolutionScaler) && (curPos.x < 172 * kResolutionScaler + 24)) + || ((curPos.x > 220 * kResolutionScaler) && (curPos.x < 220 * kResolutionScaler + 24)) + || ((curPos.x > 268 * kResolutionScaler) && (curPos.x < 268 * kResolutionScaler + 24))); + if (tes) { + int ix; + + if (curPos.x < 76 * kResolutionScaler) + ix = MENU_INVENTORY; + else if (curPos.x < 124 * kResolutionScaler) + ix = MENU_MOVE; + else if (curPos.x < 172 * kResolutionScaler) + ix = MENU_ACTION; + else if (curPos.x < 220 * kResolutionScaler) + ix = MENU_SELF; + else if (curPos.x < 268 * kResolutionScaler) + ix = MENU_DISCUSS; + else + ix = MENU_FILE; + + if ((ix != _msg3) || (!_multiTitle)) + if (!((ix == MENU_FILE) && ((_msg3 == MENU_SAVE) || (_msg3 == MENU_LOAD)))) { + menuUp(_msg3); + menuDown(ix); + _msg3 = ix; + _msg4 = OPCODE_NONE; + } + } else { // Not in the MenuTitle line + if ((curPos.y > 11) && (_multiTitle)) + util(curPos); + } + } else { // There was a click + if ((_msg3 == MENU_FILE) && (_msg4 != OPCODE_NONE)) { + // Another menu to be _displayed + _vm->setMouseClick(false); + menuUp(_msg3); + if ((_msg4 & 0xFF) == 1) + _msg3 = MENU_SAVE; + else + _msg3 = MENU_LOAD; + menuDown(_msg3); + + _vm->setMouseClick(false); + } else { + // A menu was clicked on + _menuSelected = (_multiTitle) && (_msg4 != OPCODE_NONE); + menuUp(_msg3); + _vm->_currAction = _msg4; + _vm->_currMenu = _msg3; + _msg3 = OPCODE_NONE; + _msg4 = OPCODE_NONE; + + _vm->setMouseClick(false); + } + } +} + +void Menu::setParent(MortevielleEngine *vm) { + _vm = vm; +} + +void Menu::initMenu() { + Common::File f; + + bool enMenuLoaded = false; + if (_vm->getLanguage() == Common::EN_ANY) { + // Open the mort.dat file + if (!f.open(MORT_DAT)) + warning("File %s not found. Using default menu from game data", MORT_DAT); + else { + // Validate the data file header + char fileId[4]; + f.read(fileId, 4); + // Do not display warnings here. They would already have been displayed in MortevielleEngine::loadMortDat(). + if (strncmp(fileId, "MORT", 4) == 0 && f.readByte() >= MORT_DAT_REQUIRED_VERSION) { + f.readByte(); // Minor version + // Loop to load resources from the data file + while (f.pos() < f.size()) { + // Get the Id and size of the next resource + char dataType[4]; + int dataSize; + f.read(dataType, 4); + dataSize = f.readUint16LE(); + if (!strncmp(dataType, "MENU", 4)) { + // MENU section + if (dataSize <= 7 * 24) { + f.read(_charArr, dataSize); + enMenuLoaded = true; + } else + warning("Wrong size %d for menu data. Expected %d or less", dataSize, 7*24); + break; + } else { + // Other sections + f.skip(dataSize); + } + } + } + // Close the file + f.close(); + if (!enMenuLoaded) + warning("Failed to load English menu. Will use default menu from game data instead"); + } + } + + if (!enMenuLoaded) { + if (_vm->getOriginalLanguage() == Common::FR_FRA) { + if (!f.open("menufr.mor")) + error("Missing file - menufr.mor"); + } else { // Common::DE_DEU + if (!f.open("menual.mor")) + error("Missing file - menual.mor"); + } + f.read(_charArr, 7 * 24); + f.close(); + } + + // Skipped: dialog asking to swap floppy + + for (int i = 1; i <= 8; ++i) + _inventoryStringArray[i] = "* "; + _inventoryStringArray[7] = "< -*-*-*-*-*-*-*-*-*- "; + for (int i = 1; i <= 7; ++i) + _moveStringArray[i] = "* "; + for (int i = 1; i < 22; i++) { + _actionStringArray[i] = _vm->getString(i + kMenuActionStringIndex); + + while (_actionStringArray[i].size() < 10) + _actionStringArray[i] += ' '; + + if (i < 9) { + if (i < 6) { + _selfStringArray[i] = _vm->getString(i + kMenuSelfStringIndex); + while (_selfStringArray[i].size() < 10) + _selfStringArray[i] += ' '; + } + _discussStringArray[i] = _vm->getString(i + kMenuSayStringIndex) + ' '; + } + } + for (int i = 1; i <= 8; ++i) { + _discussMenu[i]._menuId = MENU_DISCUSS; + _discussMenu[i]._actionId = i; + if (i < 8) { + _moveMenu[i]._menuId = MENU_MOVE; + _moveMenu[i]._actionId = i; + } + _inventoryMenu[i]._menuId = MENU_INVENTORY; + _inventoryMenu[i]._actionId = i; + if (i > 6) + disableMenuItem(_inventoryMenu[i]); + } + _msg3 = OPCODE_NONE; + _msg4 = OPCODE_NONE; + _vm->_currMenu = OPCODE_NONE; + _vm->_currAction = OPCODE_NONE; + _vm->setMouseClick(false); +} + +/** + * Engine function - Switch action menu to "Search" mode + * @remarks Originally called 'mfoudi' + */ +void Menu::setSearchMenu() { + for (int i = 1; i <= 7; ++i) + disableMenuItem(_moveMenu[i]); + + for (int i = 1; i <= 11; ++i) + disableMenuItem(_actionMenu[i]); + + MenuItem miSound; + miSound._menuId = _opcodeSound >> 8; + miSound._actionId = _opcodeSound & 0xFF; + + MenuItem miLift; + miLift._menuId = _opcodeLift >> 8; + miLift._actionId = _opcodeLift & 0xFF; + + setText(miSound, _vm->getEngineString(S_SUITE)); + setText(miLift, _vm->getEngineString(S_STOP)); +} + +/** + * Engine function - Switch action menu from "Search" mode back to normal mode + * @remarks Originally called 'mfouen' + */ +void Menu::unsetSearchMenu() { + setDestinationText(_vm->_coreVar._currPlace); + for (int i = 1; i <= 11; ++i) + enableMenuItem(_actionMenu[i]); + + MenuItem miSound; + miSound._menuId = _opcodeSound >> 8; + miSound._actionId = _opcodeSound & 0xFF; + + MenuItem miLift; + miLift._menuId = _opcodeLift >> 8; + miLift._actionId = _opcodeLift & 0xFF; + + setText(miSound, _vm->getEngineString(S_PROBE)); + setText(miLift, _vm->getEngineString(S_RAISE)); +} + +/** + * Set Inventory menu texts + * @remarks Originally called 'modinv' + */ +void Menu::setInventoryText() { + Common::String nomp; + + int cy = 0; + for (int i = 1; i <= 6; ++i) { + if (_vm->_coreVar._inventory[i] != 0) { + ++cy; + int r = _vm->_coreVar._inventory[i] + 400; + nomp = _vm->getString(r - 501 + kInventoryStringIndex); + setText(_inventoryMenu[cy], nomp); + enableMenuItem(_inventoryMenu[i]); + } + } + + if (cy < 6) { + for (int i = cy + 1; i <= 6; ++i) { + setText(_inventoryMenu[i], " "); + disableMenuItem(_inventoryMenu[i]); + } + } +} +} // End of namespace Mortevielle diff --git a/engines/mortevielle/menu.h b/engines/mortevielle/menu.h new file mode 100644 index 0000000000..d1271bca2e --- /dev/null +++ b/engines/mortevielle/menu.h @@ -0,0 +1,125 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_MENU_H +#define MORTEVIELLE_MENU_H + +#include "common/rect.h" +#include "common/str.h" + +namespace Mortevielle { +class MortevielleEngine; + +enum { + MENU_NONE = 0, MENU_INVENTORY = 1, MENU_MOVE = 2, MENU_ACTION = 3, + MENU_SELF = 4, MENU_DISCUSS = 5, MENU_FILE = 6, MENU_SAVE = 7, + MENU_LOAD = 8 +}; + +const int OPCODE_NONE = 0; + +struct MenuItem { + int _menuId; + int _actionId; +}; + +class Menu { +private: + MortevielleEngine *_vm; + + byte _charArr[7][24]; + int _msg3; + int _msg4; + + void util(Common::Point pos); + void invert(int indx); + void menuDown(int ii); + +public: + Menu(); + + bool _menuActive; + bool _menuSelected; + bool _multiTitle; + bool _menuDisplayed; + Common::String _inventoryStringArray[9]; + Common::String _moveStringArray[8]; + Common::String _actionStringArray[22]; + Common::String _selfStringArray[7]; + Common::String _discussStringArray[9]; + MenuItem _discussMenu[9]; + MenuItem _inventoryMenu[9]; + MenuItem _moveMenu[8]; + + int _opcodeAttach; + int _opcodeWait; + int _opcodeForce; + int _opcodeSleep; + int _opcodeListen; + int _opcodeEnter; + int _opcodeClose; + int _opcodeSearch; + int _opcodeKnock; + int _opcodeScratch; + int _opcodeRead; + int _opcodeEat; + int _opcodePlace; + int _opcodeOpen; + int _opcodeTake; + int _opcodeLook; + int _opcodeSmell; + int _opcodeSound; + int _opcodeLeave; + int _opcodeLift; + int _opcodeTurn; + int _opcodeSHide; + int _opcodeSSearch; + int _opcodeSRead; + int _opcodeSPut; + int _opcodeSLook; + MenuItem _actionMenu[12]; + + void setParent(MortevielleEngine *vm); + void readVerbNums(Common::File &f, int dataSize); + void setText(MenuItem item, Common::String name); + void setDestinationText(int roomId); + void setInventoryText(); + void disableMenuItem(MenuItem item); + void enableMenuItem(MenuItem item); + void displayMenu(); + void drawMenu(); + void menuUp(int msgId); + void eraseMenu(); + void updateMenu(); + void initMenu(); + + void setSearchMenu(); + void unsetSearchMenu(); +}; + +} // End of namespace Mortevielle +#endif diff --git a/engines/mortevielle/module.mk b/engines/mortevielle/module.mk new file mode 100644 index 0000000000..a9f02c2a67 --- /dev/null +++ b/engines/mortevielle/module.mk @@ -0,0 +1,23 @@ +MODULE := engines/mortevielle + +MODULE_OBJS := \ + actions.o \ + debugger.o \ + detection.o \ + dialogs.o \ + graphics.o \ + menu.o \ + mortevielle.o \ + mouse.o \ + outtext.o \ + saveload.o \ + sound.o \ + utils.o + +# This module can be built as a plugin +ifeq ($(ENABLE_MORTEVIELLE), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp new file mode 100644 index 0000000000..7748ce9371 --- /dev/null +++ b/engines/mortevielle/mortevielle.cpp @@ -0,0 +1,435 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" + +#include "mortevielle/dialogs.h" +#include "mortevielle/menu.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" +#include "mortevielle/saveload.h" +#include "mortevielle/outtext.h" + +#include "common/system.h" +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "engines/util.h" +#include "engines/engine.h" +#include "graphics/palette.h" +#include "graphics/pixelformat.h" + +namespace Mortevielle { + +MortevielleEngine *g_vm; + +MortevielleEngine::MortevielleEngine(OSystem *system, const MortevielleGameDescription *gameDesc): + Engine(system), _gameDescription(gameDesc), _randomSource("mortevielle"), + _soundManager(_mixer) { + g_vm = this; + _debugger.setParent(this); + _dialogManager.setParent(this); + _screenSurface.setParent(this); + _mouse.setParent(this); + _text.setParent(this); + _soundManager.setParent(this); + _savegameManager.setParent(this); + _menu.setParent(this); + + _lastGameFrame = 0; + _mouseClick = false; + _inMainGameLoop = false; + _quitGame = false; + + _roomPresenceLuc = false; + _roomPresenceIda = false; + _purpleRoomPresenceLeo = false; + _roomPresenceGuy = false; + _roomPresenceEva = false; + _roomPresenceMax = false; + _roomPresenceBob = false; + _roomPresencePat = false; + _toiletsPresenceBobMax = false; + _bathRoomPresenceBobMax = false; + _juliaRoomPresenceLeo = false; + + _soundOff = false; + _largestClearScreen = false; + _hiddenHero = false; + _heroSearching = false; + _keyPressedEsc = false; + _reloadCFIEC = false; + + _blo = false; + _col = false; + _syn = false; + _obpart = false; + _destinationOk = false; + _anyone = false; + _uptodatePresence = false; + + _textColor = 0; + _place = -1; + + _x26KeyCount = -1; + _caff = -1; + _day = 0; + + _curPict = nullptr; + _curAnim = nullptr; + _rightFramePict = nullptr; +} + +MortevielleEngine::~MortevielleEngine() { + free(_curPict); + free(_curAnim); + free(_rightFramePict); +} + +/** + * Specifies whether the engine supports given features + */ +bool MortevielleEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + +/** + * Return true if a game can currently be loaded + */ +bool MortevielleEngine::canLoadGameStateCurrently() { + // Saving is only allowed in the main game event loop + return _inMainGameLoop; +} + +/** + * Return true if a game can currently be saved + */ +bool MortevielleEngine::canSaveGameStateCurrently() { + // Loading is only allowed in the main game event loop + return _inMainGameLoop; +} + +/** + * Load in a savegame at the specified slot number + */ +Common::Error MortevielleEngine::loadGameState(int slot) { + return _savegameManager.loadGame(slot); +} + +/** + * Save the current game + */ +Common::Error MortevielleEngine::saveGameState(int slot, const Common::String &desc) { + if (slot == 0) + return Common::kWritingFailed; + + return _savegameManager.saveGame(slot, desc); +} + +/** + * Support method that generates a savegame name + * @param slot Slot number + */ +Common::String MortevielleEngine::generateSaveFilename(const Common::String &target, int slot) { + if (slot == 0) + // Initial game state loaded when the game starts + return "sav0.mor"; + + return Common::String::format("%s.%03d", target.c_str(), slot); +} + +/** + * Initialize the game state + */ +Common::ErrorCode MortevielleEngine::initialize() { + // Initialize graphics mode + initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, true); + + // Set debug channels + DebugMan.addDebugChannel(kMortevielleCore, "core", "Core debugging"); + DebugMan.addDebugChannel(kMortevielleGraphics, "graphics", "Graphics debugging"); + + // Set up an intermediate screen surface + _screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8()); + + _txxFileFl = false; + // Load texts from TXX files + loadTexts(); + + // Load the mort.dat resource + Common::ErrorCode result = loadMortDat(); + if (result != Common::kNoError) { + _screenSurface.free(); + return result; + } + + // Load some error messages (was previously in chartex()) + _hintPctMessage = getString(580); // You should have noticed %d hints + + // Set default EGA palette + _paletteManager.setDefaultPalette(); + + // Setup the mouse cursor + initMouse(); + + loadPalette(); + loadCFIPH(); + loadCFIEC(); + decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64); + _x26KeyCount = 1; + initMaxAnswer(); + initMouse(); + + loadPlaces(); + _soundOff = false; + _largestClearScreen = false; + + testKeyboard(); + showConfigScreen(); + testKeyboard(); + clearScreen(); + + _soundManager.loadNoise(); + _soundManager.loadAmbiantSounds(); + + return Common::kNoError; +} + +/** + * Loads the contents of the mort.dat data file + */ +Common::ErrorCode MortevielleEngine::loadMortDat() { + Common::File f; + + // Open the mort.dat file + if (!f.open(MORT_DAT)) { + GUIErrorMessage("Could not locate 'mort.dat'."); + return Common::kReadingFailed; + } + + // Validate the data file header + char fileId[4]; + f.read(fileId, 4); + if (strncmp(fileId, "MORT", 4) != 0) { + GUIErrorMessage("The located mort.dat data file is invalid"); + return Common::kReadingFailed; + } + + // Check the version + if (f.readByte() < MORT_DAT_REQUIRED_VERSION) { + GUIErrorMessage("The located mort.dat data file is too old, please download an updated version on scummvm.org"); + return Common::kReadingFailed; + } + f.readByte(); // Minor version + + // Loop to load resources from the data file + while (f.pos() < f.size()) { + // Get the Id and size of the next resource + char dataType[4]; + int dataSize; + f.read(dataType, 4); + dataSize = f.readUint16LE(); + + if (!strncmp(dataType, "FONT", 4)) { + // Font resource + _screenSurface.readFontData(f, dataSize); + } else if (!strncmp(dataType, "SSTR", 4)) { + readStaticStrings(f, dataSize, kStaticStrings); + } else if ((!strncmp(dataType, "GSTR", 4)) && (!_txxFileFl)) { + readStaticStrings(f, dataSize, kGameStrings); + } else if (!strncmp(dataType, "VERB", 4)) { + _menu.readVerbNums(f, dataSize); + } else { + // Unknown section + f.skip(dataSize); + } + } + + // Close the file + f.close(); + + assert(_engineStrings.size() > 0); + return Common::kNoError; +} + + +/** + * Read in a static strings block, and if the language matches, load up the static strings + */ +void MortevielleEngine::readStaticStrings(Common::File &f, int dataSize, DataType dataType) { + // Figure out what language Id is needed + byte desiredLanguageId; + switch(getLanguage()) { + case Common::EN_ANY: + desiredLanguageId = MORTDAT_LANG_ENGLISH; + break; + case Common::FR_FRA: + desiredLanguageId = MORTDAT_LANG_FRENCH; + break; + case Common::DE_DEU: + desiredLanguageId = MORTDAT_LANG_GERMAN; + break; + default: + warning("Language not supported, switching to English"); + desiredLanguageId = MORTDAT_LANG_ENGLISH; + break; + } + + // Read in the language + byte languageId = f.readByte(); + --dataSize; + + // If the language isn't correct, then skip the entire block + if (languageId != desiredLanguageId) { + f.skip(dataSize); + return; + } + + // Load in each of the strings + while (dataSize > 0) { + Common::String s; + char ch; + while ((ch = (char)f.readByte()) != '\0') + s += ch; + + if (dataType == kStaticStrings) + _engineStrings.push_back(s); + else if (dataType == kGameStrings) + _gameStrings.push_back(s); + + dataSize -= s.size() + 1; + } + assert(dataSize == 0); +} + +/*-------------------------------------------------------------------------*/ + +Common::Error MortevielleEngine::run() { + // Initialize the game + Common::ErrorCode err = initialize(); + if (err != Common::kNoError) + return err; + + // Check for a savegame + int loadSlot = 0; + if (ConfMan.hasKey("save_slot")) { + int gameToLoad = ConfMan.getInt("save_slot"); + if ((gameToLoad >= 1) && (gameToLoad <= 999)) + loadSlot = gameToLoad; + } + + if (loadSlot == 0) + // Show the game introduction + showIntroduction(); + + // Either load the initial game state savegame, or the specified savegame number + adzon(); + if (loadSlot != 0) + _savegameManager.loadSavegame(generateSaveFilename(loadSlot)); + else + resetVariables(); + + // Run the main game loop + mainGame(); + + // Cleanup (allocated in initialize()) + _screenSurface.free(); + free(_soundManager._cfiphBuffer); + free(_cfiecBuffer); + + return Common::kNoError; +} + +/** + * Show the game introduction + */ +void MortevielleEngine::showIntroduction() { + _dialogManager.displayIntroScreen(false); + _dialogManager.checkForF8(142, false); + if (shouldQuit()) + return; + + _dialogManager.displayIntroFrame2(); + _dialogManager.checkForF8(143, true); + if (shouldQuit()) + return; + + showTitleScreen(); + music(); + _mixer->stopAll(); +} + +/** + * Main game loop. Handles potentially playing the game multiple times, such as if the player + * loses, and chooses to start playing the game again. + */ +void MortevielleEngine::mainGame() { + if (_reloadCFIEC) + loadCFIEC(); + + for (_crep = 1; _crep <= _x26KeyCount; ++_crep) + decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64); + + _menu.initMenu(); + + charToHour(); + initGame(); + clearScreen(); + drawRightFrame(); + _mouse.showMouse(); + + // Loop to play the game + do { + playGame(); + if (shouldQuit()) + return; + } while (!_quitGame); +} + +/** + * This method handles playing a loaded game + * @remarks Originally called tjouer + */ +void MortevielleEngine::playGame() { + gameLoaded(); + + // Loop handling actions until the game has to be quit, or show the lose or end sequence + do { + handleAction(); + if (shouldQuit()) + return; + } while (!((_quitGame) || (_endGame) || (_loseGame))); + + if (_endGame) + endGame(); + else if (_loseGame) + askRestart(); +} + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h new file mode 100644 index 0000000000..4c9e57acd1 --- /dev/null +++ b/engines/mortevielle/mortevielle.h @@ -0,0 +1,485 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_MORTEVIELLE_H +#define MORTEVIELLE_MORTEVIELLE_H + +#include "common/events.h" +#include "common/file.h" +#include "common/random.h" +#include "common/rect.h" +#include "common/stack.h" +#include "engines/advancedDetector.h" +#include "engines/engine.h" +#include "common/error.h" +#include "graphics/surface.h" +#include "mortevielle/debugger.h" +#include "mortevielle/dialogs.h" +#include "mortevielle/graphics.h" +#include "mortevielle/menu.h" +#include "mortevielle/mouse.h" +#include "mortevielle/saveload.h" +#include "mortevielle/sound.h" +#include "mortevielle/outtext.h" + +namespace Mortevielle { + +// Debug channels +enum { + kMortevielleCore = 1 << 0, + kMortevielleGraphics = 1 << 1, + kMortevielleSounds = 1 << 2 +}; + +// Game languages +enum { + MORTDAT_LANG_FRENCH = 0, + MORTDAT_LANG_ENGLISH = 1, + MORTDAT_LANG_GERMAN = 2 +}; + +// Static string list +enum { + S_YES_NO = 0, S_GO_TO = 1, S_SOMEONE_ENTERS = 2, S_COOL = 3, S_LOURDE = 4, + S_MALSAINE = 5, S_IDEM = 6, S_YOU = 7, S_ARE = 8, S_ALONE = 9, + S_HEAR_NOISE = 10, S_SHOULD_HAVE_NOTICED = 11, S_NUMBER_OF_HINTS = 12, + S_WANT_TO_WAKE_UP = 13, S_OKAY = 14, S_SAVE_LOAD = 15, S_RESTART = 18, S_F3 = 19, + S_F8 = 20, S_HIDE_SELF = 21, S_TAKE = 22, S_PROBE = 23, S_RAISE = 24, S_SUITE = 25, + S_STOP = 26, S_USE_DEP_MENU = 27, S_LIFT = 28, S_READ = 29, + S_LOOK = 30, S_SEARCH = 31, S_OPEN = 32, S_PUT = 33, S_TURN = 34, S_TIE = 35, S_CLOSE = 36, + S_HIT = 37, S_POSE = 38, S_SMASH = 39, + + S_SMELL = 40, S_SCRATCH = 41, S_PROBE2 = 42, S_BEFORE_USE_DEP_MENU = 43, S_DAY = 44 +}; + +enum DataType { + kStaticStrings = 0, + kGameStrings = 1 +}; + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 400 +#define SCREEN_ORIG_HEIGHT 200 +#define MORT_DAT_REQUIRED_VERSION 1 +#define MORT_DAT "mort.dat" +#define GAME_FRAME_DELAY (1000 / 50) + +const int kTime1 = 410; +const int kTime2 = 250; + +const int kAcha = 492; +const int kFleche = 1758; + +const int kAsoul = 154; +const int kAouvr = 282; +const int kAsearch = 387; +const int kArcf = 1272; +const int kArep = 1314; +const int kAmzon = 1650; +const int kArega = 0; + +const int kMaxDialogIndex = 9000; +const int kMaxDialogHint = 600; + +const int kDescriptionStringIndex = 0; // Unused +const int kInventoryStringIndex = 186; +const int kQuestionStringIndex = 247; +const int kDialogStringIndex = 292; +const int kMenuPlaceStringIndex = 435; +const int kMenuActionStringIndex = 476; +const int kMenuSelfStringIndex = 497; +const int kMenuSayStringIndex = 502; +const int kMaxPatt = 20; + +const int kResolutionScaler = 2; +/* +9 "A glance at the forbidden$", +18 "It's already open$", +26 "A photograph$" +*/ +enum Places { + OWN_ROOM = 0, GREEN_ROOM = 1, PURPLE_ROOM = 2, TOILETS = 3, DARKBLUE_ROOM = 4, + BLUE_ROOM = 5, RED_ROOM = 6, BATHROOM = 7, GREEN_ROOM2 = 8, JULIA_ROOM = 9, + DINING_ROOM = 10, BUREAU = 11, KITCHEN = 12, ATTIC = 13, CELLAR = 14, + LANDING = 15, CRYPT = 16, SECRET_PASSAGE = 17, ROOM18 = 18, MOUNTAIN = 19, + CHAPEL = 20, MANOR_FRONT = 21, MANOR_BACK = 22, INSIDE_WELL = 23, WELL = 24, + DOOR = 25, ROOM26 = 26, COAT_ARMS = 27 +}; + +struct Pattern { + byte _tay, _tax; + byte _des[kMaxPatt + 1][kMaxPatt + 1]; +}; + +struct SaveStruct { + int _faithScore; + byte _pctHintFound[11]; + byte _availableQuestion[43]; + byte _inventory[31]; + int _currPlace; + int _atticBallHoleObjectId; + int _atticRodHoleObjectId; + int _cellarObjectId; + int _secretPassageObjectId; + int _wellObjectId; + int _selectedObjectId; + int _purpleRoomObjectId; + int _cryptObjectId; + bool _alreadyEnteredManor; + byte _fullHour; +}; + +struct Hint { + int _hintId; + byte _point; +}; + +struct MortevielleGameDescription; + +class MortevielleEngine : public Engine { +private: + const MortevielleGameDescription *_gameDescription; + Common::Stack<int> _keypresses; + uint32 _lastGameFrame; + Common::Point _mousePos; + Common::StringArray _engineStrings; + Common::StringArray _gameStrings; + + int _menuOpcode; + + bool _inMainGameLoop; // Flag when the main game loop is active + bool _quitGame; // Quit game flag. Originally called 'arret' + bool _endGame; // End game flag. Originally called 'solu' + bool _loseGame; // Lose game flag. Originally called 'perdu' + bool _txxFileFl; // Flag used to determine if texts are from the original files or from a DAT file + bool _roomPresenceLuc; + bool _roomPresenceIda; + bool _purpleRoomPresenceLeo; + bool _roomPresenceGuy; + bool _roomPresenceEva; + bool _roomPresenceMax; + bool _roomPresenceBob; + bool _roomPresencePat; + bool _toiletsPresenceBobMax; + bool _bathRoomPresenceBobMax; + bool _juliaRoomPresenceLeo; + bool _hiddenHero; + bool _heroSearching; + bool _keyPressedEsc; + bool _reloadCFIEC; + bool _col; + bool _syn; + bool _obpart; + bool _anyone; + bool _uptodatePresence; + + int _textColor; + int _place; + int _manorDistance; + int _currBitIndex; + int _currDay; + int _currHour; + int _currHalfHour; + int _day; + int _hour; + int _minute; + int _curSearchObjId; + int _controlMenu; + int _startHour; + int _endHour; + Common::Point _stdPal[91][17]; + + int _x26KeyCount; + int _roomDoorId; + int _openObjCount; + int _takeObjCount; + int _num; + int _searchCount; + bool _introSpeechPlayed; + int _inGameHourDuration; + int _x; + int _y; + int _currentHourCount; + int _currentDayHour; + + Common::String _hintPctMessage; + byte *_cfiecBuffer; + int _cfiecBufferSize; + int _openObjects[7]; + uint16 _dialogIndexArray[kMaxDialogIndex + 1]; + Hint _dialogHintArray[kMaxDialogHint + 1]; + + Common::ErrorCode initialize(); + Common::ErrorCode loadMortDat(); + void readStaticStrings(Common::File &f, int dataSize, DataType dataType); + void loadFont(Common::File &f); + bool handleEvents(); + void addKeypress(Common::Event &evt); + void initMouse(); + void showIntroduction(); + void mainGame(); + void playGame(); + void handleAction(); + void loadPalette(); + void loadTexts(); + void loadCFIEC(); + void loadCFIPH(); + void showTitleScreen(); + int readclock(); + void palette(int v1); + int checkLeoMaxRandomPresence(); + void interactNPC(); + void initCaveOrCellar(); + void displayControlMenu(); + void displayItemInHand(int objId); + void resetRoomVariables(int roomId); + int getPresenceStats(int &rand, int faithScore, int roomId); + void setPresenceFlags(int roomId); + void testKey(bool d); + void exitRoom(); + void getReadDescription(int objId); + void getSearchDescription(int objId); + int checkLeaveSecretPassage(); + void startDialog(int16 rep); + void endSearch(); + int convertCharacterIndexToBitIndex(int characterIndex); + int convertBitIndexToCharacterIndex(int bitIndex); + void clearUpperLeftPart(); + void clearDescriptionBar(); + void clearVerbBar(); + void clearUpperRightPart(); + int getRandomNumber(int minval, int maxval); + void showMoveMenuAlert(); + void showConfigScreen(); + void decodeNumber(byte *pStart, int count); + void resetVariables(); + void music(); + void drawRightFrame(); + void prepareRoom(); + void drawClock(); + void checkManorDistance(); + void gotoManorFront(); + void gotoManorBack(); + void gotoDiningRoom(); + bool checkInventory(int objectId); + void loseGame(); + void floodedInWell(); + void displayDiningRoom(); + void startMusicOrSpeech(int so); + void setTextColor(int col); + void prepareScreenType1(); + void prepareScreenType2(); + void prepareScreenType3(); + void updateHour(int &day, int &hour, int &minute); + void getKnockAnswer(); + int getPresenceStatsGreenRoom(); + int getPresenceStatsPurpleRoom(); + int getPresenceStatsToilets(); + int getPresenceStatsBlueRoom(); + int getPresenceStatsRedRoom(); + int getPresenceStatsDiningRoom(int &hour); + int getPresenceStatsBureau(int &hour); + int getPresenceStatsKitchen(); + int getPresenceStatsAttic(); + int getPresenceStatsLanding(); + int getPresenceStatsChapel(int &hour); + int getPresenceBitIndex(int roomId); + void setPresenceGreenRoom(int roomId); + void setPresencePurpleRoom(); + void setPresenceBlueRoom(); + void setPresenceRedRoom(int roomId); + int setPresenceDiningRoom(int hour); + int setPresenceBureau(int hour); + int setPresenceKitchen(); + int setPresenceLanding(); + int setPresenceChapel(int hour); + void setRandomPresenceGreenRoom(int faithScore); + void setRandomPresencePurpleRoom(int faithScore); + void setRandomPresenceBlueRoom(int faithScore); + void setRandomPresenceRedRoom(int faithScore); + void setRandomPresenceJuliaRoom(int faithScore); + void setRandomPresenceDiningRoom(int faithScore); + void setRandomPresenceBureau(int faithScore); + void setRandomPresenceKitchen(int faithScore); + void setRandomPresenceAttic(int faithScore); + void setRandomPresenceLanding(int faithScore); + void setRandomPresenceChapel(int faithScore); + void loadPlaces(); + void resetPresenceInRooms(int roomId); + void showPeoplePresent(int bitIndex); + int selectCharacters(int min, int max); + void fctMove(); + void fctTake(); + void fctInventoryTake(); + void fctLift(); + void fctRead(); + void fctSelfRead(); + void fctLook(); + void fctSelftLook(); + void fctSearch(); + void fctSelfSearch(); + void fctOpen(); + void fctPlace(); + void fctTurn(); + void fctSelfHide(); + void fctAttach(); + void fctClose(); + void fctKnock(); + void fctSelfPut(); + void fctListen(); + void fctEat(); + void fctEnter(); + void fctSleep(); + void fctForce(); + void fctLeave(); + void fctWait(); + void fctSound(); + void fctDiscuss(); + void fctSmell(); + void fctScratch(); + void endGame(); + void askRestart(); + void handleOpcode(); + void prepareDisplayText(); + bool decryptNextChar(char &c, int &idx, byte &pt); + void displayStatusArrow(); + void displayStatusInDescriptionBar(char stat); + void displayQuestionText(Common::String s, int cmd); + void displayTextInDescriptionBar(int x, int y, int nb, int mesgId); + void displayTextInVerbBar(Common::String text); + void displayTextBlock(Common::String text); + void mapMessageId(int &mesgId); + void resetOpenObjects(); + void setCoordinates(int sx); + void drawPicture(); + void drawPictureWithText(); + void addObjectToInventory(int objectId); + void putInHand(int &objId); + void initMaxAnswer(); + void displayAnimFrame(int frameNum, int animId); + int getFirstObject(); + void prepareNextObject(); + void putObject(); + void resetObjectPlace(); + void drawDiscussionBox(); + void displayNarrativePicture(int af, int ob); + void menuUp(); + void displayLookScreen(int objId); + + void adzon(); + +public: + Common::Point _prevPos; + int _currMenu; + int _currAction; + int _drawingSizeArr[108]; + int _charAnswerCount[9]; + int _charAnswerMax[9]; + byte _tabdon[4001]; + bool _soundOff; + bool _blo; + bool _destinationOk; + bool _largestClearScreen; + float _addFix; + int _savedBitIndex; + int _numpal; + int _key; + bool _mouseClick; + SaveStruct _coreVar, _saveStruct; + + int _maff; + int _caff; + int _crep; + + byte _destinationArray[7][25]; + + byte *_curPict; + byte *_curAnim; + byte *_rightFramePict; + + Debugger _debugger; + ScreenSurface _screenSurface; + PaletteManager _paletteManager; + GfxSurface _backgroundSurface; + Common::RandomSource _randomSource; + SoundManager _soundManager; + SavegameManager _savegameManager; + Menu _menu; + MouseHandler _mouse; + TextHandler _text; + DialogManager _dialogManager; + + MortevielleEngine(OSystem *system, const MortevielleGameDescription *gameDesc); + ~MortevielleEngine(); + virtual bool hasFeature(EngineFeature f) const; + virtual bool canLoadGameStateCurrently(); + virtual bool canSaveGameStateCurrently(); + virtual Common::Error loadGameState(int slot); + virtual Common::Error saveGameState(int slot, const Common::String &desc); + virtual Common::Error run(); + uint32 getGameFlags() const; + Common::Language getLanguage() const; + Common::Language getOriginalLanguage() const; + static Common::String generateSaveFilename(const Common::String &target, int slot); + Common::String generateSaveFilename(int slot) { return generateSaveFilename(_targetName, slot); } + + int getChar(); + bool keyPressed(); + Common::Point getMousePos() const { return _mousePos; } + void setMousePos(const Common::Point &pt); + bool getMouseClick() const { return _mouseClick; } + void setMouseClick(bool v) { _mouseClick = v; } + Common::String getEngineString(int idx) const { return _engineStrings[idx]; } + Common::String getGameString(int idx) const { return _gameStrings[idx]; } + + void delay(int amount); + void gameLoaded(); + void initGame(); + void displayAloneText(); + void draw(int x, int y); + void charToHour(); + void hourToChar(); + Common::String getString(int num); + void setPal(int n); + Common::String copy(const Common::String &s, int idx, size_t size); + void testKeyboard(); + int getPresence(int roomId); + void displayEmptyHand(); + void displayPicture(const byte *pic, int x, int y); + + int gettKeyPressed(); + void handleDescriptionText(int f, int mesgId); + int getAnimOffset(int frameNum, int animNum); + + void clearScreen(); +}; + +extern MortevielleEngine *g_vm; + +} // End of namespace Mortevielle + +#endif diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp new file mode 100644 index 0000000000..9eb4e129c0 --- /dev/null +++ b/engines/mortevielle/mouse.cpp @@ -0,0 +1,273 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/mouse.h" + +#include "common/endian.h" +#include "common/rect.h" + +namespace Mortevielle { + +/** + * Initialize the mouse + * @remarks Originally called 'init_mouse' + */ +void MouseHandler::initMouse() { + _counter = 0; + _pos = Common::Point(0, 0); + + _vm->setMouseClick(false); +} + +/** + * Backs up the area behind where the mouse cursor is to be drawn + * @remarks Originally called 'hide_mouse' + */ +void MouseHandler::hideMouse() { + // No implementation needed in ScummVM +} + +/** + * Draws the mouse cursor + * @remarks Originally called 'show_mouse' + */ +void MouseHandler::showMouse() { + // ScummVM implementation uses CursorMan for drawing the cursor +} + +/** + * Set mouse position + * @remarks Originally called 'pos_mouse' + */ +void MouseHandler::setMousePosition(Common::Point newPos) { + if (newPos.x > 314 * kResolutionScaler) + newPos.x = 314 * kResolutionScaler; + else if (newPos.x < 0) + newPos.x = 0; + if (newPos.y > 199) + newPos.y = 199; + else if (newPos.y < 0) + newPos.y = 0; + if (newPos == _pos) + return; + + // Set the new position + _vm->setMousePos(newPos); +} + +/** + * Get mouse poisition + * @remarks Originally called 'read_pos_mouse' + */ +void MouseHandler::getMousePosition(int &x, int &y, bool &click) { + x = _vm->getMousePos().x; + y = _vm->getMousePos().y; + click = _vm->getMouseClick(); +} + +/** + * Move mouse + * @remarks Originally called 'mov_mouse' + */ +void MouseHandler::moveMouse(bool &funct, char &key) { + bool p_key; + char in1, in2; + int cx, cy; + bool click; + + // Set defaults and check pending events + funct = false; + key = '\377'; + p_key = _vm->keyPressed(); + + // If mouse button clicked, return it + if (_vm->getMouseClick()) + return; + + // Handle any pending keypresses + while (p_key) { + if (_vm->shouldQuit()) + return; + + in1 = _vm->getChar(); + getMousePosition(cx, cy, click); + switch (toupper(in1)) { + case '4': + cx -= 8; + break; + case '2': + cy += 8; + break; + case '6': + cx += 8; + break; + case '8': + cy -= 8; + break; + case '7': + cy = 1; + cx = 1; + break; + case '1': + cx = 1; + cy = 190; + break; + case '9': + cx = 315 * kResolutionScaler; + cy = 1; + break; + case '3': + cy = 190; + cx = 315 * kResolutionScaler; + break; + case '5': + cy = 100; + cx = 155 * kResolutionScaler; + break; + case ' ': + case '\15': + _vm->setMouseClick(true); + return; + break; + case '\33': + p_key = _vm->keyPressed(); + + if (p_key) { + in2 = _vm->getChar(); + + if ((in2 >= ';') && (in2 <= 'D')) { + funct = true; + key = in2; + return; + } else { + switch (in2) { + case 'K': + --cx; + break; + case 'P': + ++cy; + break; + case 'M': + cx += 2; + break; + case 'H': + --cy; + break; + case 'G': + --cx; + --cy; + break; + case 'I': + ++cx; + --cy; + break; + case 'O': + --cx; + ++cy; + break; + case 'Q': + ++cx; + ++cy; + break; + default: + break; + } // case + } + } + break; + case 'I': + cx = kResolutionScaler * 32; + cy = 8; + break; + case 'D': + cx = 80 * kResolutionScaler; + cy = 8; + break; + case 'A': + cx = 126 * kResolutionScaler; + cy = 8; + break; + case 'S': + cx = 174 * kResolutionScaler; + cy = 8; + break; + case 'P': + cx = 222 * kResolutionScaler; + cy = 8; + break; + case 'F': + cx = kResolutionScaler * 270; + cy = 8; + break; + case '\23': + _vm->_soundOff = !_vm->_soundOff; + return; + break; + case '\24': // ^T => mode tandy + funct = true; + key = '\11'; + break; + case '\10': // ^H => mode Hercule + funct = true; + key = '\7'; + break; + case '\1': + case '\3': + case '\5': + funct = true; + key = in1; + break; + default: + break; + } + + setMousePosition(Common::Point(cx, cy)); + p_key = _vm->keyPressed(); + } +} + +/** + * Mouse function : Is mouse in a given rect? + * @remarks Originally called 'dans_rect' + */ +bool MouseHandler::isMouseIn(Common::Rect r) { + int x, y; + bool click; + + getMousePosition(x, y, click); + if ((x > r.left) && (x < r.right) && (y > r.top) && (y < r.bottom)) + return true; + + return false; +} + +void MouseHandler::setParent(MortevielleEngine *vm) { + _vm = vm; +} + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/mouse.h b/engines/mortevielle/mouse.h new file mode 100644 index 0000000000..1b9856e2c4 --- /dev/null +++ b/engines/mortevielle/mouse.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_MOUSE_H +#define MORTEVIELLE_MOUSE_H + +#include "common/rect.h" + +namespace Mortevielle { +class MortevielleEngine; + +class MouseHandler { +private: + MortevielleEngine *_vm; + + int s_s[12][6]; + int _counter; +public: + Common::Point _pos; + + void setParent(MortevielleEngine *vm); + void initMouse(); + void hideMouse(); + void showMouse(); + void setMousePosition(Common::Point newPos); + void getMousePosition(int &x, int &y, bool &click); + void moveMouse(bool &funct, char &key); + bool isMouseIn(Common::Rect r); +}; + +} // End of namespace Mortevielle +#endif diff --git a/engines/mortevielle/outtext.cpp b/engines/mortevielle/outtext.cpp new file mode 100644 index 0000000000..d50f4005de --- /dev/null +++ b/engines/mortevielle/outtext.cpp @@ -0,0 +1,308 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" +#include "mortevielle/graphics.h" + +#include "common/file.h" +#include "common/str.h" + +namespace Mortevielle { + +/** + * Next word + * @remarks Originally called 'l_motsuiv' + */ +int TextHandler::nextWord(int p, const char *ch, int &tab) { + int c = p; + + while ((ch[p] != ' ') && (ch[p] != '$') && (ch[p] != '@')) + ++p; + + return tab * (p - c); +} + +/** + * Engine function - Display Text + * @remarks Originally called 'afftex' + */ +void TextHandler::displayStr(Common::String inputStr, int x, int y, int dx, int dy, int typ) { + Common::String s; + int i, j; + + // Safeguard: add $ just in case + inputStr += '$'; + + _vm->_screenSurface.putxy(x, y); + int tab = 6; + dx *= 6; + dy *= 6; + int xc = x; + int yc = y; + int xf = x + dx; + int yf = y + dy; + int p = 0; + bool stringParsed = (inputStr[p] == '$'); + s = ""; + while (!stringParsed) { + switch (inputStr[p]) { + case '@': + _vm->_screenSurface.drawString(s, typ); + s = ""; + ++p; + xc = x; + yc += 6; + _vm->_screenSurface.putxy(xc, yc); + break; + case ' ': + s += ' '; + xc += tab; + ++p; + if (nextWord(p, inputStr.c_str(), tab) + xc > xf) { + _vm->_screenSurface.drawString(s, typ); + s = ""; + xc = x; + yc += 6; + if (yc > yf) { + while (!_vm->keyPressed()) + ; + i = y; + do { + j = x; + do { + _vm->_screenSurface.putxy(j, i); + _vm->_screenSurface.drawString(" ", 0); + j += 6; + } while (j <= xf); + i += 6; + } while (i <= yf); + yc = y; + } + _vm->_screenSurface.putxy(xc, yc); + } + break; + case '$': + stringParsed = true; + _vm->_screenSurface.drawString(s, typ); + break; + default: + s += inputStr[p]; + ++p; + xc += tab; + break; + } + } +} + +/** + * Load DES (picture container) file + * @remarks Originally called 'chardes' + */ +void TextHandler::loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length) { + Common::File f; + if (!f.open(filename)) { + if (!f.open(altFilename)) + error("Missing file: Either %s or %s", filename.c_str(), altFilename.c_str()); + } + // HACK: The original game contains a bug in the 2nd intro screen, in German DOS version. + // The size specified in the fxx array is wrong (too short). In order to fix it, we are using + // the value -1 to force a variable read length. + if (length == -1) + length = f.size() - skipSize; + + assert(skipSize + length <= f.size()); + + free(_vm->_curPict); + _vm->_curPict = (byte *)malloc(sizeof(byte) * length); + f.seek(skipSize); + f.read(_vm->_curPict, length); + f.close(); +} + +/** + * Load ANI file + * @remarks Originally called 'charani' + */ +void TextHandler::loadAniFile(Common::String filename, int32 skipSize, int length) { + Common::File f; + if (!f.open(filename)) + error("Missing file - %s", filename.c_str()); + + assert(skipSize + length <= f.size()); + + free(_vm->_curAnim); + _vm->_curAnim = (byte *)malloc(sizeof(byte) * length); + f.seek(skipSize); + f.read(_vm->_curAnim, length); + f.close(); +} + +void TextHandler::taffich() { + static const byte tran1[] = { 121, 121, 138, 139, 120 }; + static const byte tran2[] = { 150, 150, 152, 152, 100, 110, 159, 100, 100 }; + + int cx, drawingSize, npal; + int32 drawingStartPos; + + int a = _vm->_caff; + if ((a >= 153) && (a <= 161)) + a = tran2[a - 153]; + else if ((a >= 136) && (a <= 140)) + a = tran1[a - 136]; + int b = a; + if (_vm->_maff == a) + return; + + switch (a) { + case 16: + _vm->_coreVar._pctHintFound[9] = '*'; + _vm->_coreVar._availableQuestion[42] = '*'; + break; + case 20: + _vm->_coreVar._availableQuestion[39] = '*'; + if (_vm->_coreVar._availableQuestion[36] == '*') { + _vm->_coreVar._pctHintFound[3] = '*'; + _vm->_coreVar._availableQuestion[38] = '*'; + } + break; + case 24: + _vm->_coreVar._availableQuestion[37] = '*'; + break; + case 30: + _vm->_coreVar._availableQuestion[9] = '*'; + break; + case 31: // Coat of arms + _vm->_coreVar._pctHintFound[4] = '*'; + _vm->_coreVar._availableQuestion[35] = '*'; + break; + case 118: + _vm->_coreVar._availableQuestion[41] = '*'; + break; + case 143: + _vm->_coreVar._pctHintFound[1] = '*'; + break; + case 150: + _vm->_coreVar._availableQuestion[34] = '*'; + break; + case 151: + _vm->_coreVar._pctHintFound[2] = '*'; + break; + default: + break; + } + + _vm->_destinationOk = true; + _vm->_mouse.hideMouse(); + drawingStartPos = 0; + Common::String filename, altFilename; + + if ((a != 50) && (a != 51)) { + _vm->_maff = a; + if (a == 159) + a = 86; + else if (a > 140) + a -= 67; + else if (a > 137) + a -= 66; + else if (a > 99) + a -= 64; + else if (a > 69) + a -= 42; + else if (a > 29) + a -= 5; + else if (a == 26) + a = 24; + else if (a > 18) + --a; + npal = a; + + for (cx = 0; cx <= (a - 1); ++cx) + drawingStartPos += _vm->_drawingSizeArr[cx]; + drawingSize = _vm->_drawingSizeArr[a]; + + altFilename = filename = "DXX.mor"; + } else { + filename = "DZZ.mor"; + altFilename = "DZZALL"; + + if (a == 50) { + // First intro screen + drawingStartPos = 0; + drawingSize = _vm->_drawingSizeArr[87]; + } else { // a == 51 + // Second intro screen + drawingStartPos = _vm->_drawingSizeArr[87]; + // HACK: Force a variable size in order to fix the wrong size used by the German version + drawingSize = -1; + } + _vm->_maff = a; + npal = a + 37; + } + loadPictureFile(filename, altFilename, drawingStartPos, drawingSize); + _vm->_numpal = npal; + _vm->setPal(npal); + + if ((b < 15) || (b == 16) || (b == 17) || (b == 24) || (b == 26) || (b == 50)) { + drawingStartPos = 0; + if ((b < 15) || (b == 16) || (b == 17) || (b == 24) || (b == 26)) { + if (b == 26) + b = 18; + else if (b == 24) + b = 17; + else if (b > 15) + --b; + for (cx = 0; cx <= (b - 1); ++cx) + drawingStartPos += _vm->_drawingSizeArr[cx + 89]; + drawingSize = _vm->_drawingSizeArr[b + 89]; + filename = "AXX.mor"; + } else { // b == 50 + // CHECKME: the size of AZZ.mor is 1280 for the DOS version + // and 1260 for the Amiga version. Maybe the 20 bytes + // are a filler (to get 10 blocks of 128 bytes), + // or the size should be variable. + drawingSize = 1260; + filename = "AZZ.mor"; + } + loadAniFile(filename, drawingStartPos, drawingSize); + } + _vm->_mouse.showMouse(); + if ((a < COAT_ARMS) && ((_vm->_maff < COAT_ARMS) || (_vm->_coreVar._currPlace == LANDING)) && (_vm->_currAction != _vm->_menu._opcodeEnter)) { + if ((a == ATTIC) || (a == CELLAR)) + _vm->displayAloneText(); + else if (!_vm->_blo) + _vm->getPresence(_vm->_coreVar._currPlace); + _vm->_savedBitIndex = 0; + } +} + +void TextHandler::setParent(MortevielleEngine *vm) { + _vm = vm; +} + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/outtext.h b/engines/mortevielle/outtext.h new file mode 100644 index 0000000000..44868036d5 --- /dev/null +++ b/engines/mortevielle/outtext.h @@ -0,0 +1,49 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_OUTTEXT_H +#define MORTEVIELLE_OUTTEXT_H + +#include "common/str.h" + +namespace Mortevielle { +class MortevielleEngine; + +class TextHandler { +private: + MortevielleEngine *_vm; + int nextWord(int p, const char *ch, int &tab); +public: + void setParent(MortevielleEngine *vm); + void displayStr(Common::String inputStr, int x, int y, int dx, int dy, int typ); + void loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length); + void loadAniFile(Common::String filename, int32 skipSize, int length); + void taffich(); +}; + +} // End of namespace Mortevielle +#endif diff --git a/engines/mortevielle/saveload.cpp b/engines/mortevielle/saveload.cpp new file mode 100644 index 0000000000..651ed07b65 --- /dev/null +++ b/engines/mortevielle/saveload.cpp @@ -0,0 +1,328 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/dialogs.h" +#include "mortevielle/mouse.h" +#include "mortevielle/saveload.h" + +#include "common/file.h" +#include "common/system.h" + +namespace Mortevielle { + +static const char SAVEGAME_ID[4] = { 'M', 'O', 'R', 'T' }; + +void SavegameManager::setParent(MortevielleEngine *vm) { + _vm = vm; +} + +/** + * Handle saving or loading savegame data + */ +void SavegameManager::sync_save(Common::Serializer &sz) { + sz.syncAsSint16LE(g_vm->_saveStruct._faithScore); + for (int i = 0; i < 11; ++i) + sz.syncAsByte(g_vm->_saveStruct._pctHintFound[i]); + for (int i = 0; i < 43; ++i) + sz.syncAsByte(g_vm->_saveStruct._availableQuestion[i]); + for (int i = 0; i < 31; ++i) + sz.syncAsByte(g_vm->_saveStruct._inventory[i]); + + sz.syncAsSint16LE(g_vm->_saveStruct._currPlace); + sz.syncAsSint16LE(g_vm->_saveStruct._atticBallHoleObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._atticRodHoleObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._cellarObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._secretPassageObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._wellObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._selectedObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._purpleRoomObjectId); + sz.syncAsSint16LE(g_vm->_saveStruct._cryptObjectId); + sz.syncAsByte(g_vm->_saveStruct._alreadyEnteredManor); + sz.syncAsByte(g_vm->_saveStruct._fullHour); + + sz.syncBytes(_tabdonSaveBuffer, 391); +} + +/** + * Inner code for loading a saved game + * @remarks Originally called 'takesav' + */ +void SavegameManager::loadSavegame(const Common::String &filename) { + // Try loading first from the save area + Common::SeekableReadStream *stream = g_system->getSavefileManager()->openForLoading(filename); + + Common::File f; + if (stream == NULL) { + if (!f.open(filename)) + error("Unable to open save file '%s'", filename.c_str()); + + stream = f.readStream(f.size()); + f.close(); + } + + // Check whether it's a ScummVM saved game + char buffer[4]; + stream->read(buffer, 4); + if (!strncmp(&buffer[0], &SAVEGAME_ID[0], 4)) { + // Yes, it is, so skip over the savegame header + SavegameHeader header; + readSavegameHeader(stream, header); + delete header.thumbnail; + } else { + stream->seek(0); + } + + // Read the game contents + Common::Serializer sz(stream, NULL); + sync_save(sz); + + g_vm->_coreVar = g_vm->_saveStruct; + for (int i = 0; i <= 389; ++i) + g_vm->_tabdon[i + kAcha] = _tabdonSaveBuffer[i]; + + // Close the stream + delete stream; +} + +/** + * Load a saved game + */ +Common::Error SavegameManager::loadGame(const Common::String &filename) { + g_vm->_mouse.hideMouse(); + g_vm->displayEmptyHand(); + loadSavegame(filename); + + /* Initialization */ + g_vm->charToHour(); + g_vm->initGame(); + g_vm->gameLoaded(); + g_vm->_mouse.showMouse(); + return Common::kNoError; +} + +/** + * Save the game + */ +Common::Error SavegameManager::saveGame(int n, const Common::String &saveName) { + Common::OutSaveFile *f; + int i; + + g_vm->_mouse.hideMouse(); + g_vm->hourToChar(); + + for (i = 0; i <= 389; ++i) + _tabdonSaveBuffer[i] = g_vm->_tabdon[i + kAcha]; + g_vm->_saveStruct = g_vm->_coreVar; + if (g_vm->_saveStruct._currPlace == ROOM26) + g_vm->_saveStruct._currPlace = LANDING; + + Common::String filename = _vm->generateSaveFilename(n); + f = g_system->getSavefileManager()->openForSaving(filename); + + // Write out the savegame header + f->write(&SAVEGAME_ID[0], 4); + + // Write out the header + SavegameHeader header; + writeSavegameHeader(f, saveName); + + // Write out the savegame contents + Common::Serializer sz(NULL, f); + sync_save(sz); + + // Close the save file + f->finalize(); + delete f; + + // Skipped: dialog asking to swap floppy + + g_vm->_mouse.showMouse(); + return Common::kNoError; +} + +Common::Error SavegameManager::loadGame(int slot) { + return loadGame(_vm->generateSaveFilename(slot)); +} + +Common::Error SavegameManager::saveGame(int slot) { + return saveGame(slot, _vm->generateSaveFilename(slot)); +} + +void SavegameManager::writeSavegameHeader(Common::OutSaveFile *out, const Common::String &saveName) { + // Write out a savegame header + out->writeByte(SAVEGAME_VERSION); + + // Write savegame name + out->writeString(saveName); + out->writeByte(0); + + // Get the active palette + uint8 thumbPalette[256 * 3]; + g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256); + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + Graphics::Surface s = g_vm->_screenSurface.lockArea(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + ::createThumbnail(thumb, (const byte *)s.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette); + Graphics::saveThumbnail(*out, *thumb); + thumb->free(); + delete thumb; + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); +} + +bool SavegameManager::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) { + header.thumbnail = NULL; + + // Get the savegame version + header.version = in->readByte(); + + // Read in the save name + header.saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') + header.saveName += ch; + + // Get the thumbnail + header.thumbnail = Graphics::loadThumbnail(*in); + if (!header.thumbnail) + return false; + + // Read in save date/time + header.saveYear = in->readSint16LE(); + header.saveMonth = in->readSint16LE(); + header.saveDay = in->readSint16LE(); + header.saveHour = in->readSint16LE(); + header.saveMinutes = in->readSint16LE(); + + return true; +} + +SaveStateList SavegameManager::listSaves(const Common::String &target) { + Common::String pattern = target; + pattern += ".???"; + + Common::StringArray files = g_system->getSavefileManager()->listSavefiles(pattern); + sort(files.begin(), files.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = files.begin(); file != files.end(); ++file) { + // Obtain the last 3 digits of the filename, since they correspond to the save slot + const Common::String &fname = *file; + int slotNumber = atoi(fname.c_str() + fname.size() - 3); + + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fname); + if (in) { + // There can be two types of savegames: original interpreter savegames, and ScummVM savegames. + // Original interpreter savegames are 497 bytes, and still need to be supported because the + // initial game state is stored as a savegame + bool validFlag = false; + Common::String saveDescription; + + char buffer[4]; + in->read(buffer, 4); + if (!strncmp(&buffer[0], &SAVEGAME_ID[0], 4)) { + // ScummVm savegame. Read in the header to get the savegame name + SavegameHeader header; + validFlag = readSavegameHeader(in, header); + + if (validFlag) { + delete header.thumbnail; + saveDescription = header.saveName; + } + } else if (file->size() == 497) { + // Form an appropriate savegame name + saveDescription = (slotNumber == 0) ? "Initial game state" : + Common::String::format("Savegame #%d", slotNumber); + validFlag = true; + } + + if (validFlag) + // Got a valid savegame + saveList.push_back(SaveStateDescriptor(slotNumber, saveDescription)); + + delete in; + } + } + + return saveList; +} + +SaveStateDescriptor SavegameManager::querySaveMetaInfos(const Common::String &fileName) { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName); + + if (f) { + // Get the slot number + int slot = 1; + if (fileName.size() > 4 && fileName[fileName.size() - 4] == '.') + slot = atoi(fileName.c_str() + fileName.size() - 3); + + // Check to see if it's a ScummVM savegame or not + char buffer[4]; + f->read(buffer, 4); + + bool hasHeader = !strncmp(&buffer[0], &SAVEGAME_ID[0], 4); + + if (!hasHeader) { + // Original savegame perhaps? + delete f; + + SaveStateDescriptor desc(slot, Common::String::format("Savegame - %03d", slot)); + desc.setDeletableFlag(slot != 0); + desc.setWriteProtectedFlag(slot == 0); + return desc; + } else { + // Get the savegame header information + SavegameHeader header; + readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + desc.setDeletableFlag(true); + desc.setWriteProtectedFlag(false); + desc.setThumbnail(header.thumbnail); + desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay); + desc.setSaveTime(header.saveHour, header.saveMinutes); + + return desc; + } + } + + return SaveStateDescriptor(); +} + +} // End of namespace Mortevielle diff --git a/engines/mortevielle/saveload.h b/engines/mortevielle/saveload.h new file mode 100644 index 0000000000..0121a04d8e --- /dev/null +++ b/engines/mortevielle/saveload.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_SAVELOAD_H +#define MORTEVIELLE_SAVELOAD_H + +#include "common/savefile.h" +#include "common/serializer.h" +#include "graphics/palette.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" + +#define SAVEGAME_VERSION 1 + +namespace Mortevielle { + +struct SavegameHeader { + uint8 version; + Common::String saveName; + Graphics::Surface *thumbnail; + int saveYear, saveMonth, saveDay; + int saveHour, saveMinutes; + int totalFrames; +}; + +class MortevielleEngine; + +class SavegameManager { +private: + MortevielleEngine *_vm; + byte _tabdonSaveBuffer[391]; + + void sync_save(Common::Serializer &sz); +public: + void setParent(MortevielleEngine *vm); + void loadSavegame(const Common::String &filename); + Common::Error loadGame(const Common::String &filename); + Common::Error saveGame(int n, const Common::String &saveName); + Common::Error loadGame(int slot); + Common::Error saveGame(int slot); + + void writeSavegameHeader(Common::OutSaveFile *out, const Common::String &saveName); + static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header); + static SaveStateList listSaves(const Common::String &target); + static SaveStateDescriptor querySaveMetaInfos(const Common::String &fileName); +}; + +} // End of namespace Mortevielle +#endif diff --git a/engines/mortevielle/sound.cpp b/engines/mortevielle/sound.cpp new file mode 100644 index 0000000000..3bea96b92f --- /dev/null +++ b/engines/mortevielle/sound.cpp @@ -0,0 +1,796 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" +#include "mortevielle/sound.h" + +#include "audio/decoders/raw.h" +#include "common/scummsys.h" + +namespace Mortevielle { + + const byte _tnocon[364] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + const byte _intcon[26] = {1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}; + const byte _typcon[26] = {0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3}; + const byte _tabdph[16] = {0, 10, 2, 0, 2, 10, 3, 0, 3, 7, 5, 0, 6, 7, 7, 10}; + const byte _tabdbc[18] = {7, 23, 7, 14, 13, 9, 14, 9, 5, 12, 6, 12, 13, 4, 0, 4, 5, 9}; + +SoundManager::SoundManager(Audio::Mixer *mixer) { + _mixer = mixer; + _audioStream = nullptr; + _ambiantNoiseBuf = nullptr; + _noiseBuf = nullptr; + + _soundType = 0; + _phonemeNumb = 0; + + for (int i = 0; i < 3; i++) { + _queue[i]._val = 0; + _queue[i]._code = 0; + _queue[i]._acc = 0; + _queue[i]._freq = 0; + _queue[i]._rep = 0; + } + _buildingSentence = false; +} + +SoundManager::~SoundManager() { + if (_audioStream) + _audioStream->finish(); + free(_ambiantNoiseBuf); + free(_noiseBuf); +} + +/** + * Decode music data + */ +int SoundManager::decodeMusic(const byte *PSrc, byte *PDest, int size) { + static const int tab[16] = { -96, -72, -48, -32, -20, -12, -8, -4, 0, 4, 8, 12, 20, 32, 48, 72 }; + + uint seed = 128; + int v; + int decompSize = 0; + int skipSize = 0; + + for (int idx1 = 0; idx1 < size; ++idx1) { + byte srcByte = *PSrc++; + v = tab[srcByte >> 4]; + seed += v; + *PDest++ = seed & 0xff; + + v = tab[srcByte & 0xf]; + seed += v; + *PDest++ = seed & 0xff; + + if (srcByte == 0) + skipSize += 2; + else { + decompSize += skipSize + 2; + skipSize = 0; + } + } + return decompSize; +} + +/** + * Load sonmus.mor file + * @remarks Originally called 'charge_son' + */ +void SoundManager::loadAmbiantSounds() { + Common::File f; + if (!f.open("sonmus.mor")) + error("Missing file - sonmus.mor"); + + free(_ambiantNoiseBuf); + int size = f.size(); + byte *compMusicBuf1 = (byte *)malloc(sizeof(byte) * size); + _ambiantNoiseBuf = (byte *)malloc(sizeof(byte) * size * 2); + f.read(compMusicBuf1, size); + f.close(); + + decodeMusic(compMusicBuf1, _ambiantNoiseBuf, size); + free(compMusicBuf1); +} + +/** + * Speech function - Load Noise files + * @remarks Originally called 'charge_bruit' and 'charge_bruit5' + */ +void SoundManager::loadNoise() { + Common::File f1, f2; + + if (!f1.open("bruits")) //Translation: "noise" + error("Missing file - bruits"); + if (!f2.open("bruit5")) + error("Missing file - bruit5"); + + _noiseBuf = (byte *)malloc(sizeof(byte) * (f1.size() + f2.size())); + assert(f1.size() > 32000); + + f1.read(_noiseBuf, 32000); // 250 * 128 + f2.read(&_noiseBuf[32000], f2.size()); + f1.read(&_noiseBuf[32000 + f2.size()], f1.size() - 32000); // 19072 + + f1.close(); + f2.close(); +} + +void SoundManager::regenbruit() { + int i = 69876; + for (int j = 0; j < 100; j++) { + _cfiphBuffer[j] = READ_BE_UINT16(&_noiseBuf[i]); + i += 2; + } +} + +void SoundManager::litph(tablint &t, int typ, int tempo) { + // Skip speech + if (_soundType == 0) + return; + + if (!_buildingSentence) { + if (_mixer->isSoundHandleActive(_soundHandle)) + _mixer->stopHandle(_soundHandle); + _buildingSentence = true; + } + int freq = tempo * 252; // 25.2 * 10 + int i = 0; + while (i < _ptr_oct) { + int idx = _troctBuf[i]; + i++; + switch(idx) { + case 0: { + int val = _troctBuf[i]; + i++; + if (_soundType == 0) + warning("TODO: vclas"); + else if (_soundType == 1) { + debugC(5, kMortevielleSounds, "litph - duson"); + const static int noiseAdr[] = {0, 17224, + 17224, 33676, + 33676, 51014, + 51014, 59396, + 59396, 61286, + 61286, 69875}; + if (val > 5) { + warning("unhandled index %d", val); + } else { + if (!_audioStream) + _audioStream = Audio::makeQueuingAudioStream(freq, false); + _audioStream->queueBuffer(&_noiseBuf[noiseAdr[val * 2]], noiseAdr[(val * 2) + 1] - noiseAdr[(val * 2)], DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); + } + } else { // 2 + debugC(5, kMortevielleSounds, "litph - vadson"); + const static int ambiantNoiseAdr[] = {0, 14020, + 14020, 18994, + 18994, 19630, + 19630, 22258, + 22258, 37322, + 37322, 44472, + 44472, 52324, + 52324, 59598, + 59598, 69748}; + if (val > 8) { + warning("unhandled index %d", val); + } else { + if (!_audioStream) + _audioStream = Audio::makeQueuingAudioStream(freq, false); + _audioStream->queueBuffer(&_ambiantNoiseBuf[ambiantNoiseAdr[val * 2]], ambiantNoiseAdr[(val * 2) + 1] - ambiantNoiseAdr[(val * 2)], DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); + } + } + i++; + break; + } + case 2: { + int val = _troctBuf[i]; + i++; + int tmpidx = (val * 12) + 268; + val = _troctBuf[i]; + i++; + warning("TODO: reech %d %d", tmpidx, val); + } + break; + case 4: + if (_soundType) { + i += 2; + } else { + // Speech + warning("TODO: Interphoneme: consonne:%d voyelle:%d", _troctBuf[i], _troctBuf[i + 1]); + i += 2; + } + break; + case 6: + warning("TODO: pari2"); + i += 2; + break; + default: + static byte emptyBuf[19] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + if (idx == 62) + warning("TODO: blab"); + else if (idx == 32) { + if (!_audioStream) + _audioStream = Audio::makeQueuingAudioStream(freq, false); + _audioStream->queueBuffer(emptyBuf, 19, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); + } else if (idx == 35) { + if (i < _ptr_oct) + warning("unexpected 35 - stop the buffering"); + i = _ptr_oct; + } else if (idx == 46) { + if (!_audioStream) + _audioStream = Audio::makeQueuingAudioStream(freq, false); + for (int j = 0; j < 10; j++) + _audioStream->queueBuffer(emptyBuf, 19, DisposeAfterUse::NO, Audio::FLAG_UNSIGNED); + } else { + warning("Other code: %d - %d %d", idx, _troctBuf[i], _troctBuf[i + 1]); + } + break; + } + } +} + +void SoundManager::playSong(const byte* buf, uint size, uint loops) { + int freq = kTempoMusic * 252; // 25.2 * 10 + Audio::SeekableAudioStream *raw = Audio::makeRawStream(buf, size, freq, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO); + Audio::AudioStream *stream = Audio::makeLoopingAudioStream(raw, loops); + Audio::SoundHandle songHandle; + _mixer->playStream(Audio::Mixer::kSFXSoundType, &songHandle, stream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::YES); + + while (_mixer->isSoundHandleActive(songHandle) && !_vm->keyPressed() && !_vm->_mouseClick && !_vm->shouldQuit()) + ; + // In case the handle is still active, stop it. + _mixer->stopHandle(songHandle); +} + +void SoundManager::setParent(MortevielleEngine *vm) { + _vm = vm; +} + +void SoundManager::spfrac(int wor) { + _queue[2]._rep = (uint)wor >> 12; + if ((_soundType == 0) && (_queue[2]._code != 9)) { + if (((_queue[2]._code > 4) && (_queue[2]._val != 20) && (_queue[2]._rep != 3) && (_queue[2]._rep != 6) && (_queue[2]._rep != 9)) || + ((_queue[2]._code < 5) && ((_queue[2]._val != 19) && (_queue[2]._val != 22) && (_queue[2]._rep != 4) && (_queue[2]._rep != 9)))) { + ++_queue[2]._rep; + } + } + + _queue[2]._freq = ((uint)wor >> 6) & 7; + _queue[2]._acc = ((uint)wor >> 9) & 7; +} + +void SoundManager::charg_car(int &currWordNumb) { + assert(currWordNumb < 1712); + int wor = READ_BE_UINT16(&_wordBuf[currWordNumb]); + int int_ = wor & 0x3f; // 63 + + if ((int_ >= 0) && (int_ <= 13)) { + _queue[2]._val = int_; + _queue[2]._code = 5; + } else if ((int_ >= 14) && (int_ <= 21)) { + _queue[2]._val = int_; + _queue[2]._code = 6; + } else if ((int_ >= 22) && (int_ <= 47)) { + int_ -= 22; + _queue[2]._val = int_; + _queue[2]._code = _typcon[int_]; + } else if ((int_ >= 48) && (int_ <= 56)) { + _queue[2]._val = int_ - 22; + _queue[2]._code = 4; + } else { + switch (int_) { + case 60: + _queue[2]._val = 32; /* " " */ + _queue[2]._code = 9; + break; + case 61: + _queue[2]._val = 46; /* "." */ + _queue[2]._code = 9; + break; + case 62: + _queue[2]._val = 35; /* "#" */ + _queue[2]._code = 9; + default: + break; + } + } + + spfrac(wor); + currWordNumb += 2; +} + + +void SoundManager::entroct(byte o) { + assert(_ptr_oct < 10576); + _troctBuf[_ptr_oct] = o; + ++_ptr_oct; +} + +void SoundManager::cctable(tablint &t) { + float tb[257]; + + tb[0] = 0; + for (int k = 0; k <= 255; ++k) { + tb[k + 1] = _vm->_addFix + tb[k]; + t[255 - k] = abs((int)tb[k] + 1); + } +} + +/** + * Load phoneme sound file + * @remarks Originally called 'charge_phbruit' + */ +void SoundManager::loadPhonemeSounds() { + Common::File f; + + if (!f.open("phbrui.mor")) + error("Missing file - phbrui.mor"); + + for (int i = 1; i <= f.size() / 2; ++i) + _cfiphBuffer[i] = f.readUint16BE(); + + f.close(); +} + +void SoundManager::trait_car() { + byte d3; + int d2, i; + + switch (_queue[1]._code) { + case 9: + if (_queue[1]._val != (int)'#') { + for (i = 0; i <= _queue[1]._rep; ++i) + entroct(_queue[1]._val); + } + break; + case 5: + case 6: + if (_queue[1]._code == 6) + d3 = _tabdph[(_queue[1]._val - 14) << 1]; + else + d3 = kNullValue; + if (_queue[0]._code >= 5) { + if (_queue[0]._code == 9) { + entroct(4); + if (d3 == kNullValue) + entroct(_queue[1]._val); + else + entroct(d3); + entroct(22); + } + } + + switch (_queue[1]._rep) { + case 0: + entroct(0); + entroct(_queue[1]._val); + if (d3 == kNullValue) + if (_queue[2]._code == 9) + entroct(2); + else + entroct(4); + else if (_queue[2]._code == 9) + entroct(0); + else + entroct(1); + break; + case 4: + case 5: + case 6: + if (_queue[1]._rep != 4) { + i = _queue[1]._rep - 5; + do { + --i; + entroct(0); + if (d3 == kNullValue) + entroct(_queue[1]._val); + else + entroct(d3); + entroct(3); + } while (i >= 0); + } + if (d3 == kNullValue) { + entroct(4); + entroct(_queue[1]._val); + entroct(0); + } else { + entroct(0); + entroct(_queue[1]._val); + entroct(3); + } + + break; + case 7: + case 8: + case 9: + if (_queue[1]._rep != 7) { + i = _queue[1]._rep - 8; + do { + --i; + entroct(0); + if (d3 == kNullValue) + entroct(_queue[1]._val); + else + entroct(d3); + entroct(3); + } while (i >= 0); + } + if (d3 == kNullValue) { + entroct(0); + entroct(_queue[1]._val); + entroct(2); + } else { + entroct(0); + entroct(_queue[1]._val); + entroct(0); + } + break; + case 1: + case 2: + case 3: + if (_queue[1]._rep != 1) { + i = _queue[1]._rep - 2; + do { + --i; + entroct(0); + if (d3 == kNullValue) + entroct(_queue[1]._val); + else + entroct(d3); + entroct(3); + } while (i >= 0); + } + entroct(0); + entroct(_queue[1]._val); + if (_queue[2]._code == 9) + entroct(0); + else + entroct(1); + + break; + default: + break; + } // switch c2.rep + break; + + case 2: + case 3: + d3 = _queue[1]._code + 5; // 7 ou 8 => Corresponding vowel + if (_queue[0]._code > 4) { + if (_queue[0]._code == 9) { + entroct(4); + entroct(d3); + entroct(22); + } + } + i = _queue[1]._rep; + assert(i >= 0); + if (i != 0) { + do { + --i; + entroct(0); + entroct(d3); + entroct(3); + } while (i > 0); + } + if (_queue[2]._code == 6) { + entroct(4); + entroct(_tabdph[(_queue[2]._val - 14) << 1]); + entroct(_queue[1]._val); + } else { + entroct(4); + if (_queue[2]._val == 4) + entroct(3); + else + entroct(_queue[2]._val); + entroct(_queue[1]._val); + } + break; + case 0: + case 1: + switch (_queue[2]._code) { + case 2: + d2 = 7; + break; + case 3: + d2 = 8; + break; + case 6: + d2 = _tabdph[(_queue[2]._val - 14) << 1]; + break; + case 5: + d2 = _queue[2]._val; + break; + default: + d2 = 10; + break; + } // switch c3._code + d2 = (d2 * 26) + _queue[1]._val; + if (_tnocon[d2] == 0) + d3 = 2; + else + d3 = 6; + if (_queue[1]._rep >= 5) { + _queue[1]._rep -= 5; + d3 = 8 - d3; // Swap 2 and 6 + } + if (_queue[1]._code == 0) { + i = _queue[1]._rep; + if (i != 0) { + do { + --i; + entroct(d3); + entroct(_queue[1]._val); + entroct(3); + } while (i > 0); + } + entroct(d3); + entroct(_queue[1]._val); + entroct(4); + } else { + entroct(d3); + entroct(_queue[1]._val); + entroct(3); + i = _queue[1]._rep; + if (i != 0) { + do { + --i; + entroct(d3); + entroct(_queue[1]._val); + entroct(4); + } while (i > 0); + } + } + if (_queue[2]._code == 9) { + entroct(d3); + entroct(_queue[1]._val); + entroct(5); + } else if ((_queue[2]._code != 0) && (_queue[2]._code != 1) && (_queue[2]._code != 4)) { + switch (_queue[2]._code) { + case 3: + d2 = 8; + break; + case 6: + d2 = _tabdph[(_queue[2]._val - 14) << 1]; + break; + case 5: + d2 = _queue[2]._val; + break; + default: + d2 = 7; + break; + } // switch c3._code + if (d2 == 4) + d2 = 3; + + if (_intcon[_queue[1]._val] != 0) + ++_queue[1]._val; + + if ((_queue[1]._val == 17) || (_queue[1]._val == 18)) + _queue[1]._val = 16; + + entroct(4); + entroct(d2); + entroct(_queue[1]._val); + } + + break; + case 4: + i = _queue[1]._rep; + if (i != 0) { + do { + --i; + entroct(2); + entroct(_queue[1]._val); + entroct(3); + } while (i > 0); + } + entroct(2); + entroct(_queue[1]._val); + entroct(4); + if (_queue[2]._code == 9) { + entroct(2); + entroct(_queue[1]._val); + entroct(5); + } else if ((_queue[2]._code != 0) && (_queue[2]._code != 1) && (_queue[2]._code != 4)) { + switch (_queue[2]._code) { + case 3: + d2 = 8; + break; + case 6: + d2 = _tabdph[(_queue[2]._val - 14) << 1]; + break; + case 5: + d2 = _queue[2]._val; + break; + default: + d2 = 7; + break; + } // switch c3._code + + if (d2 == 4) + d2 = 3; + + if (_intcon[_queue[1]._val] != 0) + ++_queue[1]._val; + + entroct(4); + entroct(d2); + entroct(_tabdbc[((_queue[1]._val - 26) << 1) + 1]); + } + + break; + default: + break; + } // switch c2.code +} + +/** + * Make the queue evolve by 1 value + * @remarks Originally called 'rot_chariot' + */ +void SoundManager::moveQueue() { + _queue[0] = _queue[1]; + _queue[1] = _queue[2]; + _queue[2]._val = 32; + _queue[2]._code = 9; +} + +/** + * initialize the queue + * @remarks Originally called 'init_chariot' + */ +void SoundManager::initQueue() { + _queue[2]._rep = 0; + _queue[2]._freq = 0; + _queue[2]._acc = 0; + moveQueue(); + moveQueue(); +} + +/** + * Handle a phoneme + * @remarks Originally called 'trait_ph' + */ +void SoundManager::handlePhoneme() { + const uint16 deca[3] = {300, 30, 40}; + + uint16 startPos = _cfiphBuffer[_phonemeNumb - 1] + deca[_soundType]; + uint16 endPos = _cfiphBuffer[_phonemeNumb] + deca[_soundType]; + int wordCount = endPos - startPos; + + startPos /= 2; + endPos /= 2; + assert((endPos - startPos) < 1711); + for (int i = startPos, currWord = 0; i < endPos; i++, currWord += 2) + WRITE_BE_UINT16(&_wordBuf[currWord], _cfiphBuffer[i]); + + _ptr_oct = 0; + int currWord = 0; + initQueue(); + + do { + moveQueue(); + charg_car(currWord); + trait_car(); + } while (currWord < wordCount); + + moveQueue(); + trait_car(); + entroct((int)'#'); + +#ifdef DEBUG + warning("---"); + for (int i = 0; i < _ptr_oct; ) { + if ((_troctBuf[i] == 32) || (_troctBuf[i] == 35) || (_troctBuf[i] == 46)) { + warning("%d", _troctBuf[i]); + i++; + } else { + warning("%d %d %d", _troctBuf[i], _troctBuf[i + 1], _troctBuf[i + 1]); + i += 3; + } + } + warning("---"); +#endif +} + +/** + * Start speech + * @remarks Originally called 'parole' + */ +void SoundManager::startSpeech(int rep, int ht, int typ) { + uint16 savph[501]; + int tempo; + + if (_vm->_soundOff) + return; + + _phonemeNumb = rep; + int haut = ht; + _soundType = typ; + if (_soundType != 0) { + for (int i = 0; i <= 500; ++i) + savph[i] = _cfiphBuffer[i]; + tempo = kTempoNoise; + } else if (haut > 5) + tempo = kTempoF; + else + tempo = kTempoM; + _vm->_addFix = (float)((tempo - 8)) / 256; + cctable(_tbi); + switch (typ) { + case 1: + regenbruit(); + break; + case 2: + loadPhonemeSounds(); + break; + default: + break; + } + handlePhoneme(); + litph(_tbi, typ, tempo); + + _buildingSentence = false; + if (typ != 0) { + _audioStream->finish(); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream); + _audioStream = nullptr; + } + + if (_soundType != 0) { + for (int i = 0; i <= 500; ++i) + _cfiphBuffer[i] = savph[i]; + } + _vm->setPal(_vm->_numpal); +} + +void SoundManager::waitSpeech() { + while (_mixer->isSoundHandleActive(_soundHandle) && !_vm->keyPressed() && !_vm->_mouseClick && !_vm->shouldQuit()) + ; + // In case the handle is still active, stop it. + _mixer->stopHandle(_soundHandle); + + if (!_vm->keyPressed() && !_vm->_mouseClick && !_vm->shouldQuit()) + g_system->delayMillis(600); +} +} // End of namespace Mortevielle diff --git a/engines/mortevielle/sound.h b/engines/mortevielle/sound.h new file mode 100644 index 0000000000..cc0567fd98 --- /dev/null +++ b/engines/mortevielle/sound.h @@ -0,0 +1,106 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#ifndef MORTEVIELLE_SOUND_H +#define MORTEVIELLE_SOUND_H + +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "common/mutex.h" +#include "common/queue.h" + +namespace Mortevielle { +class MortevielleEngine; + +const int kNullValue = 255; +const int kTempoMusic = 71; +const int kTempoNoise = 78; +const int kTempoF = 80; +const int kTempoM = 89; + +struct SpeechQueue { + int _val; + int _code; + int _acc; + int _freq; + int _rep; +}; + +typedef int tablint[256]; + +class SoundManager { +private: + MortevielleEngine *_vm; + + byte *_ambiantNoiseBuf; + byte *_noiseBuf; + int _phonemeNumb; + int _soundType; + SpeechQueue _queue[3]; + byte _wordBuf[1712]; + byte _troctBuf[10576]; + bool _buildingSentence; + int _ptr_oct; + int _tbi[256]; + + Audio::QueuingAudioStream *_audioStream; + + void loadPhonemeSounds(); + void moveQueue(); + void initQueue(); + void handlePhoneme(); + + void spfrac(int wor); + void charg_car(int &currWordNumb); + void entroct(byte o); + void cctable(tablint &t); + void trait_car(); + + void regenbruit(); + void litph(tablint &t, int typ, int tempo); + +public: + SoundManager(Audio::Mixer *mixer); + ~SoundManager(); + + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + uint16 *_cfiphBuffer; + + void setParent(MortevielleEngine *vm); + + int decodeMusic(const byte *PSrc, byte *PDest, int size); + void playSong(const byte *buf, uint usize, uint loops); + void loadAmbiantSounds(); + void loadNoise(); + void startSpeech(int rep, int ht, int typ); + void waitSpeech(); +}; + +} // End of namespace Mortevielle + +#endif diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp new file mode 100644 index 0000000000..f138dde5c5 --- /dev/null +++ b/engines/mortevielle/utils.cpp @@ -0,0 +1,3379 @@ +/* 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. + * + */ + +/* + * This code is based on original Mortville Manor DOS source code + * Copyright (c) 1987-1989 Lankhor + */ + +#include "mortevielle/mortevielle.h" + +#include "mortevielle/dialogs.h" +#include "mortevielle/menu.h" +#include "mortevielle/mouse.h" +#include "mortevielle/outtext.h" + +#include "common/scummsys.h" +#include "graphics/cursorman.h" + +namespace Mortevielle { + +/** + * Check is a key was pressed + * It also delays the engine and check if the screen has to be updated + * @remarks Originally called 'keypressed' + */ +bool MortevielleEngine::keyPressed() { + // Check for any pending key presses + handleEvents(); + + // Check if it's time to draw the next frame + if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) { + _lastGameFrame = g_system->getMillis(); + + _screenSurface.updateScreen(); + + _debugger.onFrame(); + } + + // Delay briefly to keep CPU usage down + g_system->delayMillis(5); + + // Return if there are any pending key presses + return !_keypresses.empty(); +} + +/** + * Wait for a keypress + * @remarks Originally called 'get_ch' + */ +int MortevielleEngine::getChar() { + // If there isn't any pending keypress, wait until there is + while (!shouldQuit() && _keypresses.empty()) { + keyPressed(); + } + + // Return the top keypress + return shouldQuit() ? 0 : _keypresses.pop(); +} + +/** + * Handle pending events + * @remarks Since the ScummVM screen surface is double height to handle 640x200 using 640x400, + * the mouse Y position is divided by 2 to keep the game thinking the Y goes from 0 - 199 + */ +bool MortevielleEngine::handleEvents() { + Common::Event event; + if (!g_system->getEventManager()->pollEvent(event)) + return false; + + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_MOUSEMOVE: + _mousePos = Common::Point(event.mouse.x, event.mouse.y / 2); + _mouse._pos.x = event.mouse.x; + _mouse._pos.y = event.mouse.y / 2; + + if (event.type == Common::EVENT_LBUTTONDOWN) + _mouseClick = true; + else if (event.type == Common::EVENT_LBUTTONUP) + _mouseClick = false; + + break; + case Common::EVENT_KEYDOWN: + addKeypress(event); + break; + default: + break; + } + + return true; +} + +/** + * Add the specified key to the pending keypress stack + */ +void MortevielleEngine::addKeypress(Common::Event &evt) { + // Character to add + char ch = evt.kbd.ascii; + + // Check for debugger + if ((evt.kbd.keycode == Common::KEYCODE_d) && (evt.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _debugger.attach(); + _debugger.onFrame(); + } else if ((evt.kbd.keycode >= Common::KEYCODE_a) && (evt.kbd.keycode <= Common::KEYCODE_z)) { + // Handle alphabetic keys + if (evt.kbd.hasFlags(Common::KBD_CTRL)) + ch = evt.kbd.keycode - Common::KEYCODE_a + 1; + else + ch = evt.kbd.keycode - Common::KEYCODE_a + 'A'; + } else if ((evt.kbd.keycode >= Common::KEYCODE_F1) && (evt.kbd.keycode <= Common::KEYCODE_F12)) { + // Handle function keys + ch = 59 + evt.kbd.keycode - Common::KEYCODE_F1; + } else { + // Series of special cases + switch (evt.kbd.keycode) { + case Common::KEYCODE_KP4: + case Common::KEYCODE_LEFT: + ch = '4'; + break; + case Common::KEYCODE_KP2: + case Common::KEYCODE_DOWN: + ch = '2'; + break; + case Common::KEYCODE_KP6: + case Common::KEYCODE_RIGHT: + ch = '6'; + break; + case Common::KEYCODE_KP8: + case Common::KEYCODE_UP: + ch = '8'; + break; + case Common::KEYCODE_KP7: + ch = '7'; + break; + case Common::KEYCODE_KP1: + ch = '1'; + break; + case Common::KEYCODE_KP9: + ch = '9'; + break; + case Common::KEYCODE_KP3: + ch = '3'; + break; + case Common::KEYCODE_KP5: + ch = '5'; + break; + case Common::KEYCODE_RETURN: + ch = '\13'; + break; + case Common::KEYCODE_ESCAPE: + ch = '\33'; + break; + default: + break; + } + } + + if (ch != 0) + _keypresses.push(ch); +} + + +static const byte CURSOR_ARROW_DATA[16 * 16] = { + 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +/** + * Initialize the mouse + */ +void MortevielleEngine::initMouse() { + CursorMan.replaceCursor(CURSOR_ARROW_DATA, 16, 16, 0, 0, 0xff); + CursorMan.showMouse(true); + + _mouse.initMouse(); +} + +/** + * Sets the mouse position + * @remarks Since the ScummVM screen surface is double height to handle 640x200 using 640x400, + * the mouse Y position is doubled to convert from 0-199 to 0-399 + */ +void MortevielleEngine::setMousePos(const Common::Point &pt) { + // Adjust the passed position from simulated 640x200 to 640x400 co-ordinates + Common::Point newPoint(pt.x, (pt.y == 199) ? 399 : pt.y * 2); + + if (newPoint != _mousePos) + // Warp the mouse to the new position + g_system->warpMouse(newPoint.x, newPoint.y); + + // Save the new position + _mousePos = newPoint; +} + +/** + * Delay by a given amount + */ +void MortevielleEngine::delay(int amount) { + uint32 endTime = g_system->getMillis() + amount; + + while (g_system->getMillis() < endTime) { + if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) { + _lastGameFrame = g_system->getMillis(); + _screenSurface.updateScreen(); + + _debugger.onFrame(); + } + + g_system->delayMillis(10); + } +} + +/** + * Waits for the user to select an action, and then handles it + * @remarks Originally called tecran + */ +void MortevielleEngine::handleAction() { + const int lim = 20000; + int temps = 0; + char inkey = '\0'; + bool funct = false; + + clearVerbBar(); + + bool handledOpcodeFl = false; + _controlMenu = 0; + if (!_keyPressedEsc) { + _menu.drawMenu(); + _menu._menuDisplayed = true; + temps = 0; + _key = 0; + funct = false; + inkey = '.'; + + _inMainGameLoop = true; + do { + _menu.updateMenu(); + prepareRoom(); + _mouse.moveMouse(funct, inkey); + if (shouldQuit()) + return; + ++temps; + if (keyPressed() || _mouseClick) { + _soundManager._mixer->stopHandle(_soundManager._soundHandle); + } + } while (!((_menu._menuSelected) || (temps > lim) || (funct) || (_anyone))); + _inMainGameLoop = false; + + _menu.eraseMenu(); + _menu._menuDisplayed = false; + if (_menu._menuSelected && (_currMenu == MENU_SAVE)) { + Common::String saveName = Common::String::format("Savegame #%d", _currAction & 15); + _savegameManager.saveGame(_currAction & 15, saveName); + } + if (_menu._menuSelected && (_currMenu == MENU_LOAD)) + _savegameManager.loadGame((_currAction & 15) - 1); + if (inkey == '\103') { /* F9 */ + temps = _dialogManager.show(_hintPctMessage, 1); + return; + } else if (inkey == '\77') { + if ((_menuOpcode != OPCODE_NONE) && ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF))) { + _currAction = _menuOpcode; + displayTextInVerbBar(getEngineString(S_IDEM)); + } else + return; + } else if (inkey == '\104') { + if ((_x != 0) && (_y != 0)) + _num = 9999; + return; + } + } + if (inkey == '\73') { + _quitGame = true; + hourToChar(); + } else { + if ((funct) && (inkey != '\77')) + return; + if (temps > lim) { + handleDescriptionText(2, 141); + if (_num == 9999) + _num = 0; + } else { + _menuOpcode = _currMenu; + if ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF)) + _menuOpcode = _currAction; + if (!_anyone) { + if ((_heroSearching) || (_obpart)) { + if (_mouse._pos.y < 12) + return; + + if ((_currAction == _menu._opcodeSound) || (_currAction == _menu._opcodeLift)) { + handledOpcodeFl = true; + if ((_currAction == _menu._opcodeLift) || (_obpart)) { + endSearch(); + _caff = _coreVar._currPlace; + _crep = 998; + } else + prepareNextObject(); + menuUp(); + } + } + } + do { + if (!handledOpcodeFl) + handleOpcode(); + + if ((_controlMenu == 0) && (! _loseGame) && (! _endGame)) { + _text.taffich(); + if (_destinationOk) { + _destinationOk = false; + drawPicture(); + } + if ((!_syn) || (_col)) + handleDescriptionText(2, _crep); + } + } while (_syn); + if (_controlMenu != 0) + displayControlMenu(); + } + } +} + +/** + * Engine function - Init Places + * @remarks Originally called 'init_lieu' + */ +void MortevielleEngine::loadPlaces() { + Common::File f; + + if (!f.open("MXX.mor")) + if (!f.open("MFXX.mor")) + error("Missing file - MXX.mor"); + + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 25; ++j) + _destinationArray[i][j] = f.readByte(); + } + + f.close(); +} + +/** + * Set Text Color + * @remarks Originally called 'text_color' + */ +void MortevielleEngine::setTextColor(int col) { + _textColor = col; +} + +/** + * Prepare screen - Type 1! + * @remarks Originally called 'ecrf1' + */ +void MortevielleEngine::prepareScreenType1() { + // Large drawing + _screenSurface.drawBox(0, 11, 512, 164, 15); +} + +/** + * Prepare room - Type 2! + * @remarks Originally called 'ecrf2' + */ +void MortevielleEngine::prepareScreenType2() { + setTextColor(5); +} + +/** + * Prepare room - Type 3! + * @remarks Originally called 'ecrf7' + */ +void MortevielleEngine::prepareScreenType3() { + setTextColor(4); +} + +/** + * Engine function - Update hour + * @remarks Originally called 'calch' + */ +void MortevielleEngine::updateHour(int &day, int &hour, int &minute) { + int newHour = readclock(); + int th = _currentHourCount + ((newHour - _currentDayHour) / _inGameHourDuration); + minute = ((th % 2) + _currHalfHour) * 30; + hour = ((uint)th >> 1) + _currHour; + if (minute == 60) { + minute = 0; + ++hour; + } + day = (hour / 24) + _currDay; + hour = hour - ((day - _currDay) * 24); +} + +/** + * Engine function - Convert character index to bit index + * @remarks Originally called 'conv' + */ +int MortevielleEngine::convertCharacterIndexToBitIndex(int characterIndex) { + return 128 >> (characterIndex - 1); +} + +/** + * Engine function - Convert bit index to character index + * @remarks Originally called 'tip' + */ +int MortevielleEngine::convertBitIndexToCharacterIndex(int bitIndex) { + int retVal = 0; + + if (bitIndex == 128) + retVal = 1; + else if (bitIndex == 64) + retVal = 2; + else if (bitIndex == 32) + retVal = 3; + else if (bitIndex == 16) + retVal = 4; + else if (bitIndex == 8) + retVal = 5; + else if (bitIndex == 4) + retVal = 6; + else if (bitIndex == 2) + retVal = 7; + else if (bitIndex == 1) + retVal = 8; + + return retVal; +} + +/** + * Engine function - Reset presence in other rooms + * @remarks Originally called 't5' + */ +void MortevielleEngine::resetPresenceInRooms(int roomId) { + if (roomId == DINING_ROOM) + _blo = false; + + if (roomId != GREEN_ROOM) { + _roomPresenceLuc = false; + _roomPresenceIda = false; + } + + if (roomId != PURPLE_ROOM) + _purpleRoomPresenceLeo = false; + + if (roomId != DARKBLUE_ROOM) { + _roomPresenceGuy = false; + _roomPresenceEva = false; + } + + if (roomId != BLUE_ROOM) + _roomPresenceMax = false; + if (roomId != RED_ROOM) + _roomPresenceBob = false; + if (roomId != GREEN_ROOM2) + _roomPresencePat = false; + if (roomId != TOILETS) + _toiletsPresenceBobMax = false; + if (roomId != BATHROOM) + _bathRoomPresenceBobMax = false; + if (roomId != JULIA_ROOM) + _juliaRoomPresenceLeo = false; +} + +/** + * Engine function - Show the people present in the given room + * @remarks Originally called 'affper' + */ +void MortevielleEngine::showPeoplePresent(int bitIndex) { + int xp = 580 - (_screenSurface.getStringWidth("LEO") / 2); + + for (int i = 1; i <= 8; ++i) + _menu.disableMenuItem(_menu._discussMenu[i]); + + clearUpperRightPart(); + if ((bitIndex & 128) == 128) { + _screenSurface.putxy(xp, 24); + _screenSurface.drawString("LEO", 4); + _menu.enableMenuItem(_menu._discussMenu[1]); + } + if ((bitIndex & 64) == 64) { + _screenSurface.putxy(xp, 32); + _screenSurface.drawString("PAT", 4); + _menu.enableMenuItem(_menu._discussMenu[2]); + } + if ((bitIndex & 32) == 32) { + _screenSurface.putxy(xp, 40); + _screenSurface.drawString("GUY", 4); + _menu.enableMenuItem(_menu._discussMenu[3]); + } + if ((bitIndex & 16) == 16) { + _screenSurface.putxy(xp, 48); + _screenSurface.drawString("EVA", 4); + _menu.enableMenuItem(_menu._discussMenu[4]); + } + if ((bitIndex & 8) == 8) { + _screenSurface.putxy(xp, 56); + _screenSurface.drawString("BOB", 4); + _menu.enableMenuItem(_menu._discussMenu[5]); + } + if ((bitIndex & 4) == 4) { + _screenSurface.putxy(xp, 64); + _screenSurface.drawString("LUC", 4); + _menu.enableMenuItem(_menu._discussMenu[6]); + } + if ((bitIndex & 2) == 2) { + _screenSurface.putxy(xp, 72); + _screenSurface.drawString("IDA", 4); + _menu.enableMenuItem(_menu._discussMenu[7]); + } + if ((bitIndex & 1) == 1) { + _screenSurface.putxy(xp, 80); + _screenSurface.drawString("MAX", 4); + _menu.enableMenuItem(_menu._discussMenu[8]); + } + _currBitIndex = bitIndex; +} + +/** + * Engine function - Select random characters + * @remarks Originally called 'choix' + */ +int MortevielleEngine::selectCharacters(int min, int max) { + bool invertSelection = false; + int rand = getRandomNumber(min, max); + + if (rand > 4) { + rand = 8 - rand; + invertSelection = true; + } + + int i = 0; + int retVal = 0; + while (i < rand) { + int charIndex = getRandomNumber(1, 8); + int charBitIndex = convertCharacterIndexToBitIndex(charIndex); + if ((retVal & charBitIndex) != charBitIndex) { + ++i; + retVal |= charBitIndex; + } + } + if (invertSelection) + retVal = 255 - retVal; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Green Room + * @remarks Originally called 'cpl1' + */ +int MortevielleEngine::getPresenceStatsGreenRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + // The original uses an || instead of an &&, resulting + // in an always true condition. Based on the other tests, + // and on other scenes, we use an && instead. + if ((hour > 7) && (hour < 11)) + retVal = 25; + else if ((hour > 10) && (hour < 14)) + retVal = 35; + else if ((hour > 13) && (hour < 16)) + retVal = 50; + else if ((hour > 15) && (hour < 18)) + retVal = 5; + else if ((hour > 17) && (hour < 22)) + retVal = 35; + else if ((hour > 21) && (hour < 24)) + retVal = 50; + else if ((hour >= 0) && (hour < 8)) + retVal = 70; + + _menu.updateMenu(); + + return retVal; +} +/** + * Engine function - Get Presence Statistics - Purple Room + * @remarks Originally called 'cpl2' + */ +int MortevielleEngine::getPresenceStatsPurpleRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if ((hour > 7) && (hour < 11)) + retVal = -2; + else if (hour == 11) + retVal = 100; + else if ((hour > 11) && (hour < 23)) + retVal = 10; + else if (hour == 23) + retVal = 20; + else if ((hour >= 0) && (hour < 8)) + retVal = 50; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Toilets + * @remarks Originally called 'cpl3' + */ +int MortevielleEngine::getPresenceStatsToilets() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 8) && (hour < 10)) || ((hour > 19) && (hour < 24))) + retVal = 34; + else if (((hour > 9) && (hour < 20)) || ((hour >= 0) && (hour < 9))) + retVal = 0; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Blue Room + * @remarks Originally called 'cpl5' + */ +int MortevielleEngine::getPresenceStatsBlueRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if ((hour > 6) && (hour < 10)) + retVal = 0; + else if (hour == 10) + retVal = 100; + else if ((hour > 10) && (hour < 24)) + retVal = 15; + else if ((hour >= 0) && (hour < 7)) + retVal = 50; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Red Room + * @remarks Originally called 'cpl6' + */ +int MortevielleEngine::getPresenceStatsRedRoom() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 7) && (hour < 13)) || ((hour > 17) && (hour < 20))) + retVal = -2; + else if (((hour > 12) && (hour < 17)) || ((hour > 19) && (hour < 24))) + retVal = 35; + else if (hour == 17) + retVal = 100; + else if ((hour >= 0) && (hour < 8)) + retVal = 60; + + return retVal; +} + +/** + * Shows the "you are alone" message in the status area + * on the right hand side of the screen + * @remarks Originally called 'person' + */ +void MortevielleEngine::displayAloneText() { + for (int i = 1; i <= 8; ++i) + _menu.disableMenuItem(_menu._discussMenu[i]); + + Common::String sYou = getEngineString(S_YOU); + Common::String sAre = getEngineString(S_ARE); + Common::String sAlone = getEngineString(S_ALONE); + + clearUpperRightPart(); + _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sYou) / 2), 30); + _screenSurface.drawString(sYou, 4); + _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sAre) / 2), 50); + _screenSurface.drawString(sAre, 4); + _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sAlone) / 2), 70); + _screenSurface.drawString(sAlone, 4); + + _currBitIndex = 0; +} + +/** + * Engine function - Get Presence Statistics - Room Bureau + * @remarks Originally called 'cpl10' + */ +int MortevielleEngine::getPresenceStatsDiningRoom(int &hour) { + int day, minute; + + int retVal = 0; + updateHour(day, hour, minute); + if (((hour > 7) && (hour < 11)) || ((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) + retVal = 100; + else if ((hour == 11) || ((hour > 20) && (hour < 24))) + retVal = 45; + else if (((hour > 13) && (hour < 17)) || (hour == 18)) + retVal = 35; + else if (hour == 17) + retVal = 60; + else if ((hour >= 0) && (hour < 8)) + retVal = 5; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Bureau + * @remarks Originally called 'cpl11' + */ +int MortevielleEngine::getPresenceStatsBureau(int &hour) { + int day, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 8) && (hour < 12)) || ((hour > 20) && (hour < 24))) + retVal = 25; + else if (((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) + retVal = 5; + else if ((hour > 13) && (hour < 17)) + retVal = 55; + else if ((hour > 16) && (hour < 19)) + retVal = 45; + else if ((hour >= 0) && (hour < 9)) + retVal = 0; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Kitchen + * @remarks Originally called 'cpl12' + */ +int MortevielleEngine::getPresenceStatsKitchen() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (((hour > 8) && (hour < 15)) || ((hour > 16) && (hour < 22))) + retVal = 55; + else if (((hour > 14) && (hour < 17)) || ((hour > 21) && (hour < 24))) + retVal = 25; + else if ((hour >= 0) && (hour < 5)) + retVal = 0; + else if ((hour > 4) && (hour < 9)) + retVal = 15; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Attic + * @remarks Originally called 'cpl13' + */ +int MortevielleEngine::getPresenceStatsAttic() { + return 0; +} + +/** + * Engine function - Get Presence Statistics - Room Landing + * @remarks Originally called 'cpl15' + */ +int MortevielleEngine::getPresenceStatsLanding() { + int day, hour, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if ((hour > 7) && (hour < 12)) + retVal = 25; + else if ((hour > 11) && (hour < 14)) + retVal = 0; + else if ((hour > 13) && (hour < 18)) + retVal = 10; + else if ((hour > 17) && (hour < 20)) + retVal = 55; + else if ((hour > 19) && (hour < 22)) + retVal = 5; + else if ((hour > 21) && (hour < 24)) + retVal = 15; + else if ((hour >= 0) && (hour < 8)) + retVal = -15; + + return retVal; +} + +/** + * Engine function - Get Presence Statistics - Room Chapel + * @remarks Originally called 'cpl20' + */ +int MortevielleEngine::getPresenceStatsChapel(int &hour) { + int day, minute; + int retVal = 0; + + updateHour(day, hour, minute); + if (hour == 10) + retVal = 65; + else if ((hour > 10) && (hour < 21)) + retVal = 5; + else if ((hour > 20) && (hour < 24)) + retVal = -15; + else if ((hour >= 0) && (hour < 5)) + retVal = -300; + else if ((hour > 4) && (hour < 10)) + retVal = -5; + + return retVal; +} + +/** + * Engine function - Check who is in the Green Room + * @remarks Originally called 'quelq1' + */ +void MortevielleEngine::setPresenceGreenRoom(int roomId) { + int rand = getRandomNumber(1, 2); + if (roomId == GREEN_ROOM) { + if (rand == 1) + _roomPresenceLuc = true; + else + _roomPresenceIda = true; + } else if (roomId == DARKBLUE_ROOM) { + if (rand == 1) + _roomPresenceGuy = true; + else + _roomPresenceEva = true; + } + + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Purple Room + * @remarks Originally called 'quelq2' + */ +void MortevielleEngine::setPresencePurpleRoom() { + if (_place == PURPLE_ROOM) + _purpleRoomPresenceLeo = true; + else + _juliaRoomPresenceLeo = true; + + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Blue Room + * @remarks Originally called 'quelq5' + */ +void MortevielleEngine::setPresenceBlueRoom() { + _roomPresenceMax = true; + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Red Room + * @remarks Originally called 'quelq6' + */ +void MortevielleEngine::setPresenceRedRoom(int roomId) { + if (roomId == RED_ROOM) + _roomPresenceBob = true; + else if (roomId == GREEN_ROOM2) + _roomPresencePat = true; + + _currBitIndex = 10; +} + +/** + * Engine function - Check who is in the Dining Room + * @remarks Originally called 'quelq10' + */ +int MortevielleEngine::setPresenceDiningRoom(int hour) { + int retVal = 0; + + if ((hour >= 0) && (hour < 8)) + retVal = checkLeoMaxRandomPresence(); + else { + int min = 0, max = 0; + if ((hour > 7) && (hour < 10)) { + min = 5; + max = 7; + } else if ((hour > 9) && (hour < 12)) { + min = 1; + max = 4; + } else if (((hour > 11) && (hour < 15)) || ((hour > 18) && (hour < 21))) { + min = 6; + max = 8; + } else if (((hour > 14) && (hour < 19)) || ((hour > 20) && (hour < 24))) { + min = 1; + max = 5; + } + retVal = selectCharacters(min, max); + } + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the Bureau + * @remarks Originally called 'quelq11' + */ +int MortevielleEngine::setPresenceBureau(int hour) { + int retVal = 0; + + if ((hour >= 0) && (hour < 8)) + retVal = checkLeoMaxRandomPresence(); + else { + int min = 0, max = 0; + if (((hour > 7) && (hour < 10)) || ((hour > 20) && (hour < 24))) { + min = 1; + max = 3; + } else if (((hour > 9) && (hour < 12)) || ((hour > 13) && (hour < 19))) { + min = 1; + max = 4; + } else if (((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) { + min = 1; + max = 2; + } + retVal = selectCharacters(min, max); + } + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the Kitchen + * @remarks Originally called 'quelq12' + */ +int MortevielleEngine::setPresenceKitchen() { + int retVal = checkLeoMaxRandomPresence(); + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the Landing + * @remarks Originally called 'quelq15' + */ +int MortevielleEngine::setPresenceLanding() { + bool test = false; + int rand = 0; + do { + rand = getRandomNumber(1, 8); + test = (((rand == 1) && (_purpleRoomPresenceLeo || _juliaRoomPresenceLeo)) || + ((rand == 2) && _roomPresencePat) || + ((rand == 3) && _roomPresenceGuy) || + ((rand == 4) && _roomPresenceEva) || + ((rand == 5) && _roomPresenceBob) || + ((rand == 6) && _roomPresenceLuc) || + ((rand == 7) && _roomPresenceIda) || + ((rand == 8) && _roomPresenceMax)); + } while (test); + + int retVal = convertCharacterIndexToBitIndex(rand); + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Check who is in the chapel + * @remarks Originally called 'quelq20' + */ +int MortevielleEngine::setPresenceChapel(int hour) { + int retVal = 0; + + if (((hour >= 0) && (hour < 10)) || ((hour > 18) && (hour < 24))) + retVal = checkLeoMaxRandomPresence(); + else { + int min = 0, max = 0; + if ((hour > 9) && (hour < 12)) { + min = 3; + max = 7; + } else if ((hour > 11) && (hour < 18)) { + min = 1; + max = 2; + } else if (hour == 18) { + min = 2; + max = 4; + } + retVal = selectCharacters(min, max); + } + showPeoplePresent(retVal); + + return retVal; +} + +/** + * Engine function - Get the answer after you known a door + * @remarks Originally called 'frap' + */ +void MortevielleEngine::getKnockAnswer() { + int day, hour, minute; + + updateHour(day, hour, minute); + if ((hour >= 0) && (hour < 8)) + _crep = 190; + else { + if (getRandomNumber(1, 100) > 70) + _crep = 190; + else + _crep = 147; + } +} + +/** + * Engine function - Get Room Presence Bit Index + * @remarks Originally called 'nouvp' + */ +int MortevielleEngine::getPresenceBitIndex(int roomId) { + int bitIndex = 0; + if (roomId == GREEN_ROOM) { + if (_roomPresenceLuc) + bitIndex = 4; // LUC + if (_roomPresenceIda) + bitIndex = 2; // IDA + } else if ( ((roomId == PURPLE_ROOM) && (_purpleRoomPresenceLeo)) + || ((roomId == JULIA_ROOM) && (_juliaRoomPresenceLeo))) + bitIndex = 128; // LEO + else if (roomId == DARKBLUE_ROOM) { + if (_roomPresenceGuy) + bitIndex = 32; // GUY + if (_roomPresenceEva) + bitIndex = 16; // EVA + } else if ((roomId == BLUE_ROOM) && (_roomPresenceMax)) + bitIndex = 1; // MAX + else if ((roomId == RED_ROOM) && (_roomPresenceBob)) + bitIndex = 8; // BOB + else if ((roomId == GREEN_ROOM2) && (_roomPresencePat)) + bitIndex = 64; // PAT + else if ( ((roomId == TOILETS) && (_toiletsPresenceBobMax)) + || ((roomId == BATHROOM) && (_bathRoomPresenceBobMax)) ) + bitIndex = 9; // BOB + MAX + + if (bitIndex != 9) + showPeoplePresent(bitIndex); + + return bitIndex; +} + +/** + * Engine function - initGame + * @remarks Originally called 'dprog' + */ +void MortevielleEngine::initGame() { + _place = MANOR_FRONT; + _currentHourCount = 0; + if (!_coreVar._alreadyEnteredManor) + _blo = true; + _inGameHourDuration = kTime1; + _currentDayHour = readclock(); +} + +/** + * Engine function - Set Random Presence - Green Room + * @remarks Originally called 'pl1' + */ +void MortevielleEngine::setRandomPresenceGreenRoom(int faithScore) { + if ( ((_place == GREEN_ROOM) && (!_roomPresenceLuc) && (!_roomPresenceIda)) + || ((_place == DARKBLUE_ROOM) && (!_roomPresenceGuy) && (!_roomPresenceEva)) ) { + int p = getPresenceStatsGreenRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceGreenRoom(_place); + } +} + +/** + * Engine function - Set Random Presence - Purple Room + * @remarks Originally called 'pl2' + */ +void MortevielleEngine::setRandomPresencePurpleRoom(int faithScore) { + if (!_purpleRoomPresenceLeo) { + int p = getPresenceStatsPurpleRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresencePurpleRoom(); + } +} + +/** + * Engine function - Set Random Presence - Blue Room + * @remarks Originally called 'pl5' + */ +void MortevielleEngine::setRandomPresenceBlueRoom(int faithScore) { + if (!_roomPresenceMax) { + int p = getPresenceStatsBlueRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceBlueRoom(); + } +} + +/** + * Engine function - Set Random Presence - Red Room + * @remarks Originally called 'pl6' + */ +void MortevielleEngine::setRandomPresenceRedRoom(int faithScore) { + if ( ((_place == RED_ROOM) && (!_roomPresenceBob)) + || ((_place == GREEN_ROOM2) && (!_roomPresencePat)) ) { + int p = getPresenceStatsRedRoom(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceRedRoom(_place); + } +} + +/** + * Engine function - Set Random Presence - Room 9 + * @remarks Originally called 'pl9' + */ +void MortevielleEngine::setRandomPresenceJuliaRoom(int faithScore) { + if (!_juliaRoomPresenceLeo) { + faithScore = -10; + if (getRandomNumber(1, 100) > faithScore) // always true? + displayAloneText(); + else + setPresencePurpleRoom(); + } +} + +/** + * Engine function - Set Random Presence - Dining Room + * @remarks Originally called 'pl10' + */ +void MortevielleEngine::setRandomPresenceDiningRoom(int faithScore) { + int h; + int p = getPresenceStatsDiningRoom(h); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceDiningRoom(h); +} + +/** + * Engine function - Set Random Presence - Bureau + * @remarks Originally called 'pl11' + */ +void MortevielleEngine::setRandomPresenceBureau(int faithScore) { + int h; + + int p = getPresenceStatsBureau(h); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceBureau(h); +} + +/** + * Engine function - Set Random Presence - Kitchen + * @remarks Originally called 'pl12' + */ +void MortevielleEngine::setRandomPresenceKitchen(int faithScore) { + + int p = getPresenceStatsKitchen(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceKitchen(); +} + +/** + * Engine function - Set Random Presence - Attic / Cellar + * @remarks Originally called 'pl13' + */ +void MortevielleEngine::setRandomPresenceAttic(int faithScore) { + int p = getPresenceStatsAttic(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceKitchen(); +} + +/** + * Engine function - Set Random Presence - Landing + * @remarks Originally called 'pl15' + */ +void MortevielleEngine::setRandomPresenceLanding(int faithScore) { + int p = getPresenceStatsLanding(); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceLanding(); +} + +/** + * Engine function - Set Random Presence - Chapel + * @remarks Originally called 'pl20' + */ +void MortevielleEngine::setRandomPresenceChapel(int faithScore) { + int h; + + int p = getPresenceStatsChapel(h); + p += faithScore; + if (getRandomNumber(1, 100) > p) + displayAloneText(); + else + setPresenceChapel(h); +} + +/** + * Start music or speech + * @remarks Originally called 'musique' + */ +void MortevielleEngine::startMusicOrSpeech(int so) { + if (so == 0) { + /* musik(0) */ + ; + } else if ((!_introSpeechPlayed) && (!_coreVar._alreadyEnteredManor)) { + // Type 1: Speech + _soundManager.startSpeech(10, 1, 1); + _introSpeechPlayed = true; + } else { + if (((_coreVar._currPlace == MOUNTAIN) || (_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK)) && (getRandomNumber(1, 3) == 2)) + // Type 1: Speech + _soundManager.startSpeech(9, getRandomNumber(2, 4), 1); + else if ((_coreVar._currPlace == CHAPEL) && (getRandomNumber(1, 2) == 1)) + // Type 1: Speech + _soundManager.startSpeech(8, 1, 1); + else if ((_coreVar._currPlace == WELL) && (getRandomNumber(1, 2) == 2)) + // Type 1: Speech + _soundManager.startSpeech(12, 1, 1); + else if (_coreVar._currPlace == INSIDE_WELL) + // Type 1: Speech + _soundManager.startSpeech(13, 1, 1); + else + // Type 2 : music + _soundManager.startSpeech(getRandomNumber(1, 17), 1, 2); + } +} + +/** + * Engine function - You lose! + * @remarks Originally called 'tperd' + */ +void MortevielleEngine::loseGame() { + resetOpenObjects(); + _roomDoorId = OWN_ROOM; + _curSearchObjId = 0; + _menu.unsetSearchMenu(); + if (!_blo) + getPresence(MANOR_FRONT); + + _loseGame = true; + clearUpperLeftPart(); + _screenSurface.drawBox(60, 35, 400, 50, 15); + handleDescriptionText(9, _crep); + clearDescriptionBar(); + clearVerbBar(); + _col = false; + _syn = false; + _destinationOk = false; +} + +/** + * Engine function - Check inventory for a given object + * @remarks Originally called 'cherjer' + */ +bool MortevielleEngine::checkInventory(int objectId) { + bool retVal = false; + for (int i = 1; i <= 6; ++i) + retVal = (retVal || (_coreVar._inventory[i] == objectId)); + + if (_coreVar._selectedObjectId == objectId) + retVal = true; + + return retVal; +} + +/** + * Engine function - Display Dining Room + * @remarks Originally called 'st1sama' + */ +void MortevielleEngine::displayDiningRoom() { + _coreVar._currPlace = DINING_ROOM; + prepareDisplayText(); +} + +/** + * Engine function - Start non interactive Dialog + * @remarks Originally called 'sparl' + */ +void MortevielleEngine::startDialog(int16 rep) { + const int haut[9] = { 0, 0, 1, -3, 6, -2, 2, 7, -1 }; + int key; + + assert(rep >= 0); + + _mouse.hideMouse(); + Common::String dialogStr = getString(rep + kDialogStringIndex); + _text.displayStr(dialogStr, 230, 4, 65, 24, 5); + _dialogManager.drawF3F8(); + + key = 0; + do { + _soundManager.startSpeech(rep, haut[_caff - 69], 0); + key = _dialogManager.waitForF3F8(); + if (shouldQuit()) + return; + } while (key != 66); + clearScreen(); + _mouse.showMouse(); +} + +/** + * Engine function - End of Search: reset globals + * @remarks Originally called 'finfouill' + */ +void MortevielleEngine::endSearch() { + _heroSearching = false; + _obpart = false; + _searchCount = 0; + _menu.unsetSearchMenu(); +} + +/** + * Engine function - Go to Dining room + * @remarks Originally called 't1sama' + */ +void MortevielleEngine::gotoDiningRoom() { + int day, hour, minute; + + updateHour(day, hour, minute); + if ((hour < 5) && (_coreVar._currPlace > ROOM18)) { + if (!checkInventory(137)) { //You don't have the keys, and it's late + _crep = 1511; + loseGame(); + } else + displayDiningRoom(); + } else if (!_coreVar._alreadyEnteredManor) { //Is it your first time? + _currBitIndex = 255; // Everybody is present + showPeoplePresent(_currBitIndex); + _caff = 77; + drawPictureWithText(); + _screenSurface.drawBox(223, 47, 155, 92, 15); + handleDescriptionText(2, 33); + testKey(false); + menuUp(); + _mouse.hideMouse(); + clearScreen(); + drawDiscussionBox(); + startDialog(140); + drawRightFrame(); + drawClock(); + _mouse.showMouse(); + _coreVar._currPlace = OWN_ROOM; + prepareDisplayText(); + resetPresenceInRooms(DINING_ROOM); + if (!_blo) + getPresence(OWN_ROOM); + _currBitIndex = 0; + _savedBitIndex = 0; + _coreVar._alreadyEnteredManor = true; + } else + displayDiningRoom(); +} + +/** + * Engine function - Check Manor distance (in the mountains) + * @remarks Originally called 't1neig' + */ +void MortevielleEngine::checkManorDistance() { + ++_manorDistance; + if (_manorDistance > 2) { + _crep = 1506; + loseGame(); + } else { + _destinationOk = true; + _coreVar._currPlace = MOUNTAIN; + prepareDisplayText(); + } +} + +/** + * Engine function - Go to Manor front + * @remarks Originally called 't1deva' + */ +void MortevielleEngine::gotoManorFront() { + _manorDistance = 0; + _coreVar._currPlace = MANOR_FRONT; + prepareDisplayText(); +} + +/** + * Engine function - Go to Manor back + * @remarks Originally called 't1derr' + */ +void MortevielleEngine::gotoManorBack() { + _coreVar._currPlace = MANOR_BACK; + prepareDisplayText(); +} + +/** + * Engine function - Dead : Flooded in Well + * @remarks Originally called 't1deau' + */ +void MortevielleEngine::floodedInWell() { + _crep = 1503; + loseGame(); +} + +/** + * Called when a savegame has been loaded. + * @remarks Originally called 'antegame' + */ +void MortevielleEngine::gameLoaded() { + _mouse.hideMouse(); + _menu._menuDisplayed = false; + _loseGame = true; + _anyone = false; + _destinationOk = true; + _col = false; + _hiddenHero = false; + _uptodatePresence = false; + _maff = 68; + _menuOpcode = OPCODE_NONE; + _introSpeechPlayed = false; + _x = 0; + _y = 0; + _num = 0; + _startHour = 0; + _endHour = 0; + _searchCount = 0; + _roomDoorId = OWN_ROOM; + _syn = true; + _heroSearching = true; + _curSearchObjId = 0; + _manorDistance = 0; + resetOpenObjects(); + _takeObjCount = 0; + prepareDisplayText(); + _hintPctMessage = getString(580); + + _destinationOk = false; + _endGame = true; + _loseGame = false; + _heroSearching = false; + + displayAloneText(); + prepareRoom(); + drawClock(); + drawPictureWithText(); + handleDescriptionText(2, _crep); + clearVerbBar(); + _endGame = false; + _menu.setDestinationText(_coreVar._currPlace); + _menu.setInventoryText(); + if (_coreVar._selectedObjectId != 0) + displayItemInHand(_coreVar._selectedObjectId + 400); + _mouse.showMouse(); +} + +/** + * Engine function - Handle OpCodes + * @remarks Originally called 'tsitu' + */ +void MortevielleEngine::handleOpcode() { + if (!_col) + clearDescriptionBar(); + _syn = false; + _keyPressedEsc = false; + if (!_anyone) { + if (_uptodatePresence) { + if ((_currMenu == MENU_MOVE) || (_currAction == _menu._opcodeLeave) || (_currAction == _menu._opcodeSleep) || (_currAction == _menu._opcodeEat)) { + _controlMenu = 4; + menuUp(); + return; + } + } + + if (_currMenu == MENU_MOVE) + fctMove(); + else if (_currMenu == MENU_DISCUSS) + fctDiscuss(); + else if (_currMenu == MENU_INVENTORY) + fctInventoryTake(); + else if (_currAction == _menu._opcodeAttach) + fctAttach(); + else if (_currAction == _menu._opcodeWait) + fctWait(); + else if (_currAction == _menu._opcodeForce) + fctForce(); + else if (_currAction == _menu._opcodeSleep) + fctSleep(); + else if (_currAction == _menu._opcodeListen) + fctListen(); + else if (_currAction == _menu._opcodeEnter) + fctEnter(); + else if (_currAction == _menu._opcodeClose) + fctClose(); + else if (_currAction == _menu._opcodeSearch) + fctSearch(); + else if (_currAction == _menu._opcodeKnock) + fctKnock(); + else if (_currAction == _menu._opcodeScratch) + fctScratch(); + else if (_currAction == _menu._opcodeRead) + fctRead(); + else if (_currAction == _menu._opcodeEat) + fctEat(); + else if (_currAction == _menu._opcodePlace) + fctPlace(); + else if (_currAction == _menu._opcodeOpen) + fctOpen(); + else if (_currAction == _menu._opcodeTake) + fctTake(); + else if (_currAction == _menu._opcodeLook) + fctLook(); + else if (_currAction == _menu._opcodeSmell) + fctSmell(); + else if (_currAction == _menu._opcodeSound) + fctSound(); + else if (_currAction == _menu._opcodeLeave) + fctLeave(); + else if (_currAction == _menu._opcodeLift) + fctLift(); + else if (_currAction == _menu._opcodeTurn) + fctTurn(); + else if (_currAction == _menu._opcodeSSearch) + fctSelfSearch(); + else if (_currAction == _menu._opcodeSRead) + fctSelfRead(); + else if (_currAction == _menu._opcodeSPut) + fctSelfPut(); + else if (_currAction == _menu._opcodeSLook) + fctSelftLook(); + + _hiddenHero = false; + + if (_currAction == _menu._opcodeSHide) + fctSelfHide(); + } else if (_anyone) { + interactNPC(); + _anyone = false; + menuUp(); + return; + } + int hour, day, minute; + updateHour(day, hour, minute); + if ((((hour == 12) || (hour == 13) || (hour == 19)) && (_coreVar._currPlace != DINING_ROOM)) || + ((hour > 0) && (hour < 6) && (_coreVar._currPlace != OWN_ROOM))) + ++_coreVar._faithScore; + if (((_coreVar._currPlace < CRYPT) || (_coreVar._currPlace > MOUNTAIN)) && (_coreVar._currPlace != INSIDE_WELL) + && (_coreVar._currPlace != OWN_ROOM) && (_coreVar._selectedObjectId != 152) && (!_loseGame)) { + if ((_coreVar._faithScore > 99) && (hour > 8) && (hour < 16)) { + _crep = 1501; + loseGame(); + } else if ((_coreVar._faithScore > 99) && (hour > 0) && (hour < 9)) { + _crep = 1508; + loseGame(); + } else if ((day > 1) && (hour > 8) && (!_loseGame)) { + _crep = 1502; + loseGame(); + } + } + menuUp(); +} + +/** + * Engine function - Transform time into a char + * @remarks Originally called 'tmaj3' + */ +void MortevielleEngine::hourToChar() { + int day, hour, minute; + + updateHour(day, hour, minute); + if (minute == 30) + minute = 1; + hour += day * 24; + minute += hour * 2; + _coreVar._fullHour = (unsigned char)minute; +} + +/** + * Engine function - extract time from a char + * @remarks Originally called 'theure' + */ +void MortevielleEngine::charToHour() { + int fullHour = _coreVar._fullHour; + int tmpHour = fullHour % 48; + _currDay = fullHour / 48; + _currHalfHour = tmpHour % 2; + _currHour = tmpHour / 2; + _hour = _currHour; + if (_currHalfHour == 1) + _minute = 30; + else + _minute = 0; +} + +/** + * Engine function - Clear upper left part of Screen - Type 1 + * @remarks Originally called 'clsf1' + */ +void MortevielleEngine::clearUpperLeftPart() { + _mouse.hideMouse(); + _screenSurface.fillRect(0, Common::Rect(0, 11, 514, 175)); + _mouse.showMouse(); +} + +/** + * Engine function - Clear low bar used by description + * @remarks Originally called 'clsf2' + */ +void MortevielleEngine::clearDescriptionBar() { + _mouse.hideMouse(); + if (_largestClearScreen) { + _screenSurface.fillRect(0, Common::Rect(1, 176, 633, 199)); + _screenSurface.drawBox(0, 176, 634, 23, 15); + _largestClearScreen = false; + } else { + _screenSurface.fillRect(0, Common::Rect(1, 176, 633, 190)); + _screenSurface.drawBox(0, 176, 634, 14, 15); + } + _mouse.showMouse(); +} + +/** + * Engine function - Clear lowest bar used by verbs + * @remarks Originally called 'clsf3' + */ +void MortevielleEngine::clearVerbBar() { + _mouse.hideMouse(); + _screenSurface.fillRect(0, Common::Rect(1, 192, 633, 199)); + _screenSurface.drawBox(0, 191, 634, 8, 15); + _mouse.showMouse(); +} + +/** + * Engine function - Clear upper right part of the screen + * @remarks Originally called 'clsf10' + */ +void MortevielleEngine::clearUpperRightPart() { + Common::String st; + + _mouse.hideMouse(); + + // Clear ambiance description + _screenSurface.fillRect(15, Common::Rect(544, 93, 600, 98)); + if (_coreVar._faithScore < 33) + st = getEngineString(S_COOL); + else if (_coreVar._faithScore < 66) + st = getEngineString(S_LOURDE); + else if (_coreVar._faithScore > 65) + st = getEngineString(S_MALSAINE); + + int x1 = 580 - (_screenSurface.getStringWidth(st) / 2); + _screenSurface.putxy(x1, 92); + _screenSurface.drawString(st, 4); + + // Clear person list + _screenSurface.fillRect(15, Common::Rect(560, 24, 610, 86)); + _mouse.showMouse(); +} + +/** + * Engine function - Get a random number between two values + * @remarks Originally called 'get_random_number' and 'hazard' + */ +int MortevielleEngine::getRandomNumber(int minval, int maxval) { + return _randomSource.getRandomNumber(maxval - minval) + minval; +} + +/** + * Engine function - Show alert "use move menu" + * @remarks Originally called 'aldepl' + */ +void MortevielleEngine::showMoveMenuAlert() { + _dialogManager.show(getEngineString(S_USE_DEP_MENU), 1); +} + +/** + * The original engine used this method to display a starting text screen letting the player + * select the graphics mode to use + * @remarks Originally called 'dialpre' + */ +void MortevielleEngine::showConfigScreen() { + _crep = 998; +} + +/** + * Decodes a number of 64 byte blocks + * @param pStart Start of data + * @param count Number of 64 byte blocks + * @remarks Originally called 'zzuul' + */ +void MortevielleEngine::decodeNumber(byte *pStart, int count) { + while (count-- > 0) { + for (int idx = 0; idx < 64; ++pStart, ++idx) { + uint16 v = ((*pStart - 0x80) << 1) + 0x80; + + if (v & 0x8000) + *pStart = 0; + else if (v & 0xff00) + *pStart = 0xff; + else + *pStart = (byte)v; + } + } +} + +const byte cryptoArrDefaultFr[32] = { + 32, 101, 115, 97, 114, 105, 110, + 117, 116, 111, 108, 13, 100, 99, + 112, 109, 46, 118, 130, 39, 102, + 98, 44, 113, 104, 103, 33, 76, + 85, 106, 30, 31 +}; + +const byte cryptoArr30Fr[32] = { + 69, 67, 74, 138, 133, 120, 77, 122, + 121, 68, 65, 63, 73, 80, 83, 82, + 156, 45, 58, 79, 49, 86, 78, 84, + 71, 81, 64, 66, 135, 34, 136, 91 +}; + +const byte cryptoArr31Fr[32]= { + 93, 47, 48, 53, 50, 70, 124, 75, + 72, 147, 140, 150, 151, 57, 56, 51, + 107, 139, 55, 89, 131, 37, 54, 88, + 119, 0, 0, 0, 0, 0, 0, 0 +}; + +const byte cryptoArrDefaultDe[32] = { + 0x20, 0x65, 0x6E, 0x69, 0x73, 0x72, 0x74, + 0x68, 0x61, 0x75, 0x0D, 0x63, 0x6C, 0x64, + 0x6D, 0x6F, 0x67, 0x2E, 0x62, 0x66, 0x53, + 0x2C, 0x77, 0x45, 0x7A, 0x6B, 0x44, 0x76, + 0x9C, 0x47, 0x1E, 0x1F +}; + +const byte cryptoArr30De[32] = { + 0x49, 0x4D, 0x21, 0x42, 0x4C, 0x70, 0x41, 0x52, + 0x57, 0x4E, 0x48, 0x3F, 0x46, 0x50, 0x55, 0x4B, + 0x5A, 0x4A, 0x54, 0x31, 0x4F, 0x56, 0x79, 0x3A, + 0x6A, 0x5B, 0x5D, 0x40, 0x22, 0x2F, 0x30, 0x35 +}; + +const byte cryptoArr31De[32]= { + 0x78, 0x2D, 0x32, 0x82, 0x43, 0x39, 0x33, 0x38, + 0x7C, 0x27, 0x37, 0x3B, 0x25, 0x28, 0x29, 0x36, + 0x51, 0x59, 0x71, 0x81, 0x87, 0x88, 0x93, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const byte *cryptoArrDefault, *cryptoArr30, *cryptoArr31; +uint16 ctrlChar; + +/** + * Decrypt the next character + * @param c OUT, next decrypted char + * @param idx IN/OUT, current buffer index + * @param pt IN/OUT, current encryption point + * @return a boolean specifying if a stop character has been encountered + * @remarks Originally called 'cinq_huit' + */ +bool MortevielleEngine::decryptNextChar(char &c, int &idx, byte &pt) { + uint16 oct, ocd; + + /* 5-8 */ + oct = _dialogIndexArray[idx]; + oct = ((uint16)(oct << (16 - pt))) >> (16 - pt); + if (pt < 6) { + ++idx; + oct = oct << (5 - pt); + pt += 11; + oct = oct | ((uint)_dialogIndexArray[idx] >> pt); + } else { + pt -= 5; + oct = (uint)oct >> pt; + } + + if (oct == ctrlChar) { + c = '$'; + return true; + } else if (oct == 30 || oct == 31) { + ocd = _dialogIndexArray[idx]; + ocd = (uint16)(ocd << (16 - pt)) >> (16 - pt); + if (pt < 6) { + ++idx; + ocd = ocd << (5 - pt); + pt += 11; + ocd = ocd | ((uint)_dialogIndexArray[idx] >> pt); + } else { + pt -= 5; + ocd = (uint)ocd >> pt; + } + + if (oct == 30) + c = (unsigned char)cryptoArr30[ocd]; + else + c = (unsigned char)cryptoArr31[ocd]; + + if (c == '\0') { + c = '#'; + return true; + } + } else { + c = (unsigned char)cryptoArrDefault[oct]; + } + return false; +} + +/** + * Decode and extract the line with the given Id + * @remarks Originally called 'deline' + */ +Common::String MortevielleEngine::getString(int num) { + Common::String wrkStr = ""; + + if (num < 0) { + warning("getString(%d): num < 0! Skipping", num); + } else if (!_txxFileFl) { + wrkStr = getGameString(num); + } else { + int hint = _dialogHintArray[num]._hintId; + byte point = _dialogHintArray[num]._point; + int length = 0; + bool endFl = false; + char let; + do { + endFl = decryptNextChar(let, hint, point); + wrkStr += let; + ++length; + } while (!endFl); + } + + while (wrkStr.lastChar() == '$') + // Remove trailing '$'s + wrkStr.deleteLastChar(); + + return wrkStr; +} + +/** + * Reset object place + * @remarks Originally called 'copcha' + */ +void MortevielleEngine::resetObjectPlace() { + for (int i = kAcha; i < kAcha + 390; i++) + _tabdon[i] = _tabdon[i + 390]; +} + +/** + * Engine function - When restarting the game, reset the main variables used by the engine + * @remarks Originally called 'inzon' + */ +void MortevielleEngine::resetVariables() { + resetObjectPlace(); + + _coreVar._alreadyEnteredManor = false; + _coreVar._selectedObjectId = 0; + _coreVar._cellarObjectId = 0; + _coreVar._atticBallHoleObjectId = 0; + _coreVar._atticRodHoleObjectId = 0; + _coreVar._wellObjectId = 0; + _coreVar._secretPassageObjectId = 0; + _coreVar._purpleRoomObjectId = 136; + _coreVar._cryptObjectId = 141; + _coreVar._faithScore = getRandomNumber(4, 10); + _coreVar._currPlace = MANOR_FRONT; + + for (int i = 2; i <= 6; ++i) + _coreVar._inventory[i] = 0; + + // Only object in inventory: a gun + _coreVar._inventory[1] = 113; + + _coreVar._fullHour = (unsigned char)20; + + for (int i = 1; i <= 10; ++i) + _coreVar._pctHintFound[i] = ' '; + + for (int i = 1; i <= 6; ++i) + _coreVar._availableQuestion[i] = '*'; + + for (int i = 7; i <= 9; ++i) + _coreVar._availableQuestion[i] = ' '; + + for (int i = 10; i <= 28; ++i) + _coreVar._availableQuestion[i] = '*'; + + for (int i = 29; i <= 42; ++i) + _coreVar._availableQuestion[i] = ' '; + + _coreVar._availableQuestion[33] = '*'; + + for (int i = 1; i <= 8; ++i) + _charAnswerCount[i] = 0; + + initMaxAnswer(); +} + +/** + * Engine function - Set the palette + * @remarks Originally called 'writepal' + */ +void MortevielleEngine::setPal(int n) { + for (int i = 1; i <= 16; ++i) { + _curPict[(2 * i)] = _stdPal[n][i].x; + _curPict[(2 * i) + 1] = _stdPal[n][i].y; + } +} + +/** + * Engine function - Load Palette from File + * @remarks Originally called 'charpal' + */ +void MortevielleEngine::loadPalette() { + Common::File f; + + if (!f.open("fxx.mor")) { + if (f.open("mfxx.mor")) + f.seek(7 * 25); + else + error("Missing file - fxx.mor"); + } + + for (int i = 0; i < 108; ++i) + _drawingSizeArr[i] = f.readSint16LE(); + f.close(); + + if (!f.open("plxx.mor")) + error("Missing file - plxx.mor"); + for (int i = 0; i <= 90; ++i) { + for (int j = 1; j <= 16; ++j) { + _stdPal[i][j].x = f.readByte(); + _stdPal[i][j].y = f.readByte(); + } + } + f.close(); + + if (!f.open("cxx.mor")) + error("Missing file - cxx.mor"); + + // Skip CGA Palette and Patterns + + f.close(); +} + +/** + * Engine function - Load Texts from File + * @remarks Originally called 'chartex' + */ +void MortevielleEngine::loadTexts() { + Common::File inpFile; + Common::File ntpFile; + + _txxFileFl = false; + if (getLanguage() == Common::EN_ANY) { + warning("English version expected - Switching to DAT file"); + return; + } + + if (!inpFile.open("TXX.INP")) { + if (!inpFile.open("TXX.MOR")) { + warning("Missing file - TXX.INP or .MOR - Switching to DAT file"); + return; + } + } + if (ntpFile.open("TXX.NTP")) { + cryptoArr30 = cryptoArr30Fr; + cryptoArr31 = cryptoArr31Fr; + cryptoArrDefault = cryptoArrDefaultFr; + ctrlChar = 11; + } else if (ntpFile.open("TXX.IND")) { + cryptoArr30 = cryptoArr30De; + cryptoArr31 = cryptoArr31De; + cryptoArrDefault = cryptoArrDefaultDe; + ctrlChar = 10; + } else { + warning("Missing file - TXX.NTP or .IND - Switching to DAT file"); + return; + } + + if ((inpFile.size() > (kMaxDialogIndex * 2)) || (ntpFile.size() > (kMaxDialogHint * 3))) { + warning("TXX file - Unexpected format - Switching to DAT file"); + return; + } + + for (int i = 0; i < inpFile.size() / 2; ++i) + _dialogIndexArray[i] = inpFile.readUint16LE(); + + inpFile.close(); + _txxFileFl = true; + + for (int i = 0; i < (ntpFile.size() / 3); ++i) { + _dialogHintArray[i]._hintId = ntpFile.readSint16LE(); + _dialogHintArray[i]._point = ntpFile.readByte(); + } + + ntpFile.close(); + +} + +void MortevielleEngine::loadCFIEC() { + Common::File f; + + if (!f.open("cfiec.mor")) { + if (!f.open("alcfiec.mor")) + error("Missing file - *cfiec.mor"); + } + + _cfiecBufferSize = ((f.size() / 128) + 1) * 128; + int32 fileSize = f.size(); + + if (!_reloadCFIEC) + _cfiecBuffer = (byte *)malloc(sizeof(byte) * _cfiecBufferSize); + + for (int32 i = 0; i < fileSize; ++i) + _cfiecBuffer[i] = f.readByte(); + + for (int i = fileSize; i < _cfiecBufferSize; i++) + _cfiecBuffer[i] = 0; + + f.close(); + + _reloadCFIEC = false; +} + + +void MortevielleEngine::loadCFIPH() { + Common::File f; + + if (!f.open("cfiph.mor")) { + if (!f.open("alcfiph.mor")) + error("Missing file - *cfiph.mor"); + } + + _soundManager._cfiphBuffer = (uint16 *)malloc(sizeof(uint16) * (f.size() / 2)); + + for (int i = 0; i < (f.size() / 2); ++i) + _soundManager._cfiphBuffer[i] = f.readUint16BE(); + + f.close(); +} + +/** + * Engine function - Play Music + * @remarks Originally called 'music' + */ +void MortevielleEngine::music() { + if (_soundOff) + return; + + _reloadCFIEC = true; + + Common::File f; + if (!f.open("mort.img")) + error("Missing file - mort.img"); + + int size = f.size(); + byte *compMusicBuf = (byte *)malloc(sizeof(byte) * size); + byte *musicBuf = (byte *)malloc(sizeof(byte) * size * 2); + f.read(compMusicBuf, size); + f.close(); + + int musicSize = _soundManager.decodeMusic(compMusicBuf, musicBuf, size); + free(compMusicBuf); + + _soundManager.playSong(musicBuf, musicSize, 5); + while (keyPressed()) + getChar(); + + free(musicBuf); +} + +/** + * Engine function - Show title screen + * @remarks Originally called 'suite' + */ +void MortevielleEngine::showTitleScreen() { + clearScreen(); + handleDescriptionText(7, 2035); + _caff = 51; + _text.taffich(); + testKeyboard(); + clearScreen(); + draw(0, 0); + + Common::String cpr = "COPYRIGHT 1989 : LANKHOR"; + _screenSurface.putxy(104 + 72 * kResolutionScaler, 185); + _screenSurface.drawString(cpr, 0); +} + +/** + * Draw picture + * @remarks Originally called 'dessine' + */ +void MortevielleEngine::draw(int x, int y) { + _mouse.hideMouse(); + setPal(_numpal); + displayPicture(_curPict, x, y); + _mouse.showMouse(); +} + +/** + * Draw right frame + * @remarks Originally called 'dessine_rouleau' + */ +void MortevielleEngine::drawRightFrame() { + setPal(89); + _mouse.hideMouse(); + displayPicture(_rightFramePict, 0, 0); + _mouse.showMouse(); +} + +/** + * Read the current system time + */ +int MortevielleEngine::readclock() { + TimeDate dateTime; + g_system->getTimeAndDate(dateTime); + + int m = dateTime.tm_min * 60; + int h = dateTime.tm_hour * 3600; + return h + m + dateTime.tm_sec; +} + +/** + * Engine function - Prepare room and hint string + * @remarks Originally called 'tinke' + */ +void MortevielleEngine::prepareRoom() { + int day, hour, minute; + + _anyone = false; + updateHour(day, hour, minute); + if (day != _day) { + _day = day; + for (int i = 0; i < 9; i++) { + if (_charAnswerMax[i] > 0) + --_charAnswerMax[i]; + _charAnswerCount[i] = 0; + } + } + if ((hour > _hour) || ((hour == 0) && (_hour == 23))) { + _hour = hour; + _minute = 0; + drawClock(); + int hintCount = 0; + for (int i = 1; i <= 10; ++i) { + if (_coreVar._pctHintFound[i] == '*') + ++hintCount; + } + + Common::String pctStr; + if (hintCount == 10) + pctStr = "10"; + else + pctStr = (unsigned char)(hintCount + 48); + + _hintPctMessage = "[1]["; + _hintPctMessage += getEngineString(S_SHOULD_HAVE_NOTICED); + _hintPctMessage += pctStr; + _hintPctMessage += '0'; + _hintPctMessage += getEngineString(S_NUMBER_OF_HINTS); + _hintPctMessage += "]["; + _hintPctMessage += getEngineString(S_OKAY); + _hintPctMessage += ']'; + } + if (minute > _minute) { + _minute = 30; + drawClock(); + } + if (_mouse._pos.y < 12) + return; + + if (!_blo) { + if ((hour == 12) || ((hour > 18) && (hour < 21)) || ((hour >= 0) && (hour < 7))) + _inGameHourDuration = kTime2; + else + _inGameHourDuration = kTime1; + if ((_coreVar._faithScore > 33) && (_coreVar._faithScore < 66)) + _inGameHourDuration -= (_inGameHourDuration / 3); + + if (_coreVar._faithScore > 65) + _inGameHourDuration -= ((_inGameHourDuration / 3) * 2); + + int newHour = readclock(); + if ((newHour - _currentDayHour) > _inGameHourDuration) { + bool activeMenu = _menu._menuActive; + _menu.eraseMenu(); + _currentHourCount += ((newHour - _currentDayHour) / _inGameHourDuration); + _currentDayHour = newHour; + switch (_place) { + case GREEN_ROOM: + case DARKBLUE_ROOM: + setRandomPresenceGreenRoom(_coreVar._faithScore); + break; + case PURPLE_ROOM: + setRandomPresencePurpleRoom(_coreVar._faithScore); + break; + case BLUE_ROOM: + setRandomPresenceBlueRoom(_coreVar._faithScore); + break; + case RED_ROOM: + case GREEN_ROOM2: + setRandomPresenceRedRoom(_coreVar._faithScore); + break; + case JULIA_ROOM: + setRandomPresenceJuliaRoom(_coreVar._faithScore); + break; + case DINING_ROOM: + setRandomPresenceDiningRoom(_coreVar._faithScore); + break; + case BUREAU: + setRandomPresenceBureau(_coreVar._faithScore); + break; + case KITCHEN: + setRandomPresenceKitchen(_coreVar._faithScore); + break; + case ATTIC: + case CELLAR: + setRandomPresenceAttic(_coreVar._faithScore); + break; + case LANDING: + case ROOM26: + setRandomPresenceLanding(_coreVar._faithScore); + break; + case CHAPEL: + setRandomPresenceChapel(_coreVar._faithScore); + break; + } + if ((_savedBitIndex != 0) && (_currBitIndex != 10)) + _savedBitIndex = _currBitIndex; + + if ((_savedBitIndex == 0) && (_currBitIndex > 0)) { + if ((_coreVar._currPlace == ATTIC) || (_coreVar._currPlace == CELLAR)) { + initCaveOrCellar(); + } else if (_currBitIndex == 10) { + _currBitIndex = 0; + if (!_uptodatePresence) { + _uptodatePresence = true; + _startHour = readclock(); + if (getRandomNumber(1, 5) < 5) { + clearVerbBar(); + prepareScreenType2(); + displayTextInVerbBar(getEngineString(S_HEAR_NOISE)); + int rand = (getRandomNumber(0, 4)) - 2; + _soundManager.startSpeech(1, rand, 1); + _soundManager.waitSpeech(); + clearVerbBar(); + } + } + } + } + + if (activeMenu) + _menu.drawMenu(); + } + } + _endHour = readclock(); + if ((_uptodatePresence) && ((_endHour - _startHour) > 17)) { + getPresenceBitIndex(_place); + _uptodatePresence = false; + _startHour = 0; + if ((_coreVar._currPlace > OWN_ROOM) && (_coreVar._currPlace < DINING_ROOM)) + _anyone = true; + } +} + +/** + * Engine function - Draw Clock + * @remarks Originally called 'pendule' + */ +void MortevielleEngine::drawClock() { + const int cv[2][12] = { + { 5, 8, 10, 8, 5, 0, -5, -8, -10, -8, -5, 0 }, + { -5, -3, 0, 3, 5, 6, 5, 3, 0, -3, -5, -6 } + }; + const int x = 580; + const int y = 123; + const int rg = 9; + + _mouse.hideMouse(); + + _screenSurface.drawRectangle(570, 118, 20, 10); + _screenSurface.drawRectangle(578, 114, 6, 18); + + if (_minute == 0) + _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)x >> 1) * kResolutionScaler, (y - rg), 1); + else + _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)x >> 1) * kResolutionScaler, (y + rg), 1); + + int hour12 = _hour; + if (hour12 > 12) + hour12 -= 12; + if (hour12 == 0) + hour12 = 12; + + _screenSurface.drawLine(((uint)x >> 1) * kResolutionScaler, y, ((uint)(x + cv[0][hour12 - 1]) >> 1) * kResolutionScaler, y + cv[1][hour12 - 1], 1); + _mouse.showMouse(); + _screenSurface.putxy(568, 154); + + if (_hour > 11) + _screenSurface.drawString("PM ", 1); + else + _screenSurface.drawString("AM ", 1); + + _screenSurface.putxy(550, 160); + if ((_day >= 0) && (_day <= 8)) { + Common::String tmp = getEngineString(S_DAY); + tmp.insertChar((char)(_day + 49), 0); + _screenSurface.drawString(tmp, 1); + } +} + +void MortevielleEngine::palette(int v1) { + warning("TODO: palette"); +} + +/** + * Returns a substring of the given string + * @param s Source string + * @param idx Starting index (1 based) + * @param size Number of characters to return + */ + +Common::String MortevielleEngine::copy(const Common::String &s, int idx, size_t size) { + assert(idx + size < s.size()); + + // Copy the substring into a temporary buffer + char *tmp = new char[size + 1]; + strncpy(tmp, s.c_str() + idx - 1, size); + tmp[size] = '\0'; + + Common::String result(tmp); + delete[] tmp; + return result; +} + +/** + * Clear Screen + * @remarks Originally called 'hirs' + */ +void MortevielleEngine::clearScreen() { + _screenSurface.clearScreen(); +} + +/** + * Init room : Cave or Cellar + * @remarks Originally called 'cavegre' + */ +void MortevielleEngine::initCaveOrCellar() { + _coreVar._faithScore += 2; + if (_coreVar._faithScore > 69) + _coreVar._faithScore += (_coreVar._faithScore / 10); + clearVerbBar(); + prepareScreenType2(); + displayTextInVerbBar(getEngineString(S_SOMEONE_ENTERS)); + int rand = (getRandomNumber(0, 4)) - 2; + _soundManager.startSpeech(2, rand, 1); + _soundManager.waitSpeech(); + // The original was doing here a useless loop. + // It has been removed + + clearVerbBar(); + displayAloneText(); +} + +/** + * Display control menu string + * @remarks Originally called 'tctrm' + */ +void MortevielleEngine::displayControlMenu() { + handleDescriptionText(2, (3000 + _controlMenu)); + _controlMenu = 0; +} + +/** + * Display picture at a given coordinate + * @remarks Originally called 'pictout' + */ +void MortevielleEngine::displayPicture(const byte *pic, int x, int y) { + GfxSurface surface; + surface.decode(pic); + _screenSurface.drawPicture(surface, x, y); +} + +void MortevielleEngine::adzon() { + Common::File f; + + if (!f.open("don.mor")) + error("Missing file - don.mor"); + + f.read(_tabdon, 7 * 256); + f.close(); + + if (!f.open("bmor.mor")) + error("Missing file - bmor.mor"); + + f.read(&_tabdon[kFleche], 1916); + f.close(); + + // Read Right Frame Drawing + if (!f.open("dec.mor")) + error("Missing file - dec.mor"); + + free(_rightFramePict); + _rightFramePict = (byte *)malloc(sizeof(byte) * f.size()); + f.read(_rightFramePict, f.size()); + f.close(); +} + +/** + * Returns the offset within the compressed image data resource of the desired image + * @remarks Originally called 'animof' + */ +int MortevielleEngine::getAnimOffset(int frameNum, int animNum) { + int animCount = _curAnim[1]; + int aux = animNum; + if (frameNum != 1) + aux += animCount; + + return (animCount << 2) + 2 + READ_BE_UINT16(&_curAnim[aux << 1]); +} + +/** + * Display text in description bar + * @remarks Originally called 'text1' + */ +void MortevielleEngine::displayTextInDescriptionBar(int x, int y, int nb, int mesgId) { + Common::String tmpStr = getString(mesgId); + if ((y == 182) && ((int) tmpStr.size() > nb)) + y = 176; + _text.displayStr(tmpStr, x, y, nb, 20, _textColor); +} + +/** + * Display description text + * @remarks Originally called 'repon' + */ +void MortevielleEngine::handleDescriptionText(int f, int mesgId) { + if ((mesgId > 499) && (mesgId < 563)) { + Common::String tmpStr = getString(mesgId - 501 + kInventoryStringIndex); + + if ((int) tmpStr.size() > ((58 + (kResolutionScaler - 1) * 37) << 1)) + _largestClearScreen = true; + else + _largestClearScreen = false; + + clearDescriptionBar(); + _text.displayStr(tmpStr, 8, 176, 85, 3, 5); + } else { + mapMessageId(mesgId); + switch (f) { + case 2: + case 8: + clearDescriptionBar(); + prepareScreenType2(); + displayTextInDescriptionBar(8, 182, 103, mesgId); + if ((mesgId == 68) || (mesgId == 69)) + _coreVar._availableQuestion[40] = '*'; + if ((mesgId == 104) && (_caff == CELLAR)) { + _coreVar._availableQuestion[36] = '*'; + if (_coreVar._availableQuestion[39] == '*') { + _coreVar._pctHintFound[3] = '*'; + _coreVar._availableQuestion[38] = '*'; + } + } + break; + case 1: + case 6: + case 9: { + int i; + if ((f == 1) || (f == 6)) + i = 4; + else + i = 5; + + Common::String tmpStr = getString(mesgId); + _text.displayStr(tmpStr, 80, 40, 60, 25, i); + + if (mesgId == 180) + _coreVar._pctHintFound[6] = '*'; + else if (mesgId == 179) + _coreVar._pctHintFound[10] = '*'; + } + break; + default: + break; + } + } +} + +/** + * Recompute message Id + * @remarks Originally called 'modif' + */ +void MortevielleEngine::mapMessageId(int &mesgId) { + if (mesgId == 26) + mesgId = 25; + else if ((mesgId > 29) && (mesgId < 36)) + mesgId -= 4; + else if ((mesgId > 69) && (mesgId < 78)) + mesgId -= 37; + else if ((mesgId > 99) && (mesgId < 194)) + mesgId -= 59; + else if ((mesgId > 996) && (mesgId < 1000)) + mesgId -= 862; + else if ((mesgId > 1500) && (mesgId < 1507)) + mesgId -= 1363; + else if ((mesgId > 1507) && (mesgId < 1513)) + mesgId -= 1364; + else if ((mesgId > 1999) && (mesgId < 2002)) + mesgId -= 1851; + else if (mesgId == 2010) + mesgId = 151; + else if ((mesgId > 2011) && (mesgId < 2025)) + mesgId -= 1860; + else if (mesgId == 2026) + mesgId = 165; + else if ((mesgId > 2029) && (mesgId < 2037)) + mesgId -= 1864; + else if ((mesgId > 3000) && (mesgId < 3005)) + mesgId -= 2828; + else if (mesgId == 4100) + mesgId = 177; + else if (mesgId == 4150) + mesgId = 178; + else if ((mesgId > 4151) && (mesgId < 4156)) + mesgId -= 3973; + else if (mesgId == 4157) + mesgId = 183; + else if ((mesgId == 4160) || (mesgId == 4161)) + mesgId -= 3976; +} + +/** + * Initialize open objects array + * @remarks Originally called 'initouv' + */ +void MortevielleEngine::resetOpenObjects() { + for (int i = 1; i <= 6; ++i) + _openObjects[i] = 0; + _openObjCount = 0; +} + +/** + * Display Text Block + * @remarks Originally called 'ecr2' + */ +void MortevielleEngine::displayTextBlock(Common::String text) { + // Some dead code was present in the original: removed + _screenSurface.putxy(8, 177); + int tlig = 59 + (kResolutionScaler - 1) * 36; + + if ((int)text.size() < tlig) + _screenSurface.drawString(text, 5); + else if ((int)text.size() < (tlig << 1)) { + _screenSurface.putxy(8, 176); + _screenSurface.drawString(copy(text, 1, (tlig - 1)), 5); + _screenSurface.putxy(8, 182); + _screenSurface.drawString(copy(text, tlig, tlig << 1), 5); + } else { + _largestClearScreen = true; + clearDescriptionBar(); + _screenSurface.putxy(8, 176); + _screenSurface.drawString(copy(text, 1, (tlig - 1)), 5); + _screenSurface.putxy(8, 182); + _screenSurface.drawString(copy(text, tlig, ((tlig << 1) - 1)), 5); + _screenSurface.putxy(8, 190); + _screenSurface.drawString(copy(text, tlig << 1, tlig * 3), 5); + } +} + +void MortevielleEngine::displayTextInVerbBar(Common::String text) { + clearVerbBar(); + _screenSurface.putxy(8, 192); + _screenSurface.drawString(text, 5); +} + +/** + * Display item in hand + * @remarks Originally called 'modobj' + */ +void MortevielleEngine::displayItemInHand(int objId) { + Common::String strp = Common::String(' '); + + if (objId != 500) + strp = getString(objId - 501 + kInventoryStringIndex); + + _menu.setText(_menu._inventoryMenu[8], strp); + _menu.disableMenuItem(_menu._inventoryMenu[8]); +} + +/** + * Display empty hand + * @remarks Originally called 'maivid' + */ +void MortevielleEngine::displayEmptyHand() { + _coreVar._selectedObjectId = 0; + displayItemInHand(500); +} + +/** + * Set a random presence: Leo or Max + * @remarks Originally called 'chlm' + */ +int MortevielleEngine::checkLeoMaxRandomPresence() { + int retval = getRandomNumber(1, 2); + if (retval == 2) + retval = 128; + + return retval; +} + +/** + * Reset room variables + * @remarks Originally called 'debloc' + */ +void MortevielleEngine::resetRoomVariables(int roomId) { + _num = 0; + _x = 0; + _y = 0; + if ((roomId != ROOM26) && (roomId != LANDING)) + resetPresenceInRooms(roomId); + _savedBitIndex = _currBitIndex; +} + +/** + * Compute presence stats + * @remarks Originally called 'ecfren' + */ +int MortevielleEngine::getPresenceStats(int &rand, int faithScore, int roomId) { + if (roomId == OWN_ROOM) + displayAloneText(); + int retVal = -500; + rand = 0; + if ( ((roomId == GREEN_ROOM) && (!_roomPresenceLuc) && (!_roomPresenceIda)) + || ((roomId == DARKBLUE_ROOM) && (!_roomPresenceGuy) && (!_roomPresenceEva)) ) + retVal = getPresenceStatsGreenRoom(); + if ((roomId == PURPLE_ROOM) && (!_purpleRoomPresenceLeo) && (!_juliaRoomPresenceLeo)) + retVal = getPresenceStatsPurpleRoom(); + if ( ((roomId == TOILETS) && (!_toiletsPresenceBobMax)) + || ((roomId == BATHROOM) && (!_bathRoomPresenceBobMax)) ) + retVal = getPresenceStatsToilets(); + if ((roomId == BLUE_ROOM) && (!_roomPresenceMax)) + retVal = getPresenceStatsBlueRoom(); + if ( ((roomId == RED_ROOM) && (!_roomPresenceBob)) + || ((roomId == GREEN_ROOM2) && (!_roomPresencePat))) + retVal = getPresenceStatsRedRoom(); + if ((roomId == JULIA_ROOM) && (!_juliaRoomPresenceLeo) && (!_purpleRoomPresenceLeo)) + retVal = 10; + if ( ((roomId == PURPLE_ROOM) && (_juliaRoomPresenceLeo)) + || ((roomId == JULIA_ROOM) && (_purpleRoomPresenceLeo))) + retVal = -400; + if (retVal != -500) { + retVal += faithScore; + rand = getRandomNumber(1, 100); + } + + return retVal; +} + +/** + * Set presence flags + * @remarks Originally called 'becfren' + */ +void MortevielleEngine::setPresenceFlags(int roomId) { + if ((roomId == GREEN_ROOM) || (roomId == DARKBLUE_ROOM)) { + int rand = getRandomNumber(1, 2); + if (roomId == GREEN_ROOM) { + if (rand == 1) + _roomPresenceLuc = true; + else + _roomPresenceIda = true; + } else { // roomId == DARKBLUE_ROOM + if (rand == 1) + _roomPresenceGuy = true; + else + _roomPresenceEva = true; + } + } else if (roomId == PURPLE_ROOM) + _purpleRoomPresenceLeo = true; + else if (roomId == TOILETS) + _toiletsPresenceBobMax = true; + else if (roomId == BLUE_ROOM) + _roomPresenceMax = true; + else if (roomId == RED_ROOM) + _roomPresenceBob = true; + else if (roomId == BATHROOM) + _bathRoomPresenceBobMax = true; + else if (roomId == GREEN_ROOM2) + _roomPresencePat = true; + else if (roomId == JULIA_ROOM) + _juliaRoomPresenceLeo = true; +} + +/** + * Initialize max answers per character + * @remarks Originally called 'init_nbrepm' + */ +void MortevielleEngine::initMaxAnswer() { + static const byte maxAnswer[9] = { 0, 4, 5, 6, 7, 5, 6, 5, 8 }; + + for (int idx = 0; idx < 9; ++idx) { + _charAnswerMax[idx] = maxAnswer[idx]; + _charAnswerCount[idx] = 0; + } +} + +/** + * Get Presence + * @remarks Originally called 't11' + */ +int MortevielleEngine::getPresence(int roomId) { + int retVal = 0; + int rand; + + int pres = getPresenceStats(rand, _coreVar._faithScore, roomId); + _place = roomId; + if ((roomId > OWN_ROOM) && (roomId < DINING_ROOM)) { + if (pres != -500) { + if (rand > pres) { + displayAloneText(); + retVal = 0; + } else { + setPresenceFlags(_place); + retVal = getPresenceBitIndex(_place); + } + } else + retVal = getPresenceBitIndex(_place); + } + + if (roomId > JULIA_ROOM) { + if ((roomId > LANDING) && (roomId != CHAPEL) && (roomId != ROOM26)) + displayAloneText(); + else { + int h = 0; + if (roomId == DINING_ROOM) + pres = getPresenceStatsDiningRoom(h); + else if (roomId == BUREAU) + pres = getPresenceStatsBureau(h); + else if (roomId == KITCHEN) + pres = getPresenceStatsKitchen(); + else if ((roomId == ATTIC) || (roomId == CELLAR)) + pres = getPresenceStatsAttic(); + else if ((roomId == LANDING) || (roomId == ROOM26)) + pres = getPresenceStatsLanding(); + else if (roomId == CHAPEL) + pres = getPresenceStatsChapel(h); + pres += _coreVar._faithScore; + rand = getRandomNumber(1, 100); + if (rand > pres) { + displayAloneText(); + retVal = 0; + } else { + if (roomId == DINING_ROOM) + pres = setPresenceDiningRoom(h); + else if (roomId == BUREAU) + pres = setPresenceBureau(h); + else if ((roomId == KITCHEN) || (roomId == ATTIC) || (roomId == CELLAR)) + pres = setPresenceKitchen(); + else if ((roomId == LANDING) || (roomId == ROOM26)) + pres = setPresenceLanding(); + else if (roomId == CHAPEL) + pres = setPresenceChapel(h); + retVal = pres; + } + } + } + + return retVal; +} + +/** + * Display Question String + * @remarks Originally called 'writetp' + */ +void MortevielleEngine::displayQuestionText(Common::String s, int cmd) { + _screenSurface.drawString(s, cmd); +} + +/** + * Display animation frame + * @remarks Originally called 'aniof' + */ +void MortevielleEngine::displayAnimFrame(int frameNum, int animId) { + if ((_caff == BATHROOM) && ((animId == 4) || (animId == 5))) + return; + + if ((_caff == DINING_ROOM) && (animId == 7)) + animId = 6; + else if (_caff == KITCHEN) { + if (animId == 3) + animId = 4; + else if (animId == 4) + animId = 3; + } + + int offset = getAnimOffset(frameNum, animId); + + GfxSurface surface; + surface.decode(&_curAnim[offset]); + _screenSurface.drawPicture(surface, 0, 12); + + prepareScreenType1(); +} + +/** + * Draw Picture + * @remarks Originally called 'dessin' + */ +void MortevielleEngine::drawPicture() { + clearUpperLeftPart(); + if (_caff > 99) { + draw(60, 33); + _screenSurface.drawBox(118, 32, 291, 122, 15); // Medium box + } else if (_caff > 69) { + draw(112, 48); // Heads + _screenSurface.drawBox(222, 47, 155, 92, 15); + } else { + draw(0, 12); + prepareScreenType1(); + if ((_caff < 30) || (_caff > 32)) { + for (int i = 1; i <= 6; ++i) { + if (_openObjects[i] != 0) + displayAnimFrame(1, _openObjects[i]); + } + + if (_caff == ATTIC) { + if (_coreVar._atticBallHoleObjectId == 141) + displayAnimFrame(1, 7); + + if (_coreVar._atticRodHoleObjectId == 159) + displayAnimFrame(1, 6); + } else if ((_caff == CELLAR) && (_coreVar._cellarObjectId == 151)) + displayAnimFrame(1, 2); + else if ((_caff == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId == 143)) + displayAnimFrame(1, 1); + else if ((_caff == WELL) && (_coreVar._wellObjectId != 0)) + displayAnimFrame(1, 1); + } + + if (_caff < ROOM26) + startMusicOrSpeech(1); + } +} + +void MortevielleEngine::drawPictureWithText() { + _text.taffich(); + drawPicture(); + _destinationOk = false; +} + +/** + * Engine function - Place + * @remarks Originally called 'tkey1' + */ +void MortevielleEngine::testKey(bool d) { + bool quest = false; + int x, y; + bool click; + + _mouse.hideMouse(); + displayStatusInDescriptionBar('K'); + + // Wait for release from any key or mouse button + while (keyPressed()) + _key = gettKeyPressed(); + + do { + _mouse.getMousePosition(x, y, click); + keyPressed(); + } while (click); + + // Event loop + do { + if (d) + prepareRoom(); + quest = keyPressed(); + _mouse.getMousePosition(x, y, click); + if (shouldQuit()) + return; + } while (!(quest || (click) || (d && _anyone))); + if (quest) + gettKeyPressed(); + setMouseClick(false); + _mouse.showMouse(); +} + +/** + * Display Narrative Picture + * @remarks Originally called 'tlu' + */ +void MortevielleEngine::displayNarrativePicture(int af, int ob) { + _caff = 32; + drawPictureWithText(); + handleDescriptionText(6, ob + 4000); + handleDescriptionText(2, 999); + testKey(true); + _caff = af; + _currMenu = OPCODE_NONE; + _crep = 998; +} + +/** + * Prepare Display Text + * @remarks Originally called 'affrep' + */ +void MortevielleEngine::prepareDisplayText() { + _caff = _coreVar._currPlace; + _crep = _coreVar._currPlace; +} + +/** + * Exit room + * @remarks Originally called 'tsort' + */ +void MortevielleEngine::exitRoom() { + if ((_openObjCount > 0) && (_coreVar._currPlace != OWN_ROOM)) { + if (_coreVar._faithScore < 50) + _coreVar._faithScore += 2; + else + _coreVar._faithScore += (_coreVar._faithScore / 10); + } + + resetOpenObjects(); + + _roomDoorId = OWN_ROOM; + _curSearchObjId = 0; + resetRoomVariables(_coreVar._currPlace); +} + +/** + * get 'read' description + * @remarks Originally called 'st4' + */ +void MortevielleEngine::getReadDescription(int objId) { + _crep = 997; + + switch (objId) { + case 114 : + _crep = 109; + break; + case 110 : + _crep = 107; + break; + case 158 : + _crep = 113; + break; + case 152: + case 153: + case 154: + case 155: + case 156: + case 150: + case 100: + case 157: + case 160: + case 161 : + displayNarrativePicture(_caff, objId); + break; + default: + break; + } +} + +/** + * get 'search' description + * @remarks Originally called 'st7' + */ +void MortevielleEngine::getSearchDescription(int objId) { + switch (objId) { + case 116: + case 144: + _crep = 104; + break; + case 126: + case 111: + _crep = 108; + break; + case 132: + _crep = 111; + break; + case 142: + _crep = 112; + break; + default: + _crep = 183; + getReadDescription(objId); + } +} + +/** + * Menu up + * @remarks Originally called 'mennor' + */ +void MortevielleEngine::menuUp() { + _menu.menuUp(_currMenu); +} + +/** + * Draw discussion box + * @remarks Originally called 'premtet' + */ +void MortevielleEngine::drawDiscussionBox() { + draw(10, 80); + _screenSurface.drawBox(18, 79, 155, 92, 15); +} + +/** + * Try to put an object somewhere + * @remarks Originally called 'ajchai' + */ +void MortevielleEngine::putObject() { + int putId = kAcha + ((_curSearchObjId - 1) * 10) - 1; + int i; + for (i = 1; (i <= 9) && (_tabdon[putId + i] != 0); i++) + ; + + if (_tabdon[putId + i] == 0) + _tabdon[putId + i] = _coreVar._selectedObjectId; + else + _crep = 192; +} + +/** + * Check if inventory is full and, if not, add object in it. + * @remarks Originally called 'ajjer' + */ +void MortevielleEngine::addObjectToInventory(int objectId) { + int i; + + for (i = 1; (i <= 5) && (_coreVar._inventory[i] != 0); i++) + ; + + if (_coreVar._inventory[i] == 0) { + _coreVar._inventory[i] = objectId; + _menu.setInventoryText(); + } else + // Inventory is full + _crep = 139; +} + +/** + * Interact with NPC + * @remarks Originally called 'quelquun' + */ +void MortevielleEngine::interactNPC() { + if (_menu._menuDisplayed) + _menu.eraseMenu(); + + endSearch(); + _crep = 997; +L1: + if (!_hiddenHero) { + if (_crep == 997) + _crep = 138; + handleDescriptionText(2, _crep); + if (_crep == 138) + _soundManager.startSpeech(5, 2, 1); + else + _soundManager.startSpeech(4, 4, 1); + + if (_openObjCount == 0) + _coreVar._faithScore += 2; + else if (_coreVar._faithScore < 50) + _coreVar._faithScore += 4; + else + _coreVar._faithScore += 3 * (_coreVar._faithScore / 10); + exitRoom(); + _menu.setDestinationText(LANDING); + int charIdx = convertBitIndexToCharacterIndex(_currBitIndex); + _caff = 69 + charIdx; + _crep = _caff; + _currMenu = MENU_DISCUSS; + _currAction = (_menu._discussMenu[charIdx]._menuId << 8) | _menu._discussMenu[charIdx]._actionId; + _syn = true; + _col = true; + } else { + if (getRandomNumber(1, 3) == 2) { + _hiddenHero = false; + _crep = 137; + goto L1; + } else { + handleDescriptionText(2, 136); + int rand = (getRandomNumber(0, 4)) - 2; + _soundManager.startSpeech(3, rand, 1); + clearDescriptionBar(); + displayAloneText(); + resetRoomVariables(MANOR_FRONT); + prepareDisplayText(); + } + } + if (_menu._menuDisplayed) + _menu.drawMenu(); +} + +/** + * Search - Prepare next object + * @remarks Originally called 'tsuiv' + */ +void MortevielleEngine::prepareNextObject() { + int objId; + int tabIdx = kAcha + ((_curSearchObjId - 1) * 10) - 1; + int localSeearchCount = 0; + do { + ++localSeearchCount; + ++_searchCount; + objId = _tabdon[tabIdx + _searchCount]; + } while ((objId == 0) && (_searchCount <= 9)); + + if ((objId != 0) && (_searchCount < 11)) { + _caff = objId; + _crep = _caff + 400; + if (_currBitIndex != 0) + // Someone is present in the room + _coreVar._faithScore += 2; + } else { + prepareDisplayText(); + endSearch(); + if (localSeearchCount > 9) + _crep = 131; + } +} + +/** + * Display Arrow status + * @remarks Originally called 'tfleche' + */ +void MortevielleEngine::displayStatusArrow() { + bool qust; + char touch; + + if (_num == 9999) + return; + + displayStatusInDescriptionBar((unsigned char)152); + bool inRect = false; + do { + touch = '\0'; + + do { + _mouse.moveMouse(qust, touch); + if (shouldQuit()) + return; + + if (getMouseClick()) + inRect = (_mouse._pos.x < 256 * kResolutionScaler) && (_mouse._pos.y < 176) && (_mouse._pos.y > 12); + prepareRoom(); + } while (!(qust || inRect || _anyone)); + + if (qust && (touch == '\103')) + _dialogManager.show(_hintPctMessage, 1); + } while (!((touch == '\73') || ((touch == '\104') && (_x != 0) && (_y != 0)) || (_anyone) || (inRect))); + + if (touch == '\73') + _keyPressedEsc = true; + + if (inRect) { + _x = _mouse._pos.x; + _y = _mouse._pos.y; + } +} + +/** + * Set coordinates + * @remarks Originally called 'tcoord' + */ +void MortevielleEngine::setCoordinates(int sx) { + int sy, ix, iy; + int ib; + + + _num = 0; + _crep = 999; + int a = 0; + int atdon = kAmzon + 3; + int cy = 0; + while (cy < _caff) { + a += _tabdon[atdon]; + atdon += 4; + ++cy; + } + + if (_tabdon[atdon] == 0) { + _crep = 997; + return; + } + + a += kFleche; + int cb = 0; + for (cy = 0; cy <= (sx - 2); ++cy) { + ib = (_tabdon[a + cb] << 8) + _tabdon[(a + cb + 1)]; + cb += (ib * 4) + 2; + } + ib = (_tabdon[a + cb] << 8) + _tabdon[(a + cb + 1)]; + if (ib == 0) { + _crep = 997; + return; + } + + cy = 1; + do { + cb += 2; + sx = _tabdon[a + cb] * kResolutionScaler; + sy = _tabdon[(a + cb + 1)]; + cb += 2; + ix = _tabdon[a + cb] * kResolutionScaler; + iy = _tabdon[(a + cb + 1)]; + ++cy; + } while (!(((_x >= sx) && (_x <= ix) && (_y >= sy) && (_y <= iy)) || (cy > ib))); + + if ((_x >= sx) && (_x <= ix) && (_y >= sy) && (_y <= iy)) { + _num = cy - 1; + return; + } + + _crep = 997; +} + +/** + * Display LOOK Screen + * @remarks Originally called 'treg' + */ +void MortevielleEngine::displayLookScreen(int objId) { + int mdes = _caff; + _caff = objId; + + if (((_caff > 29) && (_caff < 33)) || (_caff == 144) || (_caff == 147) || (_caff == 149) || (_currAction == _menu._opcodeSLook)) { + drawPictureWithText(); + if ((_caff > 29) && (_caff < 33)) + handleDescriptionText(2, _caff); + else + handleDescriptionText(2, _caff + 400); + testKey(true); + _caff = mdes; + _currMenu = MENU_NONE; + _crep = 998; + } else { + _obpart = true; + _crep = _caff + 400; + _menu.setSearchMenu(); + } +} + +/** + * Engine function - Put in hand + * @remarks Originally called 'avpoing' + */ +void MortevielleEngine::putInHand(int &objId) { + _crep = 999; + if (_coreVar._selectedObjectId != 0) + addObjectToInventory(_coreVar._selectedObjectId); + + // If inventory wasn't full + if (_crep != 139) { + displayItemInHand(objId + 400); + _coreVar._selectedObjectId = objId; + objId = 0; + } +} + +/** + * Search - Get the first object + * @remarks Originally called 'rechai' + */ +int MortevielleEngine::getFirstObject() { + int tmpPlace = _coreVar._currPlace; + + if (_coreVar._currPlace == CRYPT) + tmpPlace = CELLAR; + + return _tabdon[kAsearch + (tmpPlace * 7) + _num - 1]; +} + +/** + * Check before leaving the secret passage + * @remarks Originally called 't23coul' + */ +int MortevielleEngine::checkLeaveSecretPassage() { + if (!checkInventory(143)) { + _crep = 1512; + loseGame(); + } + + return CELLAR; +} + +/** + * Display status character in description bar + * @remarks Originally called 'fenat' + */ +void MortevielleEngine::displayStatusInDescriptionBar(char stat) { + _mouse.hideMouse(); + _screenSurface.writeCharacter(Common::Point(306, 193), stat, 12); + _screenSurface.drawBox(300, 191, 16, 8, 15); + _mouse.showMouse(); +} + +/** + * Test Keyboard + * @remarks Originally called 'teskbd' + */ +void MortevielleEngine::testKeyboard() { + if (keyPressed()) + gettKeyPressed(); +} + +/** + * Test Key Pressed + * @remarks Originally called 'testou' + */ +int MortevielleEngine::gettKeyPressed() { + char ch = getChar(); + + switch (ch) { + case '\23' : + _soundOff = !_soundOff; + break; + case '\26' : + if ((_x26KeyCount == 1) || (_x26KeyCount == 2)) { + decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64); + ++_x26KeyCount; + + return 61; + } + break; + case '\33' : + if (keyPressed()) + ch = getChar(); + break; + default: + break; + } + + return (int)ch; +} + +} // End of namespace Mortevielle diff --git a/engines/neverhood/background.cpp b/engines/neverhood/background.cpp index 0a80bd8390..d6a9900d38 100644 --- a/engines/neverhood/background.cpp +++ b/engines/neverhood/background.cpp @@ -33,11 +33,11 @@ Background::Background(NeverhoodEngine *vm, int objectPriority) Background::Background(NeverhoodEngine *vm, uint32 fileHash, int objectPriority, int surfacePriority) : Entity(vm, objectPriority), _surface(NULL), _spriteResource(vm) { - + _spriteResource.load(fileHash); createSurface(surfacePriority, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); _surface->drawSpriteResource(_spriteResource); - + } Background::~Background() { @@ -45,7 +45,7 @@ Background::~Background() { } void Background::createSurface(int surfacePriority, int16 width, int16 height) { - _surface = new BaseSurface(_vm, surfacePriority, width, height); + _surface = new BaseSurface(_vm, surfacePriority, width, height, "background"); _surface->setTransparent(false); _spriteResource.getPosition().x = width; _spriteResource.getPosition().y = height; diff --git a/engines/neverhood/blbarchive.cpp b/engines/neverhood/blbarchive.cpp index 9f5f46487c..d730d75718 100644 --- a/engines/neverhood/blbarchive.cpp +++ b/engines/neverhood/blbarchive.cpp @@ -58,8 +58,8 @@ BlbArchive::~BlbArchive() { void BlbArchive::open(const Common::String &filename) { BlbHeader header; uint16 *extDataOffsets; - - _entries.clear(); + + _entries.clear(); if (!_fd.open(filename)) error("BlbArchive::open() Could not open %s", filename.c_str()); @@ -83,16 +83,16 @@ void BlbArchive::open(const Common::String &filename) { entry.fileHash = _fd.readUint32LE(); _entries.push_back(entry); } - + extDataOffsets = new uint16[header.fileCount]; - + // Load file records for (uint i = 0; i < header.fileCount; i++) { BlbArchiveEntry &entry = _entries[i]; entry.type = _fd.readByte(); entry.comprType = _fd.readByte(); entry.extData = NULL; - extDataOffsets[i] = _fd.readUint16LE(); + extDataOffsets[i] = _fd.readUint16LE(); entry.timeStamp = _fd.readUint32LE(); entry.offset = _fd.readUint32LE(); entry.diskSize = _fd.readUint32LE(); @@ -101,7 +101,7 @@ void BlbArchive::open(const Common::String &filename) { entry.fileHash, entry.type, entry.comprType, extDataOffsets[i], entry.timeStamp, entry.offset, entry.diskSize, entry.size); } - + // Load ext data if (header.extDataSize > 0) { _extData = new byte[header.extDataSize]; @@ -120,9 +120,9 @@ void BlbArchive::load(uint index, byte *buffer, uint32 size) { void BlbArchive::load(BlbArchiveEntry *entry, byte *buffer, uint32 size) { Common::StackLock lock(_mutex); - + _fd.seek(entry->offset); - + switch (entry->comprType) { case 1: // Uncompressed if (size == 0) diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp new file mode 100644 index 0000000000..733d7dd8a4 --- /dev/null +++ b/engines/neverhood/console.cpp @@ -0,0 +1,191 @@ +/* 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. + * + */ + +#include "neverhood/console.h" +#include "gui/debugger.h" +#include "neverhood/neverhood.h" +#include "neverhood/gamemodule.h" +#include "neverhood/scene.h" +#include "neverhood/sound.h" +#include "neverhood/modules/module1600.h" + +namespace Neverhood { + +Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) { + DCmd_Register("cheat", WRAP_METHOD(Console, Cmd_Cheat)); + DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars)); + DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); + DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces)); + DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound)); +} + +Console::~Console() { +} + +bool Console::Cmd_Room(int argc, const char **argv) { + int currentModule = _vm->_gameModule->getCurrentModuleNum(); + int previousModule = _vm->_gameModule->getPreviousModuleNum(); + int scene = _vm->gameState().sceneNum; + + DebugPrintf("Current module: %d, previous module: %d, scene %d\n", currentModule, previousModule, scene); + + if (argc != 3) { + DebugPrintf("Use room <module> <scene> to change rooms\n"); + DebugPrintf("Modules are incremental by 100, from 1000 to 3000\n"); + } else { + int newModule = atoi(argv[1]); + int newScene = atoi(argv[2]); + + _vm->gameState().sceneNum = newScene; + _vm->_gameModule->createModule(newModule, -1); + } + + return true; +} + +bool Console::Cmd_Surfaces(int argc, const char **argv) { + if (_vm->_gameModule->_childObject) { + ((Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject)->printSurfaces(this); + } + return true; +} + +bool Console::Cmd_Cheat(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Cheats for various puzzles in the game\n"); + DebugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]); + DebugPrintf("Cheats:\n-------\n"); + DebugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n"); + DebugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n"); + DebugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n"); + DebugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n"); + DebugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n"); + DebugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n"); + DebugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n"); + DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n"); + return true; + } + + Common::String cheatName = argv[1]; + int moduleNum = _vm->_gameModule->getCurrentModuleNum(); + int sceneNum = _vm->gameState().sceneNum; + + if (cheatName == "buttons") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + + scene->setSubVar(VA_LOCKS_DISABLED, 0x304008D2, 1); // kScene3010ButtonNameHashes[0] + scene->setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); // kScene3010ButtonNameHashes[1] + scene->setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); // kScene3010ButtonNameHashes[2] + + DebugPrintf("All 3 door buttons have been enabled\n"); + } else if (cheatName == "cannon") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + + for (int i = 0; i < 3; i++) + scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_1, i)); + + for (int i = 3; i < 6; i++) + scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_2, i - 3)); + + DebugPrintf("Puzzle solved\n"); + } else if (cheatName == "dice") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + DebugPrintf("Good: (%d %d %d), current: (%d %d %d)\n", + scene->getSubVar(VA_GOOD_DICE_NUMBERS, 0), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 1), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 2), + scene->getSubVar(VA_CURR_DICE_NUMBERS, 0), scene->getSubVar(VA_CURR_DICE_NUMBERS, 1), scene->getSubVar(VA_CURR_DICE_NUMBERS, 2) + ); + } else if (cheatName == "memory") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + + // Autosolve all tiles and leave only two matching tiles closed + for (int i = 0; i < 48; i++) + scene->setSubVar(VA_IS_TILE_MATCH, i, 1); + + // Close the top left tile + scene->setSubVar(VA_IS_TILE_MATCH, 0, 0); + + // Find and close the pair of the top left tile + for (int i = 0; i < 48; i++) { + if (i != 0 && scene->getSubVar(VA_TILE_SYMBOLS, i) == scene->getSubVar(VA_TILE_SYMBOLS, 0)) { + scene->setSubVar(VA_IS_TILE_MATCH, i, 0); + break; + } + } + + DebugPrintf("Puzzle solved\n"); + } else if (cheatName == "music") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + DebugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); + } else if (cheatName == "radio") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + scene->setGlobalVar(V_RADIO_ENABLED, 1); + + DebugPrintf("The radio has been enabled\n"); + } else if (cheatName == "symbols") { + if (moduleNum == 1600 && sceneNum == 8) { + Scene1609 *scene = ((Scene1609 *)((Module1600 *)_vm->_gameModule->_childObject)->_childObject); + + for (int index = 0; index < 12; index++) { + scene->_asSymbols[index]->change((int)scene->getSubVar(VA_CODE_SYMBOLS, index) + 12, index == (int)scene->getSubVar(VA_CODE_SYMBOLS, scene->_noisySymbolIndex)); + } + + scene->_changeCurrentSymbol = false; + scene->_symbolPosition = 11; + scene->_countdown1 = 36; + + DebugPrintf("Puzzle solved\n"); + } else { + DebugPrintf("Only available in module 1600, scene 8\n"); + } + } else if (cheatName == "tubes") { + Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; + DebugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); + DebugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); + } + + return true; +} + +bool Console::Cmd_Dumpvars(int argc, const char **argv) { + _vm->_gameVars->dumpVars(this); + + return true; +} + +bool Console::Cmd_PlaySound(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: %s <sound hash>\n", argv[0]); + } else { + uint32 soundHash = strtol(argv[1], NULL, 0); + AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem(_vm, soundHash); + soundItem->setVolume(100); + soundItem->playSound(false); + while (soundItem->isPlaying()) { + _vm->_system->delayMillis(10); + } + delete soundItem; + } + + return true; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/console.h b/engines/neverhood/console.h new file mode 100644 index 0000000000..62d65bd693 --- /dev/null +++ b/engines/neverhood/console.h @@ -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. + * + */ + +#ifndef NEVERHOOD_CONSOLE_H +#define NEVERHOOD_CONSOLE_H + +#include "gui/debugger.h" + +namespace Neverhood { + +class NeverhoodEngine; + +class Console : public GUI::Debugger { +public: + Console(NeverhoodEngine *vm); + virtual ~Console(void); + +private: + NeverhoodEngine *_vm; + + bool Cmd_Room(int argc, const char **argv); + bool Cmd_Surfaces(int argc, const char **argv); + bool Cmd_Cheat(int argc, const char **argv); + bool Cmd_Dumpvars(int argc, const char **argv); + bool Cmd_PlaySound(int argc, const char **argv); +}; + +} // End of namespace Neverhood +#endif diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp index 5f860f8519..3de087051a 100644 --- a/engines/neverhood/detection.cpp +++ b/engines/neverhood/detection.cpp @@ -24,6 +24,7 @@ #include "engines/advancedDetector.h" #include "common/file.h" +#include "common/translation.h" #include "neverhood/neverhood.h" @@ -143,6 +144,13 @@ static const NeverhoodGameDescription gameDescriptions[] = { } // End of namespace Neverhood +static const ExtraGuiOption neverhoodExtraGuiOption = { + _s("Use original save/load screens"), + _s("Use the original save/load screens, instead of the ScummVM ones"), + "originalsaveload", + false +}; + class NeverhoodMetaEngine : public AdvancedMetaEngine { public: NeverhoodMetaEngine() : AdvancedMetaEngine(Neverhood::gameDescriptions, sizeof(Neverhood::NeverhoodGameDescription), neverhoodGames) { @@ -160,7 +168,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; - + virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const; SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; void removeSaveState(const char *target, int slot) const; @@ -194,6 +202,12 @@ bool NeverhoodMetaEngine::createInstance(OSystem *syst, Engine **engine, const A return gd != 0; } +const ExtraGuiOptions NeverhoodMetaEngine::getExtraGuiOptions(const Common::String &target) const { + ExtraGuiOptions options; + options.push_back(neverhoodExtraGuiOption); + return options; +} + SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const { Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Neverhood::NeverhoodEngine::SaveHeader header; diff --git a/engines/neverhood/diskplayerscene.cpp b/engines/neverhood/diskplayerscene.cpp index d972943759..ef2b856b2f 100644 --- a/engines/neverhood/diskplayerscene.cpp +++ b/engines/neverhood/diskplayerscene.cpp @@ -61,7 +61,7 @@ static const uint32 kDiskplayerSmackerFileHashes[] = { 0x04002810 }; -static const uint32 kDiskplayerSlotFileHashes1[] = { +static const uint32 kDiskplayerSlotFileHashes1[] = { 0x81312280, 0x01312281, 0x01312282, @@ -84,7 +84,7 @@ static const uint32 kDiskplayerSlotFileHashes1[] = { 0x04312281 }; -static const uint32 kDiskplayerSlotFileHashes2[] = { +static const uint32 kDiskplayerSlotFileHashes2[] = { 0x90443A00, 0x90443A18, 0x90443A28, @@ -107,8 +107,8 @@ static const uint32 kDiskplayerSlotFileHashes2[] = { 0xC0443A18 }; -static const uint32 kDiskplayerSlotFileHashes3[] = { - 0x10357320, +static const uint32 kDiskplayerSlotFileHashes3[] = { + 0x10357320, 0x10557320, 0x10957320, 0x11157320, @@ -130,7 +130,7 @@ static const uint32 kDiskplayerSlotFileHashes3[] = { 0x10543320 }; -static const uint32 kDiskplayerSlotFileHashes4[] = { +static const uint32 kDiskplayerSlotFileHashes4[] = { 0xDC8020E4, 0xDC802164, 0xDC802264, @@ -155,7 +155,7 @@ static const uint32 kDiskplayerSlotFileHashes4[] = { AsDiskplayerSceneKey::AsDiskplayerSceneKey(NeverhoodEngine *vm) : AnimatedSprite(vm, 1100) { - + createSurface1(0x100B90B4, 1200); _x = 211; _y = 195; @@ -193,7 +193,7 @@ void AsDiskplayerSceneKey::stDropKeyDone() { DiskplayerPlayButton::DiskplayerPlayButton(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene) : StaticSprite(vm, 1400), _diskplayerScene(diskplayerScene), _isPlaying(false) { - + loadSprite(0x24A4A664, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); loadSound(0, 0x44043000); @@ -317,10 +317,10 @@ void DiskplayerSlot::stop() { DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int paletteIndex) : Scene(vm, parentModule), _diskIndex(0), _appearCountdown(0), _tuneInCountdown(0), - _hasAllDisks(false), _dropKey(false), _inputDisabled(true), _updateStatus(kUSStopped) { + _hasAllDisks(false), _dropKey(false), _inputDisabled(true), _updateStatus(kUSStopped) { int availableDisksCount = 0; - + setBackground(0x8A000044); setPalette(kDiskplayerPaletteFileHashes[paletteIndex]); @@ -344,7 +344,7 @@ DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int } _hasAllDisks = availableDisksCount == 20; - + if (_hasAllDisks && !getGlobalVar(V_HAS_FINAL_KEY)) _dropKey = true; @@ -354,16 +354,14 @@ DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int insertPuzzleMouse(0x000408A8, 20, 620); showMouse(false); - _diskSmackerPlayer = new SmackerPlayer(_vm, this, 0x08288103, false, true); - addEntity(_diskSmackerPlayer); - addSurface(_diskSmackerPlayer->getSurface()); + _diskSmackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08288103, false, true)); _diskSmackerPlayer->setDrawPos(154, 86); _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder()); _palette->usePalette(); - SetMessageHandler(&DiskplayerScene::handleMessage); - SetUpdateHandler(&DiskplayerScene::update); + SetMessageHandler(&DiskplayerScene::handleMessage); + SetUpdateHandler(&DiskplayerScene::update); _appearCountdown = 6; } @@ -419,7 +417,7 @@ void DiskplayerScene::update() { } _diskIndex++; while (!_diskAvailable[_diskIndex] && _diskIndex < 19) - _diskIndex++; + _diskIndex++; if (_diskIndex < 20) { _appearCountdown = 1; } else { @@ -450,7 +448,7 @@ uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam ¶m, } else if (!_dropKey && param.asPoint().x > 38 && param.asPoint().x < 598 && param.asPoint().y > 400 && param.asPoint().y < 460) { - + _diskSlots[_diskIndex]->stop(); _diskIndex = (param.asPoint().x - 38) / 28; _diskSlots[_diskIndex]->activate(); @@ -464,45 +462,43 @@ uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam ¶m, break; case 0x2000: tuneIn(); - break; + break; case 0x2001: stop(); - break; + break; } } return 0; } -void DiskplayerScene::stop() { - _diskSmackerPlayer->open(0x08288103, true); +void DiskplayerScene::openSmacker(uint32 fileHash, bool keepLastFrame) { + _diskSmackerPlayer->open(fileHash, keepLastFrame); _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder()); _palette->usePalette(); +} + +void DiskplayerScene::stop() { + openSmacker(0x08288103, true); _ssPlayButton->release(); _updateStatus = kUSStopped; _diskSlots[_diskIndex]->activate(); } void DiskplayerScene::tuneIn() { - _diskSmackerPlayer->open(0x900001C1, false); - _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder()); - _palette->usePalette(); + openSmacker(0x900001C1, false); _ssPlayButton->release(); _updateStatus = kUSTuningIn; _diskSlots[_diskIndex]->activate(); } void DiskplayerScene::playDisk() { - _diskSmackerPlayer->open(kDiskplayerSmackerFileHashes[_diskIndex], false); - _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder()); - _palette->usePalette(); + openSmacker(kDiskplayerSmackerFileHashes[_diskIndex], false); _updateStatus = kUSPlaying; _diskSlots[_diskIndex]->play(); } void DiskplayerScene::playStatic() { - _diskSmackerPlayer->open(0x90000101, false); - _vm->_screen->setSmackerDecoder(_diskSmackerPlayer->getSmackerDecoder()); - _palette->usePalette(); + openSmacker(0x90000101, false); _ssPlayButton->release(); _updateStatus = kUSPlaying; _diskSlots[_diskIndex]->activate(); diff --git a/engines/neverhood/diskplayerscene.h b/engines/neverhood/diskplayerscene.h index f3fd9ea874..150d5c58ed 100644 --- a/engines/neverhood/diskplayerscene.h +++ b/engines/neverhood/diskplayerscene.h @@ -36,7 +36,7 @@ class AsDiskplayerSceneKey : public AnimatedSprite { public: AsDiskplayerSceneKey(NeverhoodEngine *vm); void stDropKey(); -protected: +protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); void stDropKeyDone(); }; @@ -47,7 +47,7 @@ public: void press(); void release(); protected: - DiskplayerScene *_diskplayerScene; + DiskplayerScene *_diskplayerScene; bool _isPlaying; uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; @@ -69,7 +69,7 @@ protected: int _blinkCountdown; bool _isLocked; bool _isBlinking; - void update(); + void update(); }; enum { @@ -99,6 +99,7 @@ protected: bool _dropKey; void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void openSmacker(uint32 fileHash, bool keepLastFrame); void stop(); void tuneIn(); void playDisk(); diff --git a/engines/neverhood/entity.cpp b/engines/neverhood/entity.cpp index 8b1298916c..1ebf1dcf6c 100644 --- a/engines/neverhood/entity.cpp +++ b/engines/neverhood/entity.cpp @@ -25,29 +25,29 @@ namespace Neverhood { -uint32 MessageParam::asInteger() const { - assert(_type == mptInteger); - return _integer; +uint32 MessageParam::asInteger() const { + assert(_type == mptInteger); + return _integer; } -NPoint MessageParam::asPoint() const { +NPoint MessageParam::asPoint() const { assert(_type == mptInteger || _type == mptPoint); if (_type == mptInteger) { NPoint pt; pt.x = _integer & 0xFFFF; - pt.y = (_integer >> 16) & 0xFFFF; + pt.y = (_integer >> 16) & 0xFFFF; return pt; - } - return _point; + } + return _point; } Entity *MessageParam::asEntity() const { - assert(_type == mptEntity); - return _entity; + assert(_type == mptEntity); + return _entity; } Entity::Entity(NeverhoodEngine *vm, int priority) - : _vm(vm), _updateHandlerCb(NULL), _messageHandlerCb(NULL), _priority(priority), _soundResources(NULL) { + : _vm(vm), _updateHandlerCb(NULL), _messageHandlerCb(nullptr), _priority(priority), _soundResources(NULL) { } Entity::~Entity() { diff --git a/engines/neverhood/entity.h b/engines/neverhood/entity.h index cba1bb9a7f..5c29bf8a4f 100644 --- a/engines/neverhood/entity.h +++ b/engines/neverhood/entity.h @@ -98,7 +98,7 @@ public: void incGlobalVar(uint32 nameHash, int incrValue); void incSubVar(uint32 nameHash, uint32 subNameHash, int incrValue); int getPriority() const { return _priority; } - bool hasMessageHandler() const { return _messageHandlerCb != NULL; } + bool hasMessageHandler() const { return _messageHandlerCb != nullptr; } protected: void (Entity::*_updateHandlerCb)(); uint32 (Entity::*_messageHandlerCb)(int messageNum, const MessageParam ¶m, Entity *sender); diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp index 49682b0d29..47cc818fea 100644 --- a/engines/neverhood/gamemodule.cpp +++ b/engines/neverhood/gamemodule.cpp @@ -77,7 +77,7 @@ GameModule::GameModule(NeverhoodEngine *vm) : Module(vm, NULL), _moduleNum(-1), _prevChildObject(NULL), _prevModuleNum(-1), _restoreGameRequested(false), _restartGameRequested(false), _canRequestMainMenu(true), _mainMenuRequested(false) { - + // Other initializations moved to actual engine class _vm->_soundMan->playSoundThree(0x002D0031, 0x8861079); SetMessageHandler(&GameModule::handleMessage); @@ -96,7 +96,7 @@ void GameModule::handleMouseMove(int16 x, int16 y) { mousePos.y = y; debug(2, "GameModule::handleMouseMove(%d, %d)", x, y); sendPointMessage(_childObject, 0, mousePos); - } + } } void GameModule::handleMouseDown(int16 x, int16 y) { @@ -106,7 +106,7 @@ void GameModule::handleMouseDown(int16 x, int16 y) { mousePos.y = y; debug(2, "GameModule::handleMouseDown(%d, %d)", x, y); sendPointMessage(_childObject, 0x0001, mousePos); - } + } } void GameModule::handleMouseUp(int16 x, int16 y) { @@ -116,21 +116,21 @@ void GameModule::handleMouseUp(int16 x, int16 y) { mousePos.y = y; debug(2, "GameModule::handleMouseUp(%d, %d)", x, y); sendPointMessage(_childObject, 0x0002, mousePos); - } + } } void GameModule::handleSpaceKey() { if (_childObject) { debug(2, "GameModule::handleSpaceKey()"); sendMessage(_childObject, 0x0009, 0); - } + } } void GameModule::handleAsciiKey(char key) { if (_childObject) { debug(2, "GameModule::handleAsciiKey()"); sendMessage(_childObject, 0x000A, (uint32)key); - } + } } void GameModule::handleKeyDown(Common::KeyCode keyCode) { @@ -141,7 +141,7 @@ void GameModule::handleKeyDown(Common::KeyCode keyCode) { handleSpaceKey(); debug(2, "GameModule::handleKeyDown()"); sendMessage(_childObject, 0x000B, keyCode); - } + } } void GameModule::handleEscapeKey() { @@ -166,7 +166,7 @@ void GameModule::initKeySlotsPuzzle() { void GameModule::initMemoryPuzzle() { if (!getSubVar(VA_IS_PUZZLE_INIT, 0xC8606803)) { - NonRepeatingRandomNumbers diceIndices(_vm->_rnd, 3); + NonRepeatingRandomNumbers diceIndices(_vm->_rnd, 3); NonRepeatingRandomNumbers availableTiles(_vm->_rnd, 48); NonRepeatingRandomNumbers tileSymbols(_vm->_rnd, 10); for (uint32 i = 0; i < 3; i++) @@ -194,21 +194,6 @@ void GameModule::initMemoryPuzzle() { tileSymbolIndex = 0; } setSubVar(VA_IS_PUZZLE_INIT, 0xC8606803, 1); - - // DEBUG Enable to autosolve all tiles and leave only two matching tiles open -#if 0 - for (int i = 0; i < 48; i++) - setSubVar(VA_IS_TILE_MATCH, i, 1); - int debugIndex = 0; - setSubVar(VA_IS_TILE_MATCH, debugIndex, 0); - for (int i = 0; i < 48; i++) { - if (i != debugIndex && getSubVar(VA_TILE_SYMBOLS, i) == getSubVar(VA_TILE_SYMBOLS, debugIndex)) { - setSubVar(VA_IS_TILE_MATCH, i, 0); - break; - } - } -#endif - } } @@ -335,11 +320,11 @@ uint32 GameModule::handleMessage(int messageNum, const MessageParam ¶m, Enti switch (messageNum) { case 0x0800: _canRequestMainMenu = true; - break; + break; case 0x1009: _moduleResult = param.asInteger(); _done = true; - break; + break; } return messageResult; } @@ -426,6 +411,8 @@ void GameModule::checkRequests() { } if (_restoreGameRequested) { _restoreGameRequested = false; + _vm->_audioResourceMan->stopAllSounds(); + _vm->_soundMan->stopAllSounds(); delete _childObject; delete _prevChildObject; _childObject = NULL; @@ -438,8 +425,11 @@ void GameModule::checkRequests() { } void GameModule::createModule(int moduleNum, int which) { - debug("GameModule::createModule(%d, %d)", moduleNum, which); + debug(1, "GameModule::createModule(%d, %d)", moduleNum, which); _moduleNum = moduleNum; + + delete _childObject; + switch (_moduleNum) { case 1000: setGlobalVar(V_MODULE_NAME, 0x03294419); @@ -539,7 +529,7 @@ void GameModule::createModule(int moduleNum, int which) { } void GameModule::createModuleByHash(uint32 nameHash) { - debug("GameModule::createModuleByHash(%08X)", nameHash); + debug(1, "GameModule::createModuleByHash(%08X)", nameHash); switch (nameHash) { case 0x03294419: createModule(1000, -1); @@ -684,7 +674,7 @@ void GameModule::updateModule() { createModule(2300, 1); break; case 2300: - debug("module 23000 _moduleResult : %d", _moduleResult); + debug(1, "module 23000 _moduleResult : %d", _moduleResult); if (_moduleResult == 2) createModule(1200, 0); else if (_moduleResult == 0) @@ -796,6 +786,7 @@ void GameModule::openMainMenu() { createModule(1000, 0); } _vm->_screen->saveParams(); + _vm->_screen->update(); _mainMenuRequested = false; createMenuModule(); } diff --git a/engines/neverhood/gamemodule.h b/engines/neverhood/gamemodule.h index 8101d38009..2f2fecf463 100644 --- a/engines/neverhood/gamemodule.h +++ b/engines/neverhood/gamemodule.h @@ -49,12 +49,16 @@ public: void initWaterPipesPuzzle(); void initRadioPuzzle(); void initTestTubes1Puzzle(); - void initTestTubes2Puzzle(); + void initTestTubes2Puzzle(); void initCannonSymbolsPuzzle(); void initCodeSymbolsPuzzle(); void initCubeSymbolsPuzzle(); void initCrystalColorsPuzzle(); uint32 getCurrRadioMusicFileHash(); + int getCurrentModuleNum() { return _moduleNum; } + int getPreviousModuleNum() { return _moduleNum; } + + void createModule(int moduleNum, int which); protected: int _moduleNum; Entity *_prevChildObject; @@ -64,7 +68,6 @@ protected: bool _canRequestMainMenu; bool _mainMenuRequested; uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); - void createModule(int moduleNum, int which); void createModuleByHash(uint32 nameHash); void updateModule(); void openMainMenu(); diff --git a/engines/neverhood/gamevars.cpp b/engines/neverhood/gamevars.cpp index 87f5fe6dd9..9c080fea24 100644 --- a/engines/neverhood/gamevars.cpp +++ b/engines/neverhood/gamevars.cpp @@ -20,6 +20,7 @@ * */ +#include "neverhood/console.h" #include "neverhood/gamevars.h" namespace Neverhood { @@ -74,7 +75,7 @@ uint32 GameVars::getSubVar(uint32 nameHash, uint32 subNameHash) { int16 subVarIndex = findSubVarIndex(varIndex, subNameHash); if (subVarIndex != -1) value = _vars[subVarIndex].value; - } + } return value; } @@ -123,10 +124,10 @@ int16 GameVars::getSubVarIndex(int16 varIndex, uint32 subNameHash) { return subVarIndex; } -void GameVars::dumpVars() { +void GameVars::dumpVars(Console *con) { for (Common::Array<GameVar>::iterator it = _vars.begin(); it != _vars.end(); ++it) { GameVar gameVar = *it; - debug("%08X %08X %3d %3d", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex); + con->DebugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex); } } diff --git a/engines/neverhood/gamevars.h b/engines/neverhood/gamevars.h index 5337c13394..3aec4d1da4 100644 --- a/engines/neverhood/gamevars.h +++ b/engines/neverhood/gamevars.h @@ -160,7 +160,7 @@ enum { VA_HAS_KEY = 0x0090EA95, VA_IS_KEY_INSERTED = 0x08D0AB11, VA_LOCKS_DISABLED = 0x14800353, - V_END_ + V_END_ }; struct GameVar { @@ -169,6 +169,8 @@ struct GameVar { int16 firstIndex, nextIndex; }; +class Console; + class GameVars { public: GameVars(); @@ -179,7 +181,7 @@ public: void setGlobalVar(uint32 nameHash, uint32 value); uint32 getSubVar(uint32 nameHash, uint32 subNameHash); void setSubVar(uint32 nameHash, uint32 subNameHash, uint32 value); - void dumpVars(); + void dumpVars(Console *con); protected: Common::Array<GameVar> _vars; int16 addVar(uint32 nameHash, uint32 value); diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp index 5099c7a00e..490959020f 100644 --- a/engines/neverhood/graphics.cpp +++ b/engines/neverhood/graphics.cpp @@ -26,10 +26,10 @@ namespace Neverhood { -BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height) +BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height, Common::String name) : _vm(vm), _priority(priority), _visible(true), _transparent(true), - _clipRects(NULL), _clipRectsCount(0), _version(0) { - + _clipRects(NULL), _clipRectsCount(0), _version(0), _name(name) { + _drawRect.x = 0; _drawRect.y = 0; _drawRect.width = width; @@ -68,7 +68,7 @@ void BaseSurface::clear() { } void BaseSurface::drawSpriteResource(SpriteResource &spriteResource) { - if (spriteResource.getDimensions().width <= _drawRect.width && + if (spriteResource.getDimensions().width <= _drawRect.width && spriteResource.getDimensions().height <= _drawRect.height) { clear(); spriteResource.draw(_surface, false, false); @@ -77,7 +77,7 @@ void BaseSurface::drawSpriteResource(SpriteResource &spriteResource) { } void BaseSurface::drawSpriteResourceEx(SpriteResource &spriteResource, bool flipX, bool flipY, int16 width, int16 height) { - if (spriteResource.getDimensions().width <= _sysRect.width && + if (spriteResource.getDimensions().width <= _sysRect.width && spriteResource.getDimensions().height <= _sysRect.height) { if (width > 0 && width <= _sysRect.width) _drawRect.width = width; @@ -130,7 +130,7 @@ void BaseSurface::copyFrom(Graphics::Surface *sourceSurface, int16 x, int16 y, N // ShadowSurface ShadowSurface::ShadowSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height, BaseSurface *shadowSurface) - : BaseSurface(vm, priority, width, height), _shadowSurface(shadowSurface) { + : BaseSurface(vm, priority, width, height, "shadow"), _shadowSurface(shadowSurface) { // Empty } @@ -143,18 +143,18 @@ void ShadowSurface::draw() { // FontSurface FontSurface::FontSurface(NeverhoodEngine *vm, NPointArray *tracking, uint charsPerRow, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight) - : BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows), _charsPerRow(charsPerRow), _numRows(numRows), + : BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows, "font"), _charsPerRow(charsPerRow), _numRows(numRows), _firstChar(firstChar), _charWidth(charWidth), _charHeight(charHeight), _tracking(NULL) { - + _tracking = new NPointArray(); *_tracking = *tracking; } FontSurface::FontSurface(NeverhoodEngine *vm, uint32 fileHash, uint charsPerRow, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight) - : BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows), _charsPerRow(charsPerRow), _numRows(numRows), + : BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows, "font"), _charsPerRow(charsPerRow), _numRows(numRows), _firstChar(firstChar), _charWidth(charWidth), _charHeight(charHeight), _tracking(NULL) { - + SpriteResource fontSpriteResource(_vm); fontSpriteResource.load(fileHash, true); drawSpriteResourceEx(fontSpriteResource, false, false, 0, 0); @@ -182,7 +182,7 @@ void FontSurface::drawString(BaseSurface *destSurface, int16 x, int16 y, const b for (; stringLen > 0; --stringLen, ++string) { drawChar(destSurface, x, y, *string); x += _tracking ? (*_tracking)[*string - _firstChar].x : _charWidth; - } + } } @@ -201,7 +201,7 @@ FontSurface *FontSurface::createFontSurface(NeverhoodEngine *vm, uint32 fileHash uint16 charHeight = fontData.getPoint(calcHash("meCharHeight")).x; NPointArray *tracking = fontData.getPointArray(calcHash("meTracking")); fontSprite.load(fileHash, true); - fontSurface = new FontSurface(vm, tracking, 16, numRows, firstChar, charWidth, charHeight); + fontSurface = new FontSurface(vm, tracking, 16, numRows, firstChar, charWidth, charHeight); fontSurface->drawSpriteResourceEx(fontSprite, false, false, 0, 0); return fontSurface; } @@ -219,7 +219,7 @@ enum BitmapFlags { void parseBitmapResource(const byte *sprite, bool *rle, NDimensions *dimensions, NPoint *position, const byte **palette, const byte **pixels) { uint16 flags; - + flags = READ_LE_UINT16(sprite); sprite += 2; @@ -278,7 +278,7 @@ void unpackSpriteRle(const byte *source, int width, int height, byte *dest, int rows = READ_LE_UINT16(source); chunks = READ_LE_UINT16(source + 2); source += 4; - + do { if (chunks == 0) { dest += rows * destPitch; @@ -316,7 +316,7 @@ void unpackSpriteRle(const byte *source, int width, int height, byte *dest, int void unpackSpriteNormal(const byte *source, int width, int height, byte *dest, int destPitch, bool flipX, bool flipY) { const int sourcePitch = (width + 3) & 0xFFFC; - + if (flipY) { dest += destPitch * (height - 1); destPitch = -destPitch; @@ -343,7 +343,7 @@ void unpackSpriteNormal(const byte *source, int width, int height, byte *dest, i int calcDistance(int16 x1, int16 y1, int16 x2, int16 y2) { const int16 deltaX = ABS(x1 - x2); const int16 deltaY = ABS(y1 - y2); - return sqrt((double)(deltaX * deltaX + deltaY * deltaY)); + return (int)sqrt((double)(deltaX * deltaX + deltaY * deltaY)); } } // End of namespace Neverhood diff --git a/engines/neverhood/graphics.h b/engines/neverhood/graphics.h index a0ac1f09d5..b80bd60729 100644 --- a/engines/neverhood/graphics.h +++ b/engines/neverhood/graphics.h @@ -43,9 +43,11 @@ struct NDimensions { struct NRect { int16 x1, y1, x2, y2; - NRect() : x1(0), y1(0), x2(0), y2(0) {} - - NRect(int16 x01, int16 y01, int16 x02, int16 y02) : x1(x01), y1(y01), x2(x02), y2(y02) {} + static NRect make(int16 x01, int16 y01, int16 x02, int16 y02) { + NRect r; + r.set(x01, y01, x02, y02); + return r; + } void set(int16 x01, int16 y01, int16 x02, int16 y02) { x1 = x01; @@ -62,12 +64,12 @@ struct NRect { typedef Common::Array<NRect> NRectArray; -// TODO: Use Common::Rect +// TODO: Use Common::Rect struct NDrawRect { int16 x, y, width, height; NDrawRect() : x(0), y(0), width(0), height(0) {} NDrawRect(int16 x0, int16 y0, int16 width0, int16 height0) : x(x0), y(y0), width(width0), height(height0) {} - int16 x2() { return x + width; } + int16 x2() { return x + width; } int16 y2() { return y + height; } void set(int16 x0, int16 y0, int16 width0, int16 height0) { x = x0; @@ -83,7 +85,7 @@ class MouseCursorResource; class BaseSurface { public: - BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height); + BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height, Common::String name); virtual ~BaseSurface(); virtual void draw(); void clear(); @@ -104,10 +106,12 @@ public: void setVisible(bool value) { _visible = value; } void setTransparent(bool value) { _transparent = value; } Graphics::Surface *getSurface() { return _surface; } + const Common::String getName() const { return _name; } protected: NeverhoodEngine *_vm; int _priority; bool _visible; + Common::String _name; Graphics::Surface *_surface; NDrawRect _drawRect; NDrawRect _sysRect; diff --git a/engines/neverhood/klaymen.cpp b/engines/neverhood/klaymen.cpp index 06d606e18d..8ed27c825a 100644 --- a/engines/neverhood/klaymen.cpp +++ b/engines/neverhood/klaymen.cpp @@ -33,19 +33,19 @@ static const KlaymenIdleTableItem klaymenIdleTable1[] = { {1, kIdleArms}, {1, kIdleChest}, {1, kIdleHeadOff} -}; +}; static const KlaymenIdleTableItem klaymenIdleTable2[] = { {1, kIdlePickEar}, {1, kIdleSpinHead}, {1, kIdleChest}, {1, kIdleHeadOff} -}; +}; static const KlaymenIdleTableItem klaymenIdleTable3[] = { {1, kIdleTeleporterHands}, {1, kIdleTeleporterHands2} -}; +}; static const KlaymenIdleTableItem klaymenIdleTable4[] = { {1, kIdleSpinHead}, @@ -56,7 +56,7 @@ static const KlaymenIdleTableItem klaymenIdleTable4[] = { static const KlaymenIdleTableItem klaymenIdleTable1002[] = { {1, kIdlePickEar}, {2, kIdleWonderAbout} -}; +}; // Klaymen @@ -66,7 +66,7 @@ Klaymen::Klaymen(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRec _attachedSprite(NULL), _isWalking(false), _actionStatus(1), _parentScene(parentScene), _isSneaking(false), _isLargeStep(false), _doYHitIncr(false), _isLeverDown(false), _isSittingInTeleporter(false), _actionStatusChanged(false), _ladderStatus(0), _pathPoints(NULL), _soundFlag(false), _idleTableNum(0), _otherSprite(NULL), _moveObjectCountdown(0), _readyToSpit(false), _walkResumeFrameIncr(0) { - + createSurface(1000, 320, 200); _x = x; _y = y; @@ -434,7 +434,7 @@ void Klaymen::stopWalking() { } void Klaymen::startIdleAnimation(uint32 fileHash, AnimationCb callback) { - debug("startIdleAnimation(%08X)", fileHash); + debug(1, "startIdleAnimation(%08X)", fileHash); NextState(callback); SetUpdateHandler(&Klaymen::upIdleAnimation); } @@ -447,7 +447,7 @@ void Klaymen::upIdleAnimation() { bool Klaymen::stStartActionFromIdle(AnimationCb callback) { if (_busyStatus == 2) { _busyStatus = 1; - _acceptInput = false; + _acceptInput = false; startAnimation(0x9A7020B8, 0, -1); SetUpdateHandler(&Klaymen::update); SetMessageHandler(&Klaymen::hmStartAction); @@ -684,35 +684,35 @@ void Klaymen::suAction() { _x += _deltaX; } _deltaX = 0; - + if (_doDeltaY) { _y -= _deltaY; } else { _y += _deltaY; } _deltaY = 0; - + if (_frameChanged) { if (xdiff > 6) _x += 6; else if (xdiff < -6) _x -= 6; else - _x = _destX; + _x = _destX; } - + updateBounds(); - + } void Klaymen::suSneaking() { - + int16 xdiff = _destX - _x; - + if (_currFrameIndex == 9) { if (xdiff > 26) _deltaX += xdiff - 26; - else if (xdiff < -26) + else if (xdiff < -26) _deltaX -= xdiff + 26; } @@ -720,7 +720,7 @@ void Klaymen::suSneaking() { xdiff = _deltaX; else if (xdiff < -_deltaX) xdiff = -_deltaX; - _deltaX = 0; + _deltaX = 0; if (_destX != _x) { HitRect *hitRectPrev = _parentScene->findHitRectAtPos(_x, _y); @@ -749,7 +749,7 @@ void Klaymen::suSneaking() { } updateBounds(); } - + } void Klaymen::stSneak() { @@ -761,7 +761,7 @@ void Klaymen::stSneak() { SetUpdateHandler(&Klaymen::update); SetMessageHandler(&Klaymen::hmSneaking); SetSpriteUpdate(&Klaymen::suSneaking); - FinalizeState(&Klaymen::evSneakingDone); + FinalizeState(&Klaymen::evSneakingDone); } void Klaymen::evSneakingDone() { @@ -801,7 +801,7 @@ void Klaymen::stStartWalking() { SetMessageHandler(&Klaymen::hmStartWalking); SetSpriteUpdate(&Klaymen::suWalkingTestExit); NextState(&Klaymen::stWalkingFirst); - FinalizeState(&Klaymen::evStartWalkingDone); + FinalizeState(&Klaymen::evStartWalkingDone); } } @@ -832,7 +832,7 @@ void Klaymen::stWalkingFirst() { SetMessageHandler(&Klaymen::hmWalking); SetSpriteUpdate(&Klaymen::suWalkingFirst); NextState(&Klaymen::stUpdateWalkingFirst); - FinalizeState(&Klaymen::evStartWalkingDone); + FinalizeState(&Klaymen::evStartWalkingDone); } void Klaymen::suWalkingFirst() { @@ -882,20 +882,20 @@ void Klaymen::stUpdateWalkingFirst() { SetUpdateHandler(&Klaymen::update); SetMessageHandler(&Klaymen::hmSneaking); SetSpriteUpdate(&Klaymen::suSneaking); - FinalizeState(&Klaymen::evSneakingDone); + FinalizeState(&Klaymen::evSneakingDone); } } void Klaymen::suWalkingTestExit() { int16 xdiff = ABS(_destX - _x); int16 xdelta = _destX - _x; - + if (xdelta > _deltaX) xdelta = _deltaX; else if (xdelta < -_deltaX) xdelta = -_deltaX; - - _deltaX = 0; + + _deltaX = 0; if (xdiff == 0 || (_actionStatus != 2 && _actionStatus != 3 && xdiff <= 42 && _currFrameIndex >= 5 && _currFrameIndex <= 11) || @@ -928,7 +928,7 @@ void Klaymen::suWalkingTestExit() { } updateBounds(); } - + } uint32 Klaymen::hmLever(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -1363,7 +1363,7 @@ void Klaymen::stLargeStep() { SetUpdateHandler(&Klaymen::update); SetMessageHandler(&Klaymen::hmLargeStep); SetSpriteUpdate(&Klaymen::suLargeStep); - FinalizeState(&Klaymen::evLargeStepDone); + FinalizeState(&Klaymen::evLargeStepDone); } void Klaymen::evLargeStepDone() { @@ -1372,11 +1372,11 @@ void Klaymen::evLargeStepDone() { void Klaymen::suLargeStep() { int16 xdiff = _destX - _x; - + if (_doDeltaX) { _deltaX = -_deltaX; } - + if (_currFrameIndex == 7) { _deltaX = xdiff; } @@ -1385,7 +1385,7 @@ void Klaymen::suLargeStep() { xdiff = _deltaX; _deltaX = 0; - + if (_x != _destX) { HitRect *hitRectPrev = _parentScene->findHitRectAtPos(_x, _y); _x += xdiff; @@ -1420,7 +1420,7 @@ uint32 Klaymen::hmLargeStep(int messageNum, const MessageParam ¶m, Entity *s case 0x3002: _x = _destX; gotoNextStateExt(); - break; + break; } return messageResult; } @@ -1681,7 +1681,7 @@ void Klaymen::stStartClimbLadderDown() { _ladderStatus = 2; _acceptInput = true; startAnimation(0x122D1505, 29 - _currFrameIndex, -1); - } + } } } @@ -1979,7 +1979,7 @@ uint32 Klaymen::hmMoveObjectTurn(int messageNum, const MessageParam ¶m, Enti break; case 0x480A: _isMoveObjectRequested = true; - return 0; + return 0; } return hmLowLevelAnimation(messageNum, param, sender); } @@ -2521,7 +2521,7 @@ void Klaymen::stInsertKey() { more = true; } while (more); _keysToInsert++; - } + } } if (_keysToInsert == 0) { GotoState(NULL); @@ -3049,7 +3049,7 @@ void Klaymen::stFallSkipJump() { void Klaymen::upMoveObject() { if (_x >= 380) gotoNextStateExt(); - Klaymen::update(); + Klaymen::update(); } uint32 Klaymen::hmMatch(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -3165,7 +3165,7 @@ void Klaymen::stTumbleHeadless() { void Klaymen::stCloseEyes() { if (!stStartActionFromIdle(AnimationCallback(&Klaymen::stCloseEyes))) { _busyStatus = 1; - _acceptInput = false; + _acceptInput = false; startAnimation(0x5420E254, 0, -1); SetUpdateHandler(&Klaymen::update); SetMessageHandler(&Klaymen::hmLowLevel); @@ -3358,7 +3358,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4004: GotoState(&Klaymen::stTryStandIdle); - break; + break; case 0x4804: if (param.asInteger() == 2) GotoState(&Klaymen::stSleeping); @@ -3380,7 +3380,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -3408,10 +3408,10 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2002, 0); GotoState(&Klaymen::stWakeUp); } - break; + break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -3423,7 +3423,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1002::KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + setKlaymenIdleTable1(); } @@ -3438,7 +3438,7 @@ void KmScene1002::xUpdate() { _idleTableNum = 0; } } - + uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x2001: @@ -3451,7 +3451,7 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4800: startWalkToX(param.asPoint().x, false); break; - case 0x4004: + case 0x4004: GotoState(&Klaymen::stTryStandIdle); break; case 0x4803: @@ -3479,42 +3479,42 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam ¶m) { break; } break; - case 0x480A: + case 0x480A: GotoState(&Klaymen::stMoveVenusFlyTrap); break; - case 0x480D: + case 0x480D: GotoState(&Klaymen::stJumpToRingVenusFlyTrap); break; - case 0x4816: + case 0x4816: if (param.asInteger() == 0) GotoState(&Klaymen::stPressDoorButton); break; - case 0x4817: + case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); break; - case 0x481B: + case 0x481B: startWalkToAttachedSpriteXDistance(param.asInteger()); break; - case 0x4820: + case 0x4820: sendMessage(_parentScene, 0x2005, 0); - GotoState(&Klaymen::stContinueClimbLadderUp); + GotoState(&Klaymen::stContinueClimbLadderUp); break; - case 0x4821: + case 0x4821: sendMessage(_parentScene, 0x2005, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderDown); + GotoState(&Klaymen::stStartClimbLadderDown); break; - case 0x4822: + case 0x4822: sendMessage(_parentScene, 0x2005, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderUp); + GotoState(&Klaymen::stStartClimbLadderUp); break; case 0x4823: sendMessage(_parentScene, 0x2006, 0); - GotoState(&Klaymen::stClimbLadderHalf); + GotoState(&Klaymen::stClimbLadderHalf); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStep); else @@ -3529,7 +3529,7 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x483F: startSpecialWalkRight(param.asInteger()); break; - case 0x4840: + case 0x4840: startSpecialWalkLeft(param.asInteger()); break; } @@ -3540,8 +3540,8 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1004::KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - - _dataResource.load(0x01900A04); + + _dataResource.load(0x01900A04); } uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -3606,7 +3606,7 @@ uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1109::KmScene1109(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + // Empty } @@ -3615,7 +3615,7 @@ uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x2000: _isSittingInTeleporter = param.asInteger() != 0; - messageResult = 1; + messageResult = 1; break; case 0x4001: case 0x4800: @@ -3653,7 +3653,7 @@ uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2000, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2000, 0); _isSittingInTeleporter = false; @@ -3673,7 +3673,7 @@ uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1201::KmScene1201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + setKlaymenIdleTable(klaymenIdleTable4, ARRAYSIZE(klaymenIdleTable4)); _doYHitIncr = true; } @@ -3741,7 +3741,7 @@ uint32 KmScene1201::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1303::KmScene1303(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + // Empty } @@ -3762,8 +3762,8 @@ uint32 KmScene1303::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1304::KmScene1304(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - - // Empty + + // Empty } uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -3774,7 +3774,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4004: GotoState(&Klaymen::stTryStandIdle); - break; + break; case 0x4812: if (param.asInteger() == 2) GotoState(&Klaymen::stPickUpNeedle); @@ -3792,7 +3792,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam ¶m) { startWalkToXDistance(param.asPoint().y, param.asPoint().x); else startWalkToAttachedSpriteXDistance(param.asPoint().x); - break; + break; case 0x481F: if (param.asInteger() == 1) GotoState(&Klaymen::stTurnAwayFromUse); @@ -3803,7 +3803,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -3814,7 +3814,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1305::KmScene1305(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - // Empty + // Empty } uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -3825,10 +3825,10 @@ uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4004: GotoState(&Klaymen::stTryStandIdle); - break; + break; case 0x4804: GotoState(&Klaymen::stCrashDown); - break; + break; case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); @@ -3839,7 +3839,7 @@ uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1306::KmScene1306(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + // Empty } @@ -3879,9 +3879,9 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481A: - GotoState(&Klaymen::stInsertDisk); + GotoState(&Klaymen::stInsertDisk); break; case 0x481B: if (param.asPoint().y != 0) @@ -3936,7 +3936,7 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2000, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2000, 0); _isSittingInTeleporter = false; @@ -3944,13 +3944,13 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483D: teleporterAppear(0xEE084A04); - break; + break; case 0x483E: teleporterDisappear(0xB86A4274); - break; + break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -3961,7 +3961,7 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1308::KmScene1308(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - // Empty + // Empty } uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -3978,7 +3978,7 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam ¶m) { GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject); else GotoState(&Klaymen::stMoveObjectFaceObject); - break; + break; case 0x480D: GotoState(&Klaymen::stUseLever); break; @@ -3993,12 +3993,12 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481A: if (param.asInteger() == 1) - GotoState(&Klaymen::stInsertKey); + GotoState(&Klaymen::stInsertKey); else - GotoState(&Klaymen::stInsertDisk); + GotoState(&Klaymen::stInsertDisk); break; case 0x481B: if (param.asPoint().y != 0) @@ -4020,7 +4020,7 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4032,8 +4032,8 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1401::KmScene1401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - - // Empty + + // Empty } uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -4044,13 +4044,13 @@ uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4004: GotoState(&Klaymen::stTryStandIdle); - break; + break; case 0x480A: if (param.asInteger() == 1) GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject); else GotoState(&Klaymen::stMoveObjectFaceObject); - break; + break; case 0x4816: if (param.asInteger() == 1) GotoState(&Klaymen::stPressButton); @@ -4068,7 +4068,7 @@ uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam ¶m) { startWalkToXDistance(param.asPoint().y, param.asPoint().x); else startWalkToAttachedSpriteXDistance(param.asPoint().x); - break; + break; case 0x481F: if (param.asInteger() == 1) GotoState(&Klaymen::stTurnAwayFromUse); @@ -4101,8 +4101,8 @@ uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1402::KmScene1402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - - SetFilterY(&Sprite::defFilterY); + + SetFilterY(&Sprite::defFilterY); } uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -4113,13 +4113,13 @@ uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4004: GotoState(&Klaymen::stTryStandIdle); - break; + break; case 0x480A: if (param.asInteger() == 1) GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject); else GotoState(&Klaymen::stMoveObjectFaceObject); - break; + break; case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); @@ -4129,7 +4129,7 @@ uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam ¶m) { startWalkToXDistance(param.asPoint().y, param.asPoint().x); else startWalkToAttachedSpriteXDistance(param.asPoint().x); - break; + break; case 0x481D: GotoState(&Klaymen::stTurnToUse); break; @@ -4162,7 +4162,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam ¶m) { GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject); else GotoState(&Klaymen::stMoveObjectFaceObject); - break; + break; case 0x480D: GotoState(&Klaymen::stUseLever); break; @@ -4177,7 +4177,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -4189,7 +4189,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4202,7 +4202,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1404::KmScene1404(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - // Empty + // Empty } uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -4219,7 +4219,7 @@ uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam ¶m) { GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject); else GotoState(&Klaymen::stMoveObjectFaceObject); - break; + break; case 0x4812: if (param.asInteger() == 2) GotoState(&Klaymen::stPickUpNeedle); @@ -4233,7 +4233,7 @@ uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam ¶m) { gotoNextStateExt(); break; case 0x481A: - GotoState(&Klaymen::stInsertDisk); + GotoState(&Klaymen::stInsertDisk); break; case 0x481B: if (param.asPoint().y != 0) @@ -4307,7 +4307,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -4345,7 +4345,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2032, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2032, 0); _isSittingInTeleporter = false; @@ -4353,7 +4353,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4366,7 +4366,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1705::KmScene1705(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - // Empty + // Empty } uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -4388,7 +4388,7 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4803: GotoState(&Klaymen::stFallSkipJump); - break; + break; case 0x4812: if (param.asInteger() == 2) GotoState(&Klaymen::stPickUpNeedle); @@ -4435,7 +4435,7 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2000, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2000, 0); _isSittingInTeleporter = false; @@ -4443,10 +4443,10 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483D: teleporterAppear(0x5E0A4905); - break; + break; case 0x483E: teleporterDisappear(0xD86E4477); - break; + break; } return messageResult; } @@ -4454,7 +4454,7 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene1901::KmScene1901(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - // Empty + // Empty } uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -4469,7 +4469,7 @@ uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481D: GotoState(&Klaymen::stTurnToUse); break; @@ -4482,7 +4482,7 @@ uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4493,7 +4493,7 @@ uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene2001::KmScene2001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - // Empty + // Empty } uint32 KmScene2001::xHandleMessage(int messageNum, const MessageParam ¶m) { @@ -4557,7 +4557,7 @@ uint32 KmScene2001::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene2101::KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + // Empty } @@ -4600,7 +4600,7 @@ uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -4622,7 +4622,7 @@ uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2000, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2000, 0); _isSittingInTeleporter = false; @@ -4635,7 +4635,7 @@ uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam ¶m) { teleporterDisappear(0x9A28CA1C); break; } - return messageResult; + return messageResult; } KmScene2201::KmScene2201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount) @@ -4684,7 +4684,7 @@ uint32 KmScene2201::xHandleMessage(int messageNum, const MessageParam ¶m) { setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); gotoNextStateExt(); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStep); else @@ -4698,12 +4698,12 @@ uint32 KmScene2201::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; } - return 0; + return 0; } KmScene2203::KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) @@ -4711,7 +4711,7 @@ KmScene2203::KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 // Empty } - + uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x4001: @@ -4740,7 +4740,7 @@ uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToX(_dataResource.getPoint(param.asInteger()).x, false); break; @@ -4748,7 +4748,7 @@ uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam ¶m) { GotoState(&Klaymen::stClayDoorOpen); break; case 0x481A: - GotoState(&Klaymen::stInsertDisk); + GotoState(&Klaymen::stInsertDisk); break; case 0x481B: if (param.asPoint().y != 0) @@ -4768,7 +4768,7 @@ uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4785,7 +4785,7 @@ KmScene2205::KmScene2205(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 void KmScene2205::xUpdate() { setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex); } - + uint32 KmScene2205::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x4001: @@ -4809,13 +4809,13 @@ uint32 KmScene2205::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToX(_dataResource.getPoint(param.asInteger()).x, false); break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4837,7 +4837,7 @@ KmScene2206::~KmScene2206() { void KmScene2206::xUpdate() { setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex); } - + uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x4001: @@ -4874,7 +4874,7 @@ uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -4897,7 +4897,7 @@ uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam ¶m) { setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); gotoNextStateExt(); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStep); else @@ -4914,7 +4914,7 @@ uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -4927,7 +4927,7 @@ KmScene2207::KmScene2207(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 // Empty } - + uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x2001: @@ -4961,7 +4961,7 @@ uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -4977,7 +4977,7 @@ uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -5022,7 +5022,7 @@ uint32 KmScene2242::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -5080,7 +5080,7 @@ uint32 KmHallOfRecords::xHandleMessage(int messageNum, const MessageParam ¶m case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481F: if (param.asInteger() == 0) GotoState(&Klaymen::stWonderAboutHalf); @@ -5133,7 +5133,7 @@ uint32 KmScene2247::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481F: if (param.asInteger() == 0) GotoState(&Klaymen::stWonderAboutHalf); @@ -5156,13 +5156,13 @@ uint32 KmScene2247::xHandleMessage(int messageNum, const MessageParam ¶m) { } return 0; } - + KmScene2401::KmScene2401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { // Empty } - + uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam ¶m) { uint32 messageResult = 0; switch (messageNum) { @@ -5184,7 +5184,7 @@ uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); @@ -5203,7 +5203,7 @@ uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam ¶m) { setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); gotoNextStateExt(); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStep); else @@ -5228,7 +5228,7 @@ uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x483F: startSpecialWalkRight(param.asInteger()); - break; + break; case 0x4840: startSpecialWalkLeft(param.asInteger()); break; @@ -5357,23 +5357,23 @@ uint32 KmScene2403::xHandleMessage(int messageNum, const MessageParam ¶m) { else GotoState(&Klaymen::stWonderAbout); break; - case 0x4820: + case 0x4820: sendMessage(_parentScene, 0x2000, 0); - GotoState(&Klaymen::stContinueClimbLadderUp); + GotoState(&Klaymen::stContinueClimbLadderUp); break; - case 0x4821: + case 0x4821: sendMessage(_parentScene, 0x2000, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderDown); + GotoState(&Klaymen::stStartClimbLadderDown); break; - case 0x4822: + case 0x4822: sendMessage(_parentScene, 0x2000, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderUp); + GotoState(&Klaymen::stStartClimbLadderUp); break; case 0x4823: sendMessage(_parentScene, 0x2001, 0); - GotoState(&Klaymen::stClimbLadderHalf); + GotoState(&Klaymen::stClimbLadderHalf); break; case 0x482D: setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); @@ -5382,16 +5382,16 @@ uint32 KmScene2403::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x483F: startSpecialWalkRight(param.asInteger()); break; - case 0x4840: + case 0x4840: startSpecialWalkLeft(param.asInteger()); break; } return messageResult; } - + KmScene2406::KmScene2406(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount) : Klaymen(vm, parentScene, x, y) { - + _surface->setClipRects(clipRects, clipRectsCount); } @@ -5425,7 +5425,7 @@ uint32 KmScene2406::xHandleMessage(int messageNum, const MessageParam ¶m) { gotoNextStateExt(); break; case 0x481A: - GotoState(&Klaymen::stInsertDisk); + GotoState(&Klaymen::stInsertDisk); break; case 0x481B: if (param.asPoint().y != 0) @@ -5451,40 +5451,40 @@ uint32 KmScene2406::xHandleMessage(int messageNum, const MessageParam ¶m) { else GotoState(&Klaymen::stWonderAbout); break; - case 0x4820: + case 0x4820: sendMessage(_parentScene, 0x2000, 0); - GotoState(&Klaymen::stContinueClimbLadderUp); + GotoState(&Klaymen::stContinueClimbLadderUp); break; - case 0x4821: + case 0x4821: sendMessage(_parentScene, 0x2000, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderDown); + GotoState(&Klaymen::stStartClimbLadderDown); break; - case 0x4822: + case 0x4822: sendMessage(_parentScene, 0x2000, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderUp); + GotoState(&Klaymen::stStartClimbLadderUp); break; case 0x4823: sendMessage(_parentScene, 0x2001, 0); - GotoState(&Klaymen::stClimbLadderHalf); + GotoState(&Klaymen::stClimbLadderHalf); break; case 0x483F: startSpecialWalkRight(param.asInteger()); break; - case 0x4840: + case 0x4840: startSpecialWalkLeft(param.asInteger()); break; } return messageResult; } - + KmScene2501::KmScene2501(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { // Empty } - + uint32 KmScene2501::xHandleMessage(int messageNum, const MessageParam ¶m) { uint32 messageResult = 0; switch (messageNum) { @@ -5505,7 +5505,7 @@ uint32 KmScene2501::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481D: if (_isSittingInTeleporter) GotoState(&Klaymen::stTurnToUseInTeleporter); @@ -5521,7 +5521,7 @@ uint32 KmScene2501::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2000, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2000, 0); _isSittingInTeleporter = false; @@ -5536,7 +5536,7 @@ KmScene2732::KmScene2732(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 // Empty } - + uint32 KmScene2732::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x4804: @@ -5570,13 +5570,13 @@ uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481B: if (param.asPoint().y != 0) startWalkToXDistance(param.asPoint().y, param.asPoint().x); else startWalkToAttachedSpriteXDistance(param.asPoint().x); - break; + break; case 0x481D: GotoState(&Klaymen::stTurnToUse); break; @@ -5599,7 +5599,7 @@ uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam ¶m) { setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); gotoNextStateExt(); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStep); else @@ -5620,7 +5620,7 @@ uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene2803::KmScene2803(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount) : Klaymen(vm, parentScene, x, y) { - + _surface->setClipRects(clipRects, clipRectsCount); _dataResource.load(0x00900849); } @@ -5648,7 +5648,7 @@ uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToX(_dataResource.getPoint(param.asInteger()).x, false); break; @@ -5664,7 +5664,7 @@ uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam ¶m) { else GotoState(&Klaymen::stWonderAboutHalf); break; - case 0x482E: + case 0x482E: GotoState(&Klaymen::stWalkToFront); break; case 0x482F: @@ -5682,7 +5682,7 @@ uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam ¶m) { KmScene2803Small::KmScene2803Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { - + _dataResource.load(0x81120132); } @@ -5759,7 +5759,7 @@ uint32 KmScene2805::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x481D: if (_isSittingInTeleporter) GotoState(&Klaymen::stTurnToUseInTeleporter); @@ -5775,7 +5775,7 @@ uint32 KmScene2805::xHandleMessage(int messageNum, const MessageParam ¶m) { sendMessage(_parentScene, 0x2000, 1); _isSittingInTeleporter = true; GotoState(&Klaymen::stSitInTeleporter); - break; + break; case 0x4836: sendMessage(_parentScene, 0x2000, 0); _isSittingInTeleporter = false; @@ -5805,7 +5805,7 @@ KmScene2806::KmScene2806(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 loadSound(6, 0x166FC6E0); loadSound(7, 0x00018040); } - + _dataResource.load(0x98182003); _surface->setClipRects(clipRects, clipRectsCount); } @@ -5827,12 +5827,12 @@ uint32 KmScene2806::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4816: if (param.asInteger() == 0) - GotoState(&Klaymen::stPressButtonSide); + GotoState(&Klaymen::stPressButtonSide); break; case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToX(_dataResource.getPoint(param.asInteger()).x, false); break; @@ -5885,12 +5885,12 @@ uint32 KmScene2809::xHandleMessage(int messageNum, const MessageParam ¶m) { break; case 0x4816: if (param.asInteger() == 0) - GotoState(&Klaymen::stPressButtonSide); + GotoState(&Klaymen::stPressButtonSide); break; case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToX(_dataResource.getPoint(param.asInteger()).x, false); break; @@ -5907,7 +5907,7 @@ uint32 KmScene2809::xHandleMessage(int messageNum, const MessageParam ¶m) { return 0; } -KmScene2810Small::KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) +KmScene2810Small::KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : Klaymen(vm, parentScene, x, y) { // Empty @@ -5925,7 +5925,7 @@ uint32 KmScene2810Small::xHandleMessage(int messageNum, const MessageParam ¶ case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToXSmall(_dataResource.getPoint(param.asInteger()).x); break; @@ -5937,7 +5937,7 @@ uint32 KmScene2810Small::xHandleMessage(int messageNum, const MessageParam ¶ else GotoState(&Klaymen::stWonderAboutSmall); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStepSmall); else @@ -5961,7 +5961,7 @@ KmScene2810::KmScene2810(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 _surface->setClipRects(clipRects, clipRectsCount); } - + uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam ¶m) { switch (messageNum) { case 0x4001: @@ -5985,7 +5985,7 @@ uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x4817: setDoDeltaX(param.asInteger()); gotoNextStateExt(); - break; + break; case 0x4818: startWalkToX(_dataResource.getPoint(param.asInteger()).x, false); break; @@ -6009,23 +6009,23 @@ uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam ¶m) { else GotoState(&Klaymen::stWonderAbout); break; - case 0x4820: + case 0x4820: sendMessage(_parentScene, 0x2000, 0); - GotoState(&Klaymen::stContinueClimbLadderUp); + GotoState(&Klaymen::stContinueClimbLadderUp); break; - case 0x4821: + case 0x4821: sendMessage(_parentScene, 0x2000, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderDown); + GotoState(&Klaymen::stStartClimbLadderDown); break; - case 0x4822: + case 0x4822: sendMessage(_parentScene, 0x2000, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderUp); + GotoState(&Klaymen::stStartClimbLadderUp); break; case 0x4823: sendMessage(_parentScene, 0x2001, 0); - GotoState(&Klaymen::stClimbLadderHalf); + GotoState(&Klaymen::stClimbLadderHalf); break; case 0x4824: sendMessage(_parentScene, 0x2000, 0); @@ -6080,7 +6080,7 @@ uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam ¶m) { gotoNextStateExt(); break; case 0x481A: - GotoState(&Klaymen::stInsertDisk); + GotoState(&Klaymen::stInsertDisk); break; case 0x481B: if (param.asPoint().y != 0) @@ -6094,29 +6094,29 @@ uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x481E: GotoState(&Klaymen::stReturnFromUse); break; - case 0x4820: + case 0x4820: sendMessage(_parentScene, 0x2001, 0); - GotoState(&Klaymen::stContinueClimbLadderUp); + GotoState(&Klaymen::stContinueClimbLadderUp); break; - case 0x4821: + case 0x4821: sendMessage(_parentScene, 0x2001, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderDown); + GotoState(&Klaymen::stStartClimbLadderDown); break; - case 0x4822: + case 0x4822: sendMessage(_parentScene, 0x2001, 0); _destY = param.asInteger(); - GotoState(&Klaymen::stStartClimbLadderUp); + GotoState(&Klaymen::stStartClimbLadderUp); break; case 0x4823: sendMessage(_parentScene, 0x2002, 0); - GotoState(&Klaymen::stClimbLadderHalf); + GotoState(&Klaymen::stClimbLadderHalf); break; case 0x482D: setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); gotoNextStateExt(); break; - case 0x482E: + case 0x482E: if (param.asInteger() == 1) GotoState(&Klaymen::stWalkToFrontNoStep); else @@ -6131,7 +6131,7 @@ uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam ¶m) { case 0x483F: startSpecialWalkRight(param.asInteger()); break; - case 0x4840: + case 0x4840: startSpecialWalkLeft(param.asInteger()); break; } diff --git a/engines/neverhood/klaymen.h b/engines/neverhood/klaymen.h index 25443b5a35..9e461a9c9c 100644 --- a/engines/neverhood/klaymen.h +++ b/engines/neverhood/klaymen.h @@ -77,24 +77,24 @@ public: void stIdleArms(); void evIdleArmsDone(); uint32 hmIdleArms(int messageNum, const MessageParam ¶m, Entity *sender); - + void stIdleChest(); uint32 hmIdleChest(int messageNum, const MessageParam ¶m, Entity *sender); - + void stIdleHeadOff(); uint32 hmIdleHeadOff(int messageNum, const MessageParam ¶m, Entity *sender); void stIdleWonderAbout(); void stIdleTeleporterHands(); - + void stIdleTeleporterHands2(); void stTryStandIdle(); void stStandAround(); void upStandIdle(); void stIdleBlink(); - + bool stStartAction(AnimationCb callback3); bool stStartActionFromIdle(AnimationCb callback); uint32 hmStartAction(int messageNum, const MessageParam ¶m, Entity *sender); @@ -134,7 +134,7 @@ public: void stPickUpTube(); uint32 hmPickUpTube(int messageNum, const MessageParam ¶m, Entity *sender); - + void stTurnToUse(); void stTurnToUseHalf(); void stTurnAwayFromUse(); @@ -263,10 +263,10 @@ public: void stJumpToGrabFall(); uint32 hmJumpToGrab(int messageNum, const MessageParam ¶m, Entity *sender); void suJumpToGrab(); - + void stJumpToGrabRelease(); uint32 hmJumpToGrabRelease(int messageNum, const MessageParam ¶m, Entity *sender); - + void stSitInTeleporter(); uint32 hmSitInTeleporter(int messageNum, const MessageParam ¶m, Entity *sender); @@ -326,7 +326,7 @@ public: void stFinishGrow(); uint32 hmFinishGrow(int messageNum, const MessageParam ¶m, Entity *sender); - + void stJumpToRingVenusFlyTrap(); uint32 hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam ¶m, Entity *sender); @@ -363,7 +363,7 @@ public: //////////////////////////////////////////////////////////////////////////// void stopWalking(); - + void suAction(); void suUpdateDestX(); void suWalkingTestExit(); @@ -375,7 +375,7 @@ public: void setKlaymenIdleTable1(); void setKlaymenIdleTable2(); void setKlaymenIdleTable3(); - + void setSoundFlag(bool value) { _soundFlag = value; } void spitIntoPipe(); @@ -416,7 +416,7 @@ protected: NPointArray *_pathPoints; bool _soundFlag; - + int16 _spitOutCountdown; bool _isSittingInTeleporter; @@ -456,16 +456,16 @@ protected: void stStartWalkingSmall(); uint32 hmWalkingSmall(int messageNum, const MessageParam ¶m, Entity *sender); - + void enterIdleAnimation(uint idleAnimation); void walkAlongPathPoints(); - + }; class KmScene1001 : public Klaymen { public: KmScene1001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y); -protected: +protected: uint32 xHandleMessage(int messageNum, const MessageParam ¶m); }; @@ -473,7 +473,7 @@ class KmScene1002 : public Klaymen { public: KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y); protected: - void xUpdate(); + void xUpdate(); uint32 xHandleMessage(int messageNum, const MessageParam ¶m); }; diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp index a8631cb0d6..7bf64a4602 100644 --- a/engines/neverhood/menumodule.cpp +++ b/engines/neverhood/menumodule.cpp @@ -20,6 +20,11 @@ * */ +#include "common/config-manager.h" +#include "common/translation.h" + +#include "gui/saveload.h" + #include "neverhood/menumodule.h" #include "neverhood/gamemodule.h" @@ -68,17 +73,19 @@ static const uint32 kMakingOfSmackerFileHashList[] = { MenuModule::MenuModule(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule), _savegameList(NULL) { - + SetMessageHandler(&MenuModule::handleMessage); - + _savedPaletteData = _vm->_screen->getPaletteData(); _vm->_mixer->pauseAll(true); + _vm->toggleSoundUpdate(false); createScene(MAIN_MENU, -1); } MenuModule::~MenuModule() { _vm->_mixer->pauseAll(false); + _vm->toggleSoundUpdate(true); _vm->_screen->setPaletteData(_savedPaletteData); } @@ -191,24 +198,26 @@ uint32 MenuModule::handleMessage(int messageNum, const MessageParam ¶m, Enti } void MenuModule::createLoadGameMenu() { - _savegameSlot = -1; - _savegameList = new SavegameList(); - loadSavegameList(); + refreshSaveGameList(); _childObject = new LoadGameMenu(_vm, this, _savegameList); } void MenuModule::createSaveGameMenu() { - _savegameSlot = -1; - _savegameList = new SavegameList(); - loadSavegameList(); + refreshSaveGameList(); _childObject = new SaveGameMenu(_vm, this, _savegameList); } void MenuModule::createDeleteGameMenu() { + refreshSaveGameList(); + _childObject = new DeleteGameMenu(_vm, this, _savegameList); +} + +void MenuModule::refreshSaveGameList() { _savegameSlot = -1; + delete _savegameList; + _savegameList = NULL; _savegameList = new SavegameList(); loadSavegameList(); - _childObject = new DeleteGameMenu(_vm, this, _savegameList); } void MenuModule::handleLoadGameMenuAction(bool doLoad) { @@ -257,7 +266,7 @@ void MenuModule::loadSavegameList() { Neverhood::NeverhoodEngine::SaveHeader header; Common::String pattern = _vm->getTargetName(); pattern += ".???"; - + Common::StringArray filenames; filenames = saveFileMan->listSavefiles(pattern.c_str()); Common::sort(filenames.begin(), filenames.end()); @@ -315,7 +324,7 @@ uint32 MenuButton::handleMessage(int messageNum, const MessageParam ¶m, Enti MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule) { - + static const uint32 kMenuButtonFileHashes[] = { 0x36C62120, 0x56C62120, @@ -327,26 +336,26 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule) 0x16C62130, 0x16C62100 }; - + static const NRect kMenuButtonCollisionBounds[] = { - NRect(52, 121, 110, 156), - NRect(52, 192, 109, 222), - NRect(60, 257, 119, 286), - NRect(67, 326, 120, 354), - NRect(70, 389, 128, 416), - NRect(523, 113, 580, 144), - NRect(525, 176, 577, 206), - NRect(527, 384, 580, 412), - NRect(522, 255, 580, 289) + { 52, 121, 110, 156 }, + { 52, 192, 109, 222 }, + { 60, 257, 119, 286 }, + { 67, 326, 120, 354 }, + { 70, 389, 128, 416 }, + { 523, 113, 580, 144 }, + { 525, 176, 577, 206 }, + { 527, 384, 580, 412 }, + { 522, 255, 580, 289 } }; - + setBackground(0x08C0020C); setPalette(0x08C0020C); insertScreenMouse(0x00208084); - + insertStaticSprite(0x41137051, 100); insertStaticSprite(0xC10B2015, 100); - + // TODO Only if music is enabled _musicOnButton = insertStaticSprite(0x0C24C0EE, 100); @@ -355,9 +364,9 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule) kMenuButtonFileHashes[buttonIndex], kMenuButtonCollisionBounds[buttonIndex]); addCollisionSprite(menuButton); } - - SetUpdateHandler(&Scene::update); - SetMessageHandler(&MainMenu::handleMessage); + + SetUpdateHandler(&Scene::update); + SetMessageHandler(&MainMenu::handleMessage); } @@ -387,18 +396,18 @@ CreditsScene::CreditsScene(NeverhoodEngine *vm, Module *parentModule, bool canAb : Scene(vm, parentModule), _canAbort(canAbort), _screenIndex(0), _ticksDuration(0), _countdown(216) { - SetUpdateHandler(&CreditsScene::update); + SetUpdateHandler(&CreditsScene::update); SetMessageHandler(&CreditsScene::handleMessage); - + setBackground(0x6081128C); setPalette(0x6081128C); _ticksTime = _vm->_system->getMillis() + 202100; - + _musicResource = new MusicResource(_vm); _musicResource->load(0x30812225); _musicResource->play(0); - + } CreditsScene::~CreditsScene() { @@ -460,7 +469,7 @@ Widget::Widget(NeverhoodEngine *vm, int16 x, int16 y, GameStateMenu *parentScene SetUpdateHandler(&Widget::update); SetMessageHandler(&Widget::handleMessage); - + setPosition(x, y); } @@ -523,7 +532,7 @@ TextLabelWidget::TextLabelWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStat const byte *string, int stringLen, BaseSurface *drawSurface, int16 tx, int16 ty, FontSurface *fontSurface) : Widget(vm, x, y, parentScene, baseObjectPriority, baseSurfacePriority), _string(string), _stringLen(stringLen), _drawSurface(drawSurface), _tx(tx), _ty(ty), _fontSurface(fontSurface) { - + } void TextLabelWidget::initialize() { @@ -564,7 +573,7 @@ TextEditWidget::TextEditWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStateM _maxVisibleChars = (_rect.x2 - _rect.x1) / _fontSurface->getCharWidth(); _cursorPos = 0; - + SetUpdateHandler(&TextEditWidget::update); SetMessageHandler(&TextEditWidget::handleMessage); } @@ -608,7 +617,7 @@ void TextEditWidget::initialize() { _textLabelWidget->initialize(); if (_cursorFileHash != 0) { cursorSpriteResource.load(_cursorFileHash, true); - _cursorSurface = new BaseSurface(_vm, 0, cursorSpriteResource.getDimensions().width, cursorSpriteResource.getDimensions().height); + _cursorSurface = new BaseSurface(_vm, 0, cursorSpriteResource.getDimensions().width, cursorSpriteResource.getDimensions().height, "cursor"); _cursorSurface->drawSpriteResourceEx(cursorSpriteResource, false, false, cursorSpriteResource.getDimensions().width, cursorSpriteResource.getDimensions().height); _cursorSurface->setVisible(!_readOnly); } @@ -757,9 +766,7 @@ void SavegameListBox::onClick() { mousePos.y -= _y + _rect.y1; if (mousePos.x >= 0 && mousePos.x <= _rect.x2 - _rect.x1 && mousePos.y >= 0 && mousePos.y <= _rect.y2 - _rect.y1) { - // We add 1 to the char height to ensure that the correct entry is chosen if the - // user clicks at the bottom the text entry - int newIndex = _firstVisibleItem + mousePos.y / (_fontSurface->getCharHeight() + 1); + int newIndex = _firstVisibleItem + mousePos.y / _fontSurface->getCharHeight(); if (newIndex <= _lastVisibleItem) { _currIndex = newIndex; refresh(); @@ -797,7 +804,7 @@ void SavegameListBox::buildItems() { void SavegameListBox::drawItems() { for (int i = 0; i < (int)_textLabelItems.size(); ++i) { - TextLabelWidget *label = _textLabelItems[i]; + TextLabelWidget *label = _textLabelItems[i]; if (i >= _firstVisibleItem && i <= _lastVisibleItem) { label->setY(_rect.y1 + (i - _firstVisibleItem) * _fontSurface->getCharHeight()); label->updateBounds(); @@ -821,7 +828,7 @@ void SavegameListBox::scrollUp() { } void SavegameListBox::scrollDown() { - if (_lastVisibleItem < (int)_textLabelItems.size()) { + if (_lastVisibleItem < (int)_textLabelItems.size() - 1) { ++_firstVisibleItem; ++_lastVisibleItem; refresh(); @@ -838,7 +845,7 @@ void SavegameListBox::pageUp() { } void SavegameListBox::pageDown() { - int amount = MIN((int)_textLabelItems.size() - _lastVisibleItem, _maxVisibleItemsCount); + int amount = MIN((int)_textLabelItems.size() - _lastVisibleItem - 1, _maxVisibleItemsCount); if (amount > 0) { _firstVisibleItem += amount; _lastVisibleItem += amount; @@ -846,17 +853,68 @@ void SavegameListBox::pageDown() { } } +int GameStateMenu::scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc) { + const EnginePlugin *plugin = NULL; + EngineMan.findGame(ConfMan.get("gameid"), &plugin); + GUI::SaveLoadChooser *dialog; + Common::String desc; + int slot; + + if (isSave) { + dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + + slot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); + desc = dialog->getResultString(); + + if (desc.empty()) + desc = dialog->createDefaultSaveDescription(slot); + + if (desc.size() > 29) + desc = Common::String(desc.c_str(), 29); + + saveDesc = desc; + } else { + dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + slot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); + } + + delete dialog; + + return slot; +} + GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList, const uint32 *buttonFileHashes, const NRect *buttonCollisionBounds, uint32 backgroundFileHash, uint32 fontFileHash, - uint32 mouseFileHash, const NRect *mouseRect, + uint32 mouseFileHash, const NRect *mouseRect, uint32 listBoxBackgroundFileHash, int16 listBoxX, int16 listBoxY, const NRect &listBoxRect, uint32 textEditBackgroundFileHash, uint32 textEditCursorFileHash, int16 textEditX, int16 textEditY, const NRect &textEditRect, - uint32 textFileHash1, uint32 textFileHash2) + uint32 textFileHash1, uint32 textFileHash2) : Scene(vm, parentModule), _currWidget(NULL), _savegameList(savegameList) { - + + bool isSave = (textEditCursorFileHash != 0); + _fontSurface = new FontSurface(_vm, fontFileHash, 32, 7, 32, 11, 17); - + + if (!ConfMan.getBool("originalsaveload")) { + Common::String saveDesc; + int saveCount = savegameList->size(); + int slot = scummVMSaveLoadDialog(isSave, saveDesc); + + if (slot >= 0) { + if (!isSave) { + ((MenuModule*)_parentModule)->setLoadgameInfo(slot); + } else { + ((MenuModule*)_parentModule)->setSavegameInfo(saveDesc, + slot, slot >= saveCount); + } + leaveScene(0); + } else { + leaveScene(1); + } + return; + } + setBackground(backgroundFileHash); setPalette(backgroundFileHash); insertScreenMouse(mouseFileHash, mouseRect); @@ -869,13 +927,13 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame _textEditWidget = new TextEditWidget(_vm, textEditX, textEditY, this, 29, _fontSurface, textEditBackgroundFileHash, textEditRect); - if (textEditCursorFileHash != 0) + if (isSave) _textEditWidget->setCursor(textEditCursorFileHash, 2, 13); else _textEditWidget->setReadOnly(true); _textEditWidget->initialize(); setCurrWidget(_textEditWidget); - + for (uint buttonIndex = 0; buttonIndex < 6; ++buttonIndex) { Sprite *menuButton = insertSprite<MenuButton>(this, buttonIndex, buttonFileHashes[buttonIndex], buttonCollisionBounds[buttonIndex]); @@ -884,7 +942,6 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame SetUpdateHandler(&Scene::update); SetMessageHandler(&GameStateMenu::handleMessage); - } GameStateMenu::~GameStateMenu() { @@ -969,17 +1026,17 @@ static const uint32 kSaveGameMenuButtonFileHashes[] = { }; static const NRect kSaveGameMenuButtonCollisionBounds[] = { - NRect(518, 106, 602, 160), - NRect(516, 378, 596, 434), - NRect(394, 108, 458, 206), - NRect(400, 204, 458, 276), - NRect(398, 292, 456, 352), - NRect(396, 352, 460, 444) + { 518, 106, 602, 160 }, + { 516, 378, 596, 434 }, + { 394, 108, 458, 206 }, + { 400, 204, 458, 276 }, + { 398, 292, 456, 352 }, + { 396, 352, 460, 444 } }; -static const NRect kSaveGameMenuListBoxRect(0, 0, 320, 272); -static const NRect kSaveGameMenuTextEditRect(0, 0, 377, 17); -static const NRect kSaveGameMenuMouseRect(50, 47, 427, 64); +static const NRect kSaveGameMenuListBoxRect = { 0, 0, 320, 272 }; +static const NRect kSaveGameMenuTextEditRect = { 0, 0, 377, 17 }; +static const NRect kSaveGameMenuMouseRect = { 50, 47, 427, 64 }; SaveGameMenu::SaveGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList) : GameStateMenu(vm, parentModule, savegameList, kSaveGameMenuButtonFileHashes, kSaveGameMenuButtonCollisionBounds, @@ -1003,17 +1060,17 @@ static const uint32 kLoadGameMenuButtonFileHashes[] = { }; static const NRect kLoadGameMenuButtonCollisionBounds[] = { - NRect( 44, 115, 108, 147), - NRect( 52, 396, 112, 426), - NRect(188, 116, 245, 196), - NRect(189, 209, 239, 269), - NRect(187, 301, 233, 349), - NRect(182, 358, 241, 433) + { 44, 115, 108, 147 }, + { 52, 396, 112, 426 }, + { 188, 116, 245, 196 }, + { 189, 209, 239, 269 }, + { 187, 301, 233, 349 }, + { 182, 358, 241, 433 } }; -static const NRect kLoadGameMenuListBoxRect(0, 0, 320, 271); -static const NRect kLoadGameMenuTextEditRect(0, 0, 320, 17); -static const NRect kLoadGameMenuMouseRect(263, 48, 583, 65); +static const NRect kLoadGameMenuListBoxRect = { 0, 0, 320, 271 }; +static const NRect kLoadGameMenuTextEditRect = { 0, 0, 320, 17 }; +static const NRect kLoadGameMenuMouseRect = { 263, 48, 583, 65 }; LoadGameMenu::LoadGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList) : GameStateMenu(vm, parentModule, savegameList, kLoadGameMenuButtonFileHashes, kLoadGameMenuButtonCollisionBounds, @@ -1036,21 +1093,21 @@ static const uint32 kDeleteGameMenuButtonFileHashes[] = { }; static const NRect kDeleteGameMenuButtonCollisionBounds[] = { - NRect(518, 46, 595, 91), - NRect(524, 322, 599, 369), - NRect(395, 40, 462, 127), - NRect(405, 126, 460, 185), - NRect(397, 205, 456, 273), - NRect(395, 278, 452, 372) + { 518, 46, 595, 91 }, + { 524, 322, 599, 369 }, + { 395, 40, 462, 127 }, + { 405, 126, 460, 185 }, + { 397, 205, 456, 273 }, + { 395, 278, 452, 372 } }; -static const NRect kDeleteGameMenuListBoxRect(0, 0, 320, 271); -static const NRect kDeleteGameMenuTextEditRect(0, 0, 320, 17); +static const NRect kDeleteGameMenuListBoxRect = { 0, 0, 320, 271 }; +static const NRect kDeleteGameMenuTextEditRect = { 0, 0, 320, 17 }; DeleteGameMenu::DeleteGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList) : GameStateMenu(vm, parentModule, savegameList, kDeleteGameMenuButtonFileHashes, kDeleteGameMenuButtonCollisionBounds, 0x4080E01C, 0x728523ED, - 0x0E018400, NULL, + 0x0E018400, NULL, 0xA5584211, 61, 64, kDeleteGameMenuListBoxRect, 0x250A3060, 0, 49, 414, kDeleteGameMenuTextEditRect, 0x80083C01, 0x84181E81) { @@ -1071,10 +1128,10 @@ QueryOverwriteMenu::QueryOverwriteMenu(NeverhoodEngine *vm, Module *parentModule }; static const NRect kQueryOverwriteMenuCollisionBounds[] = { - NRect(145, 334, 260, 385), - NRect(365, 340, 477, 388) + { 145, 334, 260, 385 }, + { 365, 340, 477, 388 } }; - + setBackground(0x043692C4); setPalette(0x043692C4); insertScreenMouse(0x692C004B); @@ -1097,7 +1154,7 @@ QueryOverwriteMenu::QueryOverwriteMenu(NeverhoodEngine *vm, Module *parentModule fontSurface->drawString(_background->getSurface(), 106 + (423 - textLines[i].size() * 11) / 2, 127 + 31 + i * 17, (const byte*)textLines[i].c_str()); delete fontSurface; - + SetUpdateHandler(&Scene::update); SetMessageHandler(&QueryOverwriteMenu::handleMessage); } diff --git a/engines/neverhood/menumodule.h b/engines/neverhood/menumodule.h index 08858ad204..f201654ceb 100644 --- a/engines/neverhood/menumodule.h +++ b/engines/neverhood/menumodule.h @@ -45,6 +45,7 @@ public: void setLoadgameInfo(uint index); void setSavegameInfo(const Common::String &description, uint index, bool newSavegame); void setDeletegameInfo(uint index); + void refreshSaveGameList(); protected: int _sceneNum; byte *_savedPaletteData; @@ -123,8 +124,8 @@ protected: class TextLabelWidget : public Widget { public: TextLabelWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStateMenu *parentScene, - int baseObjectPriority, int baseSurfacePriority, - const byte *string, int stringLen, BaseSurface *drawSurface, int16 tx, int16 ty, FontSurface *fontSurface); + int baseObjectPriority, int baseSurfacePriority, + const byte *string, int stringLen, BaseSurface *drawSurface, int16 tx, int16 ty, FontSurface *fontSurface); virtual void initialize(); virtual int16 getWidth(); virtual int16 getHeight(); @@ -205,13 +206,13 @@ protected: uint _currIndex; int _maxVisibleItemsCount; }; - + class GameStateMenu : public Scene { public: GameStateMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList, const uint32 *buttonFileHashes, const NRect *buttonCollisionBounds, uint32 backgroundFileHash, uint32 fontFileHash, - uint32 mouseFileHash, const NRect *mouseRect, + uint32 mouseFileHash, const NRect *mouseRect, uint32 listBoxBackgroundFileHash, int16 listBoxX, int16 listBoxY, const NRect &listBoxRect, uint32 textEditBackgroundFileHash, uint32 textEditCursorFileHash, int16 textEditX, int16 textEditY, const NRect &textEditRect, uint32 textFileHash1, uint32 textFileHash2); @@ -229,6 +230,7 @@ protected: Common::String _savegameDescription; uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); virtual void performAction(); + int scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc); }; class SaveGameMenu : public GameStateMenu { diff --git a/engines/neverhood/module.cpp b/engines/neverhood/module.cpp index e384b5a4d2..d1578e680c 100644 --- a/engines/neverhood/module.cpp +++ b/engines/neverhood/module.cpp @@ -31,9 +31,9 @@ namespace Neverhood { Module::Module(NeverhoodEngine *vm, Module *parentModule) : Entity(vm, 0), _parentModule(parentModule), _childObject(NULL), _done(false), _sceneType(kSceneTypeNormal) { - + SetMessageHandler(&Module::handleMessage); - + } Module::~Module() { diff --git a/engines/neverhood/module.h b/engines/neverhood/module.h index e98012cbea..ba1e1fa3db 100644 --- a/engines/neverhood/module.h +++ b/engines/neverhood/module.h @@ -48,9 +48,10 @@ public: Module(NeverhoodEngine *vm, Module *parentModule); virtual ~Module(); virtual void draw(); + + Entity *_childObject; protected: Module *_parentModule; - Entity *_childObject; bool _done; uint32 _moduleResult; SceneType _sceneType; diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk index 714fc3079b..030c78a407 100644 --- a/engines/neverhood/module.mk +++ b/engines/neverhood/module.mk @@ -3,6 +3,7 @@ MODULE := engines/neverhood MODULE_OBJS = \ background.o \ blbarchive.o \ + console.o \ detection.o \ diskplayerscene.o \ entity.o \ diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp index 415d0f72b1..f65b89899d 100644 --- a/engines/neverhood/modules/module1000.cpp +++ b/engines/neverhood/modules/module1000.cpp @@ -26,10 +26,8 @@ namespace Neverhood { Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - - debug("Create Module1000(%d)", which); - _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144; + _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144; _vm->_soundMan->addMusic(0x03294419, 0x061880C6); _vm->_soundMan->addMusic(0x03294419, _musicFileHash); @@ -48,7 +46,7 @@ Module1000::~Module1000() { } void Module1000::createScene(int sceneNum, int which) { - debug("Module1000::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1000::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -120,11 +118,11 @@ void Module1000::updateScene() { } } -// Scene1001 +// Scene1001 AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm) : AnimatedSprite(vm, 1100) { - + createSurface(800, 137, 242); _x = 726; _y = 440; @@ -153,16 +151,16 @@ void AsScene1001Door::hammerHitsDoor() { case 1: playSound(0, 0x65482F03); startAnimation(0x624C0498, 1, 3); - NextState(&AsScene1001Door::stShowIdleDoor); + NextState(&AsScene1001Door::stShowIdleDoor); break; case 2: playSound(1); startAnimation(0x624C0498, 6, 6); - NextState(&AsScene1001Door::stBustedDoorMove); + NextState(&AsScene1001Door::stBustedDoorMove); break; default: // Nothing - break; + break; } incGlobalVar(V_DOOR_STATUS, 1); } @@ -198,9 +196,9 @@ void AsScene1001Door::stBustedDoorMove() { void AsScene1001Door::stBustedDoorGone() { playSound(0); stopAnimation(); - setVisible(false); + setVisible(false); } - + AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor) : AnimatedSprite(vm, 1100), _asDoor(asDoor) { @@ -264,7 +262,7 @@ uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam ¶ AsScene1001Lever::AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - + createSurface(1010, 71, 73); setDoDeltaX(deltaXType); startAnimation(0x04A98C36, 0, -1); @@ -304,22 +302,22 @@ uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam ¶m } return messageResult; } - + SsCommonButtonSprite::SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash) : StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene), _countdown(0) { _priority = 1100; - _soundFileHash = soundFileHash ? soundFileHash : 0x44141000; + _soundFileHash = soundFileHash ? soundFileHash : 0x44141000; setVisible(false); SetUpdateHandler(&SsCommonButtonSprite::update); SetMessageHandler(&SsCommonButtonSprite::handleMessage); } - + void SsCommonButtonSprite::update() { if (_countdown != 0 && (--_countdown) == 0) setVisible(false); } - + uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -332,19 +330,19 @@ uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam &p } return messageResult; } - + Scene1001::Scene1001(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asDoor(NULL), _asWindow(NULL) { Sprite *tempSprite; SetMessageHandler(&Scene1001::handleMessage); - + setHitRects(0x004B4860); setBackground(0x4086520E); setPalette(0x4086520E); insertScreenMouse(0x6520A400); - + if (which < 0) { // Restoring game setRectList(0x004B49F0); @@ -375,7 +373,7 @@ Scene1001::Scene1001(NeverhoodEngine *vm, Module *parentModule, int which) tempSprite = insertStaticSprite(0x2080A3A8, 1300); _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); - + if (!getGlobalVar(V_DOOR_BUSTED)) { _asDoor = insertSprite<AsScene1001Door>(); _asDoor->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); @@ -447,7 +445,7 @@ AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool i : AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) { SetUpdateHandler(&AsScene1002Ring::update); - + if (_isSpecial) { createSurface(990, 68, 314); if (isRingLow) { @@ -583,7 +581,7 @@ uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam ¶m AsScene1002Door::AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect) : StaticSprite(vm, 1200) { - + loadSprite(0x1052370F, kSLFDefDrawOffset | kSLFSetPosition, 800, 526, getGlobalVar(V_FLYTRAP_RING_DOOR) ? 49 : 239); setClipRect(clipRect); SetUpdateHandler(&AsScene1002Door::update); @@ -639,7 +637,7 @@ AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine createSurface(1025, 88, 165); setVisible(false); SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage); + SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage); } uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -718,7 +716,7 @@ void AsScene1002DoorSpy::stDoorSpyBoxingGlove() { NextState(&AsScene1002DoorSpy::stDoorSpyIdle); } -SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash) +SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash) : StaticSprite(vm, 1100), _parentScene(parentScene), _status(0), _countdown(0) { _soundFileHash = soundFileHash != 0 ? soundFileHash : 0x44141000; @@ -790,7 +788,7 @@ AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *par stRingGrabbed(); } else { stIdle(); - } + } } _flags = 4; SetUpdateHandler(&AsScene1002VenusFlyTrap::update); @@ -852,12 +850,12 @@ uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam if (_isSecond) { if (_x >= 154 && _x <= 346) messageResult = 1; - else + else messageResult = 0; } else { if (_x >= 174 && _x <= 430) messageResult = 1; - else + else messageResult = 0; } break; @@ -1025,7 +1023,7 @@ AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngi } else setVisible(false); SetUpdateHandler(&AsScene1002OutsideDoorBackground::update); - SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage); + SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage); } void AsScene1002OutsideDoorBackground::update() { @@ -1085,7 +1083,7 @@ void AsScene1002OutsideDoorBackground::stDoorClosed() { AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen) : AnimatedSprite(vm, 1200), _klaymen(klaymen) { - + createSurface(1200, 40, 163); setVisible(false); SetUpdateHandler(&AsScene1002KlaymenLadderHands::update); @@ -1097,15 +1095,15 @@ void AsScene1002KlaymenLadderHands::update() { startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1); _newStickFrameIndex = _klaymen->getFrameIndex(); setVisible(true); - _x = _klaymen->getX(); - _y = _klaymen->getY(); + _x = _klaymen->getX(); + _y = _klaymen->getY(); setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); } else if (_klaymen->getCurrAnimFileHash() == 0x122D1505) { startAnimation(0x1319150C, _klaymen->getFrameIndex(), -1); _newStickFrameIndex = _klaymen->getFrameIndex(); setVisible(true); - _x = _klaymen->getX(); - _y = _klaymen->getY(); + _x = _klaymen->getX(); + _y = _klaymen->getY(); setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0); } else setVisible(false); @@ -1115,7 +1113,7 @@ void AsScene1002KlaymenLadderHands::update() { AsScene1002KlaymenPeekHand::AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen) : AnimatedSprite(vm, 1200), _parentScene(parentScene), _klaymen(klaymen), _isClipRectSaved(false) { - + createSurface(1000, 33, 41); setVisible(false); SetUpdateHandler(&AsScene1002KlaymenPeekHand::update); @@ -1247,7 +1245,7 @@ Scene1002::Scene1002(NeverhoodEngine *vm, Module *parentModule, int which) sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap); _asOutsideDoorBackground = insertSprite<AsScene1002OutsideDoorBackground>(); - + setRectList(0x004B43A0); loadSound(1, 0x60755842); @@ -1324,11 +1322,11 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam ¶m, Entit break; case 0x2002: _messageList = NULL; - break; + break; case 0x2005: _isClimbingLadder = true; setRectList(0x004B4418); - break; + break; case 0x2006: _isClimbingLadder = false; setRectList(0x004B43A0); @@ -1362,11 +1360,11 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam ¶m, Entit if (getGlobalVar(V_FLYTRAP_RING_DOOR)) { sendMessage(_asRing3, 0x4807, 0); } - } + } break; case 0x480B: sendEntityMessage(_klaymen, 0x1014, _asDoorSpy); - break; + break; case 0x480F: setGlobalVar(V_RADIO_ENABLED, 0); playSound(1); @@ -1381,7 +1379,7 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam ¶m, Entit setSpriteSurfacePriority(_ssCeiling, 1015); setSpriteSurfacePriority(_ssLadderArch, 1015); break; - } + } return messageResult; } @@ -1391,7 +1389,7 @@ StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backg : Scene(vm, parentModule) { SetMessageHandler(&StaticScene::handleMessage); - + setBackground(backgroundFileHash); setPalette(backgroundFileHash); insertPuzzleMouse(cursorFileHash, 20, 620); @@ -1444,7 +1442,7 @@ Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _paletteAreaStatus(-1) { Sprite *tempSprite; - + SetUpdateHandler(&Scene1004::update); SetMessageHandler(&Scene1004::handleMessage); @@ -1477,16 +1475,16 @@ Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which) insertKlaymen<KmScene1004>(_dataResource.getPoint(0x80052A29).x, 27); setMessageList(0x004B7BF0); } - + updatePaletteArea(); - + _asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_klaymen); insertStaticSprite(0x800034A0, 1100); insertStaticSprite(0x64402020, 1100); insertStaticSprite(0x3060222E, 1300); tempSprite = insertStaticSprite(0x0E002004, 1300); - + _klaymen->setClipRect(0, tempSprite->getDrawRect().y, 640, 480); _asKlaymenLadderHands->setClipRect(_klaymen->getClipRect()); @@ -1520,7 +1518,7 @@ uint32 Scene1004::handleMessage(int messageNum, const MessageParam ¶m, Entit break; } return messageResult; -} +} void Scene1004::updatePaletteArea() { if (_klaymen->getY() < 150) { @@ -1559,7 +1557,7 @@ Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which) } drawTextToBackground(); - + } uint32 Scene1005::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -1567,7 +1565,7 @@ uint32 Scene1005::handleMessage(int messageNum, const MessageParam ¶m, Entit switch (messageNum) { case 0x0001: if (param.asPoint().x <= 20 || param.asPoint().x >= 620) - leaveScene(0); + leaveScene(0); break; } return 0; @@ -1616,19 +1614,19 @@ uint32 Scene1005::getTextIndex1() { textIndex = 23; else if (!getSubVar(VA_HAS_KEY, 0) && !getSubVar(VA_IS_KEY_INSERTED, 0)) textIndex = 24; - else if (!getGlobalVar(V_HAS_FINAL_KEY)) + else if (!getGlobalVar(V_HAS_FINAL_KEY)) textIndex = 26; else if (!getSubVar(VA_HAS_KEY, 1) && !getSubVar(VA_IS_KEY_INSERTED, 1)) textIndex = 27; - else if (!getGlobalVar(V_HAS_FINAL_KEY)) + else if (!getGlobalVar(V_HAS_FINAL_KEY)) textIndex = 28; - else + else textIndex = 29; } else if (!getGlobalVar(V_FELL_DOWN_HOLE)) textIndex = 20; else if (!getGlobalVar(V_SEEN_SYMBOLS_NO_LIGHT)) textIndex = 21; - else + else textIndex = 22; } else if (getGlobalVar(V_BOLT_DOOR_UNLOCKED)) { if (!getGlobalVar(V_WALL_BROKEN)) @@ -1643,7 +1641,7 @@ uint32 Scene1005::getTextIndex1() { textIndex = 15; else if (!getGlobalVar(V_BEEN_STATUE_ROOM)) textIndex = 16; - else + else textIndex = 17; } else if (!getGlobalVar(V_FLYTRAP_RING_EATEN)) { textIndex = 0; @@ -1662,7 +1660,7 @@ uint32 Scene1005::getTextIndex1() { textIndex = 9; else if (!getSubVar(VA_LOCKS_DISABLED, 0x01180951)) textIndex = 10; - else + else textIndex = 11; } else if (!getGlobalVar(V_CREATURE_ANGRY)) { textIndex = 1; diff --git a/engines/neverhood/modules/module1000.h b/engines/neverhood/modules/module1000.h index 9977590a6a..8461ecfc6f 100644 --- a/engines/neverhood/modules/module1000.h +++ b/engines/neverhood/modules/module1000.h @@ -85,7 +85,7 @@ protected: Scene *_parentScene; uint32 _soundFileHash; int16 _countdown; - void update(); + void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; diff --git a/engines/neverhood/modules/module1100.cpp b/engines/neverhood/modules/module1100.cpp index c4d90b5562..faa0516d7e 100644 --- a/engines/neverhood/modules/module1100.cpp +++ b/engines/neverhood/modules/module1100.cpp @@ -40,7 +40,7 @@ static const uint32 kModule1100SoundList[] = { Module1100::Module1100(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + if (which < 0) { createScene(_vm->gameState().sceneNum, -1); } else if (which == 1) { @@ -64,7 +64,8 @@ Module1100::~Module1100() { void Module1100::createScene(int sceneNum, int which) { static const uint32 kSmackerFileHashList06[] = {0x10880805, 0x1088081D, 0}; static const uint32 kSmackerFileHashList07[] = {0x00290321, 0x01881000, 0}; - debug("Module1100::createScene(%d, %d)", sceneNum, which); + static const byte kNavigationTypes02[] = {1, 0, 4, 1}; + debug(1, "Module1100::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -80,9 +81,9 @@ void Module1100::createScene(int sceneNum, int which) { case 2: _vm->gameState().sceneNum = 2; if (getGlobalVar(V_ROBOT_TARGET)) { - createNavigationScene(0x004B84F0, which); + createNavigationScene(0x004B84F0, which, kNavigationTypes02); } else { - createNavigationScene(0x004B8490, which); + createNavigationScene(0x004B8490, which, kNavigationTypes02); } break; case 3: @@ -270,7 +271,7 @@ static const uint32 kSsScene1105SymbolDieFileHashes[] = { SsScene1105Button::SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds) : StaticSprite(vm, fileHash, 200), _parentScene(parentScene), _countdown(0) { - + _collisionBounds = collisionBounds; SetMessageHandler(&SsScene1105Button::handleMessage); SetUpdateHandler(&SsScene1105Button::update); @@ -346,7 +347,7 @@ void SsScene1105SymbolDie::hide() { AsScene1105TeddyBear::AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - + createSurface(100, 556, 328); _x = 320; _y = 240; @@ -395,7 +396,7 @@ void AsScene1105TeddyBear::hide() { SsScene1105OpenButton::SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene) : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _isClicked(false) { - + loadSprite(0x8228A46C, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); loadSound(0, 0x44045140); @@ -431,26 +432,26 @@ uint32 SsScene1105OpenButton::handleMessage(int messageNum, const MessageParam & Scene1105::Scene1105(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule), _countdown(0), _isPanelOpen(false), _isActionButtonClicked(false), _doMoveTeddy(false), _isClosePanelDone(false), _leaveResult(0), _backgroundIndex(0) { - + Sprite *ssOpenButton; - + _vm->gameModule()->initMemoryPuzzle(); - + SetUpdateHandler(&Scene1105::update); SetMessageHandler(&Scene1105::handleMessage); - + setBackground(0x20010002); setPalette(0x20010002); - + _asTeddyBear = insertSprite<AsScene1105TeddyBear>(this); ssOpenButton = insertSprite<SsScene1105OpenButton>(this); addCollisionSprite(ssOpenButton); insertPuzzleMouse(0x10006208, 20, 620); - + loadSound(0, 0x48442057); loadSound(1, 0xC025014F); loadSound(2, 0x68E25540); - + } uint32 Scene1105::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -554,27 +555,27 @@ void Scene1105::createObjects() { _ssSymbolDice[1] = insertSprite<SsScene1105SymbolDie>(1, 339, 304); _ssSymbolDice[2] = insertSprite<SsScene1105SymbolDie>(2, 485, 304); - _ssSymbol1UpButton = insertSprite<SsScene1105Button>(this, 0x08002860, NRect(146, 362, 192, 403)); + _ssSymbol1UpButton = insertSprite<SsScene1105Button>(this, 0x08002860, NRect::make(146, 362, 192, 403)); addCollisionSprite(_ssSymbol1UpButton); - _ssSymbol1DownButton = insertSprite<SsScene1105Button>(this, 0x42012460, NRect(147, 404, 191, 442)); + _ssSymbol1DownButton = insertSprite<SsScene1105Button>(this, 0x42012460, NRect::make(147, 404, 191, 442)); addCollisionSprite(_ssSymbol1DownButton); - _ssSymbol2UpButton = insertSprite<SsScene1105Button>(this, 0x100030A0, NRect(308, 361, 355, 402)); + _ssSymbol2UpButton = insertSprite<SsScene1105Button>(this, 0x100030A0, NRect::make(308, 361, 355, 402)); addCollisionSprite(_ssSymbol2UpButton); - _ssSymbol2DownButton = insertSprite<SsScene1105Button>(this, 0x840228A0, NRect(306, 406, 352, 445)); + _ssSymbol2DownButton = insertSprite<SsScene1105Button>(this, 0x840228A0, NRect::make(306, 406, 352, 445)); addCollisionSprite(_ssSymbol2DownButton); - _ssSymbol3UpButton = insertSprite<SsScene1105Button>(this, 0x20000120, NRect(476, 358, 509, 394)); + _ssSymbol3UpButton = insertSprite<SsScene1105Button>(this, 0x20000120, NRect::make(476, 358, 509, 394)); addCollisionSprite(_ssSymbol3UpButton); - _ssSymbol3DownButton = insertSprite<SsScene1105Button>(this, 0x08043121, NRect(463, 401, 508, 438)); + _ssSymbol3DownButton = insertSprite<SsScene1105Button>(this, 0x08043121, NRect::make(463, 401, 508, 438)); addCollisionSprite(_ssSymbol3DownButton); - _ssActionButton = insertSprite<SsScene1105Button>(this, 0x8248AD35, NRect(280, 170, 354, 245)); + _ssActionButton = insertSprite<SsScene1105Button>(this, 0x8248AD35, NRect::make(280, 170, 354, 245)); addCollisionSprite(_ssActionButton); - + _isPanelOpen = true; - + _asTeddyBear->show(); insertPuzzleMouse(0x18666208, 20, 620); - + } void Scene1105::upOpenPanel() { @@ -625,13 +626,6 @@ void Scene1105::upClosePanel() { } void Scene1105::update() { - - // DEBUG: Show the correct code - debug("(%d, %d) (%d, %d) (%d, %d)", - getSubVar(VA_GOOD_DICE_NUMBERS, 0), getSubVar(VA_CURR_DICE_NUMBERS, 0), - getSubVar(VA_GOOD_DICE_NUMBERS, 1), getSubVar(VA_CURR_DICE_NUMBERS, 1), - getSubVar(VA_GOOD_DICE_NUMBERS, 2), getSubVar(VA_CURR_DICE_NUMBERS, 2)); - Scene::update(); if (_countdown != 0 && (--_countdown == 0)) createObjects(); @@ -645,13 +639,13 @@ void Scene1105::update() { Scene1109::Scene1109(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + SetMessageHandler(&Scene1109::handleMessage); - + setBackground(0x8449E02F); setPalette(0x8449E02F); insertScreenMouse(0x9E02B84C); - + _sprite1 = insertStaticSprite(0x600CEF01, 1100); if (which < 0) { diff --git a/engines/neverhood/modules/module1200.cpp b/engines/neverhood/modules/module1200.cpp index 3be3635645..e7766419f9 100644 --- a/engines/neverhood/modules/module1200.cpp +++ b/engines/neverhood/modules/module1200.cpp @@ -26,7 +26,7 @@ namespace Neverhood { Module1200::Module1200(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + SetMessageHandler(&Module1200::handleMessage); if (which < 0) @@ -45,7 +45,7 @@ Module1200::~Module1200() { } void Module1200::createScene(int sceneNum, int which) { - debug("Module1200::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1200::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -124,7 +124,7 @@ static const uint32 kScene1201TntFileHashList2[] = { 0xB140A1E6, 0x5088A068, 0x5088A068, 0x74C4C866, 0x3192C059, 0x3192C059 }; - + SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2) : StaticSprite(vm, 900) { @@ -133,13 +133,13 @@ SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 poi if (x < 300) loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50); else - loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y); + loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y - 20); setClipRect(0, 0, 640, clipY2); } - + AsScene1201Tape::AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash) : AnimatedSprite(vm, fileHash, surfacePriority, x, y), _parentScene(parentScene), _nameHash(nameHash) { - + if (!getSubVar(VA_HAS_TAPE, _nameHash) && !getSubVar(VA_IS_TAPE_INSERTED, _nameHash)) { SetMessageHandler(&AsScene1201Tape::handleMessage); } else { @@ -253,10 +253,10 @@ void AsScene1201RightDoor::stCloseDoorDone() { stopAnimation(); setVisible(false); } - + AsScene1201KlaymenHead::AsScene1201KlaymenHead(NeverhoodEngine *vm) : AnimatedSprite(vm, 1200) { - + createSurface(1200, 69, 98); SetUpdateHandler(&AnimatedSprite::update); SetMessageHandler(&AsScene1201KlaymenHead::handleMessage); @@ -301,7 +301,7 @@ AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sp AsScene1201TntMan::~AsScene1201TntMan() { _vm->_soundMan->deleteSoundGroup(0x01D00560); -} +} uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); @@ -396,7 +396,7 @@ void AsScene1201TntManFlame::suUpdate() { AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 1100), _parentScene(parentScene), _countdown(0) { - + createSurface(1100, 57, 60); SetUpdateHandler(&AsScene1201Match::update); SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove); @@ -518,7 +518,7 @@ AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene : AnimatedSprite(vm, 900), _parentScene(parentScene), _klaymen(klaymen), _klaymenTooClose(false) { // NOTE: _countdown2 and _countdown3 were unused/without effect and thus removed - + createSurface(1100, 203, 199); SetUpdateHandler(&AsScene1201Creature::update); SetMessageHandler(&AsScene1201Creature::hmWaiting); @@ -664,7 +664,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene1201::handleMessage); setHitRects(0x004AEBD0); - + if (!getSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52)) { setSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52, 1); for (uint32 index = 0; index < 18; index++) @@ -672,25 +672,25 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) } insertScreenMouse(0x9A2C0409); - + _asTape = insertSprite<AsScene1201Tape>(this, 3, 1100, 243, 340, 0x9148A011); addCollisionSprite(_asTape); - + tempSprite = insertStaticSprite(0x03C82530, 100); - topY1 = tempSprite->getY() + tempSprite->getDrawRect().height; + topY1 = tempSprite->getY() + tempSprite->getDrawRect().height; tempSprite = insertStaticSprite(0x88182069, 200); - topY2 = tempSprite->getY() + tempSprite->getDrawRect().height; + topY2 = tempSprite->getY() + tempSprite->getDrawRect().height; tempSprite = insertStaticSprite(0x476014E0, 300); - topY3 = tempSprite->getY() + tempSprite->getDrawRect().height; + topY3 = tempSprite->getY() + tempSprite->getDrawRect().height; tempSprite = insertStaticSprite(0x04063110, 500); - topY4 = tempSprite->getY() + 1; + topY4 = tempSprite->getY() + 1; _asTntManRope = insertSprite<AsScene1201TntManRope>(getGlobalVar(V_TNT_DUMMY_BUILT) && which != 1); _asTntManRope->setClipRect(0, topY4, 640, 480); - + insertStaticSprite(0x400B04B0, 1200); tempSprite = insertStaticSprite(0x40295462, 1200); @@ -735,7 +735,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) _klaymen->setClipRect(x1, 0, x2, 480); _klaymen->setRepl(64, 0); - + if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) { setBackground(0x4019A2C4); setPalette(0x4019A2C4); @@ -756,8 +756,8 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) tempSprite = insertSprite<AsScene1201TntManFlame>(_asTntMan); tempSprite->setClipRect(x1, 0, x2, 480); } - - uint32 tntIndex = 1; + + uint32 tntIndex = 1; while (tntIndex < 18) { uint32 elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex); int16 clipY2; @@ -783,10 +783,10 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) setRectList(0x004AEE58); } else { setRectList(0x004AEDC8); - } - + } + } else { - + insertStaticSprite(0x8E8A1981, 900); uint32 tntIndex = 0; @@ -795,7 +795,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) int16 clipY2; if (kScene1201PointArray[elemIndex].x < 300) { clipY2 = 480; - } else { + } else { if (kScene1201PointArray[elemIndex].y < 175) clipY2 = topY1; else if (kScene1201PointArray[elemIndex].y < 230) @@ -811,7 +811,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) setRectList(0x004AEE18); else setRectList(0x004AED88); - + } tempSprite = insertStaticSprite(0x63D400BC, 900); @@ -875,7 +875,7 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entit setMessageList2(0x004AECC0); } break; - case 0x2002: + case 0x2002: if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) { // Move the TNT dummy if the fuse is burning sendEntityMessage(_klaymen, 0x1014, _asTntMan); @@ -903,7 +903,7 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entit break; case 0x8000: sendMessage(_asKlaymenHead, 0x2006, 0); - break; + break; } return messageResult; } @@ -956,7 +956,7 @@ uint32 AsScene1202TntItem::hmShowIdle(int messageNum, const MessageParam ¶m, case 0x2001: _newPosition = (int)param.asInteger(); stChangePositionFadeOut(); - break; + break; } return messageResult; } @@ -998,7 +998,7 @@ void AsScene1202TntItem::stChangePositionDone() { } Scene1202::Scene1202(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _paletteResource(vm), + : Scene(vm, parentModule), _paletteResource(vm), _soundToggle(true), _isPuzzleSolved(false), _counter(0), _clickedIndex(-1) { SetMessageHandler(&Scene1202::handleMessage); @@ -1093,8 +1093,8 @@ uint32 Scene1202::hmSolved(int messageNum, const MessageParam ¶m, Entity *se } bool Scene1202::isSolved() { - return - getSubVar(VA_TNT_POSITIONS, 0) == 0 && getSubVar(VA_TNT_POSITIONS, 3) == 3 && + return + getSubVar(VA_TNT_POSITIONS, 0) == 0 && getSubVar(VA_TNT_POSITIONS, 3) == 3 && getSubVar(VA_TNT_POSITIONS, 6) == 6 && getSubVar(VA_TNT_POSITIONS, 9) == 9 && getSubVar(VA_TNT_POSITIONS, 12) == 12 && getSubVar(VA_TNT_POSITIONS, 15) == 15; } diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp index 8dbfcf616c..c8a561af76 100644 --- a/engines/neverhood/modules/module1300.cpp +++ b/engines/neverhood/modules/module1300.cpp @@ -45,7 +45,7 @@ static const uint32 kModule1300SoundList[] = { Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + _vm->_soundMan->addMusic(0x61C090, 0x00203197); _vm->_soundMan->addSoundList(0x61C090, kModule1300SoundList); _vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 50, 600, 20, 150); @@ -56,7 +56,7 @@ Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which) if (which < 0) { if (_vm->gameState().sceneNum >= 1 && _vm->gameState().sceneNum <= 17) createScene(_vm->gameState().sceneNum, -1); - else + else createScene(11, 0); } else { switch (which) { @@ -101,7 +101,7 @@ Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which) break; } } - + } Module1300::~Module1300() { @@ -109,7 +109,7 @@ Module1300::~Module1300() { } void Module1300::createScene(int sceneNum, int which) { - debug("Module1300::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1300::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 1: @@ -218,7 +218,7 @@ void Module1300::createScene(int sceneNum, int which) { SetUpdateHandler(&Module1300::updateScene); _childObject->handleUpdate(); } - + void Module1300::updateScene() { if (!updateChild()) { switch (_sceneNum) { @@ -274,7 +274,7 @@ void Module1300::updateScene() { createScene(11, 1); break; case 12: - if (_moduleResult == 0) + if (_moduleResult == 0) createScene(14, 1); else if (_moduleResult == 1) createScene(15, 1); @@ -367,7 +367,7 @@ void AsScene1302Bridge::cbLowerBridgeEvent() { SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm) : StaticSprite(vm, 0x11122122, 200) { - + _firstY = _y; if (getGlobalVar(V_FLYTRAP_RING_FENCE)) _y += 152; @@ -459,7 +459,7 @@ Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which) addCollisionSprite(_asVenusFlyTrap); sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap); - + } uint32 Scene1302::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -513,7 +513,7 @@ uint32 Scene1302::handleMessage(int messageNum, const MessageParam ¶m, Entit case 0x2000: if (_klaymen->getY() > 360) { sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap); - setMessageList2(0x004B08F0); + setMessageList2(0x004B08F0); } else setMessageList2(0x004B0920); break; @@ -583,7 +583,7 @@ uint32 Scene1302::handleMessage(int messageNum, const MessageParam ¶m, Entit AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - + createSurface(200, 128, 315); _x = 289; _y = 390; @@ -643,7 +643,7 @@ Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule) _asBalloon = insertSprite<AsScene1303Balloon>(this); addCollisionSprite(_asBalloon); } - + _sprite1 = insertStaticSprite(0xA014216B, 1100); insertKlaymen<KmScene1303>(207, 332); @@ -671,7 +671,7 @@ uint32 Scene1303::handleMessage(int messageNum, const MessageParam ¶m, Entit AsScene1304Needle::AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y) : AnimatedSprite(vm, 0x548E9411, surfacePriority, x, y), _parentScene(parentScene) { - // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself + // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself SetMessageHandler(&AsScene1304Needle::handleMessage); } @@ -693,14 +693,14 @@ uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam ¶ Scene1304::Scene1304(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asNeedle(NULL) { - + SetMessageHandler(&Scene1304::handleMessage); setRectList(0x004B91A8); setBackground(0x062C0214); setPalette(0x062C0214); insertScreenMouse(0xC021006A); - + if (getGlobalVar(V_BALLOON_POPPED)) { _asKey = insertSprite<AsCommonKey>(this, 0, 1100, 278, 347); addCollisionSprite(_asKey); @@ -774,7 +774,7 @@ Scene1305::Scene1305(NeverhoodEngine *vm, Module *parentModule, int which) insertKlaymen<KmScene1305>(212, 441); setMessageList(0x004B6E48); } - + } uint32 Scene1305::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -800,7 +800,7 @@ void AsScene1306Elevator::update() { if (_isUp && _countdown != 0 && (--_countdown == 0)) stGoingDown(); AnimatedSprite::update(); - if (_currFrameIndex == 7) { + if (_currFrameIndex == 7 && _asElevatorDoor->getVisible()) { playSound(1); _asElevatorDoor->setVisible(false); } @@ -868,10 +868,10 @@ void AsScene1306Elevator::cbGoingDownEvent() { Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) setGlobalVar(V_KEY3_LOCATION, 4); - + SetMessageHandler(&Scene1306::handleMessage); setBackground(0x05303114); @@ -949,7 +949,7 @@ Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which) } } - + Scene1306::~Scene1306() { setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0); } @@ -1073,7 +1073,7 @@ static const NPoint kAsScene1307KeyPoints[] = { const uint kAsScene1307KeyFrameIndicesCount = 20; static const int16 kAsScene1307KeyFrameIndices[] = { - 1, 4, 8, 11, 15, 16, 17, 17, 17, 16, + 1, 4, 8, 11, 15, 16, 17, 17, 17, 16, 15, 14, 12, 10, 9, 7, 5, 3, 2, 1 }; @@ -1084,10 +1084,10 @@ const int16 kAsScene1307KeyYDelta = -12; AsScene1307Key::AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects) : AnimatedSprite(vm, 1100), _parentScene(parentScene), _keyIndex(keyIndex), _clipRects(clipRects), _isClickable(true) { - + NPoint pt; - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; - + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + _dataResource.load(0x22102142); _pointList = _dataResource.getPointArray(0xAC849240); pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)]; @@ -1173,7 +1173,7 @@ void AsScene1307Key::suMoveKey() { } void AsScene1307Key::stRemoveKey() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; _pointIndex = 0; startAnimation(fileHashes[0], 0, -1); playSound(1); @@ -1199,7 +1199,7 @@ void AsScene1307Key::stMoveKey() { if (newX == _x && newY == _y) { stInsertKey(); } else { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; _pointIndex = 0; _frameIndex = 0; _deltaX = newX - _x; @@ -1210,13 +1210,13 @@ void AsScene1307Key::stMoveKey() { } void AsScene1307Key::stUnlock() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; startAnimation(fileHashes[1], 0, -1); _newStickFrameIndex = STICK_LAST_FRAME; } void AsScene1307Key::stInsert() { - const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; + const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex]; startAnimation(fileHashes[2], 0, -1); _newStickFrameIndex = STICK_LAST_FRAME; } @@ -1226,9 +1226,9 @@ Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule) _isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) { Sprite *tempSprite; - + _vm->gameModule()->initKeySlotsPuzzle(); - + _dataResource.load(0x22102142); _keyHolePoints = _dataResource.getPointArray(0xAC849240); @@ -1279,7 +1279,7 @@ void Scene1307::update() { if (_doLeaveScene && !isSoundPlaying(0)) { leaveScene(1); setGlobalVar(V_KEYDOOR_UNLOCKED, 1); - } + } } uint32 Scene1307::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -1294,7 +1294,7 @@ uint32 Scene1307::handleMessage(int messageNum, const MessageParam ¶m, Entit int16 mouseY = param.asPoint().y; uint clickedKeyHoleIndex; for (clickedKeyHoleIndex = 0; clickedKeyHoleIndex < 16; clickedKeyHoleIndex++) { - if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 && + if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 && mouseY >= _keyHoleRects[clickedKeyHoleIndex].y1 && mouseY <= _keyHoleRects[clickedKeyHoleIndex].y2) break; } @@ -1362,7 +1362,7 @@ static const uint32 kScene1308NumberFileHashes[] = { AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) { - + setVisible(false); stopAnimation(); SetMessageHandler(&AsScene1308JaggyDoor::handleMessage); @@ -1412,12 +1412,12 @@ void AsScene1308JaggyDoor::stCloseDoorDone() { AsScene1308KeyboardDoor::AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 0xA08A0851, 1100, 320, 240), _parentScene(parentScene) { - + playSound(0, 0x51456049); SetMessageHandler(&AsScene1308KeyboardDoor::handleMessage); NextState(&AsScene1308KeyboardDoor::stFallingKeys); } - + uint32 AsScene1308KeyboardDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -1443,7 +1443,7 @@ void AsScene1308KeyboardDoor::stFallingKeysDone() { AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) { - + setVisible(false); stopAnimation(); Entity::_priority = 1200; @@ -1486,7 +1486,7 @@ void AsScene1308LightWallSymbols::stFadeOutDone() { SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index) : StaticSprite(vm, fileHash, 100) { - + setVisible(false); _x = _spriteResource.getPosition().x + index * 20; updatePosition(); @@ -1520,11 +1520,11 @@ uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam ¶m Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _isProjecting(false), _asProjector(NULL) { - + _vm->gameModule()->initKeySlotsPuzzle(); SetMessageHandler(&Scene1308::handleMessage); - + setBackground(0x41024202); setPalette(0x41024202); insertScreenMouse(0x24206418); @@ -1536,7 +1536,7 @@ Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which) insertSprite<AsScene1308Mouse>(); insertSprite<AnimatedSprite>(0x461A1490, 200, 235, 429); } - + _sprite1 = insertStaticSprite(0x0A042060, 1100); _asJaggyDoor = insertSprite<AsScene1308JaggyDoor>(this); _asLightWallSymbols = insertSprite<AsScene1308LightWallSymbols>(this); @@ -1546,7 +1546,7 @@ Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which) _sprite2 = insertStaticSprite(0x40043120, 995); _sprite3 = insertStaticSprite(0x43003100, 995); _sprite4 = NULL; - + if (which < 0) { // Restoring game insertKlaymen<KmScene1308>(380, 440); @@ -1698,7 +1698,7 @@ uint32 Scene1308::handleMessage(int messageNum, const MessageParam ¶m, Entit Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule) { - + SetMessageHandler(&Scene1317::handleMessage); _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08982841, true, false)); _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); @@ -1711,6 +1711,7 @@ Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule) void Scene1317::update() { if (_smackerFileHash) { _smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame); + _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); _smackerFileHash = 0; } Scene::update(); @@ -1719,7 +1720,7 @@ void Scene1317::update() { void Scene1317::upChooseKing() { if (!_klaymenBlinks && _klaymenBlinkCountdown != 0 && (--_klaymenBlinkCountdown == 0)) _klaymenBlinks = true; - + if (!_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 2) { _smackerPlayer->rewind(); } else if (_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 6) { @@ -1730,14 +1731,15 @@ void Scene1317::upChooseKing() { if (!_klaymenBlinks && _decisionCountdown != 0 && (--_decisionCountdown == 0)) stNoDecisionYet(); - + if (_smackerFileHash) { _smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame); + _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); _smackerFileHash = 0; } Scene::update(); - + } uint32 Scene1317::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -1749,7 +1751,7 @@ uint32 Scene1317::handleMessage(int messageNum, const MessageParam ¶m, Entit } return messageResult; } - + uint32 Scene1317::hmChooseKing(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Scene::handleMessage(messageNum, param, sender); switch (messageNum) { diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp index 4f69637ee0..0a029632b6 100644 --- a/engines/neverhood/modules/module1400.cpp +++ b/engines/neverhood/modules/module1400.cpp @@ -31,7 +31,7 @@ namespace Neverhood { Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + _vm->_soundMan->addMusic(0x00AD0012, 0x06333232); _vm->_soundMan->addMusic(0x00AD0012, 0x624A220E); @@ -47,7 +47,7 @@ Module1400::~Module1400() { } void Module1400::createScene(int sceneNum, int which) { - debug("Module1400::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1400::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -139,7 +139,7 @@ void Module1400::updateScene() { AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm) : AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) { - + createSurface(900, 152, 147); _x = 454; _y = 217; @@ -179,10 +179,10 @@ uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam ¶m, _countdown1 = 70; _countdown2 = 8; stStartSucking(); - break; + break; case 0x483A: stSuckInProjector(); - break; + break; } return messageResult; } @@ -221,7 +221,7 @@ void AsScene1401Pipe::stSuckInProjector() { AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm) : AnimatedSprite(vm, 1100) { - + createSurface(100, 71, 41); _x = 478; _y = 433; @@ -243,7 +243,7 @@ uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam ¶m break; case 0x4839: stSuckedIn(); - break; + break; } return messageResult; } @@ -280,7 +280,7 @@ uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam ¶ switch (messageNum) { case 0x4839: stSuckedIn(); - break; + break; } return messageResult; } @@ -332,7 +332,7 @@ uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam &pa case 0x2001: if (_isOpen) _countdown = 168; - messageResult = _isOpen ? 1 : 0; + messageResult = _isOpen ? 1 : 0; break; case 0x3002: gotoNextState(); @@ -341,7 +341,7 @@ uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam &pa _countdown = 168; if (!_isOpen) stOpenDoor(); - break; + break; } return messageResult; } @@ -540,7 +540,7 @@ void AsCommonProjector::moveProjector() { playSound(1, 0x5440E474); _lockedInSlot = true; } - + } void AsCommonProjector::stSuckedIn() { @@ -627,8 +627,8 @@ void AsCommonProjector::stStartSuckedIn() { } Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL), - _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL), + : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL), + _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL), _sprite1(NULL), _sprite2(NULL), _sprite3(NULL), _ssButton(NULL) { SetMessageHandler(&Scene1401::handleMessage); @@ -638,7 +638,7 @@ Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) setBackground(0x08221FA5); setPalette(0x08221FA5); insertScreenMouse(0x21FA108A); - + _ssFloorButton = insertSprite<SsCommonFloorButton>(this, 0x980F3124, 0x12192892, 100, 0); _asPipe = insertSprite<AsScene1401Pipe>(); @@ -692,7 +692,7 @@ Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) } _asProjector->setClipRect(_sprite3->getDrawRect().x, _sprite2->getDrawRect().y, 640, 480); } - + _klaymen->setClipRect(_sprite3->getDrawRect().x, 0, 640, 480); if (which == 0 && _asProjector) @@ -752,7 +752,7 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam ¶m, Entit setMessageList2(0x004B6658); } else setMessageList2(0x004B65F0); - } + } break; case 0x482A: _sprite1->setVisible(true); @@ -772,7 +772,7 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam ¶m, Entit SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority) : StaticSprite(vm, fileHash, surfacePriority) { - + SetFilterY(&Sprite::defFilterY); SetUpdateHandler(&StaticSprite::updatePosition); } @@ -892,7 +892,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) startShaking(); } } - + if (_asPuzzleBox) _asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2()); @@ -914,7 +914,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) } _klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2()); - + } void Scene1402::upShaking() { @@ -1082,7 +1082,7 @@ static const struct { AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) { - + createSurface(100, 117, 45); _x = 108; _y = 106; @@ -1096,7 +1096,7 @@ void AsScene1407Mouse::suWalkTo() { xdelta = _deltaX; else if (xdelta < -_deltaX) xdelta = -_deltaX; - _deltaX = 0; + _deltaX = 0; if (_walkDestX == _x) sendMessage(this, 0x1019, 0); else { @@ -1231,7 +1231,7 @@ Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule) _asMouse = insertSprite<AsScene1407Mouse>(this); _ssResetButton = insertStaticSprite(0x12006600, 100); - _ssResetButton->setVisible(false); + _ssResetButton->setVisible(false); } @@ -1279,9 +1279,9 @@ uint32 Scene1407::handleMessage(int messageNum, const MessageParam ¶m, Entit Scene1403::Scene1403(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asProjector(NULL), _isProjecting(false) { - + SetMessageHandler(&Scene1403::handleMessage); - + setRectList(0x004B1FF8); setBackground(0x2110A234); setPalette(0x2110A234); @@ -1383,10 +1383,10 @@ uint32 Scene1403::handleMessage(int messageNum, const MessageParam ¶m, Entit Scene1404::Scene1404(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asProjector(NULL), _asKey(NULL) { - + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) setGlobalVar(V_KEY3_LOCATION, 5); - + SetMessageHandler(&Scene1404::handleMessage); setRectList(0x004B8D80); @@ -1555,14 +1555,14 @@ Scene1405::Scene1405(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule), _selectFirstTile(true), _tilesLeft(48), _countdown(0) { _vm->gameModule()->initMemoryPuzzle(); - + SetUpdateHandler(&Scene1405::update); SetMessageHandler(&Scene1405::handleMessage); setBackground(0x0C0C007D); setPalette(0x0C0C007D); insertPuzzleMouse(0xC00790C8, 20, 620); - + for (uint32 tileIndex = 0; tileIndex < 48; tileIndex++) { _tiles[tileIndex] = insertSprite<AsScene1405Tile>(this, tileIndex); addCollisionSprite(_tiles[tileIndex]); diff --git a/engines/neverhood/modules/module1500.cpp b/engines/neverhood/modules/module1500.cpp index 2a9597b1fd..3ce9783b69 100644 --- a/engines/neverhood/modules/module1500.cpp +++ b/engines/neverhood/modules/module1500.cpp @@ -26,7 +26,7 @@ namespace Neverhood { Module1500::Module1500(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + if (which < 0) createScene(_vm->gameState().sceneNum, -1); else @@ -35,7 +35,7 @@ Module1500::Module1500(NeverhoodEngine *vm, Module *parentModule, int which) } void Module1500::createScene(int sceneNum, int which) { - debug("Module1500::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1500::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -86,7 +86,7 @@ Scene1501::Scene1501(NeverhoodEngine *vm, Module *parentModule, uint32 backgroun SetUpdateHandler(&Scene1501::update); SetMessageHandler(&Scene1501::handleMessage); - + setBackground(backgroundFileHash); setPalette(); addEntity(_palette); @@ -118,7 +118,7 @@ void Scene1501::update() { _countdown1 = 12; _palette->startFadeToBlack(11); } - + } uint32 Scene1501::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { diff --git a/engines/neverhood/modules/module1600.cpp b/engines/neverhood/modules/module1600.cpp index f7e3c37d84..a5a785e130 100644 --- a/engines/neverhood/modules/module1600.cpp +++ b/engines/neverhood/modules/module1600.cpp @@ -34,7 +34,7 @@ static const uint32 kModule1600SoundList[] = { Module1600::Module1600(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + if (which < 0) createScene(_vm->gameState().sceneNum, -1); else if (which == 1) @@ -59,7 +59,7 @@ Module1600::~Module1600() { } void Module1600::createScene(int sceneNum, int which) { - debug("Module1600::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1600::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -109,7 +109,7 @@ void Module1600::createScene(int sceneNum, int which) { if (getGlobalVar(V_TALK_COUNTING_INDEX) >= 2) setGlobalVar(V_TALK_COUNTING_INDEX, 0); else - incGlobalVar(V_TALK_COUNTING_INDEX, +1); + incGlobalVar(V_TALK_COUNTING_INDEX, +1); break; } SetUpdateHandler(&Module1600::updateScene); @@ -185,11 +185,11 @@ void Module1600::updateScene() { AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y) : AnimatedSprite(vm, 1000), _parentScene(parentScene) { - + createSurface(200, 556, 328); _x = x; _y = y; - + _inMainArea = false; _exitDirection = 0; _currPointIndex = 0; @@ -207,7 +207,7 @@ AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 _soundCounter = 0; _pathPoints = NULL; _currMoveDirection = 0; - + startAnimation(0xD4220027, 0, -1); setDoDeltaX(getGlobalVar(V_CAR_DELTA_X)); @@ -517,7 +517,7 @@ void AsCommonCar::moveToNextPoint() { if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) && ((_currMoveDirection == 2 && nextPt.x < currPt.x) || (_currMoveDirection == 4 && nextPt.x >= currPt.x))) { - if (_currMoveDirection == 2) + if (_currMoveDirection == 2) _currMoveDirection = 4; else if (_currMoveDirection == 4) _currMoveDirection = 2; @@ -605,7 +605,7 @@ void AsCommonCar::moveToPrevPoint() { if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) && ((_currMoveDirection == 2 && prevPt.x < currPt.x) || (_currMoveDirection == 4 && prevPt.x >= currPt.x))) { - if (_currMoveDirection == 2) + if (_currMoveDirection == 2) _currMoveDirection = 4; else if (_currMoveDirection == 4) _currMoveDirection = 2; @@ -668,7 +668,7 @@ void AsCommonCar::suMoveToNextPoint() { bool firstTime = true; _ySteps = _steps; int stepsCtr = _steps; - + while (stepsCtr > 0) { NPoint pt1; NPoint pt2 = pathPoint(_currPointIndex); @@ -739,7 +739,7 @@ void AsCommonCar::suMoveToNextPoint() { stepsCtr = 0; } } - firstTime = false; + firstTime = false; } if (_yMoveTotalSteps != 0) { @@ -811,7 +811,7 @@ void AsCommonCar::suMoveToPrevPoint() { bool firstTime = true; _ySteps = _steps; int stepsCtr = _steps; - + while (stepsCtr > 0) { if (_stepError == 0) _currPointIndex--; @@ -884,7 +884,7 @@ void AsCommonCar::suMoveToPrevPoint() { stepsCtr = 0; } } - firstTime = false; + firstTime = false; } if (_yMoveTotalSteps != 0) { @@ -971,7 +971,7 @@ AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y) AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar) : AnimatedSprite(vm, 1100), _asCar(asCar) { - + createSurface1(0x60281C10, 150); startAnimation(0x60281C10, -1, -1); _newStickFrameIndex = STICK_LAST_FRAME; @@ -1006,9 +1006,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _asCar(NULL), _countdown1(0) { setGlobalVar(V_CAR_DELTA_X, 1); - + SetMessageHandler(&Scene1608::hmLowerFloor); - + _asKey = insertSprite<AsCommonKey>(this, 1, 1100, 198, 220); addCollisionSprite(_asKey); @@ -1092,9 +1092,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which) _carClipFlag = false; _carStatus = 0; setRectList(0x004B4810); - } + } - // NOTE: Not in the else because 'which' is set to 1 in the true branch + // NOTE: Not in the else because 'which' is set to 1 in the true branch if (which == 1) { // Klaymen riding the car _vm->gameState().which = 1; @@ -1134,9 +1134,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which) _carClipFlag = true; _carStatus = 0; } - + _palette->addPalette("paKlayRed", 0, 64, 0); - + } Scene1608::~Scene1608() { @@ -1308,7 +1308,7 @@ uint32 Scene1608::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity } return 0; } - + void Scene1608::updateKlaymenCliprect() { if (_kmScene1608->getX() <= 375) _kmScene1608->setClipRect(_clipRect1); @@ -1321,17 +1321,17 @@ Scene1609::Scene1609(NeverhoodEngine *vm, Module *parentModule) _vm->gameModule()->initCodeSymbolsPuzzle(); _noisySymbolIndex = getGlobalVar(V_NOISY_SYMBOL_INDEX); - + SetMessageHandler(&Scene1609::handleMessage); SetUpdateHandler(&Scene1609::update); - + setBackground(0x92124A14); setPalette(0x92124A14); insertPuzzleMouse(0x24A10929, 20, 620); - + for (int symbolPosition = 0; symbolPosition < 12; symbolPosition++) _asSymbols[symbolPosition] = insertSprite<AsScene3011Symbol>(symbolPosition, false); - + _ssButton = insertSprite<SsScene3011Button>(this, true); addCollisionSprite(_ssButton); loadSound(0, 0x68E25540); @@ -1408,5 +1408,5 @@ bool Scene1609::testVars() { return true; } - + } // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1600.h b/engines/neverhood/modules/module1600.h index 0bf44ff7b8..5f0da528ab 100644 --- a/engines/neverhood/modules/module1600.h +++ b/engines/neverhood/modules/module1600.h @@ -26,6 +26,7 @@ #include "neverhood/neverhood.h" #include "neverhood/module.h" #include "neverhood/scene.h" +#include "neverhood/console.h" #include "neverhood/modules/module3000.h" namespace Neverhood { @@ -162,6 +163,7 @@ protected: }; class Scene1609 : public Scene { + friend class Console; public: Scene1609(NeverhoodEngine *vm, Module *parentModule); protected: diff --git a/engines/neverhood/modules/module1700.cpp b/engines/neverhood/modules/module1700.cpp index 3a6d1f80cb..2aeae466ff 100644 --- a/engines/neverhood/modules/module1700.cpp +++ b/engines/neverhood/modules/module1700.cpp @@ -36,7 +36,7 @@ static const uint32 kModule1700SoundList[] = { Module1700::Module1700(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + _vm->_soundMan->addMusic(0x04212331, 0x31114225); _vm->_soundMan->addSoundList(0x04212331, kModule1700SoundList); _vm->_soundMan->setSoundListParams(kModule1700SoundList, true, 50, 600, 5, 150); @@ -58,7 +58,7 @@ Module1700::~Module1700() { } void Module1700::createScene(int sceneNum, int which) { - debug("Module1700::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1700::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -125,7 +125,7 @@ void Module1700::updateScene() { } } } - + // Scene1705 static const uint32 kScene1705FileHashes[] = { @@ -137,7 +137,7 @@ static const uint32 kScene1705FileHashes[] = { SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex) : StaticSprite(vm, fileHash, 100) { - + _x = _spriteResource.getPosition().x + symbolIndex * 30; _y = _spriteResource.getPosition().y + 160; updatePosition(); @@ -171,7 +171,7 @@ uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam ¶m, setSubVar(VA_HAS_TAPE, _tapeIndex, 1); setVisible(false); SetMessageHandler(NULL); - break; + break; } return messageResult; } @@ -180,7 +180,7 @@ Scene1705::Scene1705(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _paletteArea(1) { Sprite *tempSprite; - + setGlobalVar(V_FELL_DOWN_HOLE, 1); _vm->gameModule()->initCannonSymbolsPuzzle(); @@ -271,7 +271,7 @@ uint32 Scene1705::handleMessage(int messageNum, const MessageParam ¶m, Entit sendEntityMessage(_klaymen, 0x1014, sender); setMessageList(0x004B6AC0); } - break; + break; } return 0; } diff --git a/engines/neverhood/modules/module1700.h b/engines/neverhood/modules/module1700.h index f57c411a18..deb5573f2b 100644 --- a/engines/neverhood/modules/module1700.h +++ b/engines/neverhood/modules/module1700.h @@ -50,7 +50,7 @@ public: class SsScene1705Tape : public StaticSprite { public: SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash); -protected: +protected: Scene *_parentScene; uint32 _tapeIndex; uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); diff --git a/engines/neverhood/modules/module1800.cpp b/engines/neverhood/modules/module1800.cpp index 2a6057f9c8..b312678467 100644 --- a/engines/neverhood/modules/module1800.cpp +++ b/engines/neverhood/modules/module1800.cpp @@ -38,7 +38,7 @@ static const uint32 kModule1800SoundList[] = { Module1800::Module1800(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + _vm->_soundMan->addSoundList(0x04A14718, kModule1800SoundList); _vm->_soundMan->setSoundListParams(kModule1800SoundList, true, 50, 600, 10, 150); _vm->_soundMan->playTwoSounds(0x04A14718, 0x8A382B55, 0x0C242F1D, 0); @@ -61,7 +61,7 @@ Module1800::~Module1800() { void Module1800::createScene(int sceneNum, int which) { static const byte kNavigationTypes00[] = {1, 0, 2, 0}; static const byte kNavigationTypes01[] = {5}; - debug("Module1800::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1800::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -177,5 +177,5 @@ void Module1800::updateScene() { } } } - + } // End of namespace Neverhood diff --git a/engines/neverhood/modules/module1900.cpp b/engines/neverhood/modules/module1900.cpp index 1a9ffa127b..29c20083f9 100644 --- a/engines/neverhood/modules/module1900.cpp +++ b/engines/neverhood/modules/module1900.cpp @@ -35,8 +35,8 @@ static const uint32 kModule1900SoundList[] = { Module1900::Module1900(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - // NOTE: The original has a Scene1908 here as well but it's not used here but in another module... - + // NOTE: The original has a Scene1908 here as well but it's not used here but in another module... + if (which < 0) createScene(_vm->gameState().sceneNum, -1); else @@ -52,7 +52,7 @@ Module1900::~Module1900() { } void Module1900::createScene(int sceneNum, int which) { - debug("Module1900::createScene(%d, %d)", sceneNum, which); + debug(1, "Module1900::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -88,7 +88,7 @@ void Module1900::updateScene() { Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + Sprite *tempSprite; setRectList(0x004B34C8); @@ -98,7 +98,7 @@ Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which) insertScreenMouse(0x0322301B); insertStaticSprite(0x42213133, 1100); - + if (!getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) insertStaticSprite(0x40A40168, 100); else if (getGlobalVar(V_STAIRS_DOWN)) { @@ -132,16 +132,16 @@ static const NPoint kAsScene1907SymbolGroundPositions[] = { {400, 375}, {370, 435}, {475, 415} }; -static const NPoint kAsScene1907SymbolPluggedInPositions[] = { +static const NPoint kAsScene1907SymbolPluggedInPositions[] = { {275, 125}, {244, 125}, {238, 131}, {221, 135}, {199, 136}, {168, 149}, {145, 152}, {123, 154}, {103, 157} }; static const NPoint kAsScene1907SymbolGroundHitPositions[] = { - {275, 299}, {244, 299}, {238, 305}, - {221, 309}, {199, 310}, {168, 323}, - {145, 326}, {123, 328}, {103, 331} + {275, 299}, {244, 299}, {238, 305}, + {221, 309}, {199, 310}, {168, 323}, + {145, 326}, {123, 328}, {103, 331} }; static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = { @@ -164,7 +164,7 @@ AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene _plugInFailed = false; _plugInTryCount = 0; - + if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) { _isPluggedIn = true; _currPositionIndex = elementIndex; @@ -289,7 +289,7 @@ void AsScene1907Symbol::suMoveDown() { _y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y; _isMoving = false; SetSpriteUpdate(NULL); - } + } } void AsScene1907Symbol::suMoveUp() { @@ -423,7 +423,7 @@ void AsScene1907Symbol::moveDown() { SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol) : StaticSprite(vm, 1400), _parentScene(parentScene), _asScene1907Symbol(asScene1907Symbol), _countdown1(0) { - + loadSprite(0x64516424, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1400); setVisible(false); loadSound(0, 0x44061000); @@ -474,7 +474,7 @@ void SsScene1907UpDownButton::setToDownPosition() { AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm) : AnimatedSprite(vm, 1400) { - + createSurface1(0x110A1061, 1500); _x = 320; _y = 240; @@ -515,10 +515,10 @@ void AsScene1907WaterHint::hide() { SetMessageHandler(&Sprite::handleMessage); } -Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) - : Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0), +Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) + : Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0), _moveDownCountdown(0), _moveUpCountdown(0), _countdown3(0), _hasPlugInFailed(false) { - + setBackground(0x20628E05); setPalette(0x20628E05); @@ -529,12 +529,12 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) _asSymbols[i] = insertSprite<AsScene1907Symbol>(this, i, getRandomPositionIndex()); addCollisionSprite(_asSymbols[i]); } - + _ssUpDownButton = insertSprite<SsScene1907UpDownButton>(this, _asSymbols[8]); addCollisionSprite(_ssUpDownButton); _asWaterHint = insertSprite<AsScene1907WaterHint>(); - + insertPuzzleMouse(0x28E0120E, 20, 620); SetMessageHandler(&Scene1907::handleMessage); @@ -542,7 +542,7 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) _pluggedInCount = 9; - + loadSound(0, 0x72004A10); loadSound(1, 0x22082A12); loadSound(2, 0x21100A10); @@ -552,7 +552,7 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule) void Scene1907::update() { Scene::update(); - + if (_hasPlugInFailed) { int fallOffDelay = 0; _hasPlugInFailed = false; @@ -619,7 +619,7 @@ uint32 Scene1907::handleMessage(int messageNum, const MessageParam ¶m, Entit playSound(3); setGlobalVar(V_STAIRS_PUZZLE_SOLVED, 1); break; - } + } return 0; } diff --git a/engines/neverhood/modules/module2000.cpp b/engines/neverhood/modules/module2000.cpp index 5039da1b01..fcccdefbdd 100644 --- a/engines/neverhood/modules/module2000.cpp +++ b/engines/neverhood/modules/module2000.cpp @@ -28,7 +28,7 @@ namespace Neverhood { Module2000::Module2000(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + if (which < 0) createScene(_vm->gameState().sceneNum, -1); else if (which == 0) @@ -43,7 +43,7 @@ Module2000::~Module2000() { } void Module2000::createScene(int sceneNum, int which) { - debug("Module2000::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2000::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -137,9 +137,9 @@ Scene2001::Scene2001(NeverhoodEngine *vm, Module *parentModule, int which) sendMessage(this, 0x2000, 0); _klaymen->setDoDeltaX(1); } - + _klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480); - + } uint32 Scene2001::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -153,7 +153,7 @@ uint32 Scene2001::handleMessage(int messageNum, const MessageParam ¶m, Entit setRectList(0x004B3670); _klaymen->setKlaymenIdleTable1(); } - } + } return 0; } diff --git a/engines/neverhood/modules/module2100.cpp b/engines/neverhood/modules/module2100.cpp index 0d7f3dd22a..bcff9d9d1b 100644 --- a/engines/neverhood/modules/module2100.cpp +++ b/engines/neverhood/modules/module2100.cpp @@ -30,7 +30,7 @@ Module2100::Module2100(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { _vm->_soundMan->addMusic(0x10A10C14, 0x11482B95); - + if (which < 0) createScene(_vm->gameState().sceneNum, -1); else if (which == 1) @@ -47,7 +47,7 @@ Module2100::~Module2100() { } void Module2100::createScene(int sceneNum, int which) { - debug("Module2100::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2100::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -129,7 +129,7 @@ void AsScene2101Door::stCloseDoorDone() { AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen) : AnimatedSprite(vm, 1400), _klaymen(klaymen) { - + SetUpdateHandler(&AnimatedSprite::update); SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage); createSurface(1200, 88, 165); @@ -176,8 +176,8 @@ void SsCommonFloorButton::update() { else setVisible(false); } -} - +} + uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -195,12 +195,12 @@ uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &pa Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + Sprite *tempSprite; - + SetMessageHandler(&Scene2101::handleMessage); SetUpdateHandler(&Scene2101::update); - + setBackground(0x44242305); setPalette(0x44242305); insertScreenMouse(0x4230144A); @@ -210,9 +210,9 @@ Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which) _ssFloorButton = insertSprite<SsCommonFloorButton>(this, 0x72427010, 0x32423010, 200, 0); _asTape1 = insertSprite<AsScene1201Tape>(this, 18, 1100, 412, 443, 0x9148A011); addCollisionSprite(_asTape1); - _asTape2 = insertSprite<AsScene1201Tape>(this, 11, 1100, 441, 443, 0x9148A011); + _asTape2 = insertSprite<AsScene1201Tape>(this, 11, 1100, 441, 443, 0x9048A093); addCollisionSprite(_asTape2); - + if (which < 0) { insertKlaymen<KmScene2101>(380, 438); setMessageList(0x004B8E48); @@ -256,10 +256,10 @@ Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which) _doorStatus = 1; _countdown1 = 0; } - + _asHitByDoorEffect = insertSprite<AsScene2101HitByDoorEffect>(_klaymen); _klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480); - + } void Scene2101::update() { diff --git a/engines/neverhood/modules/module2100.h b/engines/neverhood/modules/module2100.h index 369f5ac0cc..d76bed0780 100644 --- a/engines/neverhood/modules/module2100.h +++ b/engines/neverhood/modules/module2100.h @@ -68,7 +68,7 @@ protected: uint32 _soundFileHash; uint32 _fileHash1, _fileHash2; int16 _countdown; - void update(); + void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp index 4f2d9e8fd2..99f21cad74 100644 --- a/engines/neverhood/modules/module2200.cpp +++ b/engines/neverhood/modules/module2200.cpp @@ -30,10 +30,8 @@ namespace Neverhood { Module2200::Module2200(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - - debug("Create Module2200(%d)", which); - _vm->_soundMan->addMusic(0x11391412, 0x601C908C); + _vm->_soundMan->addMusic(0x11391412, 0x601C908C); if (which < 0) createScene(_vm->gameState().sceneNum, -1); @@ -47,11 +45,12 @@ Module2200::~Module2200() { } void Module2200::createScene(int sceneNum, int which) { - debug("Module2200::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2200::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: _vm->gameState().sceneNum = 0; + _vm->_soundMan->startMusic(0x601C908C, 0, 2); _childObject = new Scene2201(_vm, this, which); break; case 1: @@ -441,7 +440,7 @@ void Module2200::updateScene() { } #undef HallOfRecordsSceneLink - + void Module2200::createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId) { _childObject = new HallOfRecordsScene(_vm, this, which, hallOfRecordsInfoId); } @@ -462,7 +461,7 @@ AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite * : AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) { _x = 408; - _y = 290; + _y = 290; createSurface(900, 63, 266); SetUpdateHandler(&AsScene2201Door::update); SetMessageHandler(&AsScene2201Door::handleMessage); @@ -529,7 +528,7 @@ void AsScene2201Door::stCloseDoor() { SsScene2201PuzzleCube::SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex) : StaticSprite(vm, 900) { - + createSurface(100, 16, 16); loadSprite(kSsScene2201PuzzleCubeFileHashes[cubeIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 0, kSsScene2201PuzzleCubePoints[positionIndex].x, kSsScene2201PuzzleCubePoints[positionIndex].y); @@ -544,7 +543,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene2201::handleMessage); SetUpdateHandler(&Scene2201::update); - + loadDataResource(0x04104242); loadHitRectList(); setBackground(0x40008208); @@ -552,9 +551,9 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) insertScreenMouse(0x0820C408); _asTape = insertSprite<AsScene1201Tape>(this, 7, 1100, 459, 432, 0x9148A011); - addCollisionSprite(_asTape); + addCollisionSprite(_asTape); _ssDoorButton = insertSprite<SsCommonPressButton>(this, 0xE4A43E29, 0xE4A43E29, 100, 0); - + for (uint32 cubeIndex = 0; cubeIndex < 9; cubeIndex++) if ((int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex) >= 0) insertSprite<SsScene2201PuzzleCube>(cubeIndex, (int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex)); @@ -563,10 +562,10 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) _clipRects[0].x2 = 640; _clipRects[1].x2 = 640; _clipRects[1].y2 = 480; - + if (!getGlobalVar(V_TILE_PUZZLE_SOLVED)) insertStaticSprite(0x00026027, 900); - + tempSprite = insertStaticSprite(0x030326A0, 1100); _clipRects[0].x1 = tempSprite->getDrawRect().x; insertStaticSprite(0x811DA061, 1100); @@ -603,7 +602,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which) setMessageList(0x004B8120); _asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, true); } - + insertSprite<AsScene2201CeilingFan>(); _vm->_soundMan->addSound(0x04106220, 0x81212040); @@ -720,7 +719,7 @@ uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam & } return messageResult; } - + void SsScene2202PuzzleCube::suMoveCubeX() { bool done = false; @@ -747,9 +746,9 @@ void SsScene2202PuzzleCube::suMoveCubeX() { if (_x == _xFlagPos) _counterDirection = true; } - + if (done) - stopMoving(); + stopMoving(); updateBounds(); @@ -781,9 +780,9 @@ void SsScene2202PuzzleCube::suMoveCubeY() { if (_x == _xFlagPos) _counterDirection = true; } - + if (done) - stopMoving(); + stopMoving(); updateBounds(); @@ -795,7 +794,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) { setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1); setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol); - + _cubePosition = newCubePosition; _errValue = 0; _counterDirection = false; @@ -838,7 +837,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) { if (_newX - _x >= 180) _xFlagPos = _newX - 90; else - _xFlagPos = _x + _newX / 2; + _xFlagPos = _x + _newX / 2; } else { if (_x - _newX >= 180) _xFlagPos = _x + 90; @@ -852,7 +851,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) { if (_newY - _y >= 180) _xFlagPos = _newY - 90; else - _xFlagPos = _y + _newY / 2; + _xFlagPos = _y + _newY / 2; } else { if (_y - _newY >= 180) _xFlagPos = _y + 90; @@ -861,7 +860,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) { } playSound(1); } - + } void SsScene2202PuzzleCube::stopMoving() { @@ -940,7 +939,7 @@ void Scene2202::update() { _isSolved = true; } } - + } uint32 Scene2202::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -982,7 +981,7 @@ int16 Scene2202::getFreeCubePosition(int16 cubePosition) { } bool Scene2202::testIsSolved() { - return + return getSubVar(VA_CUBE_POSITIONS, 0) == 0 && getSubVar(VA_CUBE_POSITIONS, 2) == 2 && getSubVar(VA_CUBE_POSITIONS, 3) == 3 && @@ -1147,7 +1146,7 @@ Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which) _ssSmallRightDoor->setVisible(false); _klaymen->setClipRect(_leftDoorClipRect); } - + } Scene2203::~Scene2203() { @@ -1221,7 +1220,7 @@ Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene2205::handleMessage); SetUpdateHandler(&Scene2205::update); - + setHitRects(0x004B0620); if (getGlobalVar(V_LIGHTS_ON)) { _isLightOn = true; @@ -1264,11 +1263,11 @@ Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which) _klaymen->setClipRect(_ssDoorFrame->getDrawRect().x, 0, 640, 480); _klaymen->setSoundFlag(true); - + loadDataResource(0x00144822); - + } - + void Scene2205::update() { Scene::update(); if (!_isLightOn && getGlobalVar(V_LIGHTS_ON)) { @@ -1344,7 +1343,7 @@ static const int16 kAsScene2206DoorSpikesXDeltasClose[] = { AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash) : StaticSprite(vm, fileHash, 200) { - + if (getGlobalVar(V_SPIKES_RETRACTED)) _x -= 63; SetUpdateHandler(&AsScene2206DoorSpikes::update); @@ -1458,10 +1457,10 @@ Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { uint32 fileHash; - + SetUpdateHandler(&Scene::update); SetMessageHandler(&Scene2206::handleMessage); - + if (getGlobalVar(V_LIGHTS_ON)) { fileHash = 0x41983216; _sprite1 = insertStaticSprite(0x2201266A, 100); @@ -1496,7 +1495,7 @@ Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which) if (!getGlobalVar(V_LIGHTS_ON)) _palette->addPalette(0x0263D144, 0, 65, 0); addCollisionSprite(_ssTestTube); - + if (which < 0) { // Restoring game insertKlaymen<KmScene2206>(200, 430); @@ -1645,7 +1644,7 @@ void AsScene2207Elevator::update() { if (_destPointIndex + _destPointIndexDelta > _pointIndex) { _pointIndex++; startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex); - _newStickFrameIndex = _pointIndex; + _newStickFrameIndex = _pointIndex; if (_destPointIndex + _destPointIndexDelta == _pointIndex) { if (_destPointIndexDelta != 0) _destPointIndexDelta = 0; @@ -1661,7 +1660,7 @@ void AsScene2207Elevator::update() { if (_pointIndex == 0) sendMessage(_parentScene, 0x2003, 0); startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex); - _newStickFrameIndex = _pointIndex; + _newStickFrameIndex = _pointIndex; if (_destPointIndex + _destPointIndexDelta == _pointIndex) { if (_destPointIndexDelta != 0) _destPointIndexDelta = 0; @@ -1676,14 +1675,14 @@ void AsScene2207Elevator::update() { sendMessage(_parentScene, 0x2002, 900); else if (_pointIndex < 20 && _surface->getPriority() != 1100) sendMessage(_parentScene, 0x2002, 1100); - + AnimatedSprite::update(); - + if (_destPointIndex + _destPointIndexDelta == _pointIndex && _isMoving) { sendMessage(_parentScene, 0x2004, 0); _isMoving = false; } - + } void AsScene2207Elevator::suSetPosition() { @@ -1707,14 +1706,14 @@ void AsScene2207Elevator::moveToY(int16 y) { if (!_pointArray || _pointArray->size() == 0) return; - + for (uint i = 0; i < _pointArray->size(); i++) { int16 distance = ABS(y - (*_pointArray)[i].y); if (distance < minDistance) { minDistance = distance; _destPointIndex = i; } - } + } if (_destPointIndex != _pointIndex) { if (_destPointIndex == 0 || _destPointIndex == (int)_pointArray->size() - 1) @@ -1733,7 +1732,7 @@ void AsScene2207Elevator::moveToY(int16 y) { AsScene2207Lever::AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - + _x = x; _y = y; createSurface(1010, 71, 73); @@ -1794,7 +1793,7 @@ void AsScene2207Lever::stLeverUpEvent() { AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 1200), _idle(true) { - + _x = 309; _y = 320; createSurface1(0xCCFD6090, 100); @@ -1875,7 +1874,7 @@ void AsScene2207WallRobotAnimation::cbStopAnimation() { AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm) : AnimatedSprite(vm, 1200), _idle(true) { - + _x = 309; _y = 320; createSurface1(0x8CAA0099, 100); @@ -1926,7 +1925,7 @@ SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int i _x = 330; _y = 246 + index * 50; - updatePosition(); + updatePosition(); } Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule) @@ -1944,7 +1943,7 @@ Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule) _klaymen->setRepl(64, 0); setMessageList(0x004B38E8); _asElevator = insertSprite<AsScene2207Elevator>(this); - + if (getGlobalVar(V_LIGHTS_ON)) { setBackground(0x88C00241); setPalette(0x88C00241); @@ -1953,7 +1952,7 @@ Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule) _ssMaskPart2 = insertStaticSprite(0x688F62A5, 1100); _ssMaskPart3 = insertStaticSprite(0x0043B038, 1100); _asTape = insertSprite<AsScene1201Tape>(this, 4, 1100, 277, 428, 0x9148A011); - addCollisionSprite(_asTape); + addCollisionSprite(_asTape); _asLever = insertSprite<AsScene2207Lever>(this, 527, 333, 0); addCollisionSprite(_asLever); _asWallRobotAnimation = insertSprite<AsScene2207WallRobotAnimation>(this); @@ -2107,7 +2106,7 @@ static const uint32 kScene2208FileHashes1[] = { 0x041023CB, 0x041020CB, 0x041026CB, 0x04102ACB, 0x041032CB, 0x041002CB }; - + static const uint32 kScene2208FileHashes2[] = { 0x091206C9, 0x091406C9, 0x091806C9, 0x090006C9, 0x093006C9, 0x095006C9 @@ -2123,13 +2122,13 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which) setGlobalVar(V_COLUMN_TEXT_NAME, calcHash("stLineagex")); _textResource.load(getGlobalVar(V_COLUMN_TEXT_NAME)); - + textStart = _textResource.getString(getGlobalVar(V_CLICKED_COLUMN_INDEX), textEnd); while (textStart < textEnd) { _strings.push_back(textStart); textStart += strlen(textStart) + 1; } - + _maxRowIndex = 8 + 10 * (3 - (getGlobalVar(V_COLUMN_TEXT_NAME) == calcHash("stLineagex") ? 1 : 0)); _background = new Background(_vm, 0); @@ -2142,20 +2141,20 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which) _fontSurface = FontSurface::createFontSurface(_vm, 0x0800090C); - _backgroundSurface = new BaseSurface(_vm, 0, 640, 480); + _backgroundSurface = new BaseSurface(_vm, 0, 640, 480, "background"); spriteResource.load(0x08100289, true); _backgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); - _topBackgroundSurface = new BaseSurface(_vm, 0, 640, 192); + _topBackgroundSurface = new BaseSurface(_vm, 0, 640, 192, "top background"); spriteResource.load(!getGlobalVar(V_COLUMN_BACK_NAME) ? kScene2208FileHashes1[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6] : getGlobalVar(V_COLUMN_BACK_NAME), true); _topBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); - _bottomBackgroundSurface = new BaseSurface(_vm, 0, 640, 192); + _bottomBackgroundSurface = new BaseSurface(_vm, 0, 640, 192, "bottom background"); spriteResource.load(kScene2208FileHashes2[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6], true); _bottomBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0); - + SetUpdateHandler(&Scene2208::update); SetMessageHandler(&Scene2208::handleMessage); @@ -2166,7 +2165,7 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which) if (_newRowIndex < 6) _newRowIndex = 0; _rowScrollY = 0; - _backgroundScrollY = 48 * _newRowIndex; + _backgroundScrollY = 48 * _newRowIndex; _currRowIndex = _newRowIndex; for (int16 rowIndex = 0; rowIndex < _visibleRowsCount; rowIndex++) @@ -2186,7 +2185,7 @@ Scene2208::~Scene2208() { void Scene2208::update() { int16 mouseY = _vm->getMouseY(); - + if (mouseY < 48) { if (_currRowIndex > 0) _newRowIndex = _currRowIndex - 1; @@ -2236,7 +2235,7 @@ uint32 Scene2208::handleMessage(int messageNum, const MessageParam ¶m, Entit } void Scene2208::drawRow(int16 rowIndex) { - NDrawRect sourceRect; + NDrawRect sourceRect; int16 y = (rowIndex * 48) % 528; if (rowIndex < 4) { sourceRect.x = 0; @@ -2281,7 +2280,7 @@ Scene2242::Scene2242(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene2242::handleMessage); SetUpdateHandler(&Scene2242::update); - + if (getGlobalVar(V_LIGHTS_ON)) { setBackground(0x11840E24); setPalette(0x11840E24); @@ -2298,7 +2297,7 @@ Scene2242::Scene2242(NeverhoodEngine *vm, Module *parentModule, int which) } _asTape = insertSprite<AsScene1201Tape>(this, 10, 1100, 464, 435, 0x9148A011); - addCollisionSprite(_asTape); + addCollisionSprite(_asTape); if (which < 0) { // Restoring game @@ -2381,7 +2380,7 @@ void Scene2242::readClickedColumn() { } static const int16 kHallOfRecordsKlaymenXPos[] = { - 68, 157, 246, 335, + 68, 157, 246, 335, 424, 513, 602 }; @@ -2397,7 +2396,7 @@ static const uint32 kHallOfRecordsSceneMessageListIds1[] = { HallOfRecordsScene::HallOfRecordsScene(NeverhoodEngine *vm, Module *parentModule, int which, uint32 hallOfRecordsInfoId) : Scene(vm, parentModule) { - + _hallOfRecordsInfo = _vm->_staticData->getHallOfRecordsInfoItem(hallOfRecordsInfoId); SetMessageHandler(&HallOfRecordsScene::handleMessage); @@ -2488,7 +2487,7 @@ static const uint32 kScene2247MessageListIds1[] = { Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + SetMessageHandler(&Scene2247::handleMessage); SetUpdateHandler(&Scene::update); @@ -2525,7 +2524,7 @@ Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which) } _klaymen->setSoundFlag(true); - + } Scene2247::~Scene2247() { diff --git a/engines/neverhood/modules/module2200.h b/engines/neverhood/modules/module2200.h index af7171dd53..5c19f2a818 100644 --- a/engines/neverhood/modules/module2200.h +++ b/engines/neverhood/modules/module2200.h @@ -100,7 +100,7 @@ class SsScene2202PuzzleCube : public StaticSprite { public: SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol); protected: - Scene *_parentScene; + Scene *_parentScene; int16 _cubeSymbol; int16 _cubePosition; int16 _newX, _newY; @@ -135,7 +135,7 @@ protected: void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); int16 getFreeCubePosition(int16 index); - bool testIsSolved(); + bool testIsSolved(); }; class AsCommonKey : public AnimatedSprite { diff --git a/engines/neverhood/modules/module2300.cpp b/engines/neverhood/modules/module2300.cpp index 34eca14bea..2a46df1ee2 100644 --- a/engines/neverhood/modules/module2300.cpp +++ b/engines/neverhood/modules/module2300.cpp @@ -32,12 +32,12 @@ static const uint32 kModule2300SoundList[] = { Module2300::Module2300(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule), _soundVolume(0) { - + _vm->_soundMan->addSoundList(0x1A214010, kModule2300SoundList); _vm->_soundMan->setSoundListParams(kModule2300SoundList, true, 50, 600, 10, 150); _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; - + if (_isWallBroken) { _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); _vm->_soundMan->playSoundLooping(0x90F0D1C3); @@ -68,7 +68,7 @@ Module2300::~Module2300() { } void Module2300::createScene(int sceneNum, int which) { - debug("Module2300::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2300::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -161,12 +161,12 @@ void Module2300::updateScene() { } else { switch (_sceneNum) { case 1: - if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && + if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 && navigationScene()->getFrameNumber() % 2) { _soundVolume++; _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); } - if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 && + if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 && navigationScene()->getFrameNumber() == 50) { _vm->_soundMan->playTwoSounds(0x1A214010, 0x48498E46, 0x50399F64, 0); _vm->_soundMan->setSoundVolume(0x48498E46, 70); @@ -182,5 +182,5 @@ void Module2300::updateScene() { } } } - + } // End of namespace Neverhood diff --git a/engines/neverhood/modules/module2400.cpp b/engines/neverhood/modules/module2400.cpp index 450812a5f3..21ea390ba2 100644 --- a/engines/neverhood/modules/module2400.cpp +++ b/engines/neverhood/modules/module2400.cpp @@ -26,11 +26,11 @@ namespace Neverhood { Module2400::Module2400(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + _vm->_soundMan->addMusic(0x202D1010, 0xB110382D); if (which < 0) - createScene(_vm->gameState().sceneNum, _vm->gameState().which); + createScene(_vm->gameState().sceneNum, -1); else createScene(0, 0); @@ -41,7 +41,7 @@ Module2400::~Module2400() { } void Module2400::createScene(int sceneNum, int which) { - debug("Module2400::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2400::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -168,11 +168,11 @@ static const uint32 kScene2401FileHashes3[] = { }; static const NRect kScene2401Rects[] = { - NRect(369, 331, 394, 389), - NRect(395, 331, 419, 389), - NRect(420, 331, 441, 389), - NRect(442, 331, 464, 389), - NRect(465, 331, 491, 389) + { 369, 331, 394, 389 }, + { 395, 331, 419, 389 }, + { 420, 331, 441, 389 }, + { 442, 331, 464, 389 }, + { 465, 331, 491, 389 } }; static const uint32 kAsScene2401WaterSpitFileHashes2[] = { @@ -187,7 +187,7 @@ static const uint32 kAsScene2401WaterSpitFileHashes1[] = { AsScene2401WaterSpit::AsScene2401WaterSpit(NeverhoodEngine *vm) : AnimatedSprite(vm, 1200) { - + _x = 240; _y = 447; createSurface(100, 146, 74); @@ -222,7 +222,7 @@ uint32 AsScene2401WaterSpit::handleMessage(int messageNum, const MessageParam &p AsScene2401FlowingWater::AsScene2401FlowingWater(NeverhoodEngine *vm) : AnimatedSprite(vm, 1200), _isWaterFlowing(false) { - + _x = 88; _y = 421; createSurface1(0x10203116, 100); @@ -262,10 +262,10 @@ uint32 AsScene2401FlowingWater::handleMessage(int messageNum, const MessageParam } return messageResult; } - + AsScene2401WaterFlushing::AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y) : AnimatedSprite(vm, 1200), _countdown(0), _flushLoopCount(0) { - + _x = x; _y = y; createSurface1(0xB8596884, 100); @@ -308,7 +308,7 @@ uint32 AsScene2401WaterFlushing::handleMessage(int messageNum, const MessagePara AsScene2401Door::AsScene2401Door(NeverhoodEngine *vm, bool isOpen) : AnimatedSprite(vm, 1100), _countdown(0), _isOpen(isOpen) { - + _x = 320; _y = 240; createSurface1(0x44687810, 100); @@ -398,7 +398,7 @@ Scene2401::Scene2401(NeverhoodEngine *vm, Module *parentModule, int which) _ssWaterPipes[i] = insertStaticSprite(kScene2401FileHashes1[i], 300); _ssWaterPipes[i]->setVisible(false); } - + _asWaterSpit[0] = insertSprite<AsScene2401WaterSpit>(); _asWaterSpit[1] = insertSprite<AsScene2401WaterSpit>(); @@ -461,7 +461,7 @@ void Scene2401::update() { if (_countdown2 != 0 && (--_countdown2) == 0) sendMessage(_asFlowingWater, 0x2003, 0); - + Scene::update(); } @@ -559,7 +559,7 @@ AsScene2402Door::AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool i } else { stopAnimation(); setVisible(false); - } + } SetUpdateHandler(&AsScene2402Door::update); SetMessageHandler(&AsScene2402Door::handleMessage); } @@ -654,7 +654,7 @@ void AsScene2402TV::upFocusKlaymen() { _newStickFrameIndex = _currFrameIndex; if (_countdown2 == 0) { _vm->_soundMan->addSound(0x01520123, 0xC42D4528); - _vm->_soundMan->playSoundLooping(0xC42D4528); + _vm->_soundMan->playSoundLooping(0xC42D4528); } _countdown2 = 5; } else if (_countdown2 != 0 && (--_countdown2 == 0)) @@ -698,7 +698,7 @@ Scene2402::Scene2402(NeverhoodEngine *vm, Module *parentModule, int which) _asTape = insertSprite<AsScene1201Tape>(this, 9, 1100, 286, 409, 0x9148A011); addCollisionSprite(_asTape); _ssButton = insertSprite<SsCommonButtonSprite>(this, 0x15288120, 100, 0); - + if (which < 0) { // Restoring game insertKlaymen<KmScene2402>(198, 404); @@ -779,7 +779,7 @@ uint32 Scene2402::handleMessage(int messageNum, const MessageParam ¶m, Entit } return messageResult; } - + void Scene2402::playPipeSound(uint32 fileHash) { playSound(_soundToggle ? 0 : 1, fileHash); _soundToggle = !_soundToggle; @@ -787,7 +787,7 @@ void Scene2402::playPipeSound(uint32 fileHash) { Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + Sprite *tempSprite1, *tempSprite2, *tempSprite3; SetMessageHandler(&Scene2403::handleMessage); @@ -799,7 +799,7 @@ Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which) addCollisionSprite(_asTape); _asLightCord = insertSprite<AsScene2803LightCord>(this, 0xA1095A10, 0x836D3813, 368, 200); _asLightCord->setClipRect(0, 25, 640, 480); - + if (which < 0) { // Restoring game _isClimbingLadder = false; @@ -828,11 +828,11 @@ Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which) } _ssButton = insertSprite<SsCommonButtonSprite>(this, 0x3130B0EB, 100, 0); - tempSprite1 = insertStaticSprite(0x20C24220, 1100); + tempSprite1 = insertStaticSprite(0x20C24220, 1100); tempSprite2 = insertStaticSprite(0x03080900, 1300); tempSprite3 = insertSprite<AsScene1002KlaymenLadderHands>(_klaymen); tempSprite3->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); - _klaymen->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); + _klaymen->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2()); loadSound(1, calcHash("fxFogHornSoft")); } @@ -887,7 +887,7 @@ Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which) setGlobalVar(V_KEY3_LOCATION, 2); SetMessageHandler(&Scene2406::handleMessage); - + setRectList(0x004B78C8); insertScreenMouse(0xB03001A8); @@ -913,7 +913,7 @@ Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which) setPalette(0x0A038595); tempSprite1 = insertStaticSprite(0x1712112A, 1100); } - + tempSprite2 = insertStaticSprite(0x22300924, 1300); _clipRects[1].x1 = tempSprite1->getDrawRect().x; _clipRects[1].y1 = tempSprite2->getDrawRect().y; diff --git a/engines/neverhood/modules/module2500.cpp b/engines/neverhood/modules/module2500.cpp index a997b5aab1..46ce2ba4fc 100644 --- a/engines/neverhood/modules/module2500.cpp +++ b/engines/neverhood/modules/module2500.cpp @@ -29,29 +29,29 @@ static const uint32 kScene2505StaticSprites[] = { 0x4000A226, 0 }; -static const NRect kScene2505ClipRect = NRect(0, 0, 564, 480); +static const NRect kScene2505ClipRect = { 0, 0, 564, 480 }; static const uint32 kScene2506StaticSprites[] = { 0x4027AF02, 0 }; -static const NRect kScene2506ClipRect = NRect(0, 0, 640, 441); +static const NRect kScene2506ClipRect = { 0, 0, 640, 441 }; static const uint32 kScene2508StaticSprites1[] = { 0x2F08E610, 0xD844E6A0, 0 }; -static const NRect kScene2508ClipRect1 = NRect(0, 0, 594, 448); +static const NRect kScene2508ClipRect1 = { 0, 0, 594, 448 }; static const uint32 kScene2508StaticSprites2[] = { 0x2F08E610, 0 }; -static const NRect kScene2508ClipRect2 = NRect(0, 0, 594, 448); +static const NRect kScene2508ClipRect2 = { 0, 0, 594, 448 }; Module2500::Module2500(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule), _soundIndex(0) { - + _vm->_soundMan->addMusic(0x29220120, 0x05343184); _vm->_soundMan->startMusic(0x05343184, 0, 0); SetMessageHandler(&Module2500::handleMessage); @@ -73,7 +73,7 @@ Module2500::~Module2500() { } void Module2500::createScene(int sceneNum, int which) { - debug("Module2500::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2500::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -212,14 +212,14 @@ uint32 Module2500::handleMessage(int messageNum, const MessageParam ¶m, Enti } return messageResult; } - + void Module2500::createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) { _childObject = new Scene2704(_vm, this, which, sceneInfoId, value, staticSprites, clipRect); } Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2628)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B264C)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2670)); @@ -282,7 +282,7 @@ Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which) _asCarTrackShadow = insertSprite<AsCommonCarTrackShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4); _asCarConnectorShadow = insertSprite<AsCommonCarConnectorShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4); insertSprite<AsCommonCarConnector>(_asCar); - + _newTrackIndex = -1; _dataResource.load(calcHash("Ashooded")); @@ -300,9 +300,9 @@ Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which) if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) sendMessage(_asCar, 0x2008, 150); } - + _carStatus = 0; - + } Scene2501::~Scene2501() { @@ -391,7 +391,7 @@ uint32 Scene2501::handleMessage(int messageNum, const MessageParam ¶m, Entit } return messageResult; } - + uint32 Scene2501::hmRidingCar(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Scene::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -434,7 +434,7 @@ uint32 Scene2501::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity } return messageResult; } - + void Scene2501::moveCarToPoint(NPoint &pt) { int minMatchTrackIndex, minMatchDistance; _tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource); @@ -472,7 +472,7 @@ void Scene2501::updateKlaymenClipRect() { SsScene2504Button::SsScene2504Button(NeverhoodEngine *vm) : StaticSprite(vm, 1400), _countdown(0), _isSoundPlaying(false) { - + loadSprite(0x070220D9, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); loadSound(0, 0x4600204C); @@ -520,9 +520,9 @@ uint32 SsScene2504Button::handleMessage(int messageNum, const MessageParam ¶ Scene2504::Scene2504(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + Sprite *ssButton; - + setBackground(0x90791B80); setPalette(0x90791B80); ssButton = insertSprite<SsScene2504Button>(); diff --git a/engines/neverhood/modules/module2600.cpp b/engines/neverhood/modules/module2600.cpp index b8dbf7bff1..2fce82b777 100644 --- a/engines/neverhood/modules/module2600.cpp +++ b/engines/neverhood/modules/module2600.cpp @@ -35,7 +35,7 @@ static const uint32 kModule2600SoundList[] = { Module2600::Module2600(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule) { - + if (which < 0) createScene(_vm->gameState().sceneNum, -1); else if (which == 1) @@ -54,7 +54,7 @@ Module2600::~Module2600() { } void Module2600::createScene(int sceneNum, int which) { - debug("Module2600::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2600::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -218,10 +218,10 @@ void Module2600::updateScene() { } } } - + SsScene2609Button::SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene) : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) { - + SetUpdateHandler(&SsScene2609Button::update); SetMessageHandler(&SsScene2609Button::handleMessage); @@ -273,7 +273,7 @@ uint32 SsScene2609Button::handleMessage(int messageNum, const MessageParam ¶ AsScene2609Water::AsScene2609Water(NeverhoodEngine *vm) : AnimatedSprite(vm, 1000) { - + _x = 240; _y = 420; setDoDeltaX(1); @@ -309,7 +309,7 @@ uint32 AsScene2609Water::handleMessage(int messageNum, const MessageParam ¶m Scene2609::Scene2609(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _isBusy(false) { - + SetUpdateHandler(&Scene::update); SetMessageHandler(&Scene2609::handleMessage); diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp index 8b69bc050e..7aea82f6b1 100644 --- a/engines/neverhood/modules/module2700.cpp +++ b/engines/neverhood/modules/module2700.cpp @@ -26,14 +26,14 @@ namespace Neverhood { -static const NRect kScene2710ClipRect = NRect(0, 0, 626, 480); +static const NRect kScene2710ClipRect = { 0, 0, 626, 480 }; static const uint32 kScene2710StaticSprites[] = { 0x0D2016C0, 0 }; -static const NRect kScene2711ClipRect = NRect(0, 0, 521, 480); +static const NRect kScene2711ClipRect = { 0, 0, 521, 480 }; static const uint32 kScene2711FileHashes1[] = { 0, @@ -68,14 +68,14 @@ static const uint32 kScene2711FileHashes3[] = { 0 }; -static const NRect kScene2724ClipRect = NRect(0, 141, 640, 480); +static const NRect kScene2724ClipRect = { 0, 141, 640, 480 }; static const uint32 kScene2724StaticSprites[] = { 0xC20D00A5, 0 }; -static const NRect kScene2725ClipRect = NRect(0, 0, 640, 413); +static const NRect kScene2725ClipRect = { 0, 0, 640, 413 }; static const uint32 kScene2725StaticSprites[] = { 0xC20E00A5, @@ -83,8 +83,8 @@ static const uint32 kScene2725StaticSprites[] = { }; Module2700::Module2700(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule), _soundIndex(0), _raidoMusicInitialized(false) { - + : Module(vm, parentModule), _soundIndex(0), _radioMusicInitialized(false) { + _vm->_soundMan->addMusic(0x42212411, 0x04020210); _vm->_soundMan->startMusic(0x04020210, 24, 2); SetMessageHandler(&Module2700::handleMessage); @@ -111,7 +111,7 @@ Module2700::~Module2700() { } void Module2700::createScene(int sceneNum, int which) { - debug("Module2700::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2700::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -500,7 +500,7 @@ void Module2700::updateScene() { } else { switch (_sceneNum) { case 21: - if (!_raidoMusicInitialized) { + if (!_radioMusicInitialized) { _vm->_soundMan->stopMusic(0x04020210, 0, 1); _vm->gameModule()->initRadioPuzzle(); _musicFileHash = getGlobalVar(V_GOOD_RADIO_MUSIC_NAME); @@ -508,7 +508,7 @@ void Module2700::updateScene() { _vm->_soundMan->startMusic(_musicFileHash, 0, 2); _vm->_soundMan->addSound(0x42212411, 0x44014282); _vm->_soundMan->setSoundParams(0x44014282, true, 120, 360, 72, 0); - _raidoMusicInitialized = true; + _radioMusicInitialized = true; } break; } @@ -527,7 +527,7 @@ uint32 Module2700::handleMessage(int messageNum, const MessageParam ¶m, Enti } return messageResult; } - + void Module2700::createScene2703(int which, uint32 trackInfoId) { _childObject = new Scene2703(_vm, this, which, trackInfoId); } @@ -545,7 +545,7 @@ static const NPoint kCarShadowOffsets[] = { SsCommonTrackShadowBackground::SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash) : StaticSprite(vm, 0) { - + loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition, 0); } @@ -555,7 +555,7 @@ AsCommonCarShadow::AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar, SetUpdateHandler(&AsCommonCarShadow::update); createShadowSurface(shadowSurface, 211, 147, 100); updateShadow(); -} +} void AsCommonCarShadow::update() { updateShadow(); @@ -589,8 +589,8 @@ AsCommonCarConnectorShadow::AsCommonCarConnectorShadow(NeverhoodEngine *vm, Spri SetUpdateHandler(&AsCommonCarConnectorShadow::update); createShadowSurface1(shadowSurface, 0x60281C10, 150); startAnimation(0x60281C10, -1, -1); - _newStickFrameIndex = STICK_LAST_FRAME; -} + _newStickFrameIndex = STICK_LAST_FRAME; +} void AsCommonCarConnectorShadow::update() { _x = _asCar->getX() + kCarShadowOffsets[_index].x; @@ -605,7 +605,7 @@ AsCommonCarTrackShadow::AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCa createShadowSurface1(shadowSurface, 0x0759129C, 100); startAnimation(0x0759129C, frameIndex, -1); _newStickFrameIndex = frameIndex; -} +} void AsCommonCarTrackShadow::update() { _x = _asCar->getX(); @@ -615,19 +615,19 @@ void AsCommonCarTrackShadow::update() { Scene2701::Scene2701(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + Sprite *tempSprite; - + NRect clipRect; TrackInfo *tracks = _vm->_staticData->getTrackInfo(0x004B2240); setGlobalVar(V_CAR_DELTA_X, 1); - + setBackground(tracks->bgFilename); setPalette(tracks->bgFilename); _palette->addPalette(calcHash("paPodFloor"), 65, 31, 65); _palette->addPalette(calcHash("paKlayFloor"), 0, 65, 0); insertScreenMouse(0x08B08180); - + tempSprite = insertStaticSprite(0x1E086325, 1200); clipRect.set(0, 0, 640, tempSprite->getDrawRect().y2()); @@ -661,7 +661,7 @@ Scene2701::Scene2701(NeverhoodEngine *vm, Module *parentModule, int which) if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480) sendMessage(_asCar, 0x2008, 150); } - + _asCar->setClipRect(clipRect); _asCarConnector->setClipRect(clipRect); @@ -715,10 +715,10 @@ uint32 Scene2701::hmCarAtHome(int messageNum, const MessageParam ¶m, Entity Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _isInLight(true), _newTrackIndex(-1) { - + SetMessageHandler(&Scene2702::handleMessage); SetUpdateHandler(&Scene2702::update); - + setBackground(0x18808B00); setPalette(0x18808B00); _palette->addPalette(calcHash("paPodFloor"), 65, 31, 65); @@ -734,7 +734,7 @@ Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which) _asCarTrackShadow = insertSprite<AsCommonCarTrackShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4); _asCarConnectorShadow = insertSprite<AsCommonCarConnectorShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4); _dataResource.load(0x04310014); - + if (which == 1) { _isUpperTrack = false; _currTrackIndex = 1; @@ -765,11 +765,11 @@ Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which) } if (_isUpperTrack) { - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F68)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F68)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F8C)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FB0)); } else { - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FD8)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FD8)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FFC)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B6020)); } @@ -873,19 +873,19 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3 : Scene(vm, parentModule) { TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId); - + SetMessageHandler(&Scene2703::handleMessage); SetUpdateHandler(&Scene2703::update); - + setBackground(tracks->bgFilename); setPalette(tracks->bgFilename); _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); addEntity(_palette); insertScreenMouse(tracks->mouseCursorFilename); - + _palStatus = 2; - + if (tracks->bgShadowFilename) { _ssTrackShadowBackground = createSprite<SsCommonTrackShadowBackground>(tracks->bgShadowFilename); addEntity(_ssTrackShadowBackground); @@ -905,7 +905,7 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3 _dataResource.load(tracks->dataResourceFilename); _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); _asCar->setPathPoints(_trackPoints); - + if (which == _which2) { NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); @@ -921,7 +921,7 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3 else sendMessage(_asCar, 0x2008, 150); } - + if (which == 0) { _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); @@ -931,9 +931,9 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3 _palette->addPalette(calcHash("paKlayBlack"), 0, 65, 0); _palStatus = 0; } - + _palette->copyBasePalette(0, 256, 0); - + } void Scene2703::update() { @@ -981,16 +981,16 @@ uint32 Scene2703::handleMessage(int messageNum, const MessageParam ¶m, Entit } return 0; } - + Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) : Scene(vm, parentModule) { TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId); - + SetMessageHandler(&Scene2704::handleMessage); SetUpdateHandler(&Scene2704::update); - + setBackground(tracks->bgFilename); setPalette(tracks->bgFilename); @@ -999,12 +999,12 @@ Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint3 if (tracks->exPaletteFilename2) _palette->addPalette(tracks->exPaletteFilename2, 65, 31, 65); - + while (staticSprites && *staticSprites) insertStaticSprite(*staticSprites++, 1100); insertScreenMouse(tracks->mouseCursorFilename); - + if (tracks->bgShadowFilename) { _ssTrackShadowBackground = createSprite<SsCommonTrackShadowBackground>(tracks->bgShadowFilename); addEntity(_ssTrackShadowBackground); @@ -1024,7 +1024,7 @@ Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint3 _dataResource.load(tracks->dataResourceFilename); _trackPoints = _dataResource.getPointArray(tracks->trackPointsName); _asCar->setPathPoints(_trackPoints); - + if (which == _which2) { NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1]; sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); @@ -1040,21 +1040,21 @@ Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint3 else sendMessage(_asCar, 0x2008, 0); } - + if (clipRect) { _asCar->getClipRect() = *clipRect; if (_asCarShadow) - _asCarShadow->getClipRect() = *clipRect; + _asCarShadow->getClipRect() = *clipRect; if (_asCarTrackShadow) - _asCarTrackShadow->getClipRect() = *clipRect; + _asCarTrackShadow->getClipRect() = *clipRect; if (_asCarConnectorShadow) - _asCarConnectorShadow->getClipRect() = *clipRect; + _asCarConnectorShadow->getClipRect() = *clipRect; if (_asCarConnector) _asCarConnector->getClipRect() = *clipRect; } } - + void Scene2704::update() { Scene::update(); if (_mouseClicked) { @@ -1083,24 +1083,24 @@ uint32 Scene2704::handleMessage(int messageNum, const MessageParam ¶m, Entit Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _newTrackIndex(-1) { - + SetMessageHandler(&Scene2706::handleMessage); - _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22A0)); + _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22A0)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22C4)); _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22E8)); - + setBackground(0x18808B88); setPalette(0x18808B88); - + _palette->addPalette(calcHash("paPodShade"), 65, 31, 65); _palette->addPalette(calcHash("paKlayShade"), 0, 65, 0); - + insertScreenMouse(0x08B8C180); _ssTrackShadowBackground = createSprite<SsCommonTrackShadowBackground>(0x18808B88); addEntity(_ssTrackShadowBackground); - + _asCar = insertSprite<AsCommonCar>(this, 320, 240); _asCarShadow = insertSprite<AsCommonCarShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4); _asCarConnector = insertSprite<AsCommonCarConnector>(_asCar); @@ -1108,10 +1108,10 @@ Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which) _asCarConnectorShadow = insertSprite<AsCommonCarConnectorShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4); _dataResource.load(0x06000162); - + if (which == 5) _currTrackIndex = 2; - else if (which == 6) + else if (which == 6) _currTrackIndex = 1; else _currTrackIndex = 0; @@ -1123,16 +1123,16 @@ Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which) sendMessage(_asCar, 0x2002, _trackPoints->size() - 1); if (which == 5) sendMessage(_asCar, 0x2007, 50); - else + else sendMessage(_asCar, 0x2007, 150); } else { sendMessage(_asCar, 0x2002, 0); if (which == 5) sendMessage(_asCar, 0x2008, 50); - else + else sendMessage(_asCar, 0x2008, 150); } - + } uint32 Scene2706::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -1192,7 +1192,7 @@ void Scene2706::changeTrack() { Scene2732::Scene2732(NeverhoodEngine *vm, Module *parentModule) : Scene(vm, parentModule) { - + Sprite *tempSprite; setBackground(0x0220C041); diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h index 003666bb7f..158bb609e9 100644 --- a/engines/neverhood/modules/module2700.h +++ b/engines/neverhood/modules/module2700.h @@ -39,7 +39,7 @@ public: protected: int _sceneNum; int _soundIndex; - bool _raidoMusicInitialized; + bool _radioMusicInitialized; uint32 _scene2711StaticSprites[6]; uint32 _musicFileHash; void createScene(int sceneNum, int which); diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp index 26df0aefa5..1c0f9fc9fb 100644 --- a/engines/neverhood/modules/module2800.cpp +++ b/engines/neverhood/modules/module2800.cpp @@ -36,7 +36,7 @@ Module2800::Module2800(NeverhoodEngine *vm, Module *parentModule, int which) _currentMusicFileHash = 0; _vm->_soundMan->addMusic(0x64210814, 0xD2FA4D14); setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 1); - + if (which < 0) { createScene(_vm->gameState().sceneNum, which); } else if (which == 2) { @@ -58,7 +58,7 @@ Module2800::~Module2800() { } void Module2800::createScene(int sceneNum, int which) { - debug("Module2800::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2800::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -224,7 +224,7 @@ void Module2800::updateScene() { _musicResource = NULL; } _currentMusicFileHash = 0; - } + } if (_moduleResult == 1) { createScene(2, 0); } else if (_moduleResult == 2) { @@ -251,7 +251,7 @@ void Module2800::updateScene() { createScene(9, 0); else if (_moduleResult == 5) createScene(25, 0); - else + else createScene(0, 1); break; case 3: @@ -318,7 +318,7 @@ void Module2800::updateScene() { createScene(22, 0); else if (_moduleResult == 22) createScene(23, 0); - else + else createScene(2, 4); break; case 10: @@ -331,7 +331,7 @@ void Module2800::updateScene() { createScene(26, 0); else if (_moduleResult == 3) createScene(9, 5); - else + else createScene(9, 1); break; case 12: @@ -401,7 +401,7 @@ void Module2800::updateMusic(bool halfVolume) { if (!_musicResource) _musicResource = new MusicResource(_vm); - + if (newMusicFileHash != _currentMusicFileHash) { _currentMusicFileHash = newMusicFileHash; if (_currentMusicFileHash != 0) { @@ -469,7 +469,7 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) _klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite2->getDrawRect().x2(), 480); insertScreenMouse(0x0066201C); _asTape = insertSprite<AsScene1201Tape>(this, 8, 1100, 302, 437, 0x9148A011); - addCollisionSprite(_asTape); + addCollisionSprite(_asTape); } else if (getGlobalVar(V_RADIO_ROOM_RIGHT_DOOR)) { setRectList(0x004B6CD0); setBackground(0x11E00684); @@ -480,7 +480,7 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) _klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480); insertScreenMouse(0x00680116); _asTape = insertSprite<SsScene1705Tape>(this, 8, 1100, 302, 437, 0x01142428); - addCollisionSprite(_asTape); + addCollisionSprite(_asTape); } else { setRectList(0x004B6CF0); setBackground(0x030006E6); @@ -491,9 +491,9 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) _klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480); insertScreenMouse(0x006E2038); _asTape = insertSprite<AsScene1201Tape>(this, 8, 1100, 302, 437, 0x9148A011); - addCollisionSprite(_asTape); + addCollisionSprite(_asTape); } - + addEntity(_palette); if (which == 1) { @@ -503,7 +503,7 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) _palette->addPalette(_paletteHash, 0, 65, 0); _palette->addBasePalette(_paletteHash, 0, 65, 0); } - + } Scene2801::~Scene2801() { @@ -565,7 +565,7 @@ Scene2802::~Scene2802() { } setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex); } - + void Scene2802::update() { int prevTuneStatus = _currTuneStatus; uint prevRadioMusicIndex = _currRadioMusicIndex; @@ -577,7 +577,7 @@ void Scene2802::update() { _currTuneStatus = 3; else if (_currTuneStatus == 4) _currTuneStatus = 6; - + switch (_currTuneStatus) { case 2: if (_currRadioMusicIndex < 90) @@ -607,24 +607,20 @@ void Scene2802::update() { } else _currTuneStatus = 0; break; - + } if (prevRadioMusicIndex != _currRadioMusicIndex) _smackerPlayer->gotoFrame(_currRadioMusicIndex); - + if (prevTuneStatus != _currTuneStatus) changeTuneStatus(prevTuneStatus, _currTuneStatus); - - //DEBUG>>> - //debug("_currRadioMusicIndex = %d; V_GOOD_RADIO_MUSIC_INDEX = %d", _currRadioMusicIndex, getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); - //DEBUG<<< if (getGlobalVar(V_RADIO_MOVE_DISH_VIDEO) && prevTuneStatus != _currTuneStatus && _currRadioMusicIndex != 0) { setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 0); leaveScene(1); } - + } uint32 Scene2802::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -762,7 +758,7 @@ void AsScene2803LightCord::setFileHashes(uint32 fileHash1, uint32 fileHash2) { AsScene2803TestTubeOne::AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2) : AnimatedSprite(vm, 1200), _fileHash1(fileHash1), _fileHash2(fileHash2) { - + createSurface1(fileHash1, 100); SetUpdateHandler(&AnimatedSprite::update); SetMessageHandler(&AsScene2803TestTubeOne::handleMessage); @@ -785,7 +781,7 @@ uint32 AsScene2803TestTubeOne::handleMessage(int messageNum, const MessageParam AsScene2803Rope::AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - + createSurface(990, 68, 476); SetUpdateHandler(&AnimatedSprite::update); SetSpriteUpdate(&AnimatedSprite::updateDeltaXY); @@ -841,7 +837,7 @@ void AsScene2803Rope::stHide() { Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _paletteArea(0) { - + static const uint32 kScene2803FileHashes1[] = { 0, 0x081000F1, @@ -858,20 +854,20 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) setGlobalVar(V_BEEN_SHRINKING_ROOM, 1); _vm->gameModule()->initTestTubes1Puzzle(); - + SetMessageHandler(&Scene2803::handleMessage); - + loadDataResource(0x00900849); - + _background = new Background(_vm, 0); _background->createSurface(0, 640, 480); addBackground(_background); - + setPalette(0x412A423E); addEntity(_palette); - + insertScreenMouse(0xA423A41A); - + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) { _asTestTubeOne = (StaticSprite*)insertStaticSprite(0x66121222, 100); } else { @@ -879,13 +875,13 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) kScene2803FileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)], kScene2803FileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)]); } - + if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3) _asTestTubeTwo = (StaticSprite*)insertStaticSprite(0x64330236, 100); if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) _asTestTubeThree = (StaticSprite*)insertStaticSprite(0x2E4A22A2, 100); - + _asLightCord = insertSprite<AsScene2803LightCord>(this, 0x8FAD5932, 0x276E1A3D, 578, 200); _sprite3 = (StaticSprite*)insertStaticSprite(0xA40EF2FB, 1100); _sprite4 = (StaticSprite*)insertStaticSprite(0x0C03AA23, 1100); @@ -900,7 +896,7 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) _clipRectsFloor[0].y1 = 0; _clipRectsFloor[0].x2 = 640; _clipRectsFloor[0].y2 = _sprite8->getDrawRect().y2(); - + _clipRectsFloor[1].x1 = _sprite8->getDrawRect().x2(); _clipRectsFloor[1].y1 = _sprite8->getDrawRect().y2(); _clipRectsFloor[1].x2 = 640; @@ -910,12 +906,12 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which) _clipRectsStairs[0].y1 = 0; _clipRectsStairs[0].x2 = _sprite5->getDrawRect().x2(); _clipRectsStairs[0].y2 = _sprite5->getDrawRect().y2(); - + _clipRectsStairs[1].x1 = _sprite6->getDrawRect().x; _clipRectsStairs[1].y1 = 0; _clipRectsStairs[1].x2 = _sprite3->getDrawRect().x; _clipRectsStairs[1].y2 = _sprite6->getDrawRect().y2(); - + _clipRectsStairs[2].x1 = _sprite3->getDrawRect().x; _clipRectsStairs[2].y1 = 0; _clipRectsStairs[2].x2 = _sprite4->getDrawRect().x2(); @@ -1116,7 +1112,7 @@ Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int wh static const uint32 kScene2803SmallFileHashes2[] = { 0, 0x286800D4, 0x286806D4, 0x28680AD4 }; - + SetMessageHandler(&Scene2803Small::handleMessage); loadDataResource(0x81120132); @@ -1164,7 +1160,7 @@ Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int wh if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3) insertStaticSprite(0x30022689, 100); } - + _sprite6->setVisible(false); _sprite7->setVisible(false); @@ -1356,7 +1352,7 @@ void Scene2803Small::updatePaletteArea(bool instantly) { SsScene2804RedButton::SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene) : StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene) { - + loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? 0x51A10202 : 0x11814A21, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); SetUpdateHandler(&SsScene2804RedButton::update); @@ -1389,7 +1385,7 @@ uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam &p SsScene2804LightCoil::SsScene2804LightCoil(NeverhoodEngine *vm) : StaticSprite(vm, 900) { - + loadSprite(0x8889B008, kSLFDefDrawOffset | kSLFDefPosition, 400); setVisible(false); SetMessageHandler(&SsScene2804LightCoil::handleMessage); @@ -1414,7 +1410,7 @@ uint32 SsScene2804LightCoil::handleMessage(int messageNum, const MessageParam &p SsScene2804LightTarget::SsScene2804LightTarget(NeverhoodEngine *vm) : StaticSprite(vm, 900) { - + loadSprite(0x06092132, kSLFDefDrawOffset | kSLFDefPosition, 400); setVisible(false); SetMessageHandler(&SsScene2804LightTarget::handleMessage); @@ -1439,7 +1435,7 @@ uint32 SsScene2804LightTarget::handleMessage(int messageNum, const MessageParam SsScene2804Flash::SsScene2804Flash(NeverhoodEngine *vm) : StaticSprite(vm, 900) { - + loadSprite(0x211003A0, kSLFDefDrawOffset | kSLFDefPosition, 400); setVisible(false); loadSound(0, 0xCB36BA54); @@ -1453,7 +1449,7 @@ void SsScene2804Flash::show() { SsScene2804BeamCoilBody::SsScene2804BeamCoilBody(NeverhoodEngine *vm) : StaticSprite(vm, 900) { - + loadSprite(0x9A816000, kSLFDefDrawOffset | kSLFDefPosition, 400); setVisible(false); } @@ -1589,7 +1585,7 @@ SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene280 0xA8042525, 0x5008292B }; - + loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? kSsScene2804CrystalButtonFileHashes1[crystalIndex] : kSsScene2804CrystalButtonFileHashes2[crystalIndex], kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); @@ -1623,7 +1619,7 @@ uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessagePara AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody) : AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), _countdown(0) { - + createSurface1(0x00494891, 1000); _x = 125; _y = 184; @@ -1663,7 +1659,7 @@ uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam &pa } return messageResult; } - + void AsScene2804BeamCoil::show() { _ssBeamCoilBody->setVisible(true); setVisible(true); @@ -1699,7 +1695,7 @@ uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam ¶m, AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm) : AnimatedSprite(vm, 1400) { - + createSurface1(0x03842000, 1000); _x = 475; _y = 278; @@ -1754,7 +1750,7 @@ Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which) _asTarget = insertSprite<AsScene2804BeamTarget>(); _ssFlash = insertSprite<SsScene2804Flash>(); } - + _ssRedButton = insertSprite<SsScene2804RedButton>(this); addCollisionSprite(_ssRedButton); @@ -1801,7 +1797,7 @@ uint32 Scene2804::handleMessage(int messageNum, const MessageParam ¶m, Entit void Scene2804::update() { Scene::update(); - + if (_countdown1 != 0 && (--_countdown1) == 0) { leaveScene(0); } @@ -1840,7 +1836,7 @@ void Scene2804::update() { Scene2805::Scene2805(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + SetMessageHandler(&Scene2805::handleMessage); setBackground(0x08021E04); @@ -1898,7 +1894,7 @@ uint32 Scene2805::handleMessage(int messageNum, const MessageParam ¶m, Entit AsScene2806Spew::AsScene2806Spew(NeverhoodEngine *vm) : AnimatedSprite(vm, 1200) { - + createSurface1(0x04211490, 1200); _x = 378; _y = 423; @@ -1923,7 +1919,7 @@ uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam ¶m, } return messageResult; } - + Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { @@ -1931,16 +1927,16 @@ Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene2806::handleMessage); SetUpdateHandler(&Scene2806::update); - + loadDataResource(0x98182003); loadHitRectList(); - + _pointList = _dataResource.getPointArray(0x3606A422); - insertScreenMouse(0x22114C13); + insertScreenMouse(0x22114C13); setBackground(0xC1B22110); setPalette(0xC1B22110); - + _sprite1 = insertStaticSprite(0xA21F82CB, 1100); _clipRects[0].x1 = _sprite1->getDrawRect().x; _clipRects[0].y1 = _sprite1->getDrawRect().y; @@ -1955,7 +1951,7 @@ Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which) _sprite4 = insertStaticSprite(0x72090342, 1100); _clipRects[1].x1 = _sprite4->getDrawRect().x; _clipRects[1].y1 = _sprite4->getDrawRect().y; - + tempSprite = insertStaticSprite(0xD2012C02, 1100); _clipRects[2].x1 = tempSprite->getDrawRect().x; _clipRects[2].y2 = tempSprite->getDrawRect().y2(); @@ -2031,7 +2027,7 @@ void Scene2806::findClosestPoint() { int16 x = MIN<int16>(_klaymen->getX(), 639); int index = 1; - + while (index < (int)_pointList->size() && (*_pointList)[index].x < x) ++index; --index; @@ -2040,12 +2036,12 @@ void Scene2806::findClosestPoint() { _pointIndex = index; _palette->addPalette(kScene2806PaletteFileHashes[index], 0, 64, 0); } - + } Scene2807::Scene2807(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { - + SetMessageHandler(&Scene2807::handleMessage); if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 1) { @@ -2140,7 +2136,7 @@ static const int16 kClass490FrameIndices2[] = { SsScene2808Dispenser::SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex) : StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _testTubeSetNum(testTubeSetNum), _testTubeIndex(testTubeIndex) { - + loadSprite(kClass428FileHashes[testTubeSetNum * 3 + testTubeIndex], kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1500); setVisible(false); SetUpdateHandler(&SsScene2808Dispenser::update); @@ -2153,7 +2149,7 @@ void SsScene2808Dispenser::update() { setVisible(false); } } - + uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -2201,16 +2197,16 @@ AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum loadSound(7, 0x70A43D2D); loadSound(8, 0xF0601E2D); } - + startAnimation(kClass490FileHashes[testTubeIndex], 0, -1); _newStickFrameIndex = 0; - + SetUpdateHandler(&AnimatedSprite::update); SetMessageHandler(&AsScene2808TestTube::handleMessage); - + if (_fillLevel == 0) setVisible(false); - + } uint32 AsScene2808TestTube::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -2257,7 +2253,7 @@ void AsScene2808TestTube::flush() { AsScene2808Handle::AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum) : AnimatedSprite(vm, 1300), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum), _isActivated(false) { - + loadSound(0, 0xE18D1F30); _x = 320; _y = 240; @@ -2329,7 +2325,7 @@ AsScene2808Flow::AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int te SetUpdateHandler(&AnimatedSprite::update); AnimatedSprite::updatePosition(); } - + uint32 AsScene2808Flow::hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -2355,7 +2351,7 @@ void AsScene2808Flow::stKeepFlowing() { AsScene2808LightEffect::AsScene2808LightEffect(NeverhoodEngine *vm, int testTubeSetNum) : AnimatedSprite(vm, 800), _countdown(1) { - + _x = 320; _y = 240; if (testTubeSetNum == 1) @@ -2385,7 +2381,7 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which) _vm->gameModule()->initTestTubes1Puzzle(); else _vm->gameModule()->initTestTubes2Puzzle(); - + SetMessageHandler(&Scene2808::handleMessage); SetUpdateHandler(&Scene2808::update); @@ -2404,7 +2400,7 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which) _asTestTubes[testTubeIndex] = insertSprite<AsScene2808TestTube>(which, testTubeIndex, ssDispenser); addCollisionSprite(_asTestTubes[testTubeIndex]); } - + insertScreenMouse(kScene2808FileHashes2[which]); } @@ -2443,18 +2439,6 @@ uint32 Scene2808::handleMessage(int messageNum, const MessageParam ¶m, Entit } void Scene2808::update() { - - // DEBUG>>> Show correct values - #if 1 - debug("---------------"); - if (_testTubeSetNum == 0) - debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); - else - debug("%03d %03d %03d", getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); - debug("%03d %03d %03d", _asTestTubes[0]->getFillLevel(), _asTestTubes[1]->getFillLevel(), _asTestTubes[2]->getFillLevel()); - #endif - // DEBUG<<< - Scene::update(); if (_countdown != 0 && (--_countdown) == 0) { leaveScene(_leaveResult); @@ -2514,13 +2498,13 @@ Scene2809::Scene2809(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule) { Sprite *tempSprite; - + SetMessageHandler(&Scene2809::handleMessage); SetUpdateHandler(&Scene2809::update); - + loadDataResource(0x1830009A); loadHitRectList(); - + _pointList = _dataResource.getPointArray(0x064A310E); setBackground(0xB22116C5); @@ -2551,7 +2535,7 @@ Scene2809::Scene2809(NeverhoodEngine *vm, Module *parentModule, int which) tempSprite = insertStaticSprite(0x877F6252, 1100); _clipRects[3].x2 = tempSprite->getDrawRect().x2(); - + insertStaticSprite(0x01612A22, 1100); insertStaticSprite(0x877F6252, 1100); @@ -2626,7 +2610,7 @@ void Scene2809::findClosestPoint() { _pointIndex = index; _palette->addPalette(kScene2809PaletteFileHashes[index], 0, 64, 0); } - + } AsScene2810Rope::AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x) @@ -2663,7 +2647,7 @@ Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which) Sprite *tempSprite; SetMessageHandler(&Scene2810::handleMessage); - + setBackground(0x26508804); setPalette(0x26508804); insertScreenMouse(0x0880026D); @@ -2699,7 +2683,7 @@ Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which) } _sprite4->setClipRect(0, _sprite1->getDrawRect().y, 640, 480); } - + if (which < 0) { if (getGlobalVar(V_KLAYMEN_SMALL)) { insertKlaymen<KmScene2810Small>(240, 448); @@ -2880,7 +2864,7 @@ uint32 Scene2810::handleMessage(int messageNum, const MessageParam ¶m, Entit AsScene2812Winch::AsScene2812Winch(NeverhoodEngine *vm) : AnimatedSprite(vm, 1100) { - + createSurface1(0x20DA08A0, 1200); SetUpdateHandler(&AnimatedSprite::update); SetMessageHandler(&AsScene2812Winch::handleMessage); @@ -2911,7 +2895,7 @@ uint32 AsScene2812Winch::handleMessage(int messageNum, const MessageParam ¶m AsScene2812Rope::AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene) : AnimatedSprite(vm, 1100), _parentScene(parentScene) { - + createSurface(990, 68, 476); SetUpdateHandler(&AnimatedSprite::update); SetMessageHandler(&AsScene2812Rope::handleMessage); @@ -2956,7 +2940,7 @@ void AsScene2812Rope::stRopingDown() { AsScene2812TrapDoor::AsScene2812TrapDoor(NeverhoodEngine *vm) : AnimatedSprite(vm, 0x805D0029, 100, 320, 240) { - + SetMessageHandler(&AsScene2812TrapDoor::handleMessage); _newStickFrameIndex = 0; } @@ -2975,15 +2959,15 @@ uint32 AsScene2812TrapDoor::handleMessage(int messageNum, const MessageParam &pa Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _paletteArea(0) { - + if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0) setGlobalVar(V_KEY3_LOCATION, 3); SetMessageHandler(&Scene2812::handleMessage); SetUpdateHandler(&Scene2812::update); - + setRectList(0x004AF700); - + setBackground(0x03600606); setPalette(0x03600606); addEntity(_palette); @@ -2999,7 +2983,7 @@ Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which) _ssTape = insertSprite<SsScene1705Tape>(this, 6, 1100, 513, 437, 0xA1361863); addCollisionSprite(_ssTape); - + _asWinch = insertSprite<AsScene2812Winch>(); _asTrapDoor = insertSprite<AsScene2812TrapDoor>(); _asRope = insertSprite<AsScene2812Rope>(this); @@ -3039,9 +3023,9 @@ Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which) _sprite1->setVisible(false); _klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2()); } - + _asRope->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2()); - + } void Scene2812::update() { @@ -3136,7 +3120,7 @@ Scene2822::Scene2822(NeverhoodEngine *vm, Module *parentModule, int which) addBackground(_background); _background->getSurface()->getDrawRect().y = -10; setPalette(0xD542022E); - insertPuzzleMouse(0x0028D089, 20, 620); + insertPuzzleMouse(0x2022AD5C, 20, 620); _ssButton = insertStaticSprite(0x1A4D4120, 1100); _ssButton->setVisible(false); loadSound(2, 0x19044E72); @@ -3156,7 +3140,7 @@ void Scene2822::update() { _ssButton->setVisible(false); _countdownStatus = 1; _countdown = 48; - } else if (_countdownStatus == 1) { + } else if (_countdownStatus == 1 && getGlobalVar(V_LADDER_DOWN_ACTION)) { playSound(0, 0x1384CB60); _countdownStatus = 2; _countdown = 12; diff --git a/engines/neverhood/modules/module2800.h b/engines/neverhood/modules/module2800.h index fe62f11307..54a9daeb16 100644 --- a/engines/neverhood/modules/module2800.h +++ b/engines/neverhood/modules/module2800.h @@ -79,7 +79,7 @@ public: protected: Scene *_parentScene; uint32 _fileHash1, _fileHash2; - bool _isPulled, _isBusy; + bool _isPulled, _isBusy; uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); uint32 hmPulled(int messageNum, const MessageParam ¶m, Entity *sender); }; @@ -323,7 +323,7 @@ protected: Scene *_parentScene; int _countdown; int _testTubeSetNum, _testTubeIndex; - void update(); + void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; @@ -408,7 +408,7 @@ protected: Sprite *_sprite3; Sprite *_sprite4; Sprite *_asSpew; - void update(); + void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); void findClosestPoint(); }; diff --git a/engines/neverhood/modules/module2900.cpp b/engines/neverhood/modules/module2900.cpp index bd95b82f4c..9e51001a2e 100644 --- a/engines/neverhood/modules/module2900.cpp +++ b/engines/neverhood/modules/module2900.cpp @@ -36,13 +36,13 @@ Module2900::Module2900(NeverhoodEngine *vm, Module *parentModule, int which) if (which >= 0) setGlobalVar(V_TELEPORTER_WHICH, which); - + createScene(0, 0); } void Module2900::createScene(int sceneNum, int which) { - debug("Module2900::createScene(%d, %d)", sceneNum, which); + debug(1, "Module2900::createScene(%d, %d)", sceneNum, which); _sceneNum = sceneNum; switch (_sceneNum) { case 0: @@ -255,7 +255,7 @@ SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene : StaticSprite(vm, 900), _parentScene(parentScene), _index(index), _countdown1(0) { const NPoint &pt = kSsScene2901LocationButtonPoints[_index]; - + loadSprite(kSsScene2901LocationButtonFileHashes[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 800); _collisionBounds.set(pt.x - 25, pt.y - 25, pt.x + 25, pt.y + 25); setVisible(false); @@ -263,7 +263,7 @@ SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene SetUpdateHandler(&SsScene2901LocationButton::update); SetMessageHandler(&SsScene2901LocationButton::handleMessage); } - + void SsScene2901LocationButton::update() { updatePosition(); if (_countdown1 != 0 && (--_countdown1) == 0) { @@ -289,7 +289,7 @@ uint32 SsScene2901LocationButton::handleMessage(int messageNum, const MessagePar SsScene2901LocationButtonLight::SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index) : StaticSprite(vm, 900), _index(index) { - + loadSprite(kSsScene2901LocationButtonLightFileHashes1[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 900); setVisible(false); loadSound(0, kSsScene2901LocationButtonLightFileHashes2[_index]); @@ -315,7 +315,7 @@ SsScene2901BrokenButton::SsScene2901BrokenButton(NeverhoodEngine *vm, int which) SsScene2901BigButton::SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which) : StaticSprite(vm, 900), _parentScene(parentScene), _which(which), _countdown1(0) { - loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400); + loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400); _collisionBounds.set(62, 94, 322, 350); setVisible(false); loadSound(0, 0xF3D420C8); @@ -330,7 +330,7 @@ void SsScene2901BigButton::update() { sendMessage(_parentScene, 0x2000, 0); } } - + uint32 SsScene2901BigButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -361,7 +361,7 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which) setBackground(kScene2901FileHashes1[_currLocationButtonNum]); setPalette(kScene2901FileHashes1[_currLocationButtonNum]); - + for (uint i = 0; i < 6; ++i) { if (i != 2 || !_isButton2Broken) { _ssLocationButtons[i] = insertSprite<SsScene2901LocationButton>(this, _currLocationButtonNum, i); @@ -369,7 +369,7 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which) _ssLocationButtonLights[i] = insertSprite<SsScene2901LocationButtonLight>(_currLocationButtonNum, i); } } - + if (_isButton2Broken) insertSprite<SsScene2901BrokenButton>(_currLocationButtonNum); @@ -377,10 +377,10 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which) addCollisionSprite(_ssBigButton); insertPuzzleMouse(kScene2901FileHashes2[_currLocationButtonNum], 20, 620); - + SetUpdateHandler(&Scene2901::update); SetMessageHandler(&Scene2901::handleMessage); - + } void Scene2901::update() { diff --git a/engines/neverhood/modules/module2900.h b/engines/neverhood/modules/module2900.h index 75b29567f6..142f39a35c 100644 --- a/engines/neverhood/modules/module2900.h +++ b/engines/neverhood/modules/module2900.h @@ -49,7 +49,7 @@ protected: Scene *_parentScene; uint _index; int _countdown1; - void update(); + void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; @@ -74,7 +74,7 @@ protected: Scene *_parentScene; int _which; int _countdown1; - void update(); + void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp index 2bdb9f0497..ab3c18d1f4 100644 --- a/engines/neverhood/modules/module3000.cpp +++ b/engines/neverhood/modules/module3000.cpp @@ -39,7 +39,7 @@ static const uint32 kModule3000SoundList[] = { Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) : Module(vm, parentModule), _soundVolume(0) { - + _vm->_soundMan->addSoundList(0x81293110, kModule3000SoundList); _vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 50, 600, 5, 150); _vm->_soundMan->setSoundParams(0x90F0D1C3, false, 20000, 30000, 20000, 30000); @@ -49,7 +49,7 @@ Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which) _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; - if (_isWallBroken) { + if (!_isWallBroken) { _vm->_soundMan->setSoundVolume(0x90F0D1C3, 0); _vm->_soundMan->playSoundLooping(0x90F0D1C3); } @@ -73,15 +73,16 @@ Module3000::~Module3000() { } void Module3000::createScene(int sceneNum, int which) { - static const byte kNavigationTypes05[] = {3, 0}; + static const byte kNavigationTypes05[] = {2, 0}; static const byte kNavigationTypes06[] = {5}; - debug("Module3000::createScene(%d, %d)", sceneNum, which); + debug(1, "Module3000::createScene(%d, %d)", sceneNum, which); _vm->gameState().sceneNum = sceneNum; + _isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0; switch (_vm->gameState().sceneNum) { case 1: if (!getGlobalVar(V_BOLT_DOOR_OPEN)) { createNavigationScene(0x004B7C80, which); - } else if (getGlobalVar(V_WALL_BROKEN)) { + } else if (_isWallBroken) { createNavigationScene(0x004B7CE0, which); } else { createNavigationScene(0x004B7CB0, which); @@ -89,11 +90,11 @@ void Module3000::createScene(int sceneNum, int which) { break; case 2: _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); - if (_isWallBroken) { + if (!_isWallBroken) { _soundVolume = 90; _vm->_soundMan->setSoundVolume(0x90F0D1C3, 90); } - if (getGlobalVar(V_WALL_BROKEN)) { + if (_isWallBroken) { createNavigationScene(0x004B7D58, which); } else { createNavigationScene(0x004B7D10, which); @@ -102,7 +103,7 @@ void Module3000::createScene(int sceneNum, int which) { case 3: if (getGlobalVar(V_STAIRS_DOWN)) createNavigationScene(0x004B7E60, which); - else if (getGlobalVar(V_WALL_BROKEN)) + else if (_isWallBroken) createNavigationScene(0x004B7DA0, which); else createNavigationScene(0x004B7E00, which); @@ -150,12 +151,12 @@ void Module3000::createScene(int sceneNum, int which) { // NOTE: Newly introduced sceneNums case 1001: if (!getGlobalVar(V_BOLT_DOOR_OPEN)) - if (getGlobalVar(V_WALL_BROKEN)) + if (_isWallBroken) createSmackerScene(0x00940021, true, true, false); else createSmackerScene(0x01140021, true, true, false); else - if (getGlobalVar(V_WALL_BROKEN)) + if (_isWallBroken) createSmackerScene(0x001011B1, true, true, false); else createSmackerScene(0x001021B1, true, true, false); @@ -299,7 +300,7 @@ void Module3000::updateScene() { } else if (frameNumber == 10) { _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); } - if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) { if (frameNumber == 0) _soundVolume = 40; else @@ -313,7 +314,7 @@ void Module3000::updateScene() { if (navigationScene()->isWalkingForward()) { uint32 frameNumber = navigationScene()->getFrameNumber(); int navigationIndex = navigationScene()->getNavigationIndex(); - if (_isWallBroken && _soundVolume > 1 && frameNumber % 2) { + if (!_isWallBroken && _soundVolume > 1 && frameNumber % 2) { _soundVolume--; _vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume); } @@ -338,7 +339,7 @@ void Module3000::updateScene() { if (frameNumber == 40) { _vm->_soundMan->playTwoSounds(0x81293110, 0x40030A51, 0xC862CA15, 0); } - if (_isWallBroken && _soundVolume < 90 && frameNumber % 2) { + if (!_isWallBroken && _soundVolume < 90 && frameNumber % 2) { if (frameNumber == 0) _soundVolume = 40; else @@ -439,7 +440,7 @@ static const uint32 kAsScene3009SymbolFileHashes[] = { }; static const uint32 kSsScene3009SymbolArrowFileHashes1[] = { - 0x24016060, + 0x24016060, 0x21216221, 0x486160A0, 0x42216422, @@ -454,7 +455,7 @@ static const uint32 kSsScene3009SymbolArrowFileHashes1[] = { }; static const uint32 kSsScene3009SymbolArrowFileHashes2[] = { - 0x40092024, + 0x40092024, 0x01636002, 0x8071E028, 0x02A56064, @@ -470,7 +471,7 @@ static const uint32 kSsScene3009SymbolArrowFileHashes2[] = { SsScene3009FireCannonButton::SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene) : StaticSprite(vm, 1400), _parentScene(parentScene), _isClicked(false) { - + loadSprite(0x120B24B0, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); SetUpdateHandler(&SsScene3009FireCannonButton::update); @@ -636,7 +637,7 @@ uint32 AsScene3009VerticalIndicator::handleMessage(int messageNum, const Message AsScene3009HorizontalIndicator::AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus) : AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) { - + _x = getGlobalVar(V_CANNON_TURNED) ? 533 : 92; _y = 150; createSurface1(0xC0C12954, 1200); @@ -701,7 +702,7 @@ AsScene3009Symbol::AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene : AnimatedSprite(vm, 1100), _parentScene(parentScene), _symbolPosition(symbolPosition) { _symbolIndex = getSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition); - + _x = kAsScene3009SymbolPoints[_symbolPosition].x; _y = kAsScene3009SymbolPoints[_symbolPosition].y; createSurface1(kAsScene3009SymbolFileHashes[_symbolPosition / 3], 1200); @@ -752,17 +753,17 @@ void AsScene3009Symbol::hide() { } Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule), _keepVideo(false), _moveCannonLeftFirst(false), + : Scene(vm, parentModule), _keepVideo(false), _moveCannonLeftFirst(false), _isTurning(false), _lockSymbolsPart1Countdown(1), _lockSymbolsPart2Countdown(1) { _cannonTargetStatus = getGlobalVar(V_CANNON_TARGET_STATUS); - + _vm->gameModule()->initCannonSymbolsPuzzle(); - + setGlobalVar(V_CANNON_SMACKER_NAME, 0); - + _vm->_screen->clear(); - + setBackground(0xD000420C); setPalette(0xD000420C); insertPuzzleMouse(0x04208D08, 20, 620); @@ -786,8 +787,8 @@ Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which) } } - _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, kScene3009CannonScopeVideos[_cannonTargetStatus], false, _keepVideo)); - _smackerPlayer->setDrawPos(89, 37); + _cannonSmackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, kScene3009CannonScopeVideos[_cannonTargetStatus], false, _keepVideo)); + _cannonSmackerPlayer->setDrawPos(89, 37); _palette->usePalette(); // Use it again since the SmackerPlayer overrides the usage insertStaticSprite(0x8540252C, 400); @@ -807,42 +808,39 @@ Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene3009::handleMessage); SetUpdateHandler(&Scene3009::update); +} - // DEBUG Enable to set the correct code -#if 0 - for (int i = 0; i < 6; i++) - setSubVar(VA_CURR_CANNON_SYMBOLS, i, _correctSymbols[i]); - sendMessage(this, 0x2003, 0); -#endif +Scene3009::~Scene3009() { +} +void Scene3009::openSmacker(uint32 fileHash, bool keepLastFrame) { + _cannonSmackerPlayer->open(fileHash, keepLastFrame); + //_vm->_screen->setSmackerDecoder(_cannonSmackerPlayer->getSmackerDecoder()); + _palette->usePalette(); } void Scene3009::update() { Scene::update(); - - if (!_keepVideo && _smackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) { + + if (!_keepVideo && _cannonSmackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) { switch (_cannonTargetStatus) { case kCTSNull: case kCTSLowerCannon: - _smackerPlayer->open(0x340A0049, true); - _palette->usePalette(); + openSmacker(0x340A0049, true); _keepVideo = true; break; case kCTSRightRobotNoTarget: - _smackerPlayer->open(0x0082080D, true); - _palette->usePalette(); + openSmacker(0x0082080D, true); _keepVideo = true; _isTurning = false; break; case kCTSRightRobotIsTarget: - _smackerPlayer->open(0x0282080D, true); - _palette->usePalette(); + openSmacker(0x0282080D, true); _keepVideo = true; _isTurning = false; break; case kCTSRightNoRobot: - _smackerPlayer->open(0x0882080D, true); - _palette->usePalette(); + openSmacker(0x0882080D, true); _keepVideo = true; _isTurning = false; break; @@ -851,12 +849,11 @@ void Scene3009::update() { case kCTSLeftNoRobot: if (_moveCannonLeftFirst) { if (_cannonTargetStatus == kCTSLeftRobotNoTarget) - _smackerPlayer->open(0x110A000F, false); - else if (_cannonTargetStatus == kCTSLeftRobotIsTarget) - _smackerPlayer->open(0x500B004F, false); - else if (_cannonTargetStatus == kCTSLeftNoRobot) - _smackerPlayer->open(0x100B010E, false); - _palette->usePalette(); + openSmacker(0x110A000F, false); + else if (_cannonTargetStatus == kCTSLeftRobotIsTarget) + openSmacker(0x500B004F, false); + else if (_cannonTargetStatus == kCTSLeftNoRobot) + openSmacker(0x100B010E, false); _moveCannonLeftFirst = false; _asHorizontalIndicator->stMoveLeft(); } else { @@ -955,15 +952,14 @@ uint32 Scene3009::handleMessage(int messageNum, const MessageParam ¶m, Entit // Cannon is at the right position if (!getGlobalVar(V_ROBOT_TARGET)) { _cannonTargetStatus = kCTSLeftRobotNoTarget; - _smackerPlayer->open(0x108A000F, false); + openSmacker(0x108A000F, false); } else if (!getGlobalVar(V_ROBOT_HIT)) { _cannonTargetStatus = kCTSLeftRobotIsTarget; - _smackerPlayer->open(0x500B002F, false); + openSmacker(0x500B002F, false); } else { _cannonTargetStatus = kCTSLeftNoRobot; - _smackerPlayer->open(0x100B008E, false); + openSmacker(0x100B008E, false); } - _palette->usePalette(); _moveCannonLeftFirst = true; _isTurning = true; _keepVideo = false; @@ -1123,7 +1119,7 @@ AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene loadSound(0, 0x420073DC); loadSound(1, 0x420073DC); } - + setVisible(false); stIdle(); if (initUnlocked) @@ -1131,7 +1127,7 @@ AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene _needRefresh = true; AnimatedSprite::updatePosition(); - + } void AsScene3010DeadBolt::update() { @@ -1221,15 +1217,8 @@ void AsScene3010DeadBolt::stDisabledMessage() { Scene3010::Scene3010(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule), _countdown(0), _doorUnlocked(false), _checkUnlocked(false) { - - int initCountdown = 0; - // DEBUG Enable to activate all buttons -#if 0 - setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[0], 1); - setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[1], 1); - setSubVar(VA_LOCKS_DISABLED, kScene3010ButtonNameHashes[2], 1); -#endif + int initCountdown = 0; setBackground(0x80802626); setPalette(0x80802626); @@ -1359,7 +1348,7 @@ static const uint32 kAsScene3011SymbolFileHashes[] = { SsScene3011Button::SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag) : StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) { - + loadSprite(flag ? 0x11282020 : 0x994D0433, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400); setVisible(false); loadSound(0, 0x44061000); @@ -1457,7 +1446,7 @@ Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which) SetMessageHandler(&Scene3011::handleMessage); SetUpdateHandler(&Scene3011::update); - + setBackground(0x92124A04); setPalette(0xA4070114); addEntity(_palette); @@ -1469,12 +1458,12 @@ Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which) _ssButton = insertSprite<SsScene3011Button>(this, true); addCollisionSprite(_ssButton); - + } void Scene3011::update() { Scene::update(); - + if (_countdown != 0 && (--_countdown == 0)) { switch (_updateStatus) { case 0: diff --git a/engines/neverhood/modules/module3000.h b/engines/neverhood/modules/module3000.h index 7634360d7c..a6cecb227e 100644 --- a/engines/neverhood/modules/module3000.h +++ b/engines/neverhood/modules/module3000.h @@ -128,11 +128,12 @@ protected: class Scene3009 : public Scene { public: Scene3009(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene3009(); bool isTurning(); protected: int _lockSymbolsPart1Countdown; int _lockSymbolsPart2Countdown; - SmackerPlayer *_smackerPlayer; + SmackerPlayer *_cannonSmackerPlayer; Sprite *_ssFireCannonButton; SsScene3009SymbolEdges *_ssSymbolEdges[2]; SsScene3009TargetLine *_ssTargetLines[2]; @@ -149,6 +150,7 @@ protected: void playActionVideo(); bool isSymbolsPart1Solved(); bool isSymbolsPart2Solved(); + void openSmacker(uint32 fileHash, bool keepLastFrame); }; // Scene3010 @@ -242,7 +244,7 @@ protected: bool _buttonClicked; int _countdown; int _noisySymbolIndex; - int _currentSymbolIndex; + int _currentSymbolIndex; int _noisyRandomSymbolIndex; void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); diff --git a/engines/neverhood/mouse.cpp b/engines/neverhood/mouse.cpp index 632f56fb74..f11a3f99ea 100644 --- a/engines/neverhood/mouse.cpp +++ b/engines/neverhood/mouse.cpp @@ -26,9 +26,9 @@ namespace Neverhood { Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, const NRect &mouseRect) - : StaticSprite(vm, 2000), _mouseType(kMouseType433), + : StaticSprite(vm, 2000), _mouseType(kMouseType433), _mouseCursorResource(vm), _frameNum(0) { - + _mouseRect = mouseRect; init(fileHash); if (_x >= _mouseRect.x1 && _x <= _mouseRect.x2 && @@ -43,7 +43,7 @@ Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, const NRect &mouseRect) Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, int16 x1, int16 x2) : StaticSprite(vm, 2000), _mouseType(kMouseType435), _mouseCursorResource(vm), _frameNum(0), _x1(x1), _x2(x2) { - + init(fileHash); if (_x <= _x1) { _mouseCursorResource.setCursorNum(6); @@ -69,8 +69,8 @@ Mouse::~Mouse() { void Mouse::init(uint32 fileHash) { _mouseCursorResource.load(fileHash); - _x = _vm->getMouseX(); - _y = _vm->getMouseY(); + _x = _vm->getMouseX(); + _y = _vm->getMouseY(); createSurface(2000, 32, 32); SetUpdateHandler(&Mouse::update); SetMessageHandler(&Mouse::handleMessage); @@ -99,7 +99,7 @@ void Mouse::update() { _frameNum++; if (_frameNum >= 6) _frameNum = 0; - _needRefresh = _frameNum % 2 == 0; + _needRefresh = _frameNum % 2 == 0; } uint32 Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -113,40 +113,40 @@ uint32 Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *s case 1: if (_x >= 320) messageResult = 1; - else + else messageResult = 0; break; case 2: default: if (_x < 100) messageResult = 0; - else if (_x > 540) + else if (_x > 540) messageResult = 1; - else + else messageResult = 2; break; case 3: if (_x < 100) messageResult = 0; - else if (_x > 540) + else if (_x > 540) messageResult = 1; - else + else messageResult = 4; break; case 4: if (_x < 100) messageResult = 0; - else if (_x > 540) + else if (_x > 540) messageResult = 1; - else if (_y >= 150) + else if (_y >= 150) messageResult = 2; - else + else messageResult = 3; break; case 5: if (_y >= 240) messageResult = 4; - else + else messageResult = 3; break; } @@ -162,7 +162,7 @@ uint32 Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *s } void Mouse::updateCursor() { - + if (!_surface) return; @@ -183,7 +183,7 @@ void Mouse::updateCursor() { _drawOffset = _mouseCursorResource.getRect(); _surface->drawMouseCursorResource(_mouseCursorResource, _frameNum / 2); Graphics::Surface *cursorSurface = _surface->getSurface(); - CursorMan.replaceCursor((const byte*)cursorSurface->pixels, + CursorMan.replaceCursor((const byte*)cursorSurface->getPixels(), cursorSurface->w, cursorSurface->h, -_drawOffset.x, -_drawOffset.y, 0); } @@ -213,44 +213,44 @@ void Mouse::updateCursorNum() { case 1: if (_x >= 320) _mouseCursorResource.setCursorNum(5); - else + else _mouseCursorResource.setCursorNum(6); break; case 2: default: if (_x < 100) _mouseCursorResource.setCursorNum(6); - else if (_x > 540) + else if (_x > 540) _mouseCursorResource.setCursorNum(5); - else + else _mouseCursorResource.setCursorNum(0); break; case 3: if (_x < 100) _mouseCursorResource.setCursorNum(1); - else if (_x > 540) + else if (_x > 540) _mouseCursorResource.setCursorNum(1); break; case 4: if (_x < 100) _mouseCursorResource.setCursorNum(6); - else if (_x > 540) + else if (_x > 540) _mouseCursorResource.setCursorNum(5); - else if (_y >= 150) + else if (_y >= 150) _mouseCursorResource.setCursorNum(0); - else + else _mouseCursorResource.setCursorNum(3); break; case 5: if (_y >= 240) _mouseCursorResource.setCursorNum(2); - else + else _mouseCursorResource.setCursorNum(3); break; } break; } - + } } // End of namespace Neverhood diff --git a/engines/neverhood/mouse.h b/engines/neverhood/mouse.h index 0b927de4df..d6f42b4071 100644 --- a/engines/neverhood/mouse.h +++ b/engines/neverhood/mouse.h @@ -52,7 +52,7 @@ protected: int16 _x1; int16 _x2; int _type; - void init(uint32 fileHash); + void init(uint32 fileHash); void update(); void updateCursorNum(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp index 9752ee618c..51ab96ef37 100644 --- a/engines/neverhood/navigationscene.cpp +++ b/engines/neverhood/navigationscene.cpp @@ -25,33 +25,35 @@ namespace Neverhood { +enum AreaType { + kAreaCanMoveForward = 0, + kAreaCannotMoveForward = 1 +}; + NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes) : Scene(vm, parentModule), _itemsTypes(itemsTypes), _navigationIndex(navigationIndex), _smackerDone(false), _isWalkingForward(false), _isTurning(false), _smackerFileHash(0), _interactive(true), _leaveSceneAfter(false) { _navigationList = _vm->_staticData->getNavigationList(navigationListId); - + if (_navigationIndex < 0) { _navigationIndex = (int)getGlobalVar(V_NAVIGATION_INDEX); if (_navigationIndex >= (int)_navigationList->size()) - _navigationIndex = 0; + _navigationIndex = 0; } setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex); - + SetUpdateHandler(&NavigationScene::update); SetMessageHandler(&NavigationScene::handleMessage); - - _smackerPlayer = new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true); - addEntity(_smackerPlayer); - addSurface(_smackerPlayer->getSurface()); - + + _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true)); + createMouseCursor(); _vm->_screen->clear(); _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); sendMessage(_parentModule, 0x100A, _navigationIndex); - } NavigationScene::~NavigationScene() { @@ -69,7 +71,7 @@ int NavigationScene::getNavigationAreaType() { void NavigationScene::update() { if (_smackerFileHash != 0) { showMouse(false); - openSmacker(_smackerFileHash, false); + _smackerPlayer->open(_smackerFileHash, false); _vm->_screen->clear(); _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); _smackerDone = false; @@ -92,22 +94,15 @@ void NavigationScene::update() { _vm->_soundMan->setTwoSoundsPlayFlag(false); _vm->_soundMan->setSoundThreePlayFlag(false); _smackerDone = false; - openSmacker(navigationItem.fileHash, true); + _smackerPlayer->open(navigationItem.fileHash, true); _vm->_screen->clear(); _vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder()); sendMessage(_parentModule, 0x100A, _navigationIndex); } - } + } Scene::update(); } -void NavigationScene::openSmacker(uint32 fileHash, bool keepLastFrame) { - // The old Smacker surface is deleted when a new Smacker is opened. - removeSurface(_smackerPlayer->getSurface()); - _smackerPlayer->open(fileHash, keepLastFrame); - addSurface(_smackerPlayer->getSurface()); -} - uint32 NavigationScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { switch (messageNum) { case 0x0000: @@ -130,39 +125,34 @@ uint32 NavigationScene::handleMessage(int messageNum, const MessageParam ¶m, } void NavigationScene::createMouseCursor() { - const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex]; uint32 mouseCursorFileHash; int areaType; - if (_mouseCursor) { + if (_mouseCursor) deleteSprite((Sprite**)&_mouseCursor); - } mouseCursorFileHash = navigationItem.mouseCursorFileHash; if (mouseCursorFileHash == 0) mouseCursorFileHash = 0x63A40028; - - if (_itemsTypes) { + + if (_itemsTypes) areaType = _itemsTypes[_navigationIndex]; - } else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag) { - areaType = 0; - } else { - areaType = 1; - } + else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag) + areaType = kAreaCanMoveForward; + else + areaType = kAreaCannotMoveForward; insertNavigationMouse(mouseCursorFileHash, areaType); sendPointMessage(_mouseCursor, 0x4002, _vm->getMousePos()); - } void NavigationScene::handleNavigation(const NPoint &mousePos) { - const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex]; bool oldIsWalkingForward = _isWalkingForward; bool oldIsTurning = _isTurning; uint32 direction = sendPointMessage(_mouseCursor, 0x2064, mousePos); - + switch (direction) { case 0: if (navigationItem.leftSmackerFileHash != 0) { @@ -213,13 +203,12 @@ void NavigationScene::handleNavigation(const NPoint &mousePos) { } break; } - + if (oldIsTurning != _isTurning) _vm->_soundMan->setSoundThreePlayFlag(_isTurning); if (oldIsWalkingForward != _isWalkingForward) _vm->_soundMan->setTwoSoundsPlayFlag(_isWalkingForward); - } } // End of namespace Neverhood diff --git a/engines/neverhood/navigationscene.h b/engines/neverhood/navigationscene.h index 767b3f5d20..ebe9a3597c 100644 --- a/engines/neverhood/navigationscene.h +++ b/engines/neverhood/navigationscene.h @@ -50,7 +50,6 @@ protected: bool _leaveSceneAfter; const byte *_itemsTypes; void update(); - void openSmacker(uint32 fileHash, bool keepLastFrame); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); void createMouseCursor(); void handleNavigation(const NPoint &mousePos); diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp index 6b27343d03..061e6d1279 100644 --- a/engines/neverhood/neverhood.cpp +++ b/engines/neverhood/neverhood.cpp @@ -22,12 +22,18 @@ #include "common/file.h" #include "common/config-manager.h" +#include "common/textconsole.h" + #include "base/plugins.h" #include "base/version.h" + #include "graphics/cursorman.h" + #include "engines/util.h" + #include "neverhood/neverhood.h" #include "neverhood/blbarchive.h" +#include "neverhood/console.h" #include "neverhood/gamemodule.h" #include "neverhood/gamevars.h" #include "neverhood/graphics.h" @@ -71,12 +77,16 @@ Common::Error NeverhoodEngine::run() { _gameState.sceneNum = 0; _gameState.which = 0; + // Assign default values to the config manager, in case settings are missing + ConfMan.registerDefault("originalsaveload", "false"); + _staticData = new StaticData(); _staticData->load("neverhood.dat"); _gameVars = new GameVars(); _screen = new Screen(this); _res = new ResourceMan(); - + _console = new Console(this); + if (isDemo()) { _res->addArchive("a.blb"); _res->addArchive("nevdemo.blb"); @@ -94,11 +104,12 @@ Common::Error NeverhoodEngine::run() { _soundMan = new SoundMan(this); _audioResourceMan = new AudioResourceMan(this); - + _gameModule = new GameModule(this); - + _isSaveAllowed = true; - + _updateSound = true; + if (isDemo()) { // Adjust this navigation list for the demo version NavigationList *navigationList = _staticData->getNavigationList(0x004B67E8); @@ -111,24 +122,26 @@ Common::Error NeverhoodEngine::run() { (*navigationList)[5].middleSmackerFileHash = 0; (*navigationList)[5].middleFlag = 1; } - - if (ConfMan.hasKey("save_slot")) - loadGameState(ConfMan.getInt("save_slot")); - else + + if (ConfMan.hasKey("save_slot")) { + if (loadGameState(ConfMan.getInt("save_slot")).getCode() != Common::kNoError) + _gameModule->startup(); + } else _gameModule->startup(); - + mainLoop(); - + delete _gameModule; delete _soundMan; delete _audioResourceMan; + delete _console; delete _res; delete _screen; delete _gameVars; delete _staticData; - + return Common::kNoError; } @@ -140,6 +153,11 @@ void NeverhoodEngine::mainLoop() { while (eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: + if (event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) { + // Open debugger console + _console->attach(); + continue; + } _gameModule->handleKeyDown(event.kbd.keycode); _gameModule->handleAsciiKey(event.kbd.ascii); break; @@ -169,11 +187,16 @@ void NeverhoodEngine::mainLoop() { _gameModule->checkRequests(); _gameModule->handleUpdate(); _gameModule->draw(); + _console->onFrame(); _screen->update(); nextFrameTime = _screen->getNextFrameTime(); }; - _soundMan->update(); - _audioResourceMan->updateMusic(); + + if (_updateSound) { + _soundMan->update(); + _audioResourceMan->updateMusic(); + } + _system->updateScreen(); _system->delayMillis(10); } diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h index 577fbd7a66..5643e345ad 100644 --- a/engines/neverhood/neverhood.h +++ b/engines/neverhood/neverhood.h @@ -48,6 +48,7 @@ class Screen; class SoundMan; class AudioResourceMan; class StaticData; +class Console; struct NPoint; struct GameState { @@ -86,12 +87,13 @@ public: ResourceMan *_res; GameModule *_gameModule; StaticData *_staticData; - + Console *_console; + SoundMan *_soundMan; AudioResourceMan *_audioResourceMan; public: - + /* Save/load */ enum kReadSaveHeaderError { @@ -116,12 +118,12 @@ public: bool canLoadGameStateCurrently() { return _isSaveAllowed; } bool canSaveGameStateCurrently() { return _isSaveAllowed; } - + Common::Error loadGameState(int slot); Common::Error saveGameState(int slot, const Common::String &description); Common::Error removeGameState(int slot); - void savegame(const char *filename, const char *description); - void loadgame(const char *filename); + bool savegame(const char *filename, const char *description); + bool loadgame(const char *filename); const char *getSavegameFilename(int num); static Common::String getSavegameFilename(const Common::String &target, int num); static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header); @@ -132,7 +134,10 @@ public: int16 getMouseY() const { return _mouseY; } NPoint getMousePos(); -public: + void toggleSoundUpdate(bool state) { _updateSound = state; } + +private: + bool _updateSound; }; diff --git a/engines/neverhood/palette.cpp b/engines/neverhood/palette.cpp index d4b9b67f53..c381f46671 100644 --- a/engines/neverhood/palette.cpp +++ b/engines/neverhood/palette.cpp @@ -81,7 +81,7 @@ void Palette::addPalette(uint32 fileHash, int toIndex, int count, int fromIndex) if (toIndex + count > 256) count = 256 - toIndex; paletteResource.load(fileHash); - memcpy(_palette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4); + memcpy(_palette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4); _vm->_screen->testPalette(_palette); } @@ -90,20 +90,20 @@ void Palette::addBasePalette(uint32 fileHash, int toIndex, int count, int fromIn if (toIndex + count > 256) count = 256 - toIndex; paletteResource.load(fileHash); - memcpy(_basePalette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4); + memcpy(_basePalette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4); } void Palette::copyPalette(const byte *palette, int toIndex, int count, int fromIndex) { if (toIndex + count > 256) count = 256 - toIndex; - memcpy(_palette + toIndex * 4, palette + fromIndex * 4, count * 4); + memcpy(_palette + toIndex * 4, palette + fromIndex * 4, count * 4); _vm->_screen->testPalette(_palette); } void Palette::copyBasePalette(int toIndex, int count, int fromIndex) { if (toIndex + count > 256) count = 256 - toIndex; - memcpy(_basePalette + toIndex * 4, _palette + fromIndex * 4, count * 4); + memcpy(_basePalette + toIndex * 4, _palette + fromIndex * 4, count * 4); } void Palette::startFadeToBlack(int counter) { @@ -115,7 +115,7 @@ void Palette::startFadeToBlack(int counter) { _fadeToB = 0; _palCounter = counter; _fadeStep = 255 / counter; - _status = 1; + _status = 1; } void Palette::startFadeToWhite(int counter) { @@ -127,7 +127,7 @@ void Palette::startFadeToWhite(int counter) { _fadeToB = 255; _palCounter = counter; _fadeStep = 255 / counter; - _status = 1; + _status = 1; } void Palette::startFadeToPalette(int counter) { @@ -136,7 +136,7 @@ void Palette::startFadeToPalette(int counter) { counter = 1; _palCounter = counter; _fadeStep = 255 / counter; - _status = 2; + _status = 2; } void Palette::fillBaseWhite(int index, int count) { diff --git a/engines/neverhood/resource.cpp b/engines/neverhood/resource.cpp index 442713196e..a1a517f251 100644 --- a/engines/neverhood/resource.cpp +++ b/engines/neverhood/resource.cpp @@ -39,7 +39,7 @@ SpriteResource::~SpriteResource() { void SpriteResource::draw(Graphics::Surface *destSurface, bool flipX, bool flipY) { if (_pixels) { - byte *dest = (byte*)destSurface->pixels; + byte *dest = (byte*)destSurface->getPixels(); const int destPitch = destSurface->pitch; if (_rle) unpackSpriteRle(_pixels, _dimensions.width, _dimensions.height, dest, destPitch, flipX, flipY); @@ -57,7 +57,7 @@ bool SpriteResource::load(uint32 fileHash, bool doLoadPosition) { const byte *spriteData = _resourceHandle.data(); NPoint *position = doLoadPosition ? &_position : NULL; parseBitmapResource(spriteData, &_rle, &_dimensions, position, NULL, &_pixels); - } + } return _pixels != NULL; } @@ -116,7 +116,7 @@ AnimResource::~AnimResource() { void AnimResource::draw(uint frameIndex, Graphics::Surface *destSurface, bool flipX, bool flipY) { const AnimFrameInfo frameInfo = _frames[frameIndex]; - byte *dest = (byte*)destSurface->pixels; + byte *dest = (byte*)destSurface->getPixels(); const int destPitch = destSurface->pitch; _currSpriteData = _spriteData + frameInfo.spriteDataOffs; _width = frameInfo.drawOffset.width; @@ -134,11 +134,11 @@ bool AnimResource::load(uint32 fileHash) { return true; unload(); - + _vm->_res->queryResource(fileHash, _resourceHandle); if (!_resourceHandle.isValid() || _resourceHandle.type() != kResTypeAnimation) return false; - + const byte *resourceData, *animList, *frameList; uint16 animInfoStartOfs, animListIndex, animListCount; uint16 frameListStartOfs, frameCount; @@ -146,20 +146,20 @@ bool AnimResource::load(uint32 fileHash) { _vm->_res->loadResource(_resourceHandle); resourceData = _resourceHandle.data(); - + animListCount = READ_LE_UINT16(resourceData); animInfoStartOfs = READ_LE_UINT16(resourceData + 2); spriteDataOfs = READ_LE_UINT32(resourceData + 4); paletteDataOfs = READ_LE_UINT32(resourceData + 8); - + animList = resourceData + 12; for (animListIndex = 0; animListIndex < animListCount; animListIndex++) { debug(8, "hash: %08X", READ_LE_UINT32(animList)); if (READ_LE_UINT32(animList) == fileHash) break; - animList += 8; + animList += 8; } - + if (animListIndex >= animListCount) { _vm->_res->unloadResource(_resourceHandle); return false; @@ -168,12 +168,12 @@ bool AnimResource::load(uint32 fileHash) { _spriteData = resourceData + spriteDataOfs; if (paletteDataOfs > 0) _paletteData = resourceData + paletteDataOfs; - + frameCount = READ_LE_UINT16(animList + 4); frameListStartOfs = READ_LE_UINT16(animList + 6); - + debug(8, "frameCount = %d; frameListStartOfs = %04X; animInfoStartOfs = %04X", frameCount, frameListStartOfs, animInfoStartOfs); - + frameList = resourceData + animInfoStartOfs + frameListStartOfs; _frames.clear(); @@ -189,13 +189,13 @@ bool AnimResource::load(uint32 fileHash) { frameInfo.drawOffset.height = READ_LE_UINT16(frameList + 12); frameInfo.deltaX = READ_LE_UINT16(frameList + 14); frameInfo.deltaY = READ_LE_UINT16(frameList + 16); - frameInfo.collisionBoundsOffset.x = READ_LE_UINT16(frameList + 18); - frameInfo.collisionBoundsOffset.y = READ_LE_UINT16(frameList + 20); - frameInfo.collisionBoundsOffset.width = READ_LE_UINT16(frameList + 22); + frameInfo.collisionBoundsOffset.x = READ_LE_UINT16(frameList + 18); + frameInfo.collisionBoundsOffset.y = READ_LE_UINT16(frameList + 20); + frameInfo.collisionBoundsOffset.width = READ_LE_UINT16(frameList + 22); frameInfo.collisionBoundsOffset.height = READ_LE_UINT16(frameList + 24); frameInfo.spriteDataOffs = READ_LE_UINT32(frameList + 28); - debug(8, "frameHash = %08X; counter = %d; rect = (%d,%d,%d,%d); deltaX = %d; deltaY = %d; collisionBoundsOffset = (%d,%d,%d,%d); spriteDataOffs = %08X", - frameInfo.frameHash, frameInfo.counter, + debug(8, "frameHash = %08X; counter = %d; rect = (%d,%d,%d,%d); deltaX = %d; deltaY = %d; collisionBoundsOffset = (%d,%d,%d,%d); spriteDataOffs = %08X", + frameInfo.frameHash, frameInfo.counter, frameInfo.drawOffset.x, frameInfo.drawOffset.y, frameInfo.drawOffset.width, frameInfo.drawOffset.height, frameInfo.deltaX, frameInfo.deltaY, frameInfo.collisionBoundsOffset.x, frameInfo.collisionBoundsOffset.y, frameInfo.collisionBoundsOffset.width, frameInfo.collisionBoundsOffset.height, @@ -203,11 +203,11 @@ bool AnimResource::load(uint32 fileHash) { frameList += 32; _frames.push_back(frameInfo); } - + _fileHash = fileHash; return true; - + } void AnimResource::unload() { @@ -229,7 +229,7 @@ int16 AnimResource::getFrameIndex(uint32 frameHash) { break; } debug(2, "AnimResource::getFrameIndex(%08X) -> %d", frameHash, frameIndex); - return frameIndex; + return frameIndex; } void AnimResource::setRepl(byte oldColor, byte newColor) { @@ -254,7 +254,7 @@ NDimensions AnimResource::loadSpriteDimensions(uint32 fileHash) { // MouseCursorResource -MouseCursorResource::MouseCursorResource(NeverhoodEngine *vm) +MouseCursorResource::MouseCursorResource(NeverhoodEngine *vm) : _cursorSprite(vm), _cursorNum(4), _currFileHash(0) { _rect.width = 32; @@ -265,7 +265,7 @@ void MouseCursorResource::load(uint32 fileHash) { if (_currFileHash != fileHash) { if (_cursorSprite.load(fileHash) && !_cursorSprite.isRle() && _cursorSprite.getDimensions().width == 96 && _cursorSprite.getDimensions().height == 224) { - _currFileHash = fileHash; + _currFileHash = fileHash; } else { unload(); } @@ -296,14 +296,14 @@ NDrawRect& MouseCursorResource::getRect() { void MouseCursorResource::draw(int frameNum, Graphics::Surface *destSurface) { if (_cursorSprite.getPixels()) { const int sourcePitch = (_cursorSprite.getDimensions().width + 3) & 0xFFFC; // 4 byte alignment - const int destPitch = destSurface->pitch; + const int destPitch = destSurface->pitch; const byte *source = _cursorSprite.getPixels() + _cursorNum * (sourcePitch * 32) + frameNum * 32; - byte *dest = (byte*)destSurface->pixels; + byte *dest = (byte*)destSurface->getPixels(); for (int16 yc = 0; yc < 32; yc++) { memcpy(dest, source, 32); source += sourcePitch; dest += destPitch; - } + } } } @@ -311,7 +311,7 @@ void MouseCursorResource::draw(int frameNum, Graphics::Surface *destSurface) { TextResource::TextResource(NeverhoodEngine *vm) : _vm(vm), _textData(NULL), _count(0) { - + } TextResource::~TextResource() { @@ -372,7 +372,7 @@ void DataResource::load(uint32 fileHash) { dataS.seek(2 + i * 8); DRDirectoryItem drDirectoryItem; drDirectoryItem.nameHash = dataS.readUint32LE(); - drDirectoryItem.offset = dataS.readUint16LE(); + drDirectoryItem.offset = dataS.readUint16LE(); drDirectoryItem.type = dataS.readUint16LE(); debug(2, "%03d nameHash = %08X; offset = %04X; type = %d", i, drDirectoryItem.nameHash, drDirectoryItem.offset, drDirectoryItem.type); dataS.seek(itemStartOffs + drDirectoryItem.offset); @@ -415,7 +415,7 @@ void DataResource::load(uint32 fileHash) { hitRect.rect.y1 = dataS.readUint16LE(); hitRect.rect.x2 = dataS.readUint16LE(); hitRect.rect.y2 = dataS.readUint16LE(); - hitRect.type = dataS.readUint16LE() + 0x5001; + hitRect.type = dataS.readUint16LE() + 0x5001; debug(3, "(%d, %d, %d, %d) -> %04d", hitRect.rect.x1, hitRect.rect.y1, hitRect.rect.x2, hitRect.rect.y2, hitRect.type); hitRectList->push_back(hitRect); } @@ -491,7 +491,7 @@ void DataResource::load(uint32 fileHash) { break; } } - _directory.push_back(drDirectoryItem); + _directory.push_back(drDirectoryItem); } } } @@ -540,12 +540,12 @@ HitRectList *DataResource::getHitRectList() { MessageList *DataResource::getMessageListAtPos(int16 klaymenX, int16 klaymenY, int16 mouseX, int16 mouseY) { for (uint i = 0; i < _drRects.size(); i++) { - if (klaymenX >= _drRects[i].rect.x1 && klaymenX <= _drRects[i].rect.x2 && + if (klaymenX >= _drRects[i].rect.x1 && klaymenX <= _drRects[i].rect.x2 && klaymenY >= _drRects[i].rect.y1 && klaymenY <= _drRects[i].rect.y2) { - DRSubRectList *drSubRectList = _drSubRectLists[_drRects[i].subRectIndex]; + DRSubRectList *drSubRectList = _drSubRectLists[_drRects[i].subRectIndex]; for (uint j = 0; j < drSubRectList->size(); j++) { DRSubRect &subRect = (*drSubRectList)[j]; - if (mouseX >= subRect.rect.x1 && mouseX <= subRect.rect.x2 && + if (mouseX >= subRect.rect.x1 && mouseX <= subRect.rect.x2 && mouseY >= subRect.rect.y1 && mouseY <= subRect.rect.y2) { return _messageLists[subRect.messageListItemIndex]; } diff --git a/engines/neverhood/resource.h b/engines/neverhood/resource.h index 6a84a69ecd..40236d9d22 100644 --- a/engines/neverhood/resource.h +++ b/engines/neverhood/resource.h @@ -168,7 +168,7 @@ protected: struct DRDirectoryItem { uint32 nameHash; - uint16 offset; + uint16 offset; uint16 type; }; @@ -195,7 +195,7 @@ protected: Common::Array<MessageList*> _messageLists; Common::Array<DRRect> _drRects; Common::Array<DRSubRectList*> _drSubRectLists; - DataResource::DRDirectoryItem *findDRDirectoryItem(uint32 nameHash, uint16 type); + DataResource::DRDirectoryItem *findDRDirectoryItem(uint32 nameHash, uint16 type); }; uint32 calcHash(const char *value); diff --git a/engines/neverhood/resourceman.cpp b/engines/neverhood/resourceman.cpp index d5e7786c17..37089a5bd6 100644 --- a/engines/neverhood/resourceman.cpp +++ b/engines/neverhood/resourceman.cpp @@ -49,7 +49,7 @@ void ResourceMan::addArchive(const Common::String &filename) { if (archiveEntry->timeStamp > entry->archiveEntry->timeStamp) { entry->archive = archive; entry->archiveEntry = archiveEntry; - } + } } else { ResourceFileEntry newEntry; newEntry.resourceHandle = -1; diff --git a/engines/neverhood/saveload.cpp b/engines/neverhood/saveload.cpp index 578d9858ff..01988769e6 100644 --- a/engines/neverhood/saveload.cpp +++ b/engines/neverhood/saveload.cpp @@ -61,12 +61,12 @@ NeverhoodEngine::kReadSaveHeaderError NeverhoodEngine::readSaveHeader(Common::Se return ((in->eos() || in->err()) ? kRSHEIoError : kRSHENoError); } -void NeverhoodEngine::savegame(const char *filename, const char *description) { +bool NeverhoodEngine::savegame(const char *filename, const char *description) { Common::OutSaveFile *out; if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); - return; + return false; } TimeDate curTime; @@ -78,7 +78,7 @@ void NeverhoodEngine::savegame(const char *filename, const char *description) { byte descriptionLen = strlen(description); out->writeByte(descriptionLen); out->write(description, descriptionLen); - + Graphics::saveThumbnail(*out); // Not used yet, reserved for future usage @@ -96,50 +96,53 @@ void NeverhoodEngine::savegame(const char *filename, const char *description) { _gameVars->setGlobalVar(V_CURRENT_SCENE_WHICH, _gameState.which); _gameVars->saveState(out); - + out->finalize(); delete out; + return true; } -void NeverhoodEngine::loadgame(const char *filename) { +bool NeverhoodEngine::loadgame(const char *filename) { Common::InSaveFile *in; if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { warning("Can't open file '%s', game not loaded", filename); - return; + return false; } SaveHeader header; kReadSaveHeaderError errorCode = readSaveHeader(in, false, header); - + if (errorCode != kRSHENoError) { warning("Error loading savegame '%s'", filename); delete in; - return; + return false; } - + g_engine->setTotalPlayTime(header.playTime * 1000); _gameVars->loadState(in); - + _gameState.sceneNum = _gameVars->getGlobalVar(V_CURRENT_SCENE); _gameState.which = _gameVars->getGlobalVar(V_CURRENT_SCENE_WHICH); _gameModule->requestRestoreGame(); delete in; - + return true; } Common::Error NeverhoodEngine::loadGameState(int slot) { const char *fileName = getSavegameFilename(slot); - loadgame(fileName); + if (!loadgame(fileName)) + return Common::kReadingFailed; return Common::kNoError; } Common::Error NeverhoodEngine::saveGameState(int slot, const Common::String &description) { const char *fileName = getSavegameFilename(slot); - savegame(fileName, description.c_str()); + if (!savegame(fileName, description.c_str())) + return Common::kWritingFailed; return Common::kNoError; } diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp index 07d41754c9..c8d7490753 100644 --- a/engines/neverhood/scene.cpp +++ b/engines/neverhood/scene.cpp @@ -20,6 +20,7 @@ * */ +#include "neverhood/console.h" #include "neverhood/scene.h" namespace Neverhood { @@ -27,7 +28,7 @@ namespace Neverhood { Scene::Scene(NeverhoodEngine *vm, Module *parentModule) : Entity(vm, 0), _parentModule(parentModule), _dataResource(vm), _hitRects(NULL), _mouseCursorWasVisible(true) { - + _isKlaymenBusy = false; _doConvertMessages = false; _messageList = NULL; @@ -49,15 +50,17 @@ Scene::Scene(NeverhoodEngine *vm, Module *parentModule) _smackerPlayer = NULL; _isMessageListBusy = false; _messageValue = -1; - + SetUpdateHandler(&Scene::update); SetMessageHandler(&Scene::handleMessage); - + _vm->_screen->clearRenderQueue(); } Scene::~Scene() { + _vm->_screen->setSmackerDecoder(NULL); + if (_palette) { removeEntity(_palette); delete _palette; @@ -68,7 +71,7 @@ Scene::~Scene() { delete *iter; // Don't delete surfaces since they always belong to an entity - + // Purge the resources after each scene _vm->_res->purgeResources(); @@ -81,7 +84,7 @@ void Scene::draw() { } else { for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++) (*iter)->draw(); - } + } } void Scene::addEntity(Entity *entity) { @@ -96,7 +99,7 @@ void Scene::addEntity(Entity *entity) { if (insertIndex >= 0) _entities.insert_at(insertIndex, entity); else - _entities.push_back(entity); + _entities.push_back(entity); } bool Scene::removeEntity(Entity *entity) { @@ -105,7 +108,7 @@ bool Scene::removeEntity(Entity *entity) { _entities.remove_at(index); return true; } - return false; + return false; } void Scene::addSurface(BaseSurface *surface) { @@ -121,7 +124,7 @@ void Scene::addSurface(BaseSurface *surface) { if (insertIndex >= 0) _surfaces.insert_at(insertIndex, surface); else - _surfaces.push_back(surface); + _surfaces.push_back(surface); } } @@ -132,7 +135,19 @@ bool Scene::removeSurface(BaseSurface *surface) { return true; } } - return false; + return false; +} + +void Scene::printSurfaces(Console *con) { + for (uint index = 0; index < _surfaces.size(); index++) { + NDrawRect drawRect = _surfaces[index]->getDrawRect(); + NRect clipRect = _surfaces[index]->getClipRect(); + int priority = _surfaces[index]->getPriority(); + con->DebugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n", + index, _surfaces[index]->getName().c_str(), priority, + drawRect.x, drawRect.y, drawRect.x2(), drawRect.y2(), + clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2); + } } Sprite *Scene::addSprite(Sprite *sprite) { @@ -197,7 +212,7 @@ Sprite *Scene::insertStaticSprite(uint32 fileHash, int surfacePriority) { } void Scene::insertScreenMouse(uint32 fileHash, const NRect *mouseRect) { - NRect rect(-1, -1, -1, -1); + NRect rect = NRect::make(-1, -1, -1, -1); if (mouseRect) rect = *mouseRect; insertMouse(new Mouse(_vm, fileHash, rect)); @@ -231,12 +246,12 @@ void Scene::update() { if (_mouseClicked) { if (_klaymen) { if (_canAcceptInput && - _klaymen->hasMessageHandler() && + _klaymen->hasMessageHandler() && sendMessage(_klaymen, 0x1008, 0) != 0 && queryPositionSprite(_mouseClickPos.x, _mouseClickPos.y)) { _mouseClicked = false; } else if (_canAcceptInput && - _klaymen->hasMessageHandler() && + _klaymen->hasMessageHandler() && sendMessage(_klaymen, 0x1008, 0) != 0) { _mouseClicked = !queryPositionRectList(_mouseClickPos.x, _mouseClickPos.y); } @@ -247,7 +262,7 @@ void Scene::update() { processMessageList(); - // Update all entities + // Update all entities for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++) (*iter)->handleUpdate(); @@ -268,7 +283,7 @@ uint32 Scene::handleMessage(int messageNum, const MessageParam ¶m, Entity *s _mouseClickPos = param.asPoint(); break; case 0x0006: - sendMessage(_parentModule, 0x1009, param); + sendMessage(_parentModule, 0x1009, param); break; case 0x1006: // Sent by Klaymen when its animation sequence has finished @@ -317,7 +332,7 @@ uint32 Scene::handleMessage(int messageNum, const MessageParam ¶m, Entity *s bool Scene::queryPositionSprite(int16 mouseX, int16 mouseY) { for (uint i = 0; i < _collisionSprites.size(); i++) { Sprite *sprite = _collisionSprites[i]; - if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) && + if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) && sendPointMessage(sprite, 0x1011, _mouseClickPos) != 0) { return true; } @@ -397,8 +412,8 @@ void Scene::processMessageList() { _messageList2 = NULL; _messageListStatus = 0; } - - if (_messageList && _klaymen) { + + if (_messageList && _klaymen) { #if 0 debug("MessageList: %p, %d", (void*)_messageList, _messageList->size()); @@ -408,11 +423,11 @@ void Scene::processMessageList() { } debug("--------------------------------"); #endif - + while (_messageList && _messageListIndex < _messageListCount && !_isKlaymenBusy) { uint32 messageNum = (*_messageList)[_messageListIndex].messageNum; uint32 messageParam = (*_messageList)[_messageListIndex].messageValue; - + ++_messageListIndex; if (_messageListIndex == _messageListCount) sendMessage(_klaymen, 0x1021, 0); @@ -445,7 +460,7 @@ void Scene::processMessageList() { if (_klaymen->hasMessageHandler() && sendMessage(_klaymen, messageNum, messageParam) != 0) { _isKlaymenBusy = false; } - } + } if (_messageListIndex == _messageListCount) { _canAcceptInput = true; _messageList = NULL; @@ -454,7 +469,7 @@ void Scene::processMessageList() { } _isMessageListBusy = false; - + } void Scene::cancelMessageList() { @@ -516,7 +531,7 @@ uint16 Scene::convertMessageNum(uint32 messageNum) { case 0x42002200: return 0x4004; case 0x428D4894: - return 0x101A; + return 0x101A; } return 0x1000; } @@ -531,7 +546,7 @@ HitRect *Scene::findHitRectAtPos(int16 x, int16 y) { for (HitRectList::iterator it = _hitRects->begin(); it != _hitRects->end(); it++) if ((*it).rect.contains(x, y)) return &(*it); - return &kDefaultHitRect; + return &kDefaultHitRect; } void Scene::addCollisionSprite(Sprite *sprite) { @@ -546,7 +561,7 @@ void Scene::addCollisionSprite(Sprite *sprite) { if (insertIndex >= 0) _collisionSprites.insert_at(insertIndex, sprite); else - _collisionSprites.push_back(sprite); + _collisionSprites.push_back(sprite); } void Scene::removeCollisionSprite(Sprite *sprite) { @@ -568,7 +583,7 @@ void Scene::checkCollision(Sprite *sprite, uint16 flags, int messageNum, uint32 if ((sprite->getFlags() & flags) && collSprite->checkCollision(sprite->getCollisionBounds())) { sprite->sendMessage(collSprite, messageNum, messageParam); } - } + } } void Scene::insertMouse(Mouse *mouseCursor) { diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h index 1abcbfb964..5e42e34418 100644 --- a/engines/neverhood/scene.h +++ b/engines/neverhood/scene.h @@ -37,6 +37,8 @@ namespace Neverhood { +class Console; + class Scene : public Entity { public: Scene(NeverhoodEngine *vm, Module *parentModule); @@ -46,6 +48,7 @@ public: bool removeEntity(Entity *entity); void addSurface(BaseSurface *surface); bool removeSurface(BaseSurface *surface); + void printSurfaces(Console *con); Sprite *addSprite(Sprite *sprite); void removeSprite(Sprite *sprite); void setSurfacePriority(BaseSurface *surface, int priority); @@ -73,89 +76,89 @@ public: void checkCollision(Sprite *sprite, uint16 flags, int messageNum, uint32 messageParam); // Some crazy templated functions to make the logic code smaller/simpler (imo!) // insertKlaymen - template<class T> + template<class T> void insertKlaymen() { _klaymen = (T*)addSprite(new T(_vm, this)); } - template<class T, class Arg1> + template<class T, class Arg1> void insertKlaymen(Arg1 arg1) { _klaymen = (T*)addSprite(new T(_vm, this, arg1)); } - template<class T, class Arg1, class Arg2> + template<class T, class Arg1, class Arg2> void insertKlaymen(Arg1 arg1, Arg2 arg2) { _klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2)); } - template<class T, class Arg1, class Arg2, class Arg3> + template<class T, class Arg1, class Arg2, class Arg3> void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3) { _klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3)); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4> void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { _klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3, arg4)); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { _klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3, arg4, arg5)); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) { _klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3, arg4, arg5, arg6)); } // insertSprite - template<class T> + template<class T> T* insertSprite() { return (T*)addSprite(new T(_vm)); } - template<class T, class Arg1> + template<class T, class Arg1> T* insertSprite(Arg1 arg1) { return (T*)addSprite(new T(_vm, arg1)); } - template<class T, class Arg1, class Arg2> + template<class T, class Arg1, class Arg2> T* insertSprite(Arg1 arg1, Arg2 arg2) { return (T*)addSprite(new T(_vm, arg1, arg2)); } - template<class T, class Arg1, class Arg2, class Arg3> + template<class T, class Arg1, class Arg2, class Arg3> T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3) { return (T*)addSprite(new T(_vm, arg1, arg2, arg3)); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4> T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4)); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4, arg5)); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) { return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4, arg5, arg6)); } // createSprite - template<class T> + template<class T> T* createSprite() { return new T(_vm); } - template<class T, class Arg1> + template<class T, class Arg1> T* createSprite(Arg1 arg1) { return new T(_vm, arg1); } - template<class T, class Arg1, class Arg2> + template<class T, class Arg1, class Arg2> T* createSprite(Arg1 arg1, Arg2 arg2) { return new T(_vm, arg1, arg2); } - template<class T, class Arg1, class Arg2, class Arg3> + template<class T, class Arg1, class Arg2, class Arg3> T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3) { return new T(_vm, arg1, arg2, arg3); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4> T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { return new T(_vm, arg1, arg2, arg3, arg4); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { return new T(_vm, arg1, arg2, arg3, arg4, arg5); } - template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> + template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6> T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) { return new T(_vm, arg1, arg2, arg3, arg4, arg5, arg6); } diff --git a/engines/neverhood/screen.cpp b/engines/neverhood/screen.cpp index 5a748cfab4..4c8dd9add0 100644 --- a/engines/neverhood/screen.cpp +++ b/engines/neverhood/screen.cpp @@ -28,16 +28,16 @@ namespace Neverhood { Screen::Screen(NeverhoodEngine *vm) : _vm(vm), _paletteData(NULL), _paletteChanged(false), _smackerDecoder(NULL), _yOffset(0), _fullRefresh(false) { - + _ticks = _vm->_system->getMillis(); - + _backScreen = new Graphics::Surface(); _backScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8()); - + _renderQueue = new RenderQueue(); _prevRenderQueue = new RenderQueue(); _microTiles = new MicroTileArray(640, 480); - + } Screen::~Screen() { @@ -54,7 +54,7 @@ void Screen::update() { if (_fullRefresh) { // NOTE When playing a fullscreen/doubled Smacker video usually a full screen refresh is needed - _vm->_system->copyRectToScreen((const byte*)_backScreen->pixels, _backScreen->pitch, 0, 0, 640, 480); + _vm->_system->copyRectToScreen((const byte*)_backScreen->getPixels(), _backScreen->pitch, 0, 0, 640, 480); _fullRefresh = false; return; } @@ -72,13 +72,13 @@ void Screen::update() { } } } - + for (RenderQueue::iterator jt = _prevRenderQueue->begin(); jt != _prevRenderQueue->end(); ++jt) { RenderItem &prevRenderItem = (*jt); if (prevRenderItem._refresh) _microTiles->addRect(Common::Rect(prevRenderItem._destX, prevRenderItem._destY, prevRenderItem._destX + prevRenderItem._width, prevRenderItem._destY + prevRenderItem._height)); } - + for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) { RenderItem &renderItem = (*it); if (renderItem._refresh) @@ -93,7 +93,7 @@ void Screen::update() { for (RectangleList::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri) blitRenderItem(renderItem, *ri); } - + SWAP(_renderQueue, _prevRenderQueue); _renderQueue->clear(); @@ -174,7 +174,7 @@ void Screen::updatePalette() { } void Screen::clear() { - memset(_backScreen->pixels, 0, _backScreen->pitch * _backScreen->h); + memset(_backScreen->getPixels(), 0, _backScreen->pitch * _backScreen->h); _fullRefresh = true; clearRenderQueue(); } @@ -202,12 +202,12 @@ void Screen::drawSurface2(const Graphics::Surface *surface, NDrawRect &drawRect, destX = drawRect.x; ddRect.x1 = 0; } - + if (drawRect.y + drawRect.height >= clipRect.y2) ddRect.y2 = clipRect.y2 - drawRect.y; else ddRect.y2 = drawRect.height; - + if (drawRect.y < clipRect.y1) { destY = clipRect.y1; ddRect.y1 = clipRect.y1 - drawRect.y; @@ -215,7 +215,7 @@ void Screen::drawSurface2(const Graphics::Surface *surface, NDrawRect &drawRect, destY = drawRect.y; ddRect.y1 = 0; } - + queueBlit(surface, destX, destY, ddRect, transparent, version, shadowSurface); } @@ -224,12 +224,12 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND int16 destX, destY; NRect ddRect; - + if (x + drawRect.width >= clipRect.x2) ddRect.x2 = clipRect.x2 - drawRect.x - x; else ddRect.x2 = drawRect.x + drawRect.width; - + if (x < clipRect.x1) { destX = clipRect.x1; ddRect.x1 = clipRect.x1 + drawRect.x - x; @@ -242,7 +242,7 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND ddRect.y2 = clipRect.y2 + drawRect.y - y; else ddRect.y2 = drawRect.y + drawRect.height; - + if (y < clipRect.y1) { destY = clipRect.y1; ddRect.y1 = clipRect.y1 + drawRect.y - y; @@ -250,14 +250,14 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND destY = y; ddRect.y1 = drawRect.y; } - + queueBlit(surface, destX, destY, ddRect, transparent, version); } void Screen::drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &drawRect) { - const byte *source = (const byte*)surface->getBasePtr(0, 0); + const byte *source = (const byte*)surface->getPixels(); byte *dest = (byte*)_backScreen->getBasePtr(drawRect.x, drawRect.y); for (int16 yc = 0; yc < surface->h; yc++) { @@ -270,13 +270,13 @@ void Screen::drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &dra dest += _backScreen->pitch; dest += _backScreen->pitch; } - + _fullRefresh = true; // See Screen::update } void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDrawRect &sysRect, NRect &clipRect, bool transparent, byte version) { - + int16 x, y; bool xflag, yflag; NDrawRect newDrawRect; @@ -292,26 +292,26 @@ void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDra y = y % sysRect.height; if (y < 0) y += sysRect.height; - + xflag = x <= 0; yflag = y <= 0; - + newDrawRect.x = x; newDrawRect.width = sysRect.width - x; if (drawRect.width < newDrawRect.width) { xflag = true; newDrawRect.width = drawRect.width; } - + newDrawRect.y = y; newDrawRect.height = sysRect.height - y; if (drawRect.height < newDrawRect.height) { yflag = true; newDrawRect.height = drawRect.height; } - + drawSurface3(surface, drawRect.x, drawRect.y, newDrawRect, clipRect, transparent, version); - + if (!xflag) { newDrawRect.x = 0; newDrawRect.y = y; @@ -321,7 +321,7 @@ void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDra newDrawRect.height = drawRect.height; drawSurface3(surface, sysRect.width + drawRect.x - x, drawRect.y, newDrawRect, clipRect, transparent, version); } - + if (!yflag) { newDrawRect.x = x; newDrawRect.y = 0; @@ -331,7 +331,7 @@ void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDra newDrawRect.width = drawRect.width; drawSurface3(surface, drawRect.x, sysRect.height + drawRect.y - y, newDrawRect, clipRect, transparent, version); } - + if (!xflag && !yflag) { newDrawRect.x = 0; newDrawRect.y = 0; @@ -350,13 +350,13 @@ void Screen::drawSurfaceClipRects(const Graphics::Surface *surface, NDrawRect &d void Screen::queueBlit(const Graphics::Surface *surface, int16 destX, int16 destY, NRect &ddRect, bool transparent, byte version, const Graphics::Surface *shadowSurface) { - + const int width = ddRect.x2 - ddRect.x1; const int height = ddRect.y2 - ddRect.y1; if (width <= 0 || height <= 0) return; - + RenderItem renderItem; renderItem._surface = surface; renderItem._shadowSurface = shadowSurface; @@ -369,7 +369,7 @@ void Screen::queueBlit(const Graphics::Surface *surface, int16 destX, int16 dest renderItem._transparent = transparent; renderItem._version = version; _renderQueue->push_back(renderItem); - + } void Screen::blitRenderItem(const RenderItem &renderItem, const Common::Rect &clipRect) { diff --git a/engines/neverhood/smackerplayer.cpp b/engines/neverhood/smackerplayer.cpp index b67c8db9fc..187939faee 100644 --- a/engines/neverhood/smackerplayer.cpp +++ b/engines/neverhood/smackerplayer.cpp @@ -31,7 +31,7 @@ namespace Neverhood { // SmackerSurface SmackerSurface::SmackerSurface(NeverhoodEngine *vm) - : BaseSurface(vm, 0, 0, 0), _smackerFrame(NULL) { + : BaseSurface(vm, 0, 0, 0, "smacker"), _smackerFrame(NULL) { } void SmackerSurface::draw() { @@ -51,6 +51,18 @@ void SmackerSurface::setSmackerFrame(const Graphics::Surface *smackerFrame) { _smackerFrame = smackerFrame; } +void SmackerSurface::unsetSmackerFrame() { + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = 0; + _drawRect.height = 0; + _sysRect.x = 0; + _sysRect.y = 0; + _sysRect.width = 0; + _sysRect.height = 0; + _smackerFrame = NULL; +} + // SmackerDoubleSurface SmackerDoubleSurface::SmackerDoubleSurface(NeverhoodEngine *vm) @@ -62,25 +74,27 @@ void SmackerDoubleSurface::draw() { _vm->_screen->drawDoubleSurface2(_smackerFrame, _drawRect); } +// NeverhoodSmackerDecoder + void NeverhoodSmackerDecoder::forceSeekToFrame(uint frame) { if (!isVideoLoaded()) return; - + if (frame >= getFrameCount()) error("Can't force Smacker seek to invalid frame %d", frame); - + if (_header.audioInfo[0].hasAudio) error("Can't force Smacker frame seek with audio"); if (!rewind()) error("Failed to rewind"); - + SmackerVideoTrack *videoTrack = (SmackerVideoTrack *)getTrack(0); uint32 offset = 0; for (uint32 i = 0; i < frame; i++) { videoTrack->increaseCurFrame(); offset += _frameSizes[i] & ~3; } - + _fileStream->seek(offset, SEEK_CUR); } @@ -92,40 +106,43 @@ SmackerPlayer::SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, _drawX(-1), _drawY(-1) { SetUpdateHandler(&SmackerPlayer::update); + + if (_doubleSurface) { + _smackerSurface = new SmackerDoubleSurface(_vm); + } else { + _smackerSurface = new SmackerSurface(_vm); + } + open(fileHash, flag); } SmackerPlayer::~SmackerPlayer() { close(); + delete _smackerSurface; + _smackerSurface = NULL; } void SmackerPlayer::open(uint32 fileHash, bool keepLastFrame) { debug(0, "SmackerPlayer::open(%08X)", fileHash); - + _fileHash = fileHash; _keepLastFrame = keepLastFrame; close(); - if (_doubleSurface) { - _smackerSurface = new SmackerDoubleSurface(_vm); - } else { - _smackerSurface = new SmackerSurface(_vm); - } - _smackerFirst = true; _stream = _vm->_res->createStream(fileHash); _smackerDecoder = new NeverhoodSmackerDecoder(); _smackerDecoder->loadStream(_stream); - + _palette = new Palette(_vm); _palette->usePalette(); if (!_paused) _smackerDecoder->start(); - + } void SmackerPlayer::close() { @@ -134,11 +151,10 @@ void SmackerPlayer::close() { delete _smackerDecoder; delete _palette; // NOTE The SmackerDecoder deletes the _stream - delete _smackerSurface; _smackerDecoder = NULL; _palette = NULL; _stream = NULL; - _smackerSurface = NULL; + _smackerSurface->unsetSmackerFrame(); } void SmackerPlayer::gotoFrame(int frameNumber) { @@ -196,10 +212,14 @@ void SmackerPlayer::update() { _videoDone = false; } } - + } void SmackerPlayer::updateFrame() { + + if (!_smackerDecoder || !_smackerSurface) + return; + const Graphics::Surface *smackerFrame = _smackerDecoder->decodeNextFrame(); if (_smackerFirst) { @@ -220,7 +240,7 @@ void SmackerPlayer::updateFrame() { if (_smackerDecoder->hasDirtyPalette()) updatePalette(); - + } void SmackerPlayer::updatePalette() { diff --git a/engines/neverhood/smackerplayer.h b/engines/neverhood/smackerplayer.h index 26ebff5d33..dd7199dd6d 100644 --- a/engines/neverhood/smackerplayer.h +++ b/engines/neverhood/smackerplayer.h @@ -37,6 +37,7 @@ public: SmackerSurface(NeverhoodEngine *vm); virtual void draw(); void setSmackerFrame(const Graphics::Surface *smackerFrame); + void unsetSmackerFrame(); protected: const Graphics::Surface *_smackerFrame; }; @@ -61,7 +62,7 @@ public: void close(); void gotoFrame(int frameNumber); uint32 getFrameCount(); - uint32 getFrameNumber(); + uint32 getFrameNumber(); uint getStatus(); void setDrawPos(int16 x, int16 y); void rewind(); diff --git a/engines/neverhood/smackerscene.cpp b/engines/neverhood/smackerscene.cpp index 115aafe5be..d9d032a3b5 100644 --- a/engines/neverhood/smackerscene.cpp +++ b/engines/neverhood/smackerscene.cpp @@ -31,16 +31,16 @@ SmackerScene::SmackerScene(NeverhoodEngine *vm, Module *parentModule, bool doubl debug(0, "SmackerScene::SmackerScene(%d, %d, %d)", doubleSurface, canSkip, canAbort); // NOTE: Merged from SmackerScene::init, maybe split again if needed (incl. parameter flags) - + if (getGlobalVar(V_SMACKER_CAN_ABORT)) { _canSkip = true; _canAbort = true; } - + if (!_doubleSurface) _vm->_screen->clear(); - _fileHash[0] = 0; + _fileHash[0] = 0; _fileHash[1] = 0; SetUpdateHandler(&SmackerScene::update); @@ -67,7 +67,7 @@ void SmackerScene::nextVideo() { debug(0, "SmackerScene::nextVideo()"); _fileHashListIndex++; - + if (_fileHashList && _fileHashList[_fileHashListIndex] != 0) { uint32 smackerFileHash = _fileHashList[_fileHashListIndex]; ResourceHandle resourceHandle; diff --git a/engines/neverhood/sound.cpp b/engines/neverhood/sound.cpp index c84b751e44..c3bc3501b5 100644 --- a/engines/neverhood/sound.cpp +++ b/engines/neverhood/sound.cpp @@ -35,7 +35,7 @@ SoundResource::~SoundResource() { unload(); } -bool SoundResource::isPlaying() { +bool SoundResource::isPlaying() { AudioResourceManSoundItem *soundItem = getSoundItem(); return soundItem ? soundItem->isPlaying() : false; } @@ -94,7 +94,7 @@ MusicResource::MusicResource(NeverhoodEngine *vm) bool MusicResource::isPlaying() { AudioResourceManMusicItem *musicItem = getMusicItem(); - return musicItem && musicItem->isPlaying(); + return musicItem && musicItem->isPlaying(); } void MusicResource::load(uint32 fileHash) { @@ -134,7 +134,7 @@ AudioResourceManMusicItem *MusicResource::getMusicItem() { MusicItem::MusicItem(NeverhoodEngine *vm, uint32 groupNameHash, uint32 musicFileHash) : _vm(vm), _musicResource(NULL) { - + _groupNameHash = groupNameHash; _fileHash = musicFileHash; _play = false; @@ -187,7 +187,7 @@ SoundItem::SoundItem(NeverhoodEngine *vm, uint32 groupNameHash, uint32 soundFile _playOnceAfterRandomCountdown(false), _minCountdown(0), _maxCountdown(0), _playOnceAfterCountdown(playOnceAfterCountdown), _initialCountdown(initialCountdown), _playLooping(false), _currCountdown(currCountdown) { - + _soundResource = new SoundResource(vm); _soundResource->load(soundFileHash); } @@ -200,7 +200,7 @@ SoundItem::~SoundItem() { void SoundItem::setSoundParams(bool playOnceAfterRandomCountdown, int16 minCountdown, int16 maxCountdown, int16 firstMinCountdown, int16 firstMaxCountdown) { - + _playOnceAfterCountdown = false; _playLooping = false; _playOnceAfterRandomCountdown = playOnceAfterRandomCountdown; @@ -254,10 +254,26 @@ SoundMan::SoundMan(NeverhoodEngine *vm) } SoundMan::~SoundMan() { - for (uint i = 0; i < _soundItems.size(); ++i) - delete _soundItems[i]; - for (uint i = 0; i < _musicItems.size(); ++i) - delete _musicItems[i]; + stopAllSounds(); +} + +void SoundMan::stopAllSounds() { + for (uint i = 0; i < _soundItems.size(); ++i) { + if (_soundItems[i]) { + _soundItems[i]->stopSound(); + delete _soundItems[i]; + _soundItems[i] = NULL; + } + } + for (uint i = 0; i < _musicItems.size(); ++i) { + if (_musicItems[i]) { + _musicItems[i]->stopMusic(0, 0); + delete _musicItems[i]; + _musicItems[i] = NULL; + } + } + + _soundIndex1 = _soundIndex2 = _soundIndex3 = -1; } void SoundMan::addMusic(uint32 groupNameHash, uint32 musicFileHash) { @@ -345,7 +361,7 @@ void SoundMan::setSoundVolume(uint32 soundFileHash, int volume) { } void SoundMan::update() { - + for (uint i = 0; i < _soundItems.size(); ++i) { SoundItem *soundItem = _soundItems[i]; if (soundItem) @@ -440,7 +456,7 @@ void SoundMan::playSoundThree(uint32 groupNameHash, uint32 soundFileHash) { SoundItem *soundItem = new SoundItem(_vm, groupNameHash, soundFileHash, false, 0, 0, false, _initialCountdown3, false, 0); _soundIndex3 = addSoundItem(soundItem); } - + } void SoundMan::setTwoSoundsPlayFlag(bool playOnceAfterCountdown) { @@ -514,16 +530,16 @@ NeverhoodAudioStream::~NeverhoodAudioStream() { int NeverhoodAudioStream::readBuffer(int16 *buffer, const int numSamples) { int samplesLeft = numSamples; - + while (samplesLeft > 0 && !_endOfData) { const int maxSamples = MIN<int>(kSampleBufferLength, samplesLeft); const int bytesToRead = maxSamples * (_isCompressed ? 1 : 2); int bytesRead = _stream->read(_buffer, bytesToRead); int samplesRead = bytesRead / (_isCompressed ? 1 : 2); - + samplesLeft -= samplesRead; - + const byte *src = _buffer; if (_isCompressed) { while (samplesRead--) { @@ -678,7 +694,7 @@ void AudioResourceManMusicItem::update() { _start = false; _isPlaying = true; } - + if (_vm->_mixer->isSoundHandleActive(_soundHandle)) { if (_isFadingIn) { _fadeVolume += _fadeVolumeStep; @@ -708,11 +724,25 @@ AudioResourceMan::AudioResourceMan(NeverhoodEngine *vm) : _vm(vm) { } +void AudioResourceMan::stopAllSounds() { + for (uint i = 0; i < _soundItems.size(); ++i) { + if (_soundItems[i]) { + _soundItems[i]->stopSound(); + delete _soundItems[i]; + _soundItems[i] = NULL; + } + } + for (uint i = 0; i < _musicItems.size(); ++i) { + if (_musicItems[i]) { + _musicItems[i]->stopMusic(0); + delete _musicItems[i]; + _musicItems[i] = NULL; + } + } +} + AudioResourceMan::~AudioResourceMan() { - for (uint i = 0; i < _soundItems.size(); ++i) - delete _soundItems[i]; - for (uint i = 0; i < _musicItems.size(); ++i) - delete _musicItems[i]; + stopAllSounds(); } int16 AudioResourceMan::addSound(uint32 fileHash) { @@ -757,11 +787,11 @@ int16 AudioResourceMan::loadMusic(uint32 fileHash) { return i; } } - + int16 musicIndex = _musicItems.size(); _musicItems.push_back(musicItem); return musicIndex; - + } void AudioResourceMan::updateMusic() { diff --git a/engines/neverhood/sound.h b/engines/neverhood/sound.h index d3318998db..0733346daa 100644 --- a/engines/neverhood/sound.h +++ b/engines/neverhood/sound.h @@ -70,7 +70,7 @@ public: void setVolume(int16 volume); protected: NeverhoodEngine *_vm; - int16 _musicIndex; + int16 _musicIndex; AudioResourceManMusicItem *getMusicItem(); }; @@ -83,7 +83,7 @@ public: void update(); uint32 getGroupNameHash() const { return _groupNameHash; } uint32 getFileHash() const { return _fileHash; } -protected: +protected: NeverhoodEngine *_vm; uint32 _groupNameHash; uint32 _fileHash; @@ -110,7 +110,7 @@ public: uint32 getGroupNameHash() const { return _groupNameHash; } uint32 getFileHash() const { return _fileHash; } int16 getCurrCountdown() const { return _currCountdown; } -protected: +protected: NeverhoodEngine *_vm; uint32 _groupNameHash; uint32 _fileHash; @@ -129,12 +129,14 @@ public: SoundMan(NeverhoodEngine *vm); ~SoundMan(); + void stopAllSounds(); + // Music void addMusic(uint32 groupNameHash, uint32 musicFileHash); void deleteMusic(uint32 musicFileHash); void startMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolumeStep); void stopMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolumeStep); - + // Sound void addSound(uint32 groupNameHash, uint32 soundFileHash); void addSoundList(uint32 groupNameHash, const uint32 *soundFileHashList); @@ -146,7 +148,7 @@ public: void playSoundLooping(uint32 soundFileHash); void stopSound(uint32 soundFileHash); void setSoundVolume(uint32 soundFileHash, int volume); - + // Misc void update(); void deleteGroup(uint32 groupNameHash); @@ -159,25 +161,25 @@ public: protected: NeverhoodEngine *_vm; - + // TODO Find out what these special sounds are used for (door sounds?) int _soundIndex1, _soundIndex2; int16 _initialCountdown; bool _playOnceAfterCountdown; - + int _soundIndex3; int16 _initialCountdown3; bool _playOnceAfterCountdown3; Common::Array<MusicItem*> _musicItems; Common::Array<SoundItem*> _soundItems; - + MusicItem *getMusicItemByHash(uint32 musicFileHash); SoundItem *getSoundItemByHash(uint32 soundFileHash); int16 addMusicItem(MusicItem *musicItem); int16 addSoundItem(SoundItem *soundItem); void deleteSoundByIndex(int index); - + }; class NeverhoodAudioStream : public Audio::AudioStream { @@ -207,7 +209,7 @@ private: // TODO Rename these class AudioResourceManSoundItem { -public: +public: AudioResourceManSoundItem(NeverhoodEngine *vm, uint32 fileHash); void loadSound(); void unloadSound(); @@ -216,7 +218,7 @@ public: void playSound(bool looping); void stopSound(); bool isPlaying(); -protected: +protected: NeverhoodEngine *_vm; uint32 _fileHash; ResourceHandle _resourceHandle; @@ -241,7 +243,7 @@ public: bool canRestart() const { return _canRestart; } bool isTerminated() const { return _terminate; } uint32 getFileHash() const { return _fileHash; } -protected: +protected: NeverhoodEngine *_vm; uint32 _fileHash; bool _isPlaying; @@ -261,16 +263,18 @@ class AudioResourceMan { public: AudioResourceMan(NeverhoodEngine *vm); ~AudioResourceMan(); - + + void stopAllSounds(); + int16 addSound(uint32 fileHash); void removeSound(int16 soundIndex); int16 loadMusic(uint32 fileHash); void updateMusic(); - + AudioResourceManSoundItem *getSoundItem(int16 index); AudioResourceManMusicItem *getMusicItem(int16 index); - + protected: NeverhoodEngine *_vm; diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp index 45d131fd3c..3c158ff7e3 100644 --- a/engines/neverhood/sprite.cpp +++ b/engines/neverhood/sprite.cpp @@ -28,11 +28,11 @@ namespace Neverhood { // Sprite Sprite::Sprite(NeverhoodEngine *vm, int objectPriority) - : Entity(vm, objectPriority), _x(0), _y(0), _spriteUpdateCb(NULL), _filterXCb(NULL), _filterYCb(NULL), + : Entity(vm, objectPriority), _x(0), _y(0), _spriteUpdateCb(NULL), _filterXCb(NULL), _filterYCb(NULL), _dataResource(vm), _doDeltaX(false), _doDeltaY(false), _needRefresh(false), _flags(0), _surface(NULL) { SetMessageHandler(&Sprite::handleMessage); - + } Sprite::~Sprite() { @@ -71,7 +71,7 @@ bool Sprite::isPointInside(int16 x, int16 y) { } bool Sprite::checkCollision(NRect &rect) { - return (_collisionBounds.x1 < rect.x2) && (rect.x1 < _collisionBounds.x2) && (_collisionBounds.y1 < rect.y2) && (rect.y1 < _collisionBounds.y2); + return (_collisionBounds.x1 < rect.x2) && (rect.x1 < _collisionBounds.x2) && (_collisionBounds.y1 < rect.y2) && (rect.y1 < _collisionBounds.y2); } uint32 Sprite::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { @@ -83,7 +83,7 @@ void Sprite::loadDataResource(uint32 fileHash) { } void Sprite::createSurface(int surfacePriority, int16 width, int16 height) { - _surface = new BaseSurface(_vm, surfacePriority, width, height); + _surface = new BaseSurface(_vm, surfacePriority, width, height, "sprite"); } int16 Sprite::defFilterY(int16 y) { @@ -153,13 +153,13 @@ void StaticSprite::updatePosition() { if (!_surface) return; - + if (_doDeltaX) { _surface->getDrawRect().x = filterX(_x - _drawOffset.x - _drawOffset.width + 1); } else { _surface->getDrawRect().x = filterX(_x + _drawOffset.x); } - + if (_doDeltaY) { _surface->getDrawRect().y = filterY(_y - _drawOffset.y - _drawOffset.height + 1); } else { @@ -261,7 +261,7 @@ void AnimatedSprite::updateAnim() { } if (_newAnimFileHash == 0 && _currFrameIndex != _currStickFrameIndex) { if (_currFrameTicks != 0 && (--_currFrameTicks == 0) && _animResource.getFrameCount() != 0) { - + if (_nextAnimFileHash != 0) { if (_animResource.load(_nextAnimFileHash)) { _currAnimFileHash = _nextAnimFileHash; @@ -270,7 +270,7 @@ void AnimatedSprite::updateAnim() { _currAnimFileHash = 0; } if (_replOldColor != _replNewColor) { - _animResource.setRepl(_replOldColor, _replNewColor); + _animResource.setRepl(_replOldColor, _replNewColor); } _nextAnimFileHash = 0; if (_animStatus != 0) { @@ -278,17 +278,17 @@ void AnimatedSprite::updateAnim() { _lastFrameIndex = _plLastFrameHash != 0 ? MAX<int16>(0, _animResource.getFrameIndex(_plLastFrameHash)) : _animResource.getFrameCount() - 1; } else { _currFrameIndex = _plFirstFrameIndex != -1 ? _plFirstFrameIndex : _animResource.getFrameCount() - 1; - _lastFrameIndex = _plLastFrameIndex != -1 ? _plLastFrameIndex : _animResource.getFrameCount() - 1; + _lastFrameIndex = _plLastFrameIndex != -1 ? _plLastFrameIndex : _animResource.getFrameCount() - 1; } } else { updateFrameIndex(); } if (_newAnimFileHash == 0) updateFrameInfo(); - } + } } } - + if (_newAnimFileHash != 0) { if (_animStatus == 2) { _currStickFrameIndex = _currFrameIndex; @@ -301,7 +301,7 @@ void AnimatedSprite::updateAnim() { _currAnimFileHash = 0; } if (_replOldColor != _replNewColor) { - _animResource.setRepl(_replOldColor, _replNewColor); + _animResource.setRepl(_replOldColor, _replNewColor); } _newAnimFileHash = 0; _currFrameIndex = _plFirstFrameHash != 0 ? MAX<int16>(0, _animResource.getFrameIndex(_plFirstFrameHash)) : 0; @@ -314,7 +314,7 @@ void AnimatedSprite::updateAnim() { _currAnimFileHash = 0; } if (_replOldColor != _replNewColor) { - _animResource.setRepl(_replOldColor, _replNewColor); + _animResource.setRepl(_replOldColor, _replNewColor); } _newAnimFileHash = 0; _currFrameIndex = _plFirstFrameIndex != -1 ? _plFirstFrameIndex : _animResource.getFrameCount() - 1; @@ -398,7 +398,7 @@ void AnimatedSprite::updateFrameInfo() { void AnimatedSprite::createSurface1(uint32 fileHash, int surfacePriority) { NDimensions dimensions = _animResource.loadSpriteDimensions(fileHash); - _surface = new BaseSurface(_vm, surfacePriority, dimensions.width, dimensions.height); + _surface = new BaseSurface(_vm, surfacePriority, dimensions.width, dimensions.height, "animated sprite"); } void AnimatedSprite::createShadowSurface1(BaseSurface *shadowSurface, uint32 fileHash, int surfacePriority) { diff --git a/engines/neverhood/staticdata.cpp b/engines/neverhood/staticdata.cpp index 3f89c2236f..006992641a 100644 --- a/engines/neverhood/staticdata.cpp +++ b/engines/neverhood/staticdata.cpp @@ -33,13 +33,13 @@ StaticData::~StaticData() { void StaticData::load(const char *filename) { Common::File fd; - + if (!fd.open(filename)) error("StaticData::load() Could not open %s", filename); - - fd.readUint32LE(); // magic + + fd.readUint32LE(); // magic fd.readUint32LE(); // version - + // Load message lists uint32 messageListsCount = fd.readUint32LE(); debug(3, "messageListsCount: %d", messageListsCount); @@ -84,7 +84,7 @@ void StaticData::load(const char *filename) { } _rectLists[id] = rectList; } - + // Load hit rects uint32 hitRectListsCount = fd.readUint32LE(); debug(3, "hitRectListsCount: %d", hitRectListsCount); diff --git a/engines/neverhood/todo.txt b/engines/neverhood/todo.txt deleted file mode 100644 index 9d781e06ec..0000000000 --- a/engines/neverhood/todo.txt +++ /dev/null @@ -1,45 +0,0 @@ -NOTE: -------- -Some of the TODOs should be done AFTER the whole game logic is implemented -else the game disasm and reimplemtation code become even more different -(unless I decide it's ok to do it :) - -TODOs which can be done any time: ------------------------------------ -- Cleanup -- Clean up staticdata structs to look more like the ones in create_neverhood - (e.g. by using template classes etc.) - - Or use a common base class and manage all stuff in one single table and cast stuff accordingly - -TODOs which should be done only after the game logic is finished: -------------------------------------------------------------------- -- Maybe rework organization of files (e.g. put ALL Sprites into one separate file, same with Modules and Scenes) - - This would solve the problem of how to organize stuff which is used several times, and less headers would have to be included - - The move special scenes (SmackerScene) into the scenes file - -DONE: -------- -- Implement game menus -- Rework sound system (I don't like that SoundResources need to be explicitly initialized in Scene constructors) - - Should be just a handle object which initializes itself - - Play routine should fill the handle so it can be stopped/queried later - - Basically like ScummVM own sound handles -- RE and implement yet unknown music/sound stuff -- Implement clever sprite redrawing code (dirty rectangles, microtiles etc.), only redraw what's neccessary -- Rework the resource system - - The current system can be simplified a lot - - Also resource purging needs to be implemented -- Maybe merge CollisionMan with Scene (since it's so far never used independently) -- Give placeholder stuff (e.g. sub?????, _flag??? etc.) better fitting names -- Use CursorMan for the mouse cursor (instead of using it like a normal sprite) - - This whould make it neccessary to call _system->updateScreen more often else - the mouse movement would be choppy - -TODOs which are experimental: -------------------------------- -NOTE: Since they affect the whole game, they really should be only implemented once the full game logic is implemented. -These are nothing more than wild ideas for now, any might never be implemented. -- Use states instead of separate callback methods -- Try to move more stuff to neverhood.dat -- Try to use more template functions instead of manually creating functions - (Can be coupled with the above to move parameters to the dat and only use IDs) diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 3135c3e8c5..f648f4b9a1 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -225,7 +225,7 @@ void DosDisk_br::loadBitmap(Common::SeekableReadStream &stream, Graphics::Surfac } surf.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - stream.read(surf.pixels, width * height); + stream.read(surf.getPixels(), width * height); } Frames* DosDisk_br::loadPointer(const char *name) { @@ -449,7 +449,7 @@ void AmigaDisk_br::init() { void AmigaDisk_br::adjustForPalette(Graphics::Surface &surf, int transparentColor) { uint size = surf.w * surf.h; - byte *data = (byte *)surf.pixels; + byte *data = (byte *)surf.getPixels(); for (uint i = 0; i < size; i++, data++) { if (transparentColor == -1 || transparentColor != *data) *data += 16; @@ -552,7 +552,7 @@ MaskBuffer *AmigaDisk_br::loadMask(const char *name, uint32 w, uint32 h) { MaskBuffer *buffer = new MaskBuffer; // surface width was shrunk to 1/4th of the bitmap width due to the pixel packing buffer->create(decoder.getSurface()->w * 4, decoder.getSurface()->h); - memcpy(buffer->data, decoder.getSurface()->pixels, buffer->size); + memcpy(buffer->data, decoder.getSurface()->getPixels(), buffer->size); buffer->bigEndian = true; finalpass(buffer->data, buffer->size); return buffer; @@ -612,7 +612,7 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) { stream->read(shadow, shadowSize); for (int32 i = 0; i < surf->h; ++i) { byte *src = shadow + shadowWidth * i; - byte *dst = (byte *)surf->pixels + surf->pitch * i; + byte *dst = (byte *)surf->getPixels() + surf->pitch * i; for (int32 j = 0; j < surf->w; ++j, ++dst) { byte bit = src[j/8] & (1 << (7 - (j & 7))); diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index 4c4893ec61..ae28e864a9 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -482,7 +482,7 @@ void DosDisk_ns::loadBackground(BackgroundInfo& info, const char *filename) { // read bitmap, mask and path data and extract them into the 3 buffers info.bg.create(info.width, info.height, Graphics::PixelFormat::createFormatCLUT8()); createMaskAndPathBuffers(info); - unpackBackground(stream, (byte *)info.bg.pixels, info._mask->data, info._path->data); + unpackBackground(stream, (byte *)info.bg.getPixels(), info._mask->data, info._path->data); delete stream; } @@ -976,7 +976,7 @@ void AmigaDisk_ns::loadMask_internal(BackgroundInfo& info, const char *name) { info._mask = new MaskBuffer; // surface width was shrunk to 1/4th of the bitmap width due to the pixel packing info._mask->create(decoder.getSurface()->w * 4, decoder.getSurface()->h); - memcpy(info._mask->data, decoder.getSurface()->pixels, info._mask->size); + memcpy(info._mask->data, decoder.getSurface()->getPixels(), info._mask->size); info._mask->bigEndian = true; } @@ -998,7 +998,7 @@ void AmigaDisk_ns::loadPath_internal(BackgroundInfo& info, const char *name) { info._path = new PathBuffer; // surface width was shrunk to 1/8th of the bitmap width due to the pixel packing info._path->create(decoder.getSurface()->w * 8, decoder.getSurface()->h); - memcpy(info._path->data, decoder.getSurface()->pixels, info._path->size); + memcpy(info._path->data, decoder.getSurface()->getPixels(), info._path->size); info._path->bigEndian = true; } diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp index 3ea4332e50..816f220b1f 100644 --- a/engines/parallaction/exec_ns.cpp +++ b/engines/parallaction/exec_ns.cpp @@ -126,9 +126,7 @@ DECLARE_INSTRUCTION_OPCODE(put) { inst->_a->getFrameRect(r); Graphics::Surface v18; - v18.w = r.width(); - v18.h = r.height(); - v18.pixels = inst->_a->getFrameData(); + v18.init(r.width(), r.height(), r.width(), inst->_a->getFrameData(), Graphics::PixelFormat::createFormatCLUT8()); int16 x = inst->_opA.getValue(); int16 y = inst->_opB.getValue(); diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index b8a8ceb61f..3f36d56420 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -332,7 +332,7 @@ void Gfx::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int void Gfx::clearScreen() { if (_doubleBuffering) { - if (_backBuffer.pixels) { + if (_backBuffer.getPixels()) { Common::Rect r(_backBuffer.w, _backBuffer.h); _backBuffer.fillRect(r, 0); } @@ -419,13 +419,13 @@ void Gfx::updateScreen() { // is needed _overlayMode = false; - bool skipBackground = (_backgroundInfo->bg.pixels == 0); // don't render frame if background is missing + bool skipBackground = (_backgroundInfo->bg.getPixels() == 0); // don't render frame if background is missing if (!skipBackground) { // background may not cover the whole screen, so adjust bulk update size uint w = _backgroundInfo->width; uint h = _backgroundInfo->height; - byte *backgroundData = (byte *)_backgroundInfo->bg.getBasePtr(0, 0); + byte *backgroundData = (byte *)_backgroundInfo->bg.getPixels(); uint16 backgroundPitch = _backgroundInfo->bg.pitch; copyRectToScreen(backgroundData, backgroundPitch, _backgroundInfo->_x, _backgroundInfo->_y, w, h); } @@ -450,7 +450,7 @@ void Gfx::applyHalfbriteEffect_NS(Graphics::Surface &surf) { return; } - byte *buf = (byte *)surf.pixels; + byte *buf = (byte *)surf.getPixels(); for (int i = 0; i < surf.w*surf.h; i++) { *buf++ |= 0x20; } @@ -493,7 +493,7 @@ void Gfx::patchBackground(Graphics::Surface &surf, int16 x, int16 y, bool mask) r.moveTo(x, y); uint16 z = (mask) ? _backgroundInfo->getMaskLayer(y) : LAYER_FOREGROUND; - blt(r, (byte *)surf.pixels, &_backgroundInfo->bg, z, 100, 0); + blt(r, (byte *)surf.getPixels(), &_backgroundInfo->bg, z, 100, 0); } void Gfx::fillBackground(const Common::Rect& r, byte color) { @@ -536,12 +536,12 @@ GfxObj *Gfx::renderFloatingLabel(Font *font, char *text) { setupLabelSurface(*cnv, w, h); font->setColor((_gameType == GType_BRA) ? 0 : 7); - font->drawString((byte *)cnv->pixels + 1, cnv->w, text); - font->drawString((byte *)cnv->pixels + 1 + cnv->w * 2, cnv->w, text); - font->drawString((byte *)cnv->pixels + cnv->w, cnv->w, text); - font->drawString((byte *)cnv->pixels + 2 + cnv->w, cnv->w, text); + font->drawString((byte *)cnv->getBasePtr(1, 0), cnv->w, text); + font->drawString((byte *)cnv->getBasePtr(1, 2), cnv->w, text); + font->drawString((byte *)cnv->getBasePtr(0, 1), cnv->w, text); + font->drawString((byte *)cnv->getBasePtr(2, 1), cnv->w, text); font->setColor((_gameType == GType_BRA) ? 11 : 1); - font->drawString((byte *)cnv->pixels + 1 + cnv->w, cnv->w, text); + font->drawString((byte *)cnv->getBasePtr(1, 1), cnv->w, text); } else { w = font->getStringWidth(text); h = font->height(); @@ -704,7 +704,7 @@ void Gfx::unregisterLabel(GfxObj *label) { void Gfx::copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surface &dst) { byte *s = (byte *)src.getBasePtr(r.left, r.top); - byte *d = (byte *)dst.getBasePtr(0, 0); + byte *d = (byte *)dst.getPixels(); for (uint16 i = 0; i < r.height(); i++) { memcpy(d, s, r.width()); diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index bf7cdc439d..a445ce0138 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -499,7 +499,7 @@ void Input::initCursors() { // TODO: scale mouse cursor (see staticres.cpp) Graphics::Surface *surf2 = new Graphics::Surface; surf2->create(32, 16, Graphics::PixelFormat::createFormatCLUT8()); - memcpy(surf2->pixels, _resMouseArrow_BR_Amiga, 32*16); + memcpy(surf2->getPixels(), _resMouseArrow_BR_Amiga, 32*16); _mouseArrow = new SurfaceToFrames(surf2); } break; diff --git a/engines/parallaction/inventory.h b/engines/parallaction/inventory.h index a3b7bf953f..d5cf8badf0 100644 --- a/engines/parallaction/inventory.h +++ b/engines/parallaction/inventory.h @@ -108,7 +108,7 @@ public: void highlightItem(ItemPosition pos, byte color); void drawItem(ItemName name, byte *buffer, uint pitch); - byte* getData() const { return (byte *)_surf.pixels; } + byte *getData() { return (byte *)_surf.getPixels(); } void getRect(Common::Rect &r) const; int16 getNumLines() const; diff --git a/engines/pegasus/cursor.cpp b/engines/pegasus/cursor.cpp index 897d31d7bd..ad0d2c2d7d 100644 --- a/engines/pegasus/cursor.cpp +++ b/engines/pegasus/cursor.cpp @@ -85,9 +85,9 @@ void Cursor::setCurrentFrameIndex(int32 index) { if (_info[index].surface->format.bytesPerPixel == 1) { CursorMan.replaceCursorPalette(_info[index].palette, 0, _info[index].colorCount); - CursorMan.replaceCursor(_info[index].surface->pixels, _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, 0); + CursorMan.replaceCursor(_info[index].surface->getPixels(), _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, 0); } else { - CursorMan.replaceCursor(_info[index].surface->pixels, _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, _info[index].surface->format.RGBToColor(0xFF, 0xFF, 0xFF), false, &_info[index].surface->format); + CursorMan.replaceCursor(_info[index].surface->getPixels(), _info[index].surface->w, _info[index].surface->h, _info[index].hotspot.x, _info[index].hotspot.y, _info[index].surface->format.RGBToColor(0xFF, 0xFF, 0xFF), false, &_info[index].surface->format); } ((PegasusEngine *)g_engine)->_gfx->markCursorAsDirty(); @@ -203,7 +203,7 @@ void Cursor::loadCursorImage(CursorInfo &cursorInfo) { // PixMap data if (pixMap.pixelSize == 8) { cursorInfo.surface->create(pixMap.rowBytes, pixMap.bounds.height(), Graphics::PixelFormat::createFormatCLUT8()); - cicnStream->read(cursorInfo.surface->pixels, pixMap.rowBytes * pixMap.bounds.height()); + cicnStream->read(cursorInfo.surface->getPixels(), pixMap.rowBytes * pixMap.bounds.height()); // While this looks sensible, it actually doesn't work for some cursors // (ie. the 'can grab' hand) diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp index 8dbd678809..5475108abd 100644 --- a/engines/pegasus/graphics.cpp +++ b/engines/pegasus/graphics.cpp @@ -318,7 +318,7 @@ void GraphicsManager::shakeTheWorld(TimeValue duration, TimeScale scale) { } if (lastOffset.x != 0 || lastOffset.y != 0) { - g_system->copyRectToScreen((byte *)oldScreen.pixels, oldScreen.pitch, 0, 0, 640, 480); + g_system->copyRectToScreen((byte *)oldScreen.getPixels(), oldScreen.pitch, 0, 0, 640, 480); g_system->updateScreen(); } diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp index 9a378a6728..0b3e1ee040 100644 --- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp +++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp @@ -200,7 +200,7 @@ void Caldoria::start() { const Graphics::Surface *frame = pullbackMovie->decodeNextFrame(); assert(frame); assert(frame->format == g_system->getScreenFormat()); - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h); + g_system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, 64, 112, frame->w, frame->h); _vm->_gfx->doFadeInSync(kTwoSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond); bool saveAllowed = _vm->swapSaveAllowed(false); @@ -216,7 +216,7 @@ void Caldoria::start() { frame = pullbackMovie->decodeNextFrame(); if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h); + g_system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, 64, 112, frame->w, frame->h); g_system->updateScreen(); } } diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp index 38366c4ba2..3116bd7978 100644 --- a/engines/pegasus/neighborhood/neighborhood.cpp +++ b/engines/pegasus/neighborhood/neighborhood.cpp @@ -1364,7 +1364,7 @@ void Neighborhood::setUpAIRules() { if (g_AIArea) { g_AIArea->forceAIUnlocked(); - if (!_vm->isDemo() && (getObjectID() == kPrehistoricID || getObjectID() == kNoradAlphaID || + if (!_vm->isOldDemo() && (getObjectID() == kPrehistoricID || getObjectID() == kNoradAlphaID || getObjectID() == kNoradDeltaID || getObjectID() == kMarsID || getObjectID() == kWSCID)) { AIEnergyMonitorCondition *condition50 = new AIEnergyMonitorCondition(kWorriedEnergy); diff --git a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp index 169f75f7d2..3491f161c7 100644 --- a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp +++ b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp @@ -201,7 +201,7 @@ void NoradAlphaFillingStation::showIntakeInProgress(uint16 numSeconds) { if (item->getObjectID() == kGasCanister) { GameState.setNoradGassed(true); - ((NoradAlpha *)getOwner())->loadAmbientLoops(); + ((NoradAlpha *)getOwner())->checkAirMask(); getOwner()->restoreStriding(kNorad03, kEast, kAltNoradAlphaNormal); } } else { diff --git a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp index e4a5e26473..6a24113465 100644 --- a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp +++ b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp @@ -576,7 +576,7 @@ void NoradAlpha::takeItemFromRoom(Item *item) { if (_fillingStationItem == item) { _fillingStationItem = 0; GameState.setNoradGassed(false); - loadAmbientLoops(); + checkAirMask(); ((NoradAlphaFillingStation *)_currentInteraction)->newFillingItem(0); forceStridingStop(kNorad03, kEast, kAltNoradAlphaNormal); } diff --git a/engines/pegasus/neighborhood/norad/norad.cpp b/engines/pegasus/neighborhood/norad/norad.cpp index 578f062dea..53b3ff9add 100644 --- a/engines/pegasus/neighborhood/norad/norad.cpp +++ b/engines/pegasus/neighborhood/norad/norad.cpp @@ -241,7 +241,9 @@ void Norad::setUpAirMask() { } void Norad::checkAirMask() { - if (g_airMask && g_airMask->isAirFilterOn()) { + // WORKAROUND: The original game forgot to handle the case where the canister would + // be removed, leading to the timer remaining active. + if (!GameState.getNoradGassed() || (g_airMask && g_airMask->isAirFilterOn())) { _airMaskTimer.stop(); } else if (GameState.getNoradGassed() && !_airMaskTimer.isRunning()) { _airMaskTimer.setTime(0); diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp index 463e81e52e..3bd29ce8dd 100644 --- a/engines/pegasus/pegasus.cpp +++ b/engines/pegasus/pegasus.cpp @@ -313,7 +313,7 @@ void PegasusEngine::runIntro() { const Graphics::Surface *frame = video->decodeNextFrame(); if (frame) { - _system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 0, 0, frame->w, frame->h); + _system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h); _system->updateScreen(); } } @@ -1367,7 +1367,7 @@ bool PegasusEngine::playMovieScaled(Video::VideoDecoder *video, uint16 x, uint16 if (frame->w <= 320 && frame->h <= 240) { drawScaledFrame(frame, x, y); } else { - _system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + _system->copyRectToScreen((const byte *)frame->getPixels(), frame->pitch, x, y, frame->w, frame->h); _system->updateScreen(); } } @@ -2270,11 +2270,11 @@ void PegasusEngine::drawScaledFrame(const Graphics::Surface *frame, uint16 x, ui scaledFrame.create(frame->w * 2, frame->h * 2, frame->format); if (frame->format.bytesPerPixel == 2) - scaleFrame<uint16>((uint16 *)frame->pixels, (uint16 *)scaledFrame.pixels, frame->w, frame->h, frame->pitch); + scaleFrame<uint16>((const uint16 *)frame->getPixels(), (uint16 *)scaledFrame.getPixels(), frame->w, frame->h, frame->pitch); else - scaleFrame<uint32>((uint32 *)frame->pixels, (uint32 *)scaledFrame.pixels, frame->w, frame->h, frame->pitch); + scaleFrame<uint32>((const uint32 *)frame->getPixels(), (uint32 *)scaledFrame.getPixels(), frame->w, frame->h, frame->pitch); - _system->copyRectToScreen((byte *)scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); + _system->copyRectToScreen((byte *)scaledFrame.getPixels(), scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); _system->updateScreen(); scaledFrame.free(); } diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp index 50cc9bc6d8..8463d866e8 100644 --- a/engines/pegasus/timers.cpp +++ b/engines/pegasus/timers.cpp @@ -115,7 +115,7 @@ void TimeBase::stop() { void TimeBase::pause() { if (isRunning() && !_paused) { _pausedRate = getRate(); - stop(); + _rate = 0; _paused = true; _pauseStart = g_system->getMillis(); } @@ -123,7 +123,7 @@ void TimeBase::pause() { void TimeBase::resume() { if (_paused) { - setRate(_pausedRate); + _rate = _pausedRate; _paused = false; if (isRunning()) diff --git a/engines/pegasus/transition.cpp b/engines/pegasus/transition.cpp index 1ae212df85..b736b115ee 100644 --- a/engines/pegasus/transition.cpp +++ b/engines/pegasus/transition.cpp @@ -70,7 +70,7 @@ void ScreenFader::setFaderValue(const int32 value) { if (value != getFaderValue()) { Fader::setFaderValue(value); - if (_screen->pixels) { + if (_screen->getPixels()) { // The original game does a gamma fade here using the Mac API. In order to do // that, it would require an immense amount of CPU processing. This does a // linear fade instead, which looks fairly well, IMO. diff --git a/engines/plugins_table.h b/engines/plugins_table.h index 6d623e5003..d1519c367f 100644 --- a/engines/plugins_table.h +++ b/engines/plugins_table.h @@ -47,6 +47,9 @@ LINK_PLUGIN(HUGO) #if PLUGIN_ENABLED_STATIC(KYRA) LINK_PLUGIN(KYRA) #endif +#if PLUGIN_ENABLED_STATIC(MORTEVIELLE) +LINK_PLUGIN(MORTEVIELLE) +#endif #if PLUGIN_ENABLED_STATIC(LASTEXPRESS) LINK_PLUGIN(LASTEXPRESS) #endif diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp index fd602ff4fb..df8283b4c2 100644 --- a/engines/saga/animation.cpp +++ b/engines/saga/animation.cpp @@ -185,7 +185,7 @@ int Anim::playCutaway(int cut, bool fade) { event.time = (40 / 3) * 1000 / _cutawayList[cut].frameRate; if (fade) - eventColumns = _vm->_events->chain(eventColumns, event); + _vm->_events->chain(eventColumns, event); else _vm->_events->queue(event); } @@ -501,7 +501,7 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { } anim = getAnimation(animId); - displayBuffer = (byte *)_vm->_render->getBackGroundSurface()->pixels; + displayBuffer = (byte *)_vm->_render->getBackGroundSurface()->getPixels(); if (playing) { anim->state = ANIM_PLAYING; diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h index c677b76324..c68160e907 100644 --- a/engines/saga/gfx.h +++ b/engines/saga/gfx.h @@ -201,7 +201,7 @@ public: // Whenever it gets called, the corresponding caller must take care // to add the corresponding dirty rectangle itself byte *getBackBufferPixels() { - return (byte *)_backBuffer.pixels; + return (byte *)_backBuffer.getPixels(); } uint16 getBackBufferWidth() { diff --git a/engines/saga/introproc_ihnm.cpp b/engines/saga/introproc_ihnm.cpp index 6015e6757a..7922d56425 100644 --- a/engines/saga/introproc_ihnm.cpp +++ b/engines/saga/introproc_ihnm.cpp @@ -212,7 +212,7 @@ bool Scene::playTitle(int title, int time, int mode) { break; case 2: // display background - _vm->_system->copyRectToScreen(backBufferSurface->pixels, backBufferSurface->w, 0, 0, + _vm->_system->copyRectToScreen(backBufferSurface->getPixels(), backBufferSurface->w, 0, 0, backBufferSurface->w, backBufferSurface->h); phase++; startTime = curTime; @@ -247,7 +247,7 @@ bool Scene::playTitle(int title, int time, int mode) { frameTime = curTime; - _vm->_system->copyRectToScreen(backBufferSurface->pixels, backBufferSurface->w, 0, 0, + _vm->_system->copyRectToScreen(backBufferSurface->getPixels(), backBufferSurface->w, 0, 0, backBufferSurface->w, backBufferSurface->h); } @@ -273,8 +273,8 @@ bool Scene::playTitle(int title, int time, int mode) { _vm->_anim->endVideo(); - memset((byte *)backBufferSurface->pixels, 0, backBufferSurface->w * backBufferSurface->h); - _vm->_system->copyRectToScreen(backBufferSurface->pixels, backBufferSurface->w, 0, 0, + memset((byte *)backBufferSurface->getPixels(), 0, backBufferSurface->w * backBufferSurface->h); + _vm->_system->copyRectToScreen(backBufferSurface->getPixels(), backBufferSurface->w, 0, 0, backBufferSurface->w, backBufferSurface->h); return interrupted; diff --git a/engines/saga/introproc_saga2.cpp b/engines/saga/introproc_saga2.cpp index 260eca98e6..e61dfbf161 100644 --- a/engines/saga/introproc_saga2.cpp +++ b/engines/saga/introproc_saga2.cpp @@ -108,7 +108,7 @@ void Scene::playMovie(const char *filename) { if (smkDecoder->needsUpdate()) { const Graphics::Surface *frame = smkDecoder->decodeNextFrame(); if (frame) { - _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); + _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h); if (smkDecoder->hasDirtyPalette()) _vm->_system->getPaletteManager()->setPalette(smkDecoder->getPalette(), 0, 256); diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 812d967b9f..3ac89bc2c2 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -364,7 +364,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) { // Load MIDI/XMI resource data if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { - // Load the external music file for Mac IHNM + // Load the external music file for Mac IHNM _player->playQuickTime(Common::String::format("Music/Music%02x", resourceId), flags & MUSIC_LOOP); } else { if (_currentMusicBuffer == &_musicBuffer[1]) { diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 75876b1c90..eff31cf98b 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -468,7 +468,7 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy pal = decoder.getPalette(); rect.setWidth(decoder.getSurface()->w); rect.setHeight(decoder.getSurface()->h); - _vm->_gfx->drawRegion(rect, (const byte *)decoder.getSurface()->pixels); + _vm->_gfx->drawRegion(rect, (const byte *)decoder.getSurface()->getPixels()); for (int j = 0; j < PAL_ENTRIES; j++) { cPal[j].red = *pal++; cPal[j].green = *pal++; @@ -1120,9 +1120,9 @@ void Scene::draw() { _vm->_render->getBackGroundSurface()->getRect(rect); rect.bottom = (_sceneClip.bottom < rect.bottom) ? getHeight() : rect.bottom; if (_vm->_render->isFullRefresh()) - _vm->_gfx->drawRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->pixels); + _vm->_gfx->drawRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->getPixels()); else - _vm->_gfx->drawBgRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->pixels); + _vm->_gfx->drawBgRegion(rect, (const byte *)_vm->_render->getBackGroundSurface()->getPixels()); } } diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp index 69c27b6a6b..619ffc243e 100644 --- a/engines/saga/shorten.cpp +++ b/engines/saga/shorten.cpp @@ -196,11 +196,13 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by break; case kTypeS16LH: flags |= Audio::FLAG_LITTLE_ENDIAN; + // fallthrough case kTypeS16HL: flags |= Audio::FLAG_16BITS; break; case kTypeU16LH: flags |= Audio::FLAG_LITTLE_ENDIAN; + // fallthrough case kTypeU16HL: flags |= Audio::FLAG_16BITS; flags |= Audio::FLAG_UNSIGNED; diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index 49d24753a1..ca843af465 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -249,11 +249,11 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff if (!memcmp(header, "Creative", 8)) { resourceType = kSoundVOC; - } else if (!memcmp(header, "RIFF", 4) != 0) { + } else if (!memcmp(header, "RIFF", 4)) { resourceType = kSoundWAV; - } else if (!memcmp(header, "FORM", 4) != 0) { + } else if (!memcmp(header, "FORM", 4)) { resourceType = kSoundAIFF; - } else if (!memcmp(header, "ajkg", 4) != 0) { + } else if (!memcmp(header, "ajkg", 4)) { resourceType = kSoundShorten; } diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 66164a1937..7c4638a992 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1054,6 +1054,23 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI, GAMEOPTION_JONES_CDAUDIO) }, + // Jones in the Fast Lane - English DOS US CD (alternate version) + // Supplied by collector9 in bug #3614668 + {"jones", "CD", { + {"resource.map", 0, "4344ff3f796707843b992adec2c87663", 4878}, + {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652062}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformDOS, ADGF_CD, GUIO1(GAMEOPTION_JONES_CDAUDIO) }, + + // Jones in the Fast Lane - English DOS US CD (alternate version) + // Same entry as the DOS version above. This one is used for the alternate + // General MIDI music tracks in the Windows version + {"jones", "CD", { + {"resource.map", 0, "4344ff3f796707843b992adec2c87663", 4878}, + {"resource.001", 0, "3876da2ce16fb7dea2f5d943d946fa84", 1652062}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformWindows, ADGF_CD, GUIO4(GUIO_MIDIGM, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_FB01_MIDI, GAMEOPTION_JONES_CDAUDIO) }, + // King's Quest 1 SCI Remake - English Amiga (from www.back2roots.org) // Executable scanning reports "1.003.007" // SCI interpreter version 0.001.010 diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 64793efa6c..3c223bebbe 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1966,7 +1966,7 @@ static bool isVertexCovered(const Patch &p, unsigned int wi) { // ---w1--1----p----w2--2---- // ^ \ (inside) if (wi > p.indexw1 && wi <= p.indexw2) - return true; + return true; // v / (outside) // ---w2--2----p----w1--1---- diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 15a9f54996..d72b1d1772 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -551,7 +551,7 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { // NOTE: To fix a corrupted jar object, type "send Glass_Jar message 52" // in the debugger. if (g_sci->getGameId() == GID_PEPPER && func == 0 && argc >= 6 && module == 894 && - tuple.noun == 26 && tuple.cond == 0 && tuple.seq == 1 && + tuple.noun == 26 && tuple.cond == 0 && tuple.seq == 1 && !s->_msgState->getMessage(module, tuple, NULL_REG)) tuple.verb = 0; diff --git a/engines/sci/engine/kvideo.cpp b/engines/sci/engine/kvideo.cpp index 9b0cb38f51..3964ccc1f8 100644 --- a/engines/sci/engine/kvideo.cpp +++ b/engines/sci/engine/kvideo.cpp @@ -103,10 +103,10 @@ void playVideo(Video::VideoDecoder *videoDecoder, VideoState videoState) { if (frame) { if (scaleBuffer) { // TODO: Probably should do aspect ratio correction in e.g. GK1 Windows - g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel); + g_sci->_gfxScreen->scale2x((const byte *)frame->getPixels(), scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel); g_system->copyRectToScreen(scaleBuffer, pitch, x, y, width, height); } else { - g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, width, height); + g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, width, height); } if (videoDecoder->hasDirtyPalette()) { diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index bf1ce6da64..76510fa53b 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -532,7 +532,7 @@ void GfxFrameout::showVideo() { if (videoDecoder->needsUpdate()) { const Graphics::Surface *frame = videoDecoder->decodeNextFrame(); if (frame) { - g_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); + g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h); if (videoDecoder->hasDirtyPalette()) g_system->getPaletteManager()->setPalette(videoDecoder->getPalette(), 0, 256); @@ -745,7 +745,7 @@ void GfxFrameout::kernelFrameout() { // Process global scaling, if needed. // TODO: Seems like SCI32 always processes global scaling for scaled objects // TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY) - if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) && + if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) && !(itemEntry->scaleSignal & kScaleSignalDisableGlobalScaling32) && (itemEntry->scaleX == itemEntry->scaleY) && itemEntry->scaleX != 128) @@ -779,6 +779,14 @@ void GfxFrameout::kernelFrameout() { _coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right); g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); } + + // TODO: For some reason, the top left nsRect coordinates get + // swapped in the GK1 inventory screen, investigate why. + // HACK: Fix the coordinates by explicitly setting them here. + Common::Rect objNSRect = g_sci->_gfxCompare->getNSRect(itemEntry->object); + if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0) { + g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect); + } } // Don't attempt to draw sprites that are outside the visible diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp index dfb50b0edb..4df80b289f 100644 --- a/engines/sci/graphics/maciconbar.cpp +++ b/engines/sci/graphics/maciconbar.cpp @@ -129,7 +129,7 @@ void GfxMacIconBar::drawIcon(uint16 iconIndex, bool selected) { void GfxMacIconBar::drawEnabledImage(Graphics::Surface *surface, const Common::Rect &rect) { if (surface) - g_system->copyRectToScreen(surface->pixels, surface->pitch, rect.left, rect.top, rect.width(), rect.height()); + g_system->copyRectToScreen(surface->getPixels(), surface->pitch, rect.left, rect.top, rect.width(), rect.height()); } void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common::Rect &rect) { @@ -153,7 +153,7 @@ void GfxMacIconBar::drawDisabledImage(Graphics::Surface *surface, const Common:: *((byte *)newSurf.getBasePtr(j, i)) = 0; } - g_system->copyRectToScreen(newSurf.pixels, newSurf.pitch, rect.left, rect.top, rect.width(), rect.height()); + g_system->copyRectToScreen(newSurf.getPixels(), newSurf.pitch, rect.left, rect.top, rect.width(), rect.height()); newSurf.free(); } @@ -224,7 +224,7 @@ Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected) } void GfxMacIconBar::remapColors(Graphics::Surface *surf, const byte *palette) { - byte *pixels = (byte *)surf->pixels; + byte *pixels = (byte *)surf->getPixels(); // Remap to the screen palette for (uint16 i = 0; i < surf->w * surf->h; i++) { diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 527e2ae973..6d9dc03195 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -116,7 +116,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te setPort(_wmgrPort); // SCI0 games till kq4 (.502 - not including) did not adjust against _wmgrPort in kNewWindow // We leave _wmgrPort top at 0, so the adjustment wont get done - if (!g_sci->_features->usesOldGfxFunctions()) { + if (!_usesOldGfxFunctions) { setOrigin(0, offTop); _wmgrPort->rect.bottom = _screen->getHeight() - offTop; } else { @@ -131,7 +131,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te _picWind = addWindow(Common::Rect(0, offTop, _screen->getWidth(), _screen->getHeight()), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true); // For SCI0 games till kq4 (.502 - not including) we set _picWind top to offTop instead // Because of the menu/status bar - if (g_sci->_features->usesOldGfxFunctions()) + if (_usesOldGfxFunctions) _picWind->top = offTop; kernelInitPriorityBands(); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 74503c0c77..7b92bc89eb 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -170,14 +170,14 @@ void GfxScreen::copyToScreen() { void GfxScreen::copyFromScreen(byte *buffer) { // TODO this ignores the pitch Graphics::Surface *screen = g_system->lockScreen(); - memcpy(buffer, screen->pixels, _displayPixels); + memcpy(buffer, screen->getPixels(), _displayPixels); g_system->unlockScreen(); } void GfxScreen::kernelSyncWithFramebuffer() { // TODO this ignores the pitch Graphics::Surface *screen = g_system->lockScreen(); - memcpy(_displayScreen, screen->pixels, _displayPixels); + memcpy(_displayScreen, screen->getPixels(), _displayPixels); g_system->unlockScreen(); } diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 9546b1503f..9653d9ccff 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -57,6 +57,7 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : _signalToSet = 0; _dataincAdd = false; _dataincToAdd = 0; + _jumpToHoldTick = false; _resetOnPause = false; _pSnd = 0; } @@ -452,6 +453,10 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { debugC(4, kDebugLevelSound, "signal %04x", _signalToSet); } + if (_jumpToHoldTick) { + _jumpToHoldTick = false; + jumpToTick(_loopTick, false, false); + } info.start = _position._playPos; info.delta = 0; @@ -486,6 +491,10 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { // though, so ignoring these signals in SCI0 games will result // in glitches (e.g. the intro of LB1 Amiga gets stuck - bug // #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp. + // FIXME: SSCI doesn't start playing at the very beginning + // of the stream, but at a fixed location a few commands later. + // That is probably why this signal isn't triggered + // immediately there. if (_soundVersion <= SCI_VERSION_0_LATE || _position._playTick || info.delta) { _signalSet = true; @@ -531,10 +540,15 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { // Check if the hold ID marker is the same as the hold ID // marker set for that song by cmdSetSoundHold. // If it is, loop back, but don't stop notes when jumping. + // We need to wait for the delta of the current event before + // jumping, thus the jump will be performed on the next + // parseNextEvent() call, like with the signal set events. + // In LSL6, room 360, song 381, this ends up jumping forward + // one tick (the hold marker occurs at playtick 27, with + // _loopTick being 15 and the event itself having a delta of + // 13, total = 28) - bug #3614566. if (info.basic.param2 == _pSnd->hold) { - uint32 extraDelta = info.delta; - jumpToTick(_loopTick, false, false); - _nextEvent.delta += extraDelta; + _jumpToHoldTick = true; } break; case kUpdateCue: @@ -637,7 +651,14 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { // (e.g. song 110, during the intro). The original interpreter // treats this case as an infinite loop (bug #3311911). if (_pSnd->loop || _pSnd->hold > 0) { - // We need to play it again... + // TODO: this jump is also vulnerable to the same lockup as + // the MIDI hold one above. However, we can't perform the + // jump on the next tick like with the MIDI hold jump above, + // as there aren't any subsequent MIDI events after this one. + // This assert is here to detect cases where the song ends + // up jumping forward, like with bug #3614566 (see above). + assert(_loopTick + info.delta < _position._playTick); + uint32 extraDelta = info.delta; jumpToTick(_loopTick); _nextEvent.delta += extraDelta; diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index d3fd337644..7bd68994c8 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -110,6 +110,7 @@ protected: int16 _signalToSet; bool _dataincAdd; int16 _dataincToAdd; + bool _jumpToHoldTick; bool _resetOnPause; bool _channelUsed[16]; diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index daba976f50..b0102a002b 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -530,17 +530,21 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { } reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { + // The 4 parameter variant of this call is used in at least LSL1VGA, room + // 110 (Lefty's bar), to distort the music when Larry is drunk and stands + // up - bug #3614447. reg_t obj = argv[0]; byte channel = argv[1].toUint16() & 0xf; - byte midiCmd = argv[2].toUint16() & 0xff; + byte midiCmd = (argc == 5) ? argv[2].toUint16() & 0xff : 0xB0; // 0xB0: controller + uint16 controller = (argc == 5) ? argv[3].toUint16() : argv[2].toUint16(); + uint16 param = (argc == 5) ? argv[4].toUint16() : argv[3].toUint16(); - // TODO: first there is a 4-parameter variant of this call which needs to get reversed - // second the current code isn't 100% accurate, sierra sci does checks on the 4th parameter - if (argc == 4) - return acc; - - uint16 controller = argv[3].toUint16(); - uint16 param = argv[4].toUint16(); + if (argc == 4 && controller == 0xFF) { + midiCmd = 0xE0; // 0xE0: pitch wheel + uint16 pitch = CLIP<uint16>(argv[3].toSint16() + 0x2000, 0x0000, 0x3FFF); + controller = pitch & 0x7F; + param = pitch >> 7; + } debugC(kDebugLevelSound, "kDoSound(sendMidi): %04x:%04x, %d, %d, %d, %d", PRINT_REG(obj), channel, midiCmd, controller, param); if (channel) diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index 0337a8d306..a567ece2ea 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -210,7 +210,7 @@ void RobotDecoder::readNextPacket() { // Copy over the decompressed frame byte *inFrame = decompressedFrame; - byte *outFrame = (byte *)surface->pixels; + byte *outFrame = (byte *)surface->getPixels(); // Black out the surface memset(outFrame, 0, surface->w * surface->h); diff --git a/engines/sci/video/seq_decoder.cpp b/engines/sci/video/seq_decoder.cpp index a7b6346eca..54603ec1f1 100644 --- a/engines/sci/video/seq_decoder.cpp +++ b/engines/sci/video/seq_decoder.cpp @@ -119,7 +119,7 @@ const Graphics::Surface *SEQDecoder::SEQVideoTrack::decodeNextFrame() { _fileStream->seek(offset); if (frameType == kSeqFrameFull) { - byte *dst = (byte *)_surface->pixels + frameTop * SEQ_SCREEN_WIDTH + frameLeft; + byte *dst = (byte *)_surface->getBasePtr(frameLeft, frameTop); byte *linebuf = new byte[frameWidth]; @@ -133,7 +133,7 @@ const Graphics::Surface *SEQDecoder::SEQVideoTrack::decodeNextFrame() { } else { byte *buf = new byte[frameSize]; _fileStream->read(buf, frameSize); - decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, (byte *)_surface->pixels + SEQ_SCREEN_WIDTH * frameTop, frameLeft, frameWidth, frameHeight, colorKey); + decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, (byte *)_surface->getBasePtr(0, frameTop), frameLeft, frameWidth, frameHeight, colorKey); delete[] buf; } diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 5c148a7b57..4e14473921 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -1485,7 +1485,7 @@ void ScummEngine::playActorSounds() { int sound; for (i = 1; i < _numActors; i++) { - if (_actors[i]->_cost.soundCounter && _actors[i]->isInCurrentRoom() && _actors[i]->_sound) { + if (_actors[i]->_cost.soundCounter && _actors[i]->isInCurrentRoom()) { _currentScript = 0xFF; if (_game.version == 0) { sound = v0ActorSounds[i - 1] & 0x3F; diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp index b6acf01050..481c4af432 100644 --- a/engines/scumm/akos.cpp +++ b/engines/scumm/akos.cpp @@ -994,7 +994,7 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) { if (_draw_bottom < rect.bottom) _draw_bottom = rect.bottom; - v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x * _vm->_bytesPerPixel; + v1.destptr = (byte *)_out.getBasePtr(v1.x, v1.y); codec1_genericDecode(v1); @@ -1288,7 +1288,7 @@ byte AkosRenderer::codec16(int xmoveCur, int ymoveCur) { int32 numskip_before = skip_x + (skip_y * _width); int32 numskip_after = _width - cur_x; - byte *dst = (byte *)_out.pixels + height_unk * _out.pitch + width_unk * _vm->_bytesPerPixel; + byte *dst = (byte *)_out.getBasePtr(width_unk, height_unk); akos16Decompress(dst, _out.pitch, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, transparency, clip.left, clip.top, _zbuf); return 0; @@ -1358,7 +1358,7 @@ byte AkosRenderer::codec32(int xmoveCur, int ymoveCur) { palPtr = _vm->_hePalettes + _vm->_hePaletteSlot + 768; } - byte *dstPtr = (byte *)_out.pixels + dst.top * _out.pitch + dst.left * _vm->_bytesPerPixel; + byte *dstPtr = (byte *)_out.getBasePtr(dst.left, dst.top); if (_shadow_mode == 3) { Wiz::decompressWizImage<kWizXMap>(dstPtr, _out.pitch, kDstScreen, _srcptr, src, 0, palPtr, xmap, _vm->_bytesPerPixel); } else { diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp index 46c68c81b0..e1a8688bb9 100644 --- a/engines/scumm/base-costume.cpp +++ b/engines/scumm/base-costume.cpp @@ -32,13 +32,15 @@ byte BaseCostumeRenderer::drawCostume(const VirtScreen &vs, int numStrips, const _out = vs; if (drawToBackBuf) - _out.pixels = vs.getBackPixels(0, 0); + _out.setPixels(vs.getBackPixels(0, 0)); else - _out.pixels = vs.getPixels(0, 0); + _out.setPixels(vs.getPixels(0, 0)); _actorX += _vm->_virtscr[kMainVirtScreen].xstart & 7; _out.w = _out.pitch / _vm->_bytesPerPixel; - _out.pixels = (byte *)_out.pixels - (_vm->_virtscr[kMainVirtScreen].xstart & 7); + // We do not use getBasePtr here because the offset to pixels never used + // _vm->_bytesPerPixel, but it seems unclear why. + _out.setPixels((byte *)_out.getPixels() - (_vm->_virtscr[kMainVirtScreen].xstart & 7)); _numStrips = numStrips; diff --git a/engines/scumm/bomp.cpp b/engines/scumm/bomp.cpp index 845cf70722..5b87f3042c 100644 --- a/engines/scumm/bomp.cpp +++ b/engines/scumm/bomp.cpp @@ -231,7 +231,10 @@ void drawBomp(const BompDrawData &bd) { } src = bd.src; - dst = (byte *)bd.dst.pixels + bd.y * bd.dst.pitch + (bd.x + clip.left); + // FIXME: This gets passed a const destination Surface. Intuitively this + // should never get written to. But sadly it does... For now we simply + // cast the const qualifier away. + dst = (byte *)const_cast<void *>(bd.dst.getBasePtr((bd.x + clip.left), bd.y)); const byte maskbit = revBitMask((bd.x + clip.left) & 7); diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 9ae75b6683..dd79aff2da 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -799,7 +799,7 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, if (ignoreCharsetMask || !vs->hasTwoBuffers) { dstPtr = vs->getPixels(0, 0); } else { - dstPtr = (byte *)_vm->_textSurface.pixels; + dstPtr = (byte *)_vm->_textSurface.getPixels(); } if (_blitAlso && vs->hasTwoBuffers) { @@ -829,7 +829,7 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr, dstPtr = vs->getPixels(_left, drawTop); } else { dstSurface = _vm->_textSurface; - dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier; + dstPtr = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier); } if (_blitAlso && vs->hasTwoBuffers) { @@ -907,7 +907,7 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) { void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) { if (!prepareDraw(chr)) return; - byte *dst = (byte *)s.pixels + y * s.pitch + x; + byte *dst = (byte *)s.getBasePtr(x, y); drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height); } @@ -1242,7 +1242,7 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) { if (ignoreCharsetMask) { VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen]; s = *vs; - s.pixels = vs->getPixels(0, 0); + s.setPixels(vs->getPixels(0, 0)); } else { s = _vm->_textSurface; drawTop -= _vm->_screenTop; @@ -1401,7 +1401,7 @@ void CharsetRendererTownsClassic::drawBitsN(const Graphics::Surface&, byte *dst, } bool scale2x = (_vm->_textSurfaceMultiplier == 2); - dst = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier; + dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier); int y, x; int color; diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp index 4ebdd00fdc..85c60f9a40 100644 --- a/engines/scumm/costume.cpp +++ b/engines/scumm/costume.cpp @@ -293,7 +293,7 @@ byte ClassicCostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) { return 2; } - v1.destptr = (byte *)_out.pixels + v1.y * _out.pitch + v1.x * _vm->_bytesPerPixel; + v1.destptr = (byte *)_out.getBasePtr(v1.x, v1.y); v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf); @@ -826,7 +826,7 @@ byte NESCostumeRenderer::drawLimb(const Actor *a, int limb) { int my = _actorY + y + ty; int mx = _actorX + x + tx; if (!(_zbuf && (maskBuf[my * _numStrips + mx / 8] & revBitMask(mx & 7)))) - *((byte *)_out.pixels + my * _out.pitch + mx) = palette[c]; + *((byte *)_out.getBasePtr(mx, my)) = palette[c]; } } } @@ -1238,7 +1238,7 @@ byte V0CostumeRenderer::drawLimb(const Actor *a, int limb) { int destY = ypos + y; if (destY >= 0 && destY < _out.h && destX >= 0 && destX < _out.w) { - byte *dst = (byte *)_out.pixels + destY * _out.pitch + destX; + byte *dst = (byte *)_out.getBasePtr(destX, destY); byte *mask = _vm->getMaskBuffer(0, destY, _zbuf); if (a0->_limb_flipped[limb]) { LINE(0, 0); LINE(2, 2); LINE(4, 4); LINE(6, 6); diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp index 269ae9e10a..721644b554 100644 --- a/engines/scumm/cursor.cpp +++ b/engines/scumm/cursor.cpp @@ -139,7 +139,7 @@ void ScummEngine_v6::grabCursor(int x, int y, int w, int h) { return; } - setCursorFromBuffer((byte *)vs->pixels + (y - vs->topline) * vs->pitch + x, w, h, vs->pitch); + setCursorFromBuffer((byte *)vs->getBasePtr(x, y - vs->topline), w, h, vs->pitch); } void ScummEngine_v6::setDefaultCursor() { @@ -417,13 +417,11 @@ void ScummEngine_v5::redefineBuiltinCursorFromChar(int index, int chr) { Graphics::Surface s; byte buf[16*17]; memset(buf, 123, 16*17); - s.pixels = buf; - s.w = _charset->getCharWidth(chr); - s.h = _charset->getFontHeight(); - s.pitch = s.w; + s.init(_charset->getCharWidth(chr), _charset->getFontHeight(), + _charset->getCharWidth(chr), buf, + Graphics::PixelFormat::createFormatCLUT8()); // s.h = 17 for FM-TOWNS Loom Japanese. Fixes bug #1166917 assert(s.w <= 16 && s.h <= 17); - s.format = Graphics::PixelFormat::createFormatCLUT8(); _charset->drawChar(chr, s, 0, 0); diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index 9b6dd1e687..872293f821 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -641,7 +641,7 @@ static void hlineColor(ScummEngine *scumm, int x1, int x2, int y, byte color) { x2 = right - 1; - ptr = (byte *)vs->pixels + x1 + y * vs->pitch; + ptr = (byte *)vs->getBasePtr(x1, y); while (x1++ <= x2) { *ptr++ = color; diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index cb807997e9..6717ea9b06 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -299,7 +299,11 @@ static const GameSettings gameVariantsTable[] = { // Changed o_getResourceSize to cover all resource types {"farm", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, - {"puttzoo", "", 0, GID_HEGAME, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"puttzoo", "", 0, GID_PUTTZOO, 6, 73, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"puttzoo", "HE 72", 0, GID_PUTTZOO, 6, 72, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"puttzoo", "HE 98.5", 0, GID_PUTTZOO, 6, 98, MDT_NONE, GF_USE_KEY | GF_HE_985, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"puttzoo", "HE 99", 0, GID_PUTTZOO, 6, 99, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"puttzoo", "HE 100", 0, GID_PUTTZOO, 6, 100, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, // Added VAR_PLATFORM variable {"jungle", "", 0, GID_HEGAME, 6, 74, MDT_NONE, GF_USE_KEY, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, @@ -385,7 +389,8 @@ static const GameSettings gameVariantsTable[] = { {"Soccer2004", 0, 0, GID_SOCCER2004, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, // U32 code required, for testing only - {"moonbase", 0, 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"moonbase", "1.0", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, + {"moonbase", "1.1", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, {"moonbase", "Demo", 0, GID_MOONBASE, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR | GF_DEMO, UNK, GUIO3(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI, GUIO_NOASPECT)}, // HE100 games, which use older o72_debugInput code @@ -758,6 +763,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "pajama2", "PYJAMADB", kGenHEPC, Common::DE_DEU, UNK, 0 }, { "pajama2", "PyjamaDBMN", kGenHEPC, Common::DE_DEU, UNK, 0 }, { "pajama2", "PyjamaDBMN", kGenHEMac, Common::DE_DEU, Common::kPlatformMacintosh, 0 }, + { "pajama2", "PyjamaHM", kGenHEPC, Common::FR_FRA, UNK, 0 }, { "pajama2", "PyjamaHM", kGenHEMac, Common::FR_FRA, Common::kPlatformMacintosh, 0 }, { "pajama2", "PYJAMA2", kGenHEPC, Common::DE_DEU, UNK, 0 }, { "pajama2", "Pyjama Pit 2", kGenHEMac, Common::DE_DEU, Common::kPlatformMacintosh, 0 }, @@ -858,6 +864,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "puttzoo", "Zoo Demo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "puttzoo", "Putt-Putt Saves the Zoo", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, { "puttzoo", "game", kGenHEPC, Common::EN_ANY, Common::kPlatformIOS, 0 }, + { "puttzoo", "pp3_unlocked", kGenHEPC, Common::EN_ANY, Common::kPlatformWindows, 0 }, { "SamsFunShop", "SamsFunShop", kGenHEPC, UNK_LANG, UNK, 0 }, { "SamsFunShop", "Sam's FunShop", kGenHEMac, UNK_LANG, Common::kPlatformMacintosh, 0 }, diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 50ff0b3988..4d65ccc88a 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -421,8 +421,8 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int } _res->createResource(rtBuffer, slot + 1, size); - vs->pixels = getResourceAddress(rtBuffer, slot + 1); - memset(vs->pixels, 0, size); // reset background + vs->setPixels(getResourceAddress(rtBuffer, slot + 1)); + memset(vs->getBasePtr(0, 0), 0, size); // reset background if (twobufs) { vs->backBuf = _res->createResource(rtBuffer, slot + 5, size); @@ -612,7 +612,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i // Some paranoia checks assert(top >= 0 && bottom <= vs->h); assert(x >= 0 && width <= vs->pitch); - assert(_textSurface.pixels); + assert(_textSurface.getPixels()); // Perform some clipping if (width > vs->w - x) @@ -1135,7 +1135,7 @@ void ScummEngine::clearTextSurface() { _townsScreen->fillLayerRect(1, 0, 0, _textSurface.w, _textSurface.h, 0); #endif - fill((byte *)_textSurface.pixels, _textSurface.pitch, + fill((byte *)_textSurface.getPixels(), _textSurface.pitch, #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE _game.platform == Common::kPlatformFMTowns ? 0 : #endif @@ -1590,7 +1590,7 @@ void GdiV2::prepareDrawBitmap(const byte *ptr, VirtScreen *vs, if (vs->hasTwoBuffers) dst = vs->backBuf + y * vs->pitch + x * 8; else - dst = (byte *)vs->pixels + y * vs->pitch + x * 8; + dst = (byte *)vs->getBasePtr(x * 8, y); mask_ptr = getMaskBuffer(x, y, 1); @@ -1827,7 +1827,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const if (vs->hasTwoBuffers) dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel); else - dstPtr = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel); + dstPtr = (byte *)vs->getBasePtr(x * 8, y); transpStrip = drawStrip(dstPtr, vs, x, y, width, height, stripnr, smap_ptr); @@ -1836,7 +1836,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const transpStrip = true; if (vs->hasTwoBuffers) { - byte *frontBuf = (byte *)vs->pixels + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel); + byte *frontBuf = (byte *)vs->getBasePtr(x * 8, y); if (lightsOn) copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->format.bytesPerPixel); else @@ -1888,7 +1888,7 @@ bool Gdi::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, if (stripnr * 4 + 4 < smapLen) offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 4); } else { - smapLen = READ_BE_UINT32(smap_ptr); + smapLen = READ_BE_UINT32(smap_ptr + 4); if (stripnr * 4 + 8 < smapLen) offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 8); } @@ -2262,7 +2262,7 @@ void Gdi::resetBackground(int top, int bottom, int strip) { vs->bdirty[strip] = bottom; bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel; - backbuff_ptr = (byte *)vs->pixels + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel; + backbuff_ptr = (byte *)vs->getBasePtr((strip + vs->xstart/8) * 8, top); numLinesToProcess = bottom - top; if (numLinesToProcess) { diff --git a/engines/scumm/gfx_towns.cpp b/engines/scumm/gfx_towns.cpp index f86a4e56d5..0aed181afd 100644 --- a/engines/scumm/gfx_towns.cpp +++ b/engines/scumm/gfx_towns.cpp @@ -34,7 +34,7 @@ void ScummEngine::towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, in if (width <= 0 || height <= 0) return; - assert(_textSurface.pixels); + assert(_textSurface.getPixels()); int m = _textSurfaceMultiplier; diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp index be17a3b305..d01b456c8b 100644 --- a/engines/scumm/he/animation_he.cpp +++ b/engines/scumm/he/animation_he.cpp @@ -90,7 +90,7 @@ void MoviePlayer::copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint if (!surface) return; - byte *src = (byte *)surface->pixels; + const byte *src = (const byte *)surface->getPixels(); if (_video->hasDirtyPalette()) _vm->setPaletteFromPtr(_video->getPalette(), 256); @@ -119,7 +119,7 @@ void MoviePlayer::copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint dst += y * pitch + x * 2; do { for (uint i = 0; i < w; i++) { - uint16 color = *((uint16 *)src + i); + uint16 color = *((const uint16 *)src + i); switch (dstType) { case kDstScreen: WRITE_UINT16(dst + i * 2, color); diff --git a/engines/scumm/he/logic/moonbase.cpp b/engines/scumm/he/logic/moonbase.cpp index fac2ea27ff..5b4618a4ad 100644 --- a/engines/scumm/he/logic/moonbase.cpp +++ b/engines/scumm/he/logic/moonbase.cpp @@ -39,6 +39,8 @@ public: int LogicHEmoonbase::versionID() { if (_vm->_game.features & GF_DEMO) return -100; + else if (strcmp(_vm->_game.variant, "1.1") == 0) + return 110; else return 100; } diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp index b024154c7f..987f74957c 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -2148,7 +2148,7 @@ void ScummEngine_v100he::o100_systemOps() { break; case 132: // Confirm shutdown - quitGame(); + confirmExitDialog(); break; case 133: quitGame(); diff --git a/engines/scumm/he/script_v70he.cpp b/engines/scumm/he/script_v70he.cpp index adb2fcac2e..9259e0db2f 100644 --- a/engines/scumm/he/script_v70he.cpp +++ b/engines/scumm/he/script_v70he.cpp @@ -309,7 +309,7 @@ void ScummEngine_v70he::o70_systemOps() { break; case 160: // Confirm shutdown - quitGame(); + confirmExitDialog(); break; case 244: quitGame(); diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp index b9f454de0f..42bf9a4bb6 100644 --- a/engines/scumm/he/script_v72he.cpp +++ b/engines/scumm/he/script_v72he.cpp @@ -158,7 +158,7 @@ int ScummEngine_v72he::readArray(int array, int idx2, int idx1) { ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(array)); - if (ah == NULL || ah->data == NULL) + if (!ah) error("readArray: invalid array %d (%d)", array, readVar(array)); if (idx2 < (int)FROM_LE_32(ah->dim2start) || idx2 > (int)FROM_LE_32(ah->dim2end) || @@ -1199,7 +1199,7 @@ void ScummEngine_v72he::o72_systemOps() { break; case 160: // Confirm shutdown - quitGame(); + confirmExitDialog(); break; case 244: quitGame(); @@ -1779,8 +1779,11 @@ void ScummEngine_v72he::copyArray(int array1, int a1_dim2start, int a1_dim2end, copyArrayHelper(ah, a1_dim2start, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize); copyArrayHelper(ah, a2_dim2start, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize); } else { + // start at the end, so we copy backwards (in case the indices overlap) copyArrayHelper(ah, a1_dim2end, a1_dim1start, a1_dim1end, &dst, &dstPitch, &rowSize); copyArrayHelper(ah, a2_dim2end, a2_dim1start, a2_dim1end, &src, &srcPitch, &rowSize); + dstPitch = -dstPitch; + srcPitch = -srcPitch; } for (; a1_dim2start <= a1_dim2end; ++a1_dim2start) { memcpy(dst, src, rowSize); diff --git a/engines/scumm/he/script_v80he.cpp b/engines/scumm/he/script_v80he.cpp index eb62b650a4..ae43d714ad 100644 --- a/engines/scumm/he/script_v80he.cpp +++ b/engines/scumm/he/script_v80he.cpp @@ -23,7 +23,7 @@ #ifdef ENABLE_HE #include "common/archive.h" -#include "common/config-file.h" +#include "common/ini-file.h" #include "common/config-manager.h" #include "common/macresman.h" #include "common/savefile.h" @@ -180,7 +180,7 @@ void ScummEngine_v80he::o80_readConfigFile() { } } else { // Normal Windows INI files - Common::ConfigFile confFile; + Common::INIFile confFile; if (!strcmp((char *)filename + r, "map.ini")) confFile.loadFromFile((const char *)filename + r); else @@ -250,7 +250,7 @@ void ScummEngine_v80he::o80_writeConfigFile() { memcpy(section, "BluesTreasureHunt-Disc2\0", 24); } - Common::ConfigFile ConfFile; + Common::INIFile ConfFile; ConfFile.loadFromSaveFile((const char *)filename + r); ConfFile.setKey((char *)option, (char *)section, (char *)string); ConfFile.saveToSaveFile((const char *)filename + r); diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 12ebfef9b7..0e96952a48 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -1483,7 +1483,7 @@ void IMuseInternal::initMT32(MidiDriver *midi) { } void IMuseInternal::initGM(MidiDriver *midi) { - byte buffer[11]; + byte buffer[12]; int i; // General MIDI System On message @@ -1509,7 +1509,7 @@ void IMuseInternal::initGM(MidiDriver *midi) { midi->sysEx(buffer, 9); debug(2, "GS SysEx: GS Reset"); _system->delayMillis(200); - + // Set global Master Tune to 442.0kHz, as on the MT-32 memcpy(&buffer[4], "\x40\x00\x00\x00\x04\x04\x0F\x29", 8); midi->sysEx(buffer, 12); @@ -1540,7 +1540,7 @@ void IMuseInternal::initGM(MidiDriver *midi) { // Set Channels 1-16 Reverb to 64, which is the // equivalent of MT-32 default Reverb Level 5 for (i = 0; i < 16; ++i) - midi->send((64 << 16) | (91 << 8) | (0xB0 | i)); + midi->send((64 << 16) | (91 << 8) | (0xB0 | i)); debug(2, "GM Controller 91 Change: Channels 1-16 Reverb Level is 64"); // Set Channels 1-16 Pitch Bend Sensitivity to diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index ee2de49475..d1786dfb60 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -535,7 +535,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) { openMainMenuDialog(); // Display global main menu - if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0) + if (VAR_SAVELOAD_SCRIPT2 != 0xFF && _currentRoom != 0) runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0); } else if (restartKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F8 && lastKeyHit.hasFlags(0))) { diff --git a/engines/scumm/insane/insane_enemy.cpp b/engines/scumm/insane/insane_enemy.cpp index fa6d4264ec..d711b63342 100644 --- a/engines/scumm/insane/insane_enemy.cpp +++ b/engines/scumm/insane/insane_enemy.cpp @@ -1519,8 +1519,7 @@ void Insane::chooseEnemyWeaponAnim(int32 buttons) { case INV_BOOT: case INV_HAND: case INV_DUST: - _actor[1].act[2].state = 0; - switchEnemyWeapon(); + // fallthrough default: switchEnemyWeapon(); } @@ -2437,6 +2436,7 @@ void Insane::actor12Reaction(int32 buttons) { smlayer_setActorFacing(1, 2, 6, 180); smlayer_setActorLayer(1, 2, 25); _actor[1].act[2].state = 103; + break; case 103: _actor[1].kicking = false; diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp index 048b29d68b..d9f0b412e1 100644 --- a/engines/scumm/nut_renderer.cpp +++ b/engines/scumm/nut_renderer.cpp @@ -357,7 +357,10 @@ void NutRenderer::drawFrame(byte *dst, int c, int x, int y) { } void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color) { - byte *dst = (byte *)s.pixels + y * s.pitch + x; + // FIXME: This gets passed a const destination Surface. Intuitively this + // should never get written to. But sadly it does... For now we simply + // cast the const qualifier away. + byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y)); const int width = MIN((int)_chars[c].width, s.w - x); const int height = MIN((int)_chars[c].height, s.h - y); const byte *src = unpackChar(c); @@ -391,7 +394,10 @@ void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byt } void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) { - byte *dst = (byte *)s.pixels + y * s.pitch + x; + // FIXME: This gets passed a const destination Surface. Intuitively this + // should never get written to. But sadly it does... For now we simply + // cast the const qualifier away. + byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y)); const int width = _vm->_2byteWidth; const int height = MIN(_vm->_2byteHeight, s.h - y); const byte *src = _vm->get2byteCharPtr(c); diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index ed77a863cd..d266183f85 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -1715,7 +1715,7 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) { error("object %d is not a blast object", eo->number); bdd.dst = *vs; - bdd.dst.pixels = vs->getPixels(0, 0); + bdd.dst.setPixels(vs->getPixels(0, 0)); bdd.x = eo->rect.left; bdd.y = eo->rect.top; diff --git a/engines/scumm/player_mac.cpp b/engines/scumm/player_mac.cpp index c16c85bff3..a60736df5e 100644 --- a/engines/scumm/player_mac.cpp +++ b/engines/scumm/player_mac.cpp @@ -289,12 +289,16 @@ uint32 Player_Mac::durationToSamples(uint16 duration) { // (duration * 473 * _sampleRate) / (4 * 480 * 480) // // But that's likely to cause integer overflow, so we do it in two - // steps and hope that the rounding error won't be noticeable. + // steps using bitwise operations to perform + // ((duration * 473 * _sampleRate) / 4096) without overflowing, + // then divide this by 225 + // (note that 4 * 480 * 480 == 225 * 4096 == 225 << 12) // // The original code is a bit unclear on if it should be 473 or 437, // but since the comments indicated 473 I'm assuming 437 was a typo. - uint32 samples = (duration * _sampleRate) / (4 * 480); - samples = (samples * 473) / 480; + uint32 samples = (duration * _sampleRate); + samples = (samples >> 12) * 473 + (((samples & 4095) * 473) >> 12); + samples = samples / 225; return samples; } diff --git a/engines/scumm/player_v3m.cpp b/engines/scumm/player_v3m.cpp index 0f222d84fe..bf65ec797f 100644 --- a/engines/scumm/player_v3m.cpp +++ b/engines/scumm/player_v3m.cpp @@ -124,7 +124,7 @@ bool Player_V3M::checkMusicAvailable() { return true; } } - + GUI::MessageDialog dialog(_( "Could not find the 'Loom' Macintosh executable to read the\n" "instruments from. Music will be disabled."), _("OK")); diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp index a75e864e7a..6983c51f30 100644 --- a/engines/scumm/script_v6.cpp +++ b/engines/scumm/script_v6.cpp @@ -394,7 +394,7 @@ ScummEngine_v6::ArrayHeader *ScummEngine_v6::getArray(int array) { int ScummEngine_v6::readArray(int array, int idx, int base) { ArrayHeader *ah = getArray(array); - if (ah == NULL || ah->data == NULL) + if (!ah) error("readArray: invalid array %d (%d)", array, readVar(array)); // WORKAROUND bug #645711. This is clearly a script bug, as this script diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 6aad52578d..979573c5f5 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Thu May 2 21:27:50 2013 + This file was generated by the md5table tool on Thu Aug 15 12:47:39 2013 DO NOT EDIT MANUALLY! */ @@ -124,6 +124,7 @@ static const MD5Table md5table[] = { { "28d24a33448fab6795850bc9f159a4a2", "atlantis", "FM-TOWNS", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns }, { "28ef68ee3ed76d7e2ee8ee13c15fbd5b", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformDOS }, { "28f07458f1b6c24e118a1ea056827701", "lost", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, + { "291fb06071e65897f755846611f5ad40", "ft", "", "7-Wolf", 19697, Common::RU_RUS, Common::kPlatformUnknown }, { "2a208ffbcd0e83e86f4356e6f64aa6e1", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformDOS }, { "2a41b53cf1a90b6e6f26c10cc6041084", "tentacle", "", "Demo", 2439158, Common::EN_ANY, Common::kPlatformMacintosh }, { "2a446817ffcabfef8716e0c456ecaf81", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows }, @@ -238,7 +239,7 @@ static const MD5Table md5table[] = { { "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", 20103, Common::EN_ANY, Common::kPlatformUnknown }, { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", 7617, Common::EN_ANY, Common::kPlatformAmiga }, { "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown }, - { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, + { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "Akella", -1, Common::RU_RUS, Common::kPlatformUnknown }, { "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows }, { "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows }, { "56b5922751be7ffd771b38dda56b028b", "freddi", "HE 100", "", 34837, Common::NL_NLD, Common::kPlatformWii }, @@ -327,6 +328,7 @@ static const MD5Table md5table[] = { { "73e5ab7dbb9a8061cc6d25df02dbd1e7", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformDOS }, { "7410a8ba9795020cd42f171c4320659e", "pajama3", "", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "746e88c172a5b7a1ae89ac0ee3ee681a", "freddi", "HE 90", "Updated", -1, Common::RU_RUS, Common::kPlatformWindows }, + { "7477bc23d0383516c5e310cd8771dcc9", "pajama2", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "74da3494fbe1a7d20213b0afe0954755", "catalog", "HE CUP", "Preview", 10841544, Common::FR_FRA, Common::kPlatformUnknown }, { "754feb59d3bf86b8a00840df74fd7b26", "freddi3", "", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "75ba23fff4fd63fa446c02864f2a5a4b", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformDOS }, @@ -342,6 +344,7 @@ static const MD5Table md5table[] = { { "78c07ca088526d8d4446a4c2cb501203", "freddi3", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "7974365d3dc0f43a2748c975f91ff042", "monkey2", "", "", -1, Common::ES_ESP, Common::kPlatformDOS }, { "79b05f628586837e7166e82b2279bb50", "loom", "PC-Engine", "", -1, Common::JA_JPN, Common::kPlatformPCEngine }, + { "7b4ee071eecadc2d8cd0c3509110825c", "puttzoo", "HE 100", "Remastered", -1, Common::EN_ANY, Common::kPlatformWindows }, { "7bad72e332a59f9fcc1d437f4edad32a", "puttcircus", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, { "7c2e76087027eeee9c8f8985f93a1cc5", "freddi4", "", "Demo", 13584, Common::EN_ANY, Common::kPlatformUnknown }, { "7c8100e360e8ef05f88069d4cfa0afd1", "puttrace", "HE 99", "Demo", 13108, Common::EN_GRB, Common::kPlatformWindows }, @@ -534,7 +537,7 @@ static const MD5Table md5table[] = { { "ce7733f185b838e248927c7ba1a04204", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformAmiga }, { "ce7fd0c382389a6791fc3e199c117ef4", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformDOS }, { "cea91e3dd47f2518ea418e41611aa77f", "spyfox2", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, - { "cf400d20769fb70eb21766582f4924f7", "moonbase", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "cf400d20769fb70eb21766582f4924f7", "moonbase", "1.0", "1.0", -1, Common::EN_ANY, Common::kPlatformWindows }, { "cf4ef315214c7d8cdab6302cdb7e50db", "freddi", "HE 73", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows }, { "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", -1, Common::DE_DEU, Common::kPlatformWindows }, @@ -582,6 +585,7 @@ static const MD5Table md5table[] = { { "e03ed1474ec14de78359970e0457a820", "freddi4", "HE 99", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows }, { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", 51152, Common::EN_ANY, Common::kPlatformWindows }, { "e17db1ddf91b39ca6bbc8ad3ed19e883", "monkey", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, + { "e1c9998826ce7fa8bde5cc3a5023edec", "moonbase", "1.1", "1.1", -1, Common::EN_ANY, Common::kPlatformWindows }, { "e246e02db9630533a40d99c9f54a8e01", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "e361a7058ed8e8ebb462663c0a3ae8d6", "puttputt", "HE 62", "", -1, Common::HE_ISR, Common::kPlatformDOS }, { "e41de1c2a15abbcdbf9977e2d7e8a340", "freddi2", "HE 100", "Updated", -1, Common::RU_RUS, Common::kPlatformWindows }, diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index a77c1c0141..ca05c90936 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -240,6 +240,7 @@ enum ScummGameId { GID_FBEAR, GID_PUTTMOON, GID_FUNPACK, + GID_PUTTZOO, GID_FREDDI3, GID_BIRTHDAYRED, GID_BIRTHDAYYELLOW, diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp index 77c7daa0df..9c90d7575d 100644 --- a/engines/scumm/vars.cpp +++ b/engines/scumm/vars.cpp @@ -714,6 +714,12 @@ void ScummEngine_v99he::resetScummVars() { VAR(140) = 0; #endif } + + if (_game.id == GID_PUTTZOO && _game.heversion == 100 && _game.platform == Common::kPlatformWindows) { + // Specific to Nimbus Games version. + VAR(156) = 1; + VAR(157) = 0; + } } #endif diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index fd90015aa3..4c47dfafc7 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -187,9 +187,14 @@ Common::Error SkyEngine::go() { } if (!shouldQuit()) { - _skyLogic->initScreen0(); + // restartGame() takes us to the first scene, without showing the + // initial animation where Foster is being chased. initScreen0() + // shows the first scene together with that animation. We can't + // call both, as they both load the same scene. if (introSkipped) _skyControl->restartGame(); + else + _skyLogic->initScreen0(); } } diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index 206bd68b07..742aac1a53 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -37,7 +37,14 @@ #include "gui/message.h" +#ifdef USE_MPEG2 +#include "video/avi_decoder.h" +#endif + +#ifdef USE_ZLIB #include "video/dxa_decoder.h" +#endif + #include "video/psx_decoder.h" #include "video/smk_decoder.h" @@ -176,27 +183,26 @@ bool MoviePlayer::load(uint32 id) { break; case kVideoDecoderPSX: filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]); + break; + case kVideoDecoderMP2: + filename = Common::String::format("%s.mp2", sequenceList[id]); + break; + } - // Need to switch to true color + // Need to switch to true color for PSX/MP2 videos + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0); - // Need to load here in case it fails in which case we'd need - // to go back to paletted mode - if (_decoder->loadFile(filename)) { - _decoder->start(); - return true; - } else { + if (!_decoder->loadFile(filename)) { + // Go back to 8bpp color + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) initGraphics(g_system->getWidth(), g_system->getHeight(), true); - return false; - } - break; - } - if (!_decoder->loadFile(filename)) return false; + } - // For DXA, also add the external sound file - if (_decoderType == kVideoDecoderDXA) + // For DXA/MP2, also add the external sound file + if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2) _decoder->addStreamFileTrack(sequenceList[id]); _decoder->start(); @@ -224,9 +230,9 @@ void MoviePlayer::play() { } void MoviePlayer::performPostProcessing(byte *screen) { - // TODO: We don't support the PSX stream videos yet + // TODO: We don't support displaying these in true color yet, // nor using the PSX fonts to display subtitles. - if (_vm->isPsx()) + if (_vm->isPsx() || _decoderType == kVideoDecoderMP2) return; if (!_movieTexts.empty()) { @@ -308,7 +314,7 @@ bool MoviePlayer::playVideo() { if (_decoderType == kVideoDecoderPSX) drawFramePSX(frame); else - _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); + _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h); } if (_decoder->hasDirtyPalette()) { @@ -401,7 +407,7 @@ bool MoviePlayer::playVideo() { } Graphics::Surface *screen = _vm->_system->lockScreen(); - performPostProcessing((byte *)screen->pixels); + performPostProcessing((byte *)screen->getPixels()); _vm->_system->unlockScreen(); _vm->_system->updateScreen(); } @@ -414,20 +420,19 @@ bool MoviePlayer::playVideo() { _vm->_system->delayMillis(10); } - if (_decoderType == kVideoDecoderPSX) { - // Need to jump back to paletted color + // Need to jump back to paletted color + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) initGraphics(g_system->getWidth(), g_system->getHeight(), true); - } return !_vm->shouldQuit() && !skipped; } uint32 MoviePlayer::getBlackColor() { - return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black; + return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black; } uint32 MoviePlayer::findTextColor() { - if (_decoderType == kVideoDecoderPSX) { + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) { // We're in true color mode, so return the actual colors switch (_textColor) { case 1: @@ -493,7 +498,7 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) { uint16 x = (g_system->getWidth() - scaledFrame.w) / 2; uint16 y = (g_system->getHeight() - scaledFrame.h) / 2; - _vm->_system->copyRectToScreen(scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); + _vm->_system->copyRectToScreen(scaledFrame.getPixels(), scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); scaledFrame.free(); } @@ -547,9 +552,16 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan * filename = Common::String::format("%s.mp2", sequenceList[id]); if (Common::File::exists(filename)) { - GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK")); +#ifdef USE_MPEG2 + // HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video + // to be played back at 12fps. + Video::VideoDecoder *aviDecoder = new Video::AVIDecoder(12); + return new MoviePlayer(vm, textMan, resMan, system, aviDecoder, kVideoDecoderMP2); +#else + GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2"), _("OK")); dialog.runModal(); return 0; +#endif } if (!vm->isPsx() || scumm_stricmp(sequenceList[id], "enddemo") != 0) { diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h index d0c61f5eb3..2c51a74f71 100644 --- a/engines/sword1/animation.h +++ b/engines/sword1/animation.h @@ -41,7 +41,8 @@ namespace Sword1 { enum DecoderType { kVideoDecoderDXA = 0, kVideoDecoderSMK = 1, - kVideoDecoderPSX = 2 + kVideoDecoderPSX = 2, + kVideoDecoderMP2 = 3 }; class MovieText { diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp index 00260f789a..92fa9d0e44 100644 --- a/engines/sword2/animation.cpp +++ b/engines/sword2/animation.cpp @@ -42,7 +42,14 @@ #include "gui/message.h" +#ifdef USE_MPEG2 +#include "video/avi_decoder.h" +#endif + +#ifdef USE_ZLIB #include "video/dxa_decoder.h" +#endif + #include "video/smk_decoder.h" #include "video/psx_decoder.h" @@ -88,26 +95,26 @@ bool MoviePlayer::load(const char *name) { break; case kVideoDecoderPSX: filename = Common::String::format("%s.str", name); + break; + case kVideoDecoderMP2: + filename = Common::String::format("%s.mp2", name); + break; + } - // Need to switch to true color - initGraphics(640, 480, true, 0); + // Need to switch to true color for PSX/MP2 videos + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) + initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0); - // Need to load here in case it fails in which case we'd need - // to go back to paletted mode - if (_decoder->loadFile(filename)) { - _decoder->start(); - return true; - } else { - initGraphics(640, 480, true); - return false; - } - } + if (!_decoder->loadFile(filename)) { + // Go back to 8bpp color + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) + initGraphics(g_system->getWidth(), g_system->getHeight(), true); - if (!_decoder->loadFile(filename)) return false; + } - // For DXA, also add the external sound file - if (_decoderType == kVideoDecoderDXA) + // For DXA/MP2, also add the external sound file + if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2) _decoder->addStreamFileTrack(name); _decoder->start(); @@ -136,10 +143,9 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI _vm->_sound->stopSpeech(); } - if (_decoderType == kVideoDecoderPSX) { - // Need to jump back to paletted color + // Need to jump back to paletted color + if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) initGraphics(640, 480, true); - } } void MoviePlayer::openTextObject(uint32 index) { @@ -328,7 +334,7 @@ bool MoviePlayer::playVideo() { if (_decoderType == kVideoDecoderPSX) drawFramePSX(frame); else - _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, x, y, frame->w, frame->h); + _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h); } if (_decoder->hasDirtyPalette()) { @@ -378,11 +384,11 @@ bool MoviePlayer::playVideo() { } uint32 MoviePlayer::getBlackColor() { - return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black; + return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black; } uint32 MoviePlayer::getWhiteColor() { - return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF) : _white; + return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF) : _white; } void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) { @@ -397,7 +403,7 @@ void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) { uint16 x = (g_system->getWidth() - scaledFrame.w) / 2; uint16 y = (g_system->getHeight() - scaledFrame.h) / 2; - _vm->_system->copyRectToScreen(scaledFrame.pixels, scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); + _vm->_system->copyRectToScreen(scaledFrame.getPixels(), scaledFrame.pitch, x, y, scaledFrame.w, scaledFrame.h); scaledFrame.free(); } @@ -446,9 +452,16 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system filename = Common::String::format("%s.mp2", name); if (Common::File::exists(filename)) { - GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK")); +#ifdef USE_MPEG2 + // HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video + // to be played back at 12fps. + Video::AVIDecoder *aviDecoder = new Video::AVIDecoder(12); + return new MoviePlayer(vm, system, aviDecoder, kVideoDecoderMP2); +#else + GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"), _("OK")); dialog.runModal(); return NULL; +#endif } // The demo tries to play some cutscenes that aren't there, so make those warnings more discreet. diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h index b2a243b2ca..8669bdc8d8 100644 --- a/engines/sword2/animation.h +++ b/engines/sword2/animation.h @@ -40,7 +40,8 @@ namespace Sword2 { enum DecoderType { kVideoDecoderDXA = 0, kVideoDecoderSMK = 1, - kVideoDecoderPSX = 2 + kVideoDecoderPSX = 2, + kVideoDecoderMP2 = 3 }; struct MovieText { diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp index a95532ec65..3cdce1b493 100644 --- a/engines/sword25/fmv/movieplayer.cpp +++ b/engines/sword25/fmv/movieplayer.cpp @@ -130,10 +130,10 @@ void MoviePlayer::update() { assert(s->format.bytesPerPixel == 4); #ifdef THEORA_INDIRECT_RENDERING - const byte *frameData = (const byte *)s->getBasePtr(0, 0); + const byte *frameData = (const byte *)s->getPixels(); _outputBitmap->setContent(frameData, s->pitch * s->h, 0, s->pitch); #else - g_system->copyRectToScreen(s->getBasePtr(0, 0), s->pitch, _outX, _outY, MIN(s->w, _backSurface->w), MIN(s->h, _backSurface->h)); + g_system->copyRectToScreen(s->getPixels(), s->pitch, _outX, _outY, MIN(s->w, _backSurface->w), MIN(s->h, _backSurface->h)); g_system->updateScreen(); #endif } diff --git a/engines/sword25/gfx/dynamicbitmap.cpp b/engines/sword25/gfx/dynamicbitmap.cpp index 242508bf85..1f3d2d063d 100644 --- a/engines/sword25/gfx/dynamicbitmap.cpp +++ b/engines/sword25/gfx/dynamicbitmap.cpp @@ -53,7 +53,7 @@ DynamicBitmap::DynamicBitmap(InputPersistenceBlock &reader, RenderObjectPtr<Rend bool DynamicBitmap::createRenderedImage(uint width, uint height) { bool result = false; _image.reset(new RenderedImage(width, height, result)); - + _originalWidth = _width = width; _originalHeight = _height = height; @@ -77,7 +77,7 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) { // Get the frame buffer object GraphicEngine *pGfx = Kernel::getInstance()->getGfx(); assert(pGfx); - + // Draw the bitmap bool result; if (_scaleFactorX == 1.0f && _scaleFactorY == 1.0f) { diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h index 9d7fc43251..8db54e7c54 100644 --- a/engines/sword25/gfx/image/image.h +++ b/engines/sword25/gfx/image/image.h @@ -205,7 +205,7 @@ public: @brief Returns true, if the content of the BS_Image is allowed to be replaced by call of SetContent(). */ virtual bool isSetContentAllowed() const = 0; - + virtual bool isSolid() const { return false; } //@} diff --git a/engines/sword25/gfx/image/imgloader.cpp b/engines/sword25/gfx/image/imgloader.cpp index e103626416..9006a596b4 100644 --- a/engines/sword25/gfx/image/imgloader.cpp +++ b/engines/sword25/gfx/image/imgloader.cpp @@ -50,7 +50,7 @@ bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&un width = pngSurface->w; height = pngSurface->h; uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h]; - memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h); + memcpy(uncompressedDataPtr, (byte *)pngSurface->getPixels(), pngSurface->pitch * pngSurface->h); pngSurface->free(); delete pngSurface; diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index c8a6666046..346b46f3b4 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -41,6 +41,7 @@ #include "sword25/gfx/renderobjectmanager.h" #include "common/system.h" +#include "graphics/thumbnail.h" namespace Sword25 { @@ -250,14 +251,10 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe // Create an encapsulating surface for the data Graphics::Surface srcImage; // TODO: Is the data really in the screen format? - srcImage.format = g_system->getScreenFormat(); - srcImage.pitch = _width * 4; - srcImage.w = _width; - srcImage.h = _height; - srcImage.pixels = _data; + srcImage.init(_width, _height, _width * 4, _data, g_system->getScreenFormat()); if (pPartRect) { - srcImage.pixels = &_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4]; + srcImage.setPixels(&_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4]); srcImage.w = pPartRect->right - pPartRect->left; srcImage.h = pPartRect->bottom - pPartRect->top; @@ -286,14 +283,14 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe if ((width != srcImage.w) || (height != srcImage.h)) { // Scale the image img = imgScaled = scale(srcImage, width, height); - savedPixels = (byte *)img->pixels; + savedPixels = (byte *)img->getPixels(); } else { img = &srcImage; } for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) { const Common::Rect &clipRect = *it; - + int skipLeft = 0, skipTop = 0; int drawX = posX, drawY = posY; int drawWidth = img->w; @@ -305,7 +302,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe drawWidth -= skipLeft; drawX = clipRect.left; } - + if (drawY < clipRect.top) { skipTop = clipRect.top - drawY; drawHeight -= skipTop; @@ -314,13 +311,13 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe if (drawX + drawWidth >= clipRect.right) drawWidth = clipRect.right - drawX; - + if (drawY + drawHeight >= clipRect.bottom) drawHeight = clipRect.bottom - drawY; - + if ((drawWidth > 0) && (drawHeight > 0)) { int xp = 0, yp = 0; - + int inStep = 4; int inoStep = img->pitch; if (flipping & Image::FLIP_V) { @@ -329,14 +326,14 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe } else { xp = skipLeft; } - + if (flipping & Image::FLIP_H) { inoStep = -inoStep; yp = img->h - 1 - skipTop; } else { yp = skipTop; } - + byte *ino = (byte *)img->getBasePtr(xp, yp); byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY); @@ -350,7 +347,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe ino += inoStep; } } else -#endif +#endif { byte *in, *out; for (int i = 0; i < drawHeight; i++) { @@ -360,7 +357,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe uint32 pix = *(uint32 *)in; int a = (pix >> 24) & 0xff; in += inStep; - + if (ca != 255) { a = a * ca >> 8; } @@ -370,11 +367,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe out += 4; continue; } - + int b = (pix >> 0) & 0xff; int g = (pix >> 8) & 0xff; int r = (pix >> 16) & 0xff; - + if (a == 255) { #if defined(SCUMM_LITTLE_ENDIAN) if (cb != 255) @@ -459,11 +456,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe } } - + } if (imgScaled) { - imgScaled->pixels = savedPixels; + imgScaled->setPixels(savedPixels); imgScaled->free(); delete imgScaled; } @@ -509,60 +506,4 @@ void RenderedImage::checkForTransparency() { } } -/** - * Scales a passed surface, creating a new surface with the result - * @param srcImage Source image to scale - * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero) - * @remarks Caller is responsible for freeing the returned surface - */ -Graphics::Surface *RenderedImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) { - Graphics::Surface *s = new Graphics::Surface(); - s->create(xSize, ySize, srcImage.format); - - int *horizUsage = scaleLine(xSize, srcImage.w); - int *vertUsage = scaleLine(ySize, srcImage.h); - - // Loop to create scaled version - for (int yp = 0; yp < ySize; ++yp) { - const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]); - byte *destP = (byte *)s->getBasePtr(0, yp); - - for (int xp = 0; xp < xSize; ++xp) { - const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel); - for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) { - *destP++ = *tempSrcP++; - } - } - } - - // Delete arrays and return surface - delete[] horizUsage; - delete[] vertUsage; - return s; -} - -/** - * Returns an array indicating which pixels of a source image horizontally or vertically get - * included in a scaled image - */ -int *RenderedImage::scaleLine(int size, int srcSize) { - int scale = 100 * size / srcSize; - assert(scale > 0); - int *v = new int[size]; - Common::fill(v, &v[size], 0); - - int distCtr = 0; - int *destP = v; - for (int distIndex = 0; distIndex < srcSize; ++distIndex) { - distCtr += scale; - while (distCtr >= 100) { - assert(destP < &v[size]); - *destP++ = distIndex; - distCtr -= 100; - } - } - - return v; -} - } // End of namespace Sword25 diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h index a25b258592..116f97de26 100644 --- a/engines/sword25/gfx/image/renderedimage.h +++ b/engines/sword25/gfx/image/renderedimage.h @@ -104,8 +104,6 @@ public: return true; } - static Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize); - void setIsTransparent(bool isTransparent) { _isTransparent = isTransparent; } virtual bool isSolid() const { return !_isTransparent; } @@ -119,7 +117,6 @@ private: Graphics::Surface *_backSurface; void checkForTransparency(); - static int *scaleLine(int size, int srcSize); }; } // End of namespace Sword25 diff --git a/engines/sword25/gfx/panel.cpp b/engines/sword25/gfx/panel.cpp index 931b9cdbe7..b9bb8b087d 100644 --- a/engines/sword25/gfx/panel.cpp +++ b/engines/sword25/gfx/panel.cpp @@ -84,7 +84,7 @@ bool Panel::doRender(RectangleList *updateRects) { gfxPtr->fill(&intersectionRect, _color); } } - + return true; } diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp index 807c1eb64b..1dd6f4590f 100644 --- a/engines/sword25/gfx/renderobject.cpp +++ b/engines/sword25/gfx/renderobject.cpp @@ -183,7 +183,7 @@ bool RenderObject::updateObjectState() { // Die Bounding-Box neu berechnen und Update-Regions registrieren. updateBoxes(); - + ++_version; // Änderungen Validieren diff --git a/engines/sword25/gfx/renderobject.h b/engines/sword25/gfx/renderobject.h index 7e0334ee88..1116c3284c 100644 --- a/engines/sword25/gfx/renderobject.h +++ b/engines/sword25/gfx/renderobject.h @@ -236,7 +236,7 @@ public: @brief Löscht alle Kinderobjekte. */ void deleteAllChildren(); - + // Accessor-Methoden // ----------------- /** @@ -305,11 +305,11 @@ public: int getZ() const { return _z; } - + int getAbsoluteZ() const { return _absoluteZ; } - + /** @brief Gibt die Breite des Objektes zurück. */ @@ -363,11 +363,11 @@ public: return _handle; } - // Get the RenderObjects current version + // Get the RenderObjects current version int getVersion() const { return _version; } - + bool isSolid() const { return _isSolid; } @@ -410,7 +410,7 @@ protected: bool _oldVisible; static int _nextGlobalVersion; - + int _version; // This should be set to true if the RenderObject is NOT alpha-blended to optimize drawing @@ -509,9 +509,9 @@ private: @brief Berechnet die absolute Position des Objektes. */ int calcAbsoluteY() const; - + int calcAbsoluteZ() const; - + /** @brief Sortiert alle Kinderobjekte nach ihrem Renderang. */ diff --git a/engines/sword25/gfx/renderobjectmanager.cpp b/engines/sword25/gfx/renderobjectmanager.cpp index 994d9367ab..77f944c9e0 100644 --- a/engines/sword25/gfx/renderobjectmanager.cpp +++ b/engines/sword25/gfx/renderobjectmanager.cpp @@ -113,7 +113,7 @@ bool RenderObjectManager::render() { RectangleList *updateRects = _uta->getRectangles(); Common::Array<int> updateRectsMinZ; - + updateRectsMinZ.reserve(updateRects->size()); // Calculate the minimum drawing Z value of each update rectangle @@ -144,9 +144,9 @@ bool RenderObjectManager::render() { } delete updateRects; - + SWAP(_currQueue, _prevQueue); - + return true; } diff --git a/engines/sword25/gfx/screenshot.cpp b/engines/sword25/gfx/screenshot.cpp index 0ea4bff906..7b56a6e9f3 100644 --- a/engines/sword25/gfx/screenshot.cpp +++ b/engines/sword25/gfx/screenshot.cpp @@ -40,7 +40,7 @@ namespace Sword25 { bool Screenshot::saveToFile(Graphics::Surface *data, Common::WriteStream *stream) { // Convert the RGBA data to RGB - const byte *pSrc = (const byte *)data->getBasePtr(0, 0); + const byte *pSrc = (const byte *)data->getPixels(); // Write our own custom header stream->writeUint32BE(MKTAG('S','C','R','N')); // SCRN, short for "Screenshot" @@ -85,7 +85,7 @@ Common::SeekableReadStream *Screenshot::createThumbnail(Graphics::Surface *data) uint x, y; x = y = 0; - for (byte *pDest = (byte *)thumbnail.pixels; pDest < ((byte *)thumbnail.pixels + thumbnail.pitch * thumbnail.h); ) { + for (byte *pDest = (byte *)thumbnail.getPixels(); pDest < ((byte *)thumbnail.getBasePtr(0, thumbnail.h)); ) { // Get an average over a 4x4 pixel block in the source image int alpha, red, green, blue; alpha = red = green = blue = 0; diff --git a/engines/sword25/gfx/staticbitmap.cpp b/engines/sword25/gfx/staticbitmap.cpp index 91b93e8910..bb57fa3a03 100644 --- a/engines/sword25/gfx/staticbitmap.cpp +++ b/engines/sword25/gfx/staticbitmap.cpp @@ -71,7 +71,7 @@ bool StaticBitmap::initBitmapResource(const Common::String &filename) { // RenderObject Eigenschaften aktualisieren _originalWidth = _width = bitmapPtr->getWidth(); _originalHeight = _height = bitmapPtr->getHeight(); - + _isSolid = bitmapPtr->isSolid(); // Bild-Resource freigeben diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp index b7f5e30340..b7a8fd3c8b 100644 --- a/engines/sword25/util/pluto/pluto.cpp +++ b/engines/sword25/util/pluto/pluto.cpp @@ -1,6 +1,6 @@ /* $Id$ */ -/* Pluto - Heavy-duty persistence for Lua +/* Tamed Pluto - Heavy-duty persistence for Lua * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public * domain. People making use of this software as part of an application * are politely requested to email the author at sneftel@gmail.com @@ -14,11 +14,17 @@ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Instrumented by Stefan Reich (info@luaos.net) + * for Mobile Lua (http://luaos.net/pages/mobile-lua.php) */ +#include "config.h" #include "sword25/util/lua/lua.h" #include "pluto.h" +#undef TOTEXT + #define USE_PDEP #ifdef USE_PDEP @@ -42,10 +48,20 @@ #include <string.h> +/* Define this if you want size_t values to be written in 64-bit + (even on 32-bit systems). Should eliminate at least one source of + 32/64 bit incompatibility. */ +#define SIZES64 + /* #define PLUTO_DEBUG */ +#ifdef SIZES64 +#define VERSION "Tamed Pluto 1.0 with SIZES64 flag" +#else +#define VERSION "Tamed Pluto 1.0" +#endif #ifdef PLUTO_DEBUG @@ -56,6 +72,23 @@ #define verify(x) { int v = (int)((x)); v=v; lua_assert(v); } +#define NUMTYPES 9 +static const char* typenames[] = { + "nil", + "boolean", + "lightuserdata", + "number", + "string", + "table", + "function", + "userdata", + "thread" +}; + +static int humanReadable = 0; +#define hrBufSize 200 +static char hrBuf[hrBufSize]; + typedef struct PersistInfo_t { lua_State *L; int counter; @@ -76,6 +109,77 @@ void printindent(int indent) } #endif +/* lua_Chunkwriter signature: (lua_State *L, const void *p, size_t sz, void *ud). + ud is a pointer to the WriterInfo struct (holds the buffer pointer) +*/ + +static void pi_write(PersistInfo *pi, const void *p, size_t size, void *ud) { + if (humanReadable) { + uint i; + snprintf(hrBuf, hrBufSize, " pi_write %d ", (int) size); + pi->writer(pi->L, hrBuf, strlen(hrBuf), ud); + for (i = 0; i < size; i++) { + char b = ((char *)p)[i]; + snprintf(hrBuf, hrBufSize, "%X%X", (b >> 4) & 0xF, b & 0xF); + pi->writer(pi->L, hrBuf, strlen(hrBuf), ud); + } + snprintf(hrBuf, hrBufSize, "\n"); + pi->writer(pi->L, hrBuf, strlen(hrBuf), ud); + } else { + pi->writer(pi->L, p, size, ud); + } +#ifdef TOTEXT + int i; + printf(" pi_write %d ", (int) size); + for (i = 0; i < size; i++) { + char b = ((char *)p)[i]; + printf("%X%X", (b >> 4) & 0xF, b & 0xF); + } + printf("\n"); +#endif +} + +static void hrOut(PersistInfo *pi) { + pi->writer(pi->L, hrBuf, strlen(hrBuf), pi->ud); +} + +static void write_size(PersistInfo *pi, size_t *val) +{ +#ifdef SIZES64 + int64 longval; /* yeah, you really need long long to get 8 bytes on win32... duh. */ + longval = *val; + pi_write(pi, &longval, 8, pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "write_size64 %ld\n", longval); + hrOut(pi); + } +#ifdef TOTEXT + printf("write_size64 %ld\n", longval); +#endif +#else + pi_write(pi, val, sizeof(size_t), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "write_size %ld\n", *((size_t *)val)); + hrOut(pi); + } +#ifdef TOTEXT + printf("write_size %ld\n", *val); +#endif +#endif +} + +static void read_size(ZIO *zio, size_t *val) +{ +#ifdef SIZES64 + int64 longval; + verify(LIF(Z,read)(zio, &longval, 8) == 0); + *val = longval; +#else + verify(LIF(Z,read)(zio, val, sizeof(size_t)) == 0); +#endif +} + + /* Mutual recursion requires prototype */ static void persist(PersistInfo *pi); @@ -107,7 +211,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction) if(defaction) { { int zero = 0; - pi->writer(pi->L, &zero, sizeof(int), pi->ud); + pi_write(pi, &zero, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistspecialobject_write_zero\n"); +#endif } return 0; } else { @@ -127,7 +238,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction) if(defaction) { { int zero = 0; - pi->writer(pi->L, &zero, sizeof(int), pi->ud); + pi_write(pi, &zero, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero2\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistspecialobject_write_zero2\n"); +#endif } return 0; } else { @@ -143,7 +261,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction) /* perms reftbl sptbl ... obj */ { int zero = 0; - pi->writer(pi->L, &zero, sizeof(int), pi->ud); + pi_write(pi, &zero, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero3\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistspecialobject_write_zero3\n"); +#endif } return 0; } else { @@ -176,7 +301,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction) /* perms reftbl ... obj mt func */ { int one = 1; - pi->writer(pi->L, &one, sizeof(int), pi->ud); + pi_write(pi, &one, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistspecialobject_write_one\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistspecialobject_write_one\n"); +#endif } persist(pi); /* perms reftbl ... obj mt func */ @@ -187,6 +319,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction) static void persisttable(PersistInfo *pi) { + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persisttable\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persisttable\n"); +#endif + /* perms reftbl ... tbl */ lua_checkstack(pi->L, 3); if(persistspecialobject(pi, 1)) { @@ -235,8 +375,15 @@ static void persistuserdata(PersistInfo *pi) { } else { /* Use literal persistence */ size_t length = uvalue(getobject(pi->L, -1))->len; - pi->writer(pi->L, &length, sizeof(size_t), pi->ud); - pi->writer(pi->L, lua_touserdata(pi->L, -1), length, pi->ud); + write_size(pi, &length); + pi_write(pi, lua_touserdata(pi->L, -1), length, pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistuserdata %ld\n", (long) length); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistuserdata %ld\n", (long) length); +#endif if(!lua_getmetatable(pi->L, -1)) { /* perms reftbl ... udata */ lua_pushnil(pi->L); @@ -269,8 +416,8 @@ static void pushproto(lua_State *L, Proto *proto) #define setuvvalue(L,obj,x) \ { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \ - checkliveness(G(L),i_o); } + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \ + checkliveness(G(L),i_o); } static void pushupval(lua_State *L, UpVal *upval) { @@ -309,7 +456,14 @@ static void persistfunction(PersistInfo *pi) { /* We don't really _NEED_ the number of upvals, * but it'll simplify things a bit */ - pi->writer(pi->L, &cl->l.p->nups, sizeof(lu_byte), pi->ud); + pi_write(pi, &cl->l.p->nups, sizeof(lu_byte), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistfunction_number_upvalues %d\n", (int) cl->l.p->nups); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistfunction_number_upvalues %d\n", (int) cl->l.p->nups); +#endif } /* Persist prototype */ { @@ -401,7 +555,14 @@ static void persistproto(PersistInfo *pi) /* Persist constant refs */ { int i; - pi->writer(pi->L, &p->sizek, sizeof(int), pi->ud); + pi_write(pi, &p->sizek, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_sizek %d\n", p->sizek); + hrOut(pi); + } + #ifdef TOTEXT + printf("persistproto_sizek %d\n", p->sizek); + #endif for(i=0; i<p->sizek; i++) { LIF(A,pushobject)(pi->L, &p->k[i]); /* perms reftbl ... proto const */ @@ -415,7 +576,14 @@ static void persistproto(PersistInfo *pi) /* serialize inner Proto refs */ { int i; - pi->writer(pi->L, &p->sizep, sizeof(int), pi->ud); + pi_write(pi, &p->sizep, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_sizep %d\n", p->sizep); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_sizep %d\n", p->sizep); +#endif for(i=0; i<p->sizep; i++) { pushproto(pi->L, p->p[i]); @@ -429,14 +597,37 @@ static void persistproto(PersistInfo *pi) /* Serialize code */ { - pi->writer(pi->L, &p->sizecode, sizeof(int), pi->ud); - pi->writer(pi->L, p->code, sizeof(Instruction) * p->sizecode, pi->ud); + int len; + pi_write(pi, &p->sizecode, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_sizecode %d\n", p->sizecode); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_sizecode %d\n", p->sizecode); +#endif + len = sizeof(Instruction) * p->sizecode; + pi_write(pi, p->code, len, pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_code %d\n", len); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_code %d\n", len); +#endif } /* Serialize upvalue names */ { int i; - pi->writer(pi->L, &p->sizeupvalues, sizeof(int), pi->ud); + pi_write(pi, &p->sizeupvalues, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_upvalues %d\n", p->sizeupvalues); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_upvalues %d\n", p->sizeupvalues); +#endif for(i=0; i<p->sizeupvalues; i++) { pushstring(pi->L, p->upvalues[i]); @@ -447,15 +638,36 @@ static void persistproto(PersistInfo *pi) /* Serialize local variable infos */ { int i; - pi->writer(pi->L, &p->sizelocvars, sizeof(int), pi->ud); + pi_write(pi, &p->sizelocvars, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_sizelocvars %d\n", p->sizelocvars); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_sizelocvars %d\n", p->sizelocvars); +#endif for(i=0; i<p->sizelocvars; i++) { pushstring(pi->L, p->locvars[i].varname); persist(pi); lua_pop(pi->L, 1); - pi->writer(pi->L, &p->locvars[i].startpc, sizeof(int), pi->ud); - pi->writer(pi->L, &p->locvars[i].endpc, sizeof(int), pi->ud); + pi_write(pi, &p->locvars[i].startpc, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_startpc %d\n", p->locvars[i].startpc); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_startpc %d\n", p->locvars[i].startpc); +#endif + pi_write(pi, &p->locvars[i].endpc, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_endpc %d\n", p->locvars[i].endpc); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_endpc %d\n", p->locvars[i].endpc); +#endif } } @@ -466,23 +678,81 @@ static void persistproto(PersistInfo *pi) /* Serialize line numbers */ { - pi->writer(pi->L, &p->sizelineinfo, sizeof(int), pi->ud); + pi_write(pi, &p->sizelineinfo, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_sizelineinfo %d\n", p->sizelineinfo); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_sizelineinfo %d\n", p->sizelineinfo); +#endif if (p->sizelineinfo) { - pi->writer(pi->L, p->lineinfo, sizeof(int) * p->sizelineinfo, pi->ud); + int len; + len = sizeof(int) * p->sizelineinfo; + pi_write(pi, p->lineinfo, len, pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_lineinfo %d\n", len); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_lineinfo %d\n", len); +#endif } } /* Serialize linedefined and lastlinedefined */ - pi->writer(pi->L, &p->linedefined, sizeof(int), pi->ud); - pi->writer(pi->L, &p->lastlinedefined, sizeof(int), pi->ud); + pi_write(pi, &p->linedefined, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_linedefined %d\n", p->linedefined); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_linedefined %d\n", p->linedefined); +#endif + pi_write(pi, &p->lastlinedefined, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_lastlinedefined %d\n", p->lastlinedefined); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_lastlinedefined %d\n", p->lastlinedefined); +#endif /* Serialize misc values */ { - pi->writer(pi->L, &p->nups, sizeof(lu_byte), pi->ud); - pi->writer(pi->L, &p->numparams, sizeof(lu_byte), pi->ud); - pi->writer(pi->L, &p->is_vararg, sizeof(lu_byte), pi->ud); - pi->writer(pi->L, &p->maxstacksize, sizeof(lu_byte), pi->ud); + pi_write(pi, &p->nups, sizeof(lu_byte), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_nups %d\n", (int) p->nups); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_nups %d\n", (int) p->nups); +#endif + pi_write(pi, &p->numparams, sizeof(lu_byte), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_numparams %d\n", (int) p->numparams); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_numparams %d\n", (int) p->numparams); +#endif + pi_write(pi, &p->is_vararg, sizeof(lu_byte), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_is_vararg %d\n", (int) p->is_vararg); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_is_vararg %d\n", (int) p->is_vararg); +#endif + pi_write(pi, &p->maxstacksize, sizeof(lu_byte), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistproto_maxstacksize %d\n", (int) p->maxstacksize); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistproto_maxstacksize %d\n", (int) p->maxstacksize); +#endif } /* We do not currently persist upvalue names, local variable names, * variable lifetimes, line info, or source code. */ @@ -518,7 +788,7 @@ static void persistthread(PersistInfo *pi) /* Persist the stack */ posremaining = revappendstack(L2, pi->L); /* perms reftbl ... thr (rev'ed contents of L2) */ - pi->writer(pi->L, &posremaining, sizeof(size_t), pi->ud); + write_size(pi, &posremaining); for(; posremaining > 0; posremaining--) { persist(pi); lua_pop(pi->L, 1); @@ -527,7 +797,7 @@ static void persistthread(PersistInfo *pi) /* Now, persist the CallInfo stack. */ { size_t i, numframes = (L2->ci - L2->base_ci) + 1; - pi->writer(pi->L, &numframes, sizeof(size_t), pi->ud); + write_size(pi, &numframes); for(i=0; i<numframes; i++) { CallInfo *ci = L2->base_ci + i; size_t stackbase = ci->base - L2->stack; @@ -536,11 +806,18 @@ static void persistthread(PersistInfo *pi) size_t savedpc = (ci != L2->base_ci) ? ci->savedpc - ci_func(ci)->l.p->code : 0; - pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud); - pi->writer(pi->L, &stackfunc, sizeof(size_t), pi->ud); - pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud); - pi->writer(pi->L, &ci->nresults, sizeof(int), pi->ud); - pi->writer(pi->L, &savedpc, sizeof(size_t), pi->ud); + write_size(pi, &stackbase); + write_size(pi, &stackfunc); + write_size(pi, &stacktop); + pi_write(pi, &ci->nresults, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistthread %d\n", ci->nresults); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistthread %d\n", ci->nresults); +#endif + write_size(pi, &savedpc); } } @@ -549,10 +826,18 @@ static void persistthread(PersistInfo *pi) size_t stackbase = L2->base - L2->stack; size_t stacktop = L2->top - L2->stack; lua_assert(L2->nCcalls <= 1); - pi->writer(pi->L, &L2->status, sizeof(lu_byte), pi->ud); - pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud); - pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud); - pi->writer(pi->L, &L2->errfunc, sizeof(ptrdiff_t), pi->ud); + pi_write(pi, &L2->status, sizeof(lu_byte), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistthread_status %d\n", (int) L2->status); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistthread_status %d\n", (int) L2->status); +#endif + write_size(pi, &stackbase); + write_size(pi, &stacktop); + pi_write(pi, &L2->errfunc, sizeof(ptrdiff_t), pi->ud); + //write_size(pi, (size_t *)&L2->errfunc); } /* Finally, record upvalues which need to be reopened */ @@ -573,7 +858,7 @@ static void persistthread(PersistInfo *pi) lua_pop(pi->L, 1); /* perms reftbl ... thr */ stackpos = uv->v - L2->stack; - pi->writer(pi->L, &stackpos, sizeof(size_t), pi->ud); + write_size(pi, &stackpos); } /* perms reftbl ... thr */ lua_pushnil(pi->L); @@ -588,26 +873,62 @@ static void persistthread(PersistInfo *pi) static void persistboolean(PersistInfo *pi) { int b = lua_toboolean(pi->L, -1); - pi->writer(pi->L, &b, sizeof(int), pi->ud); + pi_write(pi, &b, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistboolean %d\n", b); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistboolean %d\n", b); +#endif } static void persistlightuserdata(PersistInfo *pi) { void *p = lua_touserdata(pi->L, -1); - pi->writer(pi->L, &p, sizeof(void *), pi->ud); + pi_write(pi, &p, sizeof(void *), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistlightuserdata %p\n", p); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistlightuserdata %d\n", (int) p); +#endif } static void persistnumber(PersistInfo *pi) { lua_Number n = lua_tonumber(pi->L, -1); - pi->writer(pi->L, &n, sizeof(lua_Number), pi->ud); + pi_write(pi, &n, sizeof(lua_Number), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persistnumber %d (%d)\n", (int) n, (int) sizeof(lua_Number)); + hrOut(pi); + } +#ifdef TOTEXT + printf("persistnumber %d (%d)\n", (int) n, (int) sizeof(lua_Number)); +#endif } static void persiststring(PersistInfo *pi) { + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persiststring\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persiststring\n"); +#endif size_t length = lua_strlen(pi->L, -1); - pi->writer(pi->L, &length, sizeof(size_t), pi->ud); - pi->writer(pi->L, lua_tostring(pi->L, -1), length, pi->ud); + write_size(pi, &length); + const char* s = lua_tostring(pi->L, -1); + pi_write(pi, s, length, pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persiststring %d \"%s\"\n", (int)length, s); + hrOut(pi); + } +#ifdef TOTEXT + printf("persiststring %d \"%s\"\n", length, s); +#endif } /* Top-level delegating persist function @@ -630,8 +951,22 @@ static void persist(PersistInfo *pi) // since size_t is supposedly the same size as a pointer on most // (modern) architectures. int ref = (int)(size_t)lua_touserdata(pi->L, -1); - pi->writer(pi->L, &zero, sizeof(int), pi->ud); - pi->writer(pi->L, &ref, sizeof(int), pi->ud); + pi_write(pi, &zero, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist_seenobject\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist_seenobject\n"); +#endif + pi_write(pi, &ref, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist_touserdata_ref %d\n", ref); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist_touserdata_ref %d\n", ref); +#endif lua_pop(pi->L, 1); /* perms reftbl ... obj ref */ #ifdef PLUTO_DEBUG @@ -647,9 +982,16 @@ static void persist(PersistInfo *pi) if(lua_isnil(pi->L, -1)) { int zero = 0; /* firsttime */ - pi->writer(pi->L, &zero, sizeof(int), pi->ud); + pi_write(pi, &zero, sizeof(int), pi->ud); /* ref */ - pi->writer(pi->L, &zero, sizeof(int), pi->ud); + pi_write(pi, &zero, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist_nil (last 2 lines)\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist_nil (last 2 lines)\n"); +#endif #ifdef PLUTO_DEBUG printindent(pi->level); printf("0 0\n"); @@ -659,7 +1001,14 @@ static void persist(PersistInfo *pi) { /* indicate that it's the first time */ int one = 1; - pi->writer(pi->L, &one, sizeof(int), pi->ud); + pi_write(pi, &one, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist_newobject\n"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist_newobject\n"); +#endif } lua_pushvalue(pi->L, -1); /* perms reftbl ... obj obj */ @@ -668,7 +1017,14 @@ static void persist(PersistInfo *pi) lua_rawset(pi->L, 2); /* perms reftbl ... obj */ - pi->writer(pi->L, &pi->counter, sizeof(int), pi->ud); + pi_write(pi, &pi->counter, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist_counter %d\n", pi->counter); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist_counter %d\n", pi->counter); +#endif /* At this point, we'll give the permanents table a chance to play. */ @@ -685,7 +1041,14 @@ static void persist(PersistInfo *pi) printf("1 %d PERM\n", pi->counter); pi->level++; #endif - pi->writer(pi->L, &type, sizeof(int), pi->ud); + pi_write(pi, &type, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist_permtype %d\n", type); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist_permtype %d\n", type); +#endif persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... obj */ @@ -702,7 +1065,14 @@ static void persist(PersistInfo *pi) } { int type = lua_type(pi->L, -1); - pi->writer(pi->L, &type, sizeof(int), pi->ud); + pi_write(pi, &type, sizeof(int), pi->ud); + if (humanReadable) { + snprintf(hrBuf, hrBufSize, "persist %s\n", type >= 0 && type < NUMTYPES ? typenames[type] : "?"); + hrOut(pi); + } +#ifdef TOTEXT + printf("persist %s\n", type >= 0 && type < NUMTYPES ? typenames[type] : "?"); +#endif #ifdef PLUTO_DEBUG printindent(pi->level); @@ -798,8 +1168,8 @@ typedef struct WriterInfo_t { size_t buflen; } WriterInfo; -static int bufwriter (lua_State *L, const void* p, size_t sz, void* ud) { - const char* cp = (const char*)p; +static int bufwriter (lua_State *L, const void *p, size_t sz, void *ud) { + const char *cp = (const char *)p; WriterInfo *wi = (WriterInfo *)ud; LIF(M,reallocvector)(L, wi->buf, wi->buflen, wi->buflen+sz, char); @@ -819,7 +1189,7 @@ int persist_l(lua_State *L) wi.buf = NULL; wi.buflen = 0; - + lua_settop(L, 2); /* perms? rootobj? */ luaL_checktype(L, 1, LUA_TTABLE); @@ -895,10 +1265,13 @@ static void unpersistnumber(UnpersistInfo *upi) static void unpersiststring(UnpersistInfo *upi) { /* perms reftbl sptbl ref */ + /*int length;*/ size_t length; char* string; lua_checkstack(upi->L, 1); - verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0); + /*verify(LIF(Z,read)(&upi->zio, &length, sizeof(int)) == 0);*/ + /*verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);*/ + read_size(&upi->zio, &length); string = pdep_newvector(upi->L, length, char); verify(LIF(Z,read)(&upi->zio, string, length) == 0); lua_pushlstring(upi->L, string, length); @@ -1312,7 +1685,7 @@ static void unpersistthread(int ref, UnpersistInfo *upi) /* First, deserialize the object stack. */ { size_t i, stacksize; - verify(LIF(Z,read)(&upi->zio, &stacksize, sizeof(size_t)) == 0); + read_size(&upi->zio, &stacksize); LIF(D,growstack)(L2, (int)stacksize); /* Make sure that the first stack element (a nil, representing * the imaginary top-level C function) is written to the very, @@ -1331,16 +1704,16 @@ static void unpersistthread(int ref, UnpersistInfo *upi) /* Now, deserialize the CallInfo stack. */ { size_t i, numframes; - verify(LIF(Z,read)(&upi->zio, &numframes, sizeof(size_t)) == 0); + read_size(&upi->zio, &numframes); LIF(D,reallocCI)(L2,numframes*2); for(i=0; i<numframes; i++) { CallInfo *ci = L2->base_ci + i; size_t stackbase, stackfunc, stacktop, savedpc; - verify(LIF(Z,read)(&upi->zio, &stackbase, sizeof(size_t)) == 0); - verify(LIF(Z,read)(&upi->zio, &stackfunc, sizeof(size_t)) == 0); - verify(LIF(Z,read)(&upi->zio, &stacktop, sizeof(size_t)) == 0); + read_size(&upi->zio, &stackbase); + read_size(&upi->zio, &stackfunc); + read_size(&upi->zio, &stacktop); verify(LIF(Z,read)(&upi->zio, &ci->nresults, sizeof(int)) == 0); - verify(LIF(Z,read)(&upi->zio, &savedpc, sizeof(size_t)) == 0); + read_size(&upi->zio, &savedpc); if(stacklimit < stacktop) stacklimit = stacktop; @@ -1363,9 +1736,10 @@ static void unpersistthread(int ref, UnpersistInfo *upi) size_t stackbase, stacktop; L2->savedpc = L2->ci->savedpc; verify(LIF(Z,read)(&upi->zio, &L2->status, sizeof(lu_byte)) == 0); - verify(LIF(Z,read)(&upi->zio, &stackbase, sizeof(size_t)) == 0); - verify(LIF(Z,read)(&upi->zio, &stacktop, sizeof(size_t)) == 0); + read_size(&upi->zio, &stackbase); + read_size(&upi->zio, &stacktop); verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0); + //read_size(&upi->zio, (size_t *)&L2->errfunc); L2->base = L2->stack + stackbase; L2->top = L2->stack + stacktop; } @@ -1391,7 +1765,7 @@ static void unpersistthread(int ref, UnpersistInfo *upi) lua_pop(upi->L, 1); /* perms reftbl ... thr */ - verify(LIF(Z,read)(&upi->zio, &stackpos, sizeof(size_t)) == 0); + read_size(&upi->zio, &stackpos); uv->v = L2->stack + stackpos; gcunlink(upi->L, (GCObject *)uv); uv->marked = luaC_white(g); @@ -1443,7 +1817,7 @@ static void unpersistuserdata(int ref, UnpersistInfo *upi) /* perms reftbl ... udata */ } else { size_t length; - verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0); + read_size(&upi->zio, &length); lua_newuserdata(upi->L, length); /* perms reftbl ... udata */ @@ -1611,8 +1985,8 @@ void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud) } typedef struct LoadInfo_t { - char *buf; - size_t size; + char *buf; + size_t size; } LoadInfo; @@ -1653,9 +2027,41 @@ int unpersist_l(lua_State *L) return 1; } +/* Stefan's first C function for Lua! :) + Returns a string describing the Pluto version you're using. */ + +int version_l(lua_State *L) +{ + const char *version = VERSION; + + lua_settop(L, 0); + /* (empty) */ + lua_pushlstring(L, version, strlen(version)); + /* str */ + return 1; +} + +/* Set human-readable output on or off. */ +int human_l(lua_State *L) +{ + /* flag? ...? */ + lua_settop(L, 1); + /* flag? */ + /*luaL_checktype(L, 1, LUA_TBOOLEAN);*/ + /* flag */ + + humanReadable = lua_toboolean(L, 1); + + lua_settop(L, 0); + /* (empty) */ + return 0; +} + static luaL_reg pluto_reg[] = { { "persist", persist_l }, { "unpersist", unpersist_l }, + { "version", version_l }, + { "human", human_l }, { NULL, NULL } }; diff --git a/engines/teenagent/callbacks.cpp b/engines/teenagent/callbacks.cpp index 2de81abb37..3e6e40a8fa 100644 --- a/engines/teenagent/callbacks.cpp +++ b/engines/teenagent/callbacks.cpp @@ -294,7 +294,7 @@ bool TeenAgentEngine::fnRobotSafeAlreadyUnlockedCheck() { } void TeenAgentEngine::fnRobotSafeUnlockCheck() { - if (CHECK_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1) && + if (CHECK_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1) && CHECK_FLAG(dsAddr_MansionRobotSafeScentTestPassedFlag, 1) && CHECK_FLAG(dsAddr_MansionRobotSafeViewTestPassedFlag, 1)) { waitLanAnimationFrame(1, 1); @@ -546,7 +546,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { break; case 0x4056: - // FIXME - This is the bird use callback in the first act at + // FIXME - This is the bird use callback in the first act at // the mudpool. Current Code based on behaviour. Need to analyse cseg data. dialog->popMark(scene, dsAddr_dialogStackMudpoolBird); break; @@ -1603,7 +1603,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) { break; case 0x5b44: - // FIXME - This is the doorbell use callback on House #2 + // FIXME - This is the doorbell use callback on House #2 // i.e. Granny and Anne's House. Need to analyse cseg data properly. // Current code inferred from behaviour. // FIXME - Add animation call for Ego pushing doorbell. diff --git a/engines/teenagent/dialog.cpp b/engines/teenagent/dialog.cpp index 870aca6400..312757a462 100644 --- a/engines/teenagent/dialog.cpp +++ b/engines/teenagent/dialog.cpp @@ -28,7 +28,7 @@ namespace TeenAgent { void Dialog::show(uint16 dialogNum, Scene *scene, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2) { uint16 addr = _vm->res->getDialogAddr(dialogNum); - // WORKAROUND: For Dialog 163, The usage of this in the engine overlaps the previous dialog i.e. the + // WORKAROUND: For Dialog 163, The usage of this in the engine overlaps the previous dialog i.e. the // starting offset used is two bytes early, thus implicitly changing the first command of this dialog // from NEW_LINE to CHANGE_CHARACTER. // FIXME: Unsure if this is correct behaviour or if this is a regression from the original. Check this. diff --git a/engines/teenagent/font.cpp b/engines/teenagent/font.cpp index 47f52ff90f..9d85328f20 100644 --- a/engines/teenagent/font.cpp +++ b/engines/teenagent/font.cpp @@ -65,7 +65,7 @@ uint Font::render(Graphics::Surface *surface, int x, int y, char c, byte color) byte *glyph = _data + READ_LE_UINT16(_data + idx * 2); int h = glyph[0], w = glyph[1]; - if (surface == NULL || surface->pixels == NULL || y + h <= 0 || y >= kScreenHeight || x + w <= 0 || x >= kScreenWidth) + if (surface == NULL || surface->getPixels() == NULL || y + h <= 0 || y >= kScreenHeight || x + w <= 0 || x >= kScreenWidth) return w - _widthPack; int i0 = 0, j0 = 0; diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp index 442d0abf16..cdbdcf9655 100644 --- a/engines/teenagent/resources.cpp +++ b/engines/teenagent/resources.cpp @@ -160,7 +160,7 @@ void Resources::loadOff(Graphics::Surface &surface, byte *palette, int id) { off.read(id, buf, bufferSize); byte *src = buf; - byte *dst = (byte *)surface.pixels; + byte *dst = (byte *)surface.getPixels(); memcpy(dst, src, 64000); memcpy(palette, buf + 64000, 768); @@ -206,16 +206,19 @@ Common::SeekableReadStream *Resources::loadLan000(uint32 id) const { if (dseg.get_byte(dsAddr_birdOnBarRadioAntennaFlag) == 1) { return lan500.getStream(380); } + break; case 30: if (dseg.get_byte(dsAddr_birdOnBarRadioAntennaFlag) == 1) { return lan500.getStream(381); } + break; case 42: if (dseg.get_byte(dsAddr_johnNotyOutsideMansionDoorFlag) == 1) { return lan500.getStream(400); } + break; } return lan000.getStream(id); } diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp index bdeb11a841..f36a60932c 100644 --- a/engines/teenagent/scene.cpp +++ b/engines/teenagent/scene.cpp @@ -48,7 +48,6 @@ Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0), onEnabled = true; memset(palette, 0, sizeof(palette)); - background.pixels = 0; FilePack varia; varia.open("varia.res"); @@ -74,8 +73,7 @@ Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0), } Scene::~Scene() { - if (background.pixels) - background.free(); + background.free(); delete[] ons; ons = 0; @@ -372,7 +370,7 @@ void Scene::init(int id, const Common::Point &pos) { for (byte i = 0; i < 4; ++i) customAnimation[i].free(); - if (background.pixels == NULL) + if (background.getPixels() == NULL) background.create(kScreenWidth, kScreenHeight, Graphics::PixelFormat::createFormatCLUT8()); warp(pos); @@ -416,7 +414,7 @@ void Scene::init(int id, const Common::Point &pos) { if (nowPlaying != _vm->res->dseg.get_byte(dsAddr_currentMusic)) _vm->music->load(_vm->res->dseg.get_byte(dsAddr_currentMusic)); - _vm->_system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h); + _vm->_system->copyRectToScreen(background.getPixels(), background.pitch, 0, 0, background.w, background.h); setPalette(0); } @@ -642,8 +640,8 @@ bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) { return true; } - if (background.pixels && debugFeatures.feature[DebugFeatures::kShowBack]) { - _vm->_system->copyRectToScreen(background.pixels, background.pitch, 0, 0, background.w, background.h); + if (background.getPixels() && debugFeatures.feature[DebugFeatures::kShowBack]) { + _vm->_system->copyRectToScreen(background.getPixels(), background.pitch, 0, 0, background.w, background.h); } else _vm->_system->fillScreen(0); diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp index 0b48a18b26..e73f1100d6 100644 --- a/engines/teenagent/teenagent.cpp +++ b/engines/teenagent/teenagent.cpp @@ -399,7 +399,7 @@ bool TeenAgentEngine::showLogo() { return true; } - _system->copyRectToScreen(s.pixels, s.w, s.x, s.y, s.w, s.h); + _system->copyRectToScreen(s.getPixels(), s.w, s.x, s.y, s.w, s.h); _system->updateScreen(); _system->delayMillis(100); diff --git a/engines/testbed/config.cpp b/engines/testbed/config.cpp index 6b56616c9b..a40d239ebf 100644 --- a/engines/testbed/config.cpp +++ b/engines/testbed/config.cpp @@ -213,22 +213,22 @@ void TestbedConfigManager::parseConfigFile() { return; } _configFileInterface.loadFromStream(*rs); - Common::ConfigFile::SectionList sections = _configFileInterface.getSections(); + Common::INIFile::SectionList sections = _configFileInterface.getSections(); Testsuite *currTS = 0; - for (Common::ConfigFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) { + for (Common::INIFile::SectionList::const_iterator i = sections.begin(); i != sections.end(); i++) { if (i->name.equalsIgnoreCase("Global")) { // Global params may be directly queried, ignore them } else { // A testsuite, process it. currTS = getTestsuiteByName(i->name); - Common::ConfigFile::SectionKeyList kList = i->getKeys(); + Common::INIFile::SectionKeyList kList = i->getKeys(); if (!currTS) { Testsuite::logPrintf("Warning! Error in config: Testsuite %s not found\n", i->name.c_str()); continue; } - for (Common::ConfigFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) { + for (Common::INIFile::SectionKeyList::const_iterator j = kList.begin(); j != kList.end(); j++) { if (j->key.equalsIgnoreCase("this")) { currTS->enable(stringToBool(j->value)); } else { diff --git a/engines/testbed/config.h b/engines/testbed/config.h index fd5588aa31..d611ae4ec3 100644 --- a/engines/testbed/config.h +++ b/engines/testbed/config.h @@ -24,7 +24,7 @@ #include "common/array.h" -#include "common/config-file.h" +#include "common/ini-file.h" #include "common/str-array.h" #include "common/tokenizer.h" @@ -62,7 +62,7 @@ public: private: Common::Array<Testsuite *> &_testsuiteList; Common::String _configFileName; - Common::ConfigFile _configFileInterface; + Common::INIFile _configFileInterface; void parseConfigFile(); }; diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp index 590e6c6d81..26e073d407 100644 --- a/engines/testbed/graphics.cpp +++ b/engines/testbed/graphics.cpp @@ -927,17 +927,29 @@ TestExitStatus GFXtests::overlayGraphics() { Graphics::PixelFormat pf = g_system->getOverlayFormat(); - OverlayColor buffer[50 * 100]; - OverlayColor value = pf.RGBToColor(0, 255, 0); + byte *buffer = new byte[50 * 100 * pf.bytesPerPixel]; + const uint32 value = pf.RGBToColor(0, 255, 0); - for (int i = 0; i < 50 * 100; i++) { - buffer[i] = value; + if (pf.bytesPerPixel == 2) { + uint16 *dst = (uint16 *)buffer; + for (int i = 50 * 100; i > 0; --i) { + *dst++ = value; + } + } else if (pf.bytesPerPixel == 4) { + uint32 *dst = (uint32 *)buffer; + for (int i = 50 * 100; i > 0; --i) { + *dst++ = value; + } + } else { + error("GFXtests::overlayGraphics: Unsupported color depth: %d", pf.bytesPerPixel); } g_system->showOverlay(); - g_system->copyRectToOverlay(buffer, 200, 270, 175, 100, 50); + g_system->copyRectToOverlay(buffer, 100 * pf.bytesPerPixel, 270, 175, 100, 50); g_system->updateScreen(); + delete[] buffer; + g_system->delayMillis(1000); g_system->hideOverlay(); diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp index 106e1542d5..fa66b7ad8e 100644 --- a/engines/tinsel/bmv.cpp +++ b/engines/tinsel/bmv.cpp @@ -1031,7 +1031,7 @@ void BMVPlayer::CopyMovieToScreen() { // The movie surface is slightly less high than the output screen (429 rows versus 432). // Because of this, there's some extra line clearing above and below the displayed area int yStart = (SCREEN_HEIGHT - SCREEN_HIGH) / 2; - memset(_vm->screen().getBasePtr(0, 0), 0, yStart * SCREEN_WIDTH); + memset(_vm->screen().getPixels(), 0, yStart * SCREEN_WIDTH); memcpy(_vm->screen().getBasePtr(0, yStart), ScreenBeg, SCREEN_WIDTH * SCREEN_HIGH); memset(_vm->screen().getBasePtr(0, yStart + SCREEN_HIGH), 0, (SCREEN_HEIGHT - SCREEN_HIGH - yStart) * SCREEN_WIDTH); diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp index 5dae984def..c4f341f6fe 100644 --- a/engines/tinsel/graphics.cpp +++ b/engines/tinsel/graphics.cpp @@ -798,7 +798,7 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, */ void ClearScreen() { byte blackColorIndex = (!TinselV1Mac) ? 0 : 255; - void *pDest = _vm->screen().getBasePtr(0, 0); + void *pDest = _vm->screen().getPixels(); memset(pDest, blackColorIndex, SCREEN_WIDTH * SCREEN_HEIGHT); g_system->fillScreen(blackColorIndex); g_system->updateScreen(); diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 3921414b01..104adf72a2 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -300,7 +300,7 @@ void LoadFile(MEMHANDLE *pH) { // discardable - unlock the memory MemoryUnlock(pH->_node); - + // set the loaded flag pH->filesize |= fLoaded; diff --git a/engines/tinsel/rince.cpp b/engines/tinsel/rince.cpp index 3e6334f583..49666c13ca 100644 --- a/engines/tinsel/rince.cpp +++ b/engines/tinsel/rince.cpp @@ -808,7 +808,8 @@ void T2MoverProcess(CORO_PARAM, const void *param) { PokeInPalette(pmi); pMover->actorObj = MultiInitObject(pmi); - pMover->actorID = pMover->actorID; + // FIXME: This is what the original did. A bug, perhaps? + // pMover->actorID = pMover->actorID; pMover->bActive = true; // add it to display list diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp index b652e394a0..43654fc3af 100644 --- a/engines/tinsel/scene.cpp +++ b/engines/tinsel/scene.cpp @@ -130,15 +130,15 @@ const SCENE_STRUC *GetSceneStruc(const byte *pStruc) { const byte *p = pStruc; memset(&g_tempStruc, 0, sizeof(SCENE_STRUC)); - g_tempStruc.numEntrance = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.numPoly = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.numTaggedActor = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.defRefer = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.hSceneScript = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.hEntrance = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.hPoly = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - g_tempStruc.hTaggedActor = FROM_LE_32(READ_32(p)); p += sizeof(uint32); - + g_tempStruc.numEntrance = READ_32(p); p += sizeof(uint32); + g_tempStruc.numPoly = READ_32(p); p += sizeof(uint32); + g_tempStruc.numTaggedActor = READ_32(p); p += sizeof(uint32); + g_tempStruc.defRefer = READ_32(p); p += sizeof(uint32); + g_tempStruc.hSceneScript = READ_32(p); p += sizeof(uint32); + g_tempStruc.hEntrance = READ_32(p); p += sizeof(uint32); + g_tempStruc.hPoly = READ_32(p); p += sizeof(uint32); + g_tempStruc.hTaggedActor = READ_32(p); p += sizeof(uint32); + return &g_tempStruc; } diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 9075e1adb1..5d410e62c7 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -868,9 +868,6 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) } TinselEngine::~TinselEngine() { - if (_bmv->MoviePlaying()) - _bmv->FinishBMV(); - _system->getAudioCDManager()->stop(); delete _bmv; delete _sound; @@ -1007,6 +1004,9 @@ Common::Error TinselEngine::run() { g_system->delayMillis(10); } + if (_bmv->MoviePlaying()) + _bmv->FinishBMV(); + // Write configuration _vm->_config->writeToDisk(); diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index 56fed3007f..5eb3b7d7b8 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -226,7 +226,11 @@ public: Graphics::Surface &screen() { return _screenSurface; } Common::Point getMousePosition() const { return _mousePos; } - void setMousePosition(const Common::Point &pt) { + void setMousePosition(Common::Point pt) { + // Clip mouse position to be within the screen coordinates + pt.x = CLIP<int16>(pt.x, 0, SCREEN_WIDTH - 1); + pt.y = CLIP<int16>(pt.y, 0, SCREEN_HEIGHT - 1); + int yOffset = TinselV2 ? (g_system->getHeight() - _screenSurface.h) / 2 : 0; g_system->warpMouse(pt.x, pt.y + yOffset); _mousePos = pt; diff --git a/engines/toltecs/menu.cpp b/engines/toltecs/menu.cpp index b52d7dad82..0850630c43 100644 --- a/engines/toltecs/menu.cpp +++ b/engines/toltecs/menu.cpp @@ -69,7 +69,7 @@ int MenuSystem::run(MenuID menuId) { _vm->_screen->blastSprite(0x140 + _vm->_cameraX, 0x175 + _vm->_cameraY, 0, 1, 0x4000); shadeRect(60, 39, 520, 247, 225, 229); - memcpy(_background->pixels, _vm->_screen->_frontScreen, 640 * 400); + memcpy(_background->getPixels(), _vm->_screen->_frontScreen, 640 * 400); while (_running) { update(); @@ -229,7 +229,7 @@ void MenuSystem::initMenu(MenuID menuID) { _items.clear(); - memcpy(_vm->_screen->_frontScreen, _background->pixels, 640 * 400); + memcpy(_vm->_screen->_frontScreen, _background->getPixels(), 640 * 400); switch (menuID) { case kMenuIdMain: diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp index 5e12773e1b..1eb2f41fd2 100644 --- a/engines/toltecs/screen.cpp +++ b/engines/toltecs/screen.cpp @@ -651,7 +651,7 @@ void Screen::drawSurface(int16 x, int16 y, Graphics::Surface *surface) { int16 skipX = 0; int16 width = surface->w; int16 height = surface->h; - byte *surfacePixels = (byte *)surface->getBasePtr(0, 0); + byte *surfacePixels = (byte *)surface->getPixels(); byte *frontScreen; // Not on screen, skip diff --git a/engines/toltecs/segmap.cpp b/engines/toltecs/segmap.cpp index b06c0af675..fea40f3277 100644 --- a/engines/toltecs/segmap.cpp +++ b/engines/toltecs/segmap.cpp @@ -373,7 +373,7 @@ void SegmentMap::loadSegmapMaskRectSurface(byte *maskData, SegmapMaskRect &maskR maskRect.surface->create(maskRect.width, maskRect.height, Graphics::PixelFormat::createFormatCLUT8()); byte *backScreen = _vm->_screen->_backScreen + maskRect.x + (maskRect.y * _vm->_sceneWidth); - byte *dest = (byte *)maskRect.surface->getBasePtr(0, 0); + byte *dest = (byte *)maskRect.surface->getPixels(); for (int16 h = 0; h < maskRect.height; h++) { int16 w = maskRect.width; diff --git a/engines/tony/detection.cpp b/engines/tony/detection.cpp index 1094950e2c..d355450153 100644 --- a/engines/tony/detection.cpp +++ b/engines/tony/detection.cpp @@ -154,26 +154,16 @@ void TonyMetaEngine::removeSaveState(const char *target, int slot) const { SaveStateDescriptor TonyMetaEngine::querySaveMetaInfos(const char *target, int slot) const { Common::String saveName; byte difficulty; - byte thumbData[160 * 120 * 2]; - - if (Tony::RMOptionScreen::loadThumbnailFromSaveState(slot, thumbData, saveName, difficulty)) { - // Convert the 565 thumbnail data to the needed overlay format - Common::MemoryReadStream thumbStream(thumbData, 160 * 120 * 2); - Graphics::PixelFormat destFormat = g_system->getOverlayFormat(); - Graphics::Surface *to = new Graphics::Surface(); - to->create(160, 120, destFormat); - - OverlayColor *pixels = (OverlayColor *)to->pixels; - for (int y = 0; y < to->h; ++y) { - for (int x = 0; x < to->w; ++x) { - uint8 r, g, b; - Graphics::colorToRGB<Graphics::ColorMasks<555> >(thumbStream.readUint16LE(), r, g, b); - - // converting to current OSystem Color - *pixels++ = destFormat.RGBToColor(r, g, b); - } - } + Graphics::Surface *to = new Graphics::Surface(); + to->create(160, 120, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); + + if (Tony::RMOptionScreen::loadThumbnailFromSaveState(slot, (byte *)to->getPixels(), saveName, difficulty)) { +#ifdef SCUMM_BIG_ENDIAN + uint16 *pixels = (uint16 *)to->getPixels(); + for (int i = 0; i < to->w * to->h; ++i) + pixels[i] = READ_LE_UINT16(pixels + i); +#endif // Create the return descriptor SaveStateDescriptor desc(slot, saveName); desc.setDeletableFlag(true); @@ -183,6 +173,7 @@ SaveStateDescriptor TonyMetaEngine::querySaveMetaInfos(const char *target, int s return desc; } + delete to; return SaveStateDescriptor(); } diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h index ee137927dc..ca16495903 100644 --- a/engines/tony/detection_tables.h +++ b/engines/tony/detection_tables.h @@ -196,6 +196,40 @@ static const TonyGameDescription gameDescriptions[] = { }, }, + { + // Tony Tough English Unpacked + { + "tony", + 0, + { + {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071}, + {"roasted.mpc", 0, "57c4a3860cf899443c357e0078ea6f49", 366773}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, + + { + // Tony Tough German "Shoe Box", reported in bug #3582420 + { + "tony", + 0, + { + {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071}, + {"roasted.mpc", 0, "bc3471f098e591dc509dcad401a8d8a5", 389554}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, + { AD_TABLE_END_MARKER } }; diff --git a/engines/tony/game.cpp b/engines/tony/game.cpp index 501a588ff5..ca7c07ad8c 100644 --- a/engines/tony/game.cpp +++ b/engines/tony/game.cpp @@ -508,7 +508,8 @@ void RMOptionScreen::refreshThumbnails() { _curThumb[i] = NULL; _curThumbName[i].clear(); _curThumbDiff[i] = 11; - } + } else + _curThumb[i]->prepareImage(); } } diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp index dc82c78ee5..410f9b8971 100644 --- a/engines/tony/gfxcore.cpp +++ b/engines/tony/gfxcore.cpp @@ -1865,7 +1865,7 @@ void RMGfxSourceBuffer8RLEWordAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RM CORO_END_CODE; } -int RMGfxSourceBuffer8RLEWordAA::init(byte *buf, int dimx, int dimy, bool bLoadPalette) { +int RMGfxSourceBuffer8RLEWordAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) { return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette); } diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h index 1bacf7e5a9..9e8f5225c0 100644 --- a/engines/tony/gfxcore.h +++ b/engines/tony/gfxcore.h @@ -208,8 +208,10 @@ public: * 16-bit color source */ class RMGfxSourceBuffer16 : public RMGfxSourceBuffer { -protected: +public: virtual void prepareImage(); + +protected: bool _bTrasp0; public: @@ -408,7 +410,7 @@ public: // Overloaded initialization methods virtual void init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette = false); - virtual int init(byte *buf, int dimx, int dimy, bool bLoadPalette = false); + virtual int init(const byte *buf, int dimx, int dimy, bool bLoadPalette = false); virtual ~RMGfxSourceBuffer8RLEWordAA(); }; diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index 1de5c6850c..5e6d44f0a3 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -1876,14 +1876,11 @@ MpalHandle mpalQueryHANDLE(uint16 wQueryType, ...) { * @remarks This is the specialised version of the original single mpalQuery * method that needs to run within a co-routine context. */ -void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, ...) { +void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet) { CORO_BEGIN_CONTEXT; uint32 dwRet; CORO_END_CONTEXT(_ctx); - va_list v; - va_start(v, dwRet); - CORO_BEGIN_CODE(_ctx); if (wQueryType == MPQ_DIALOG_WAITFORCHOICE) { @@ -1909,8 +1906,6 @@ void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, ...) { } CORO_END_CODE; - - va_end(v); } /** @@ -2040,7 +2035,13 @@ int mpalGetSaveStateSize() { void mpalSaveState(byte *buf) { lockVar(); WRITE_LE_UINT32(buf, GLOBALS._nVars); - memcpy(buf + 4, (byte *)GLOBALS._lpmvVars, GLOBALS._nVars * sizeof(MpalVar)); + buf += 4; + for (uint i = 0; i < GLOBALS._nVars; ++i) { + LpMpalVar var = &GLOBALS._lpmvVars[i]; + WRITE_LE_UINT32(buf, var->_dwVal); + memcpy(buf + 4, var->_lpszVarName, sizeof(var->_lpszVarName)); + buf += (4 + sizeof(var->_lpszVarName)); + } unlockVar(); } @@ -2055,10 +2056,16 @@ int mpalLoadState(byte *buf) { globalFree(GLOBALS._hVars); GLOBALS._nVars = READ_LE_UINT32(buf); + buf += 4; GLOBALS._hVars = globalAllocate(GMEM_ZEROINIT | GMEM_MOVEABLE, GLOBALS._nVars * sizeof(MpalVar)); lockVar(); - memcpy((byte *)GLOBALS._lpmvVars, buf + 4, GLOBALS._nVars * sizeof(MpalVar)); + for (uint i = 0; i < GLOBALS._nVars; ++i) { + LpMpalVar var = &GLOBALS._lpmvVars[i]; + var->_dwVal = READ_LE_UINT32(buf); + memcpy(var->_lpszVarName, buf + 4, sizeof(var->_lpszVarName)); + buf += (4 + sizeof(var->_lpszVarName)); + } unlockVar(); return GLOBALS._nVars * sizeof(MpalVar) + 4; diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h index 779bdd6188..2d22ee8faf 100644 --- a/engines/tony/mpal/mpal.h +++ b/engines/tony/mpal/mpal.h @@ -417,7 +417,7 @@ MpalHandle mpalQueryHANDLE(uint16 wQueryType, ...); * @remarks This is the specialised version of the original single mpalQuery * method that needs to run within a co-routine context. */ -void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet, ...); +void mpalQueryCORO(CORO_PARAM, uint16 wQueryType, uint32 *dwRet); /** * Execute a script. The script runs on multitasking by a thread. diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp index 90ae241db0..547f31906e 100644 --- a/engines/tony/sound.cpp +++ b/engines/tony/sound.cpp @@ -500,7 +500,13 @@ bool FPStream::loadFile(const Common::String &fileName, uint32 codec, int bufSiz break; case FPCODEC_ADPCM: +#ifdef __amigaos4__ + // HACK: AmigaOS 4 has weird performance problems with reading in the audio thread, + // so we read the whole stream into memory. + _rewindableStream = Audio::makeADPCMStream(_file.readStream(_size), DisposeAfterUse::YES, 0, Audio::kADPCMDVI, 44100, 2); +#else _rewindableStream = Audio::makeADPCMStream(&_file, DisposeAfterUse::NO, 0, Audio::kADPCMDVI, 44100, 2); +#endif break; default: diff --git a/engines/tony/window.cpp b/engines/tony/window.cpp index 61497a8066..a732862854 100644 --- a/engines/tony/window.cpp +++ b/engines/tony/window.cpp @@ -330,6 +330,14 @@ void RMSnapshot::grabScreenshot(byte *lpBuf, int dezoom, uint16 *lpDestBuf) { src += RM_BBX * dezoom; } } + +#ifdef SCUMM_BIG_ENDIAN + if (lpDestBuf != NULL) { + for (int i = 0; i < dimx * dimy; i++) { + lpDestBuf[i] = SWAP_BYTES_16(lpDestBuf[i]); + } + } +#endif } } // End of namespace Tony diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp index a6744568f7..78d3954325 100644 --- a/engines/toon/anim.cpp +++ b/engines/toon/anim.cpp @@ -190,7 +190,7 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int16 xx, int int32 destPitch = surface.pitch; uint8 *srcRow = _frames[frame]._data + offsX + (_frames[frame]._x2 - _frames[frame]._x1) * offsY; - uint8 *curRow = (uint8 *)surface.pixels + (yy + _frames[frame]._y1 + _y1 + offsY) * destPitch + (xx + _x1 + _frames[frame]._x1 + offsX); + uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1 + offsX, yy + _frames[frame]._y1 + _y1 + offsY); for (int16 y = 0; y < rectY; y++) { uint8 *cur = curRow; uint8 *c = srcRow + y * (_frames[frame]._x2 - _frames[frame]._x1); @@ -231,7 +231,7 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram int32 destPitch = surface.pitch; int32 destPitchMask = mask->getWidth(); uint8 *c = _frames[frame]._data; - uint8 *curRow = (uint8 *)surface.pixels; + uint8 *curRow = (uint8 *)surface.getPixels(); uint8 *curRowMask = mask->getDataPtr(); bool shadowFlag = false; @@ -341,7 +341,7 @@ void Animation::drawFontFrame(Graphics::Surface &surface, int32 frame, int16 xx, int32 destPitch = surface.pitch; uint8 *c = _frames[frame]._data; - uint8 *curRow = (uint8 *)surface.pixels + (yy + _frames[frame]._y1 + _y1) * destPitch + (xx + _x1 + _frames[frame]._x1); + uint8 *curRow = (uint8 *)surface.getBasePtr(xx + _x1 + _frames[frame]._x1, yy + _frames[frame]._y1 + _y1); for (int16 y = 0; y < rectY; y++) { unsigned char *cur = curRow; for (int16 x = 0; x < rectX; x++) { diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp index 479f4965f3..83c9e3ec70 100644 --- a/engines/toon/character.cpp +++ b/engines/toon/character.cpp @@ -58,6 +58,7 @@ Character::Character(ToonEngine *vm) : _vm(vm) { _animSpecialDefaultId = 0; _currentPathNode = 0; _currentWalkStamp = 0; + _currentFacingStamp = 0; _visible = true; _speed = 150; // 150 = nominal drew speed _lastWalkTime = 0; @@ -99,6 +100,9 @@ void Character::setFacing(int32 facing) { if (_blockingWalk) { _flags |= 2; + _currentFacingStamp++; + int32 localFacingStamp = _currentFacingStamp; + int32 dir = 0; _lastWalkTime = _vm->_system->getMillis(); @@ -127,6 +131,11 @@ void Character::setFacing(int32 facing) { else playWalkAnim(0, 0); _vm->doFrame(); + + if (_currentFacingStamp != localFacingStamp) { + // another setFacing was started in doFrame, we need to cancel this one. + return; + } }; _flags &= ~2; diff --git a/engines/toon/character.h b/engines/toon/character.h index d33c314bf7..b248e7ccf2 100644 --- a/engines/toon/character.h +++ b/engines/toon/character.h @@ -143,6 +143,7 @@ protected: Common::Array<Common::Point> _currentPath; uint32 _currentPathNode; int32 _currentWalkStamp; + int32 _currentFacingStamp; }; } // End of namespace Toon diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp index 8c85e20f7c..f0463a52e1 100644 --- a/engines/toon/movie.cpp +++ b/engines/toon/movie.cpp @@ -112,7 +112,7 @@ bool Movie::playVideo(bool isFirstIntroVideo) { } _vm->_system->unlockScreen(); } else { - _vm->_system->copyRectToScreen(frame->pixels, frame->pitch, 0, 0, frame->w, frame->h); + _vm->_system->copyRectToScreen(frame->getPixels(), frame->pitch, 0, 0, frame->w, frame->h); // WORKAROUND: There is an encoding glitch in the first intro video. This hides this using the adjacent pixels. if (isFirstIntroVideo) { diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp index f59cdca064..65cc3a70e1 100644 --- a/engines/toon/picture.cpp +++ b/engines/toon/picture.cpp @@ -170,7 +170,7 @@ void Picture::drawMask(Graphics::Surface &surface, int16 x, int16 y, int16 dx, i int32 destPitch = surface.pitch; int32 srcPitch = _width; uint8 *c = _data + _width * dy + dx; - uint8 *curRow = (uint8 *)surface.pixels + y * destPitch + x; + uint8 *curRow = (uint8 *)surface.getBasePtr(x, y); for (int16 yy = 0; yy < ry; yy++) { uint8 *curSrc = c; @@ -205,7 +205,7 @@ void Picture::drawWithRectList(Graphics::Surface& surface, int16 x, int16 y, int int16 fillRy = MIN<int32>(ry, rect.bottom - rect.top); uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left); - uint8 *curRow = (uint8 *)surface.pixels + (y + rect.top) * destPitch + (x + rect.left); + uint8 *curRow = (uint8 *)surface.getBasePtr(x + rect.left, y + rect.top); for (int16 yy = 0; yy < fillRy; yy++) { uint8 *curSrc = c; @@ -233,7 +233,7 @@ void Picture::draw(Graphics::Surface &surface, int16 x, int16 y, int16 dx, int16 int32 destPitch = surface.pitch; int32 srcPitch = _width; uint8 *c = _data + _width * dy + dx; - uint8 *curRow = (uint8 *)surface.pixels + y * destPitch + x; + uint8 *curRow = (uint8 *)surface.getBasePtr(x, y); for (int16 yy = 0; yy < ry; yy++) { uint8 *curSrc = c; diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp index 7ad29ab8d8..286bcf1941 100644 --- a/engines/toon/toon.cpp +++ b/engines/toon/toon.cpp @@ -466,8 +466,7 @@ void ToonEngine::doMagnifierEffect() { int32 cy = CLIP<int32>(posY + y, 0, TOON_BACKBUFFER_HEIGHT-1); for (int32 x = -12; x <= 12; x++) { int32 cx = CLIP<int32>(posX + x, 0, TOON_BACKBUFFER_WIDTH-1); - int32 destPitch = surface.pitch; - uint8 *curRow = (uint8 *)surface.pixels + cy * destPitch + cx; + uint8 *curRow = (uint8 *)surface.getBasePtr(cx, cy); tempBuffer[(y + 12) * 25 + x + 12] = *curRow; } } @@ -479,8 +478,7 @@ void ToonEngine::doMagnifierEffect() { if (dist > 144) continue; int32 cx = CLIP<int32>(posX + x, 0, TOON_BACKBUFFER_WIDTH-1); - int32 destPitch = surface.pitch; - uint8 *curRow = (uint8 *)surface.pixels + cy * destPitch + cx; + uint8 *curRow = (uint8 *)surface.getBasePtr(cx, cy); int32 lerp = (512 + intSqrt[dist] * 256 / 12); *curRow = tempBuffer[(y * lerp / 1024 + 12) * 25 + x * lerp / 1024 + 12]; } @@ -501,7 +499,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) { if (_dirtyAll || _gameState->_currentScrollValue != lastScroll) { // we have to refresh everything in case of scrolling. - _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT); + _system->copyRectToScreen((byte *)_mainSurface->getPixels() + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT); } else { int32 offX = 0; @@ -517,7 +515,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) { } rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT); if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) { - _system->copyRectToScreen((byte *)_mainSurface->pixels + _oldDirtyRects[i].left + offX + _oldDirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top); + _system->copyRectToScreen((byte *)_mainSurface->getBasePtr(_oldDirtyRects[i].left + offX, _oldDirtyRects[i].top), TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top); } } @@ -533,7 +531,7 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) { } rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT); if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) { - _system->copyRectToScreen((byte *)_mainSurface->pixels + _dirtyRects[i].left + offX + _dirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top); + _system->copyRectToScreen((byte *)_mainSurface->getBasePtr(_dirtyRects[i].left + offX, _dirtyRects[i].top), TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top); } } } diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp index 1cb8191640..52115b95fe 100644 --- a/engines/tsage/blue_force/blueforce_scenes9.cpp +++ b/engines/tsage/blue_force/blueforce_scenes9.cpp @@ -705,6 +705,10 @@ void Scene900::process(Event &event) { void Scene900::dispatch() { SceneExt::dispatch(); + // WORKAROUND:: Fix for invalid data in the Blue Force floppy version when opening gate + if (_sceneMode == 9006 && (g_vm->getFeatures() & GF_FLOPPY) && BF_GLOBALS._player._endFrame == 8) + BF_GLOBALS._player._endFrame = 6; + if (BF_GLOBALS.getFlag(fWithLyle) && _lyle.isNoMover()) { _lyle.updateAngle(BF_GLOBALS._player._position); } diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp index de5ac62425..8ae6a0d97e 100644 --- a/engines/tsage/converse.cpp +++ b/engines/tsage/converse.cpp @@ -416,7 +416,7 @@ SequenceManager *SequenceManager::globalManager() { ConversationChoiceDialog::ConversationChoiceDialog() { _stdColor = 23; _highlightColor = g_globals->_scenePalette._colors.background; - _fontNumber = 1; + _fontNumber = (g_vm->getGameID() == GType_Ringworld2) ? 3 : 1; _savedFgColor = _savedFontNumber = 0; _selectedIndex = 0; } @@ -424,15 +424,15 @@ ConversationChoiceDialog::ConversationChoiceDialog() { int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) { _gfxManager._font.setFontNumber(_fontNumber); - _bounds = Rect(20, 0, 20, 0); + _bounds = Rect(40, 0, 40, 0); _choiceList.clear(); // Set up the list of choices int yp = 0; for (uint idx = 0; idx < choiceList.size(); ++idx) { Rect tempRect; - _gfxManager._font.getStringBounds(choiceList[idx].c_str(), tempRect, 265); - tempRect.moveTo(25, yp + 10); + _gfxManager._font.getStringBounds(choiceList[idx].c_str(), tempRect, textMaxWidth()); + tempRect.moveTo(textLeft(), yp + 10); _choiceList.push_back(ChoiceEntry(choiceList[idx], tempRect)); yp += tempRect.height() + 5; @@ -444,7 +444,8 @@ int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) { _bounds.bottom -= 10; yp = 180 - _bounds.height(); _bounds.translate(0, yp); - _bounds.right = _bounds.left + 280; + _bounds.setWidth(textMaxWidth() + 15); + _bounds.moveTo(160 - (_bounds.width() / 2), _bounds.top); // Draw the dialog draw(); @@ -513,6 +514,7 @@ void ConversationChoiceDialog::draw() { // Fill in the contents of the entire dialog _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + drawFrame(); _gfxManager._bounds = tempRect; @@ -524,7 +526,7 @@ void ConversationChoiceDialog::draw() { Common::String strNum = Common::String::format("%d", idx + 1); // Write the choice number - _gfxManager._font.setPosition(13, _choiceList[idx]._bounds.top); + _gfxManager._font.setPosition(numberLeft(), _choiceList[idx]._bounds.top); _gfxManager._font.writeString(strNum.c_str()); _gfxManager._font.writeLines(_choiceList[idx]._msg.c_str(), _choiceList[idx]._bounds, ALIGN_LEFT); @@ -533,6 +535,18 @@ void ConversationChoiceDialog::draw() { _gfxManager.deactivate(); } +int ConversationChoiceDialog::textLeft() const { + return (g_vm->getGameID() == GType_Ringworld2) ? 20 : 25; +} + +int ConversationChoiceDialog::textMaxWidth() const { + return (g_vm->getGameID() == GType_Ringworld2) ? 250 : 265; +} + +int ConversationChoiceDialog::numberLeft() const { + return (g_vm->getGameID() == GType_Ringworld2) ? 8 : 13; +} + /*--------------------------------------------------------------------------*/ void Obj44::load(const byte *dataP) { @@ -542,8 +556,8 @@ void Obj44::load(const byte *dataP) { _mode = s.readSint16LE(); _lookupValue = s.readSint16LE(); _lookupIndex = s.readSint16LE(); - _field6 = s.readSint16LE(); - _field8 = s.readSint16LE(); + _exitMode = s.readSint16LE(); + _speakerMode = s.readSint16LE(); } _id = s.readSint16LE(); @@ -551,8 +565,8 @@ void Obj44::load(const byte *dataP) { _callbackId[idx] = s.readSint16LE(); if (g_vm->getGameID() == GType_Ringworld2) { - _field16 = s.readSint16LE(); - s.skip(20); + for (int i = 0; i < 11; ++i) + _field16[i] = s.readSint16LE(); } else { s.skip(4); } @@ -578,9 +592,11 @@ void Obj44::synchronize(Serializer &s) { s.syncAsSint16LE(_mode); s.syncAsSint16LE(_lookupValue); s.syncAsSint16LE(_lookupIndex); - s.syncAsSint16LE(_field6); - s.syncAsSint16LE(_field8); - s.syncAsSint16LE(_field16); + s.syncAsSint16LE(_exitMode); + s.syncAsSint16LE(_speakerMode); + + for (int i = 0; i < 11; ++i) + s.syncAsSint16LE(_field16[i]); } } @@ -632,6 +648,7 @@ void StripManager::reset() { _activeSpeaker = NULL; _textShown = false; _callbackObject = NULL; + _exitMode = 0; _obj44List.clear(); if (!_script.empty()) { @@ -679,6 +696,8 @@ void StripManager::synchronize(Serializer &s) { s.syncAsByte(_textShown); s.syncAsByte(_field2E6); s.syncAsSint32LE(_field2E8); + if (g_vm->getGameID() == GType_Ringworld2) + s.syncAsSint16LE(_exitMode); // Synchronize the item list int arrSize = _obj44List.size(); @@ -708,14 +727,24 @@ void StripManager::synchronize(Serializer &s) { } void StripManager::remove() { + if (g_vm->getGameID() == GType_Ringworld2) { + for (uint i = 0; i < _speakerList.size(); ++i) { + if (_activeSpeaker != _speakerList[i]) + _speakerList[i]->proc16(); + } + } + if (_textShown) { if (_activeSpeaker) _activeSpeaker->removeText(); _textShown = false; } - if (_activeSpeaker) + if (_activeSpeaker) { + if (g_vm->getGameID() == GType_Ringworld2) + static_cast<Ringworld2::VisualSpeaker *>(_activeSpeaker)->_speakerMode = 0xff; _activeSpeaker->remove(); + } if (_sceneNumber != g_globals->_sceneManager._scene->_screenNumber) { g_globals->_sceneManager._scene->_sceneBounds = _sceneBounds; @@ -725,10 +754,15 @@ void StripManager::remove() { if (_onEnd) _onEnd(); + if (g_vm->getGameID() == GType_Ringworld2) + _endHandler = NULL; + Action::remove(); } void StripManager::signal() { + int strIndex = 0; + if (_textShown) { _activeSpeaker->removeText(); _textShown = false; @@ -760,12 +794,10 @@ void StripManager::signal() { Obj44 &obj44 = _obj44List[_obj44Index]; - if (g_vm->getGameID() != GType_Ringworld2) { - _field2E8 = obj44._id; - } else { + if (g_vm->getGameID() == GType_Ringworld2) { // Return to Ringworld specific handling - if (obj44._field6) - _field2E8 = obj44._field6; + if (obj44._exitMode) + _exitMode = obj44._exitMode; switch (obj44._mode) { case 1: @@ -781,40 +813,91 @@ void StripManager::signal() { break; } } - + + _field2E8 = obj44._id; Common::StringArray choiceList; // Build up a list of script entries int idx; + bool delayFlag = false; - if (g_vm->getGameID() == GType_Ringworld2 && obj44._field16) { + if ((g_vm->getGameID() == GType_Ringworld2) && obj44._field16[0]) { // Special loading mode used in Return to Ringworld for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) { - int objIndex = _lookupList[obj44._field16 - 1]; - - if (!obj44._list[objIndex]._id) + int f16Index = _lookupList[obj44._field16[0] - 1]; + int entryId = obj44._field16[f16Index]; + + Obj0A &entry = obj44._list[idx]; + if (entry._id == entryId) { + // Get the next one + choiceList.push_back((const char *)&_script[0] + entry._scriptOffset); + strIndex = idx; + delayFlag = true; break; - - // Get the next one - choiceList.push_back((const char *)&_script[0] + obj44._list[objIndex]._scriptOffset); + } } } else { // Standard choices loading - for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) { + for (idx = 0; idx < OBJ0A_LIST_SIZE; ++idx) { if (!obj44._list[idx]._id) break; // Get the next one - choiceList.push_back((const char *)&_script[0] + obj44._list[idx]._scriptOffset); + const char *choiceStr = (const char *)&_script[0] + obj44._list[idx]._scriptOffset; + + if (!*choiceStr) { + // Choice is empty + assert(g_vm->getGameID() == GType_Ringworld2); + + if (obj44._list[1]._id) { + // it's a reference to another list slot + int listId = obj44._list[idx]._id; + + int obj44Idx = 0; + while (_obj44List[obj44Idx]._id != listId) + ++obj44Idx; + + if (_obj44List[obj44Idx]._field16[0]) { + // WORKAROUND: The _lookupList isn't always correctly initialised. But it always + // seems to be set to the R2_GLOBALS._stripManager_lookupList, so manually set it + if (!_lookupList) + _lookupList = R2_GLOBALS._stripManager_lookupList; + + int f16Index = _lookupList[_obj44List[obj44Idx]._field16[0] - 1]; + listId = _obj44List[obj44Idx]._field16[f16Index]; + + if (_lookupList[_obj44List[obj44Idx]._field16[0] - 1]) { + int listIdx = 0; + while (_obj44List[obj44Idx]._list[listIdx]._id != listId) + ++listIdx; + + choiceStr = (const char *)&_script[0] + _obj44List[obj44Idx]._list[listIdx]._scriptOffset; + } else { + for (int listIdx = idx; listIdx < (OBJ0A_LIST_SIZE - 1); ++listIdx) { + obj44._list[listIdx]._id = obj44._list[listIdx + 1]._id; + obj44._list[listIdx]._scriptOffset = obj44._list[listIdx + 1]._scriptOffset; + + if (!obj44._list[listIdx + 1]._id) + obj44._list[listIdx]._id = 0; + } + + --idx; + continue; + } + } + } + } + + // Add entry to the list + choiceList.push_back(choiceStr); } } - int strIndex = 0; if (choiceList.size() > 1) // Get the user to select a conversation option strIndex = _choiceDialog.execute(choiceList); - if ((choiceList.size() != 1) && !_field2E6) + if ((delayFlag || choiceList.size() != 1) && !_field2E6) _delayFrames = 1; else { Speaker *speakerP = getSpeaker((const char *)&_script[0] + obj44._speakerOffset); @@ -843,11 +926,28 @@ void StripManager::signal() { } } - if ((g_vm->getGameID() == GType_Ringworld2) && (_obj44List.size() > 0)) - static_cast<Ringworld2::VisualSpeaker *>(_activeSpeaker)->proc15(); + if (g_vm->getGameID() == GType_Ringworld2) { + Ringworld2::VisualSpeaker *speaker = static_cast<Ringworld2::VisualSpeaker *>(_activeSpeaker); + + if (speaker) { + speaker->_speakerMode = obj44._speakerMode; + if (!choiceList[strIndex].empty()) + speaker->proc15(); + } - _textShown = true; - _activeSpeaker->setText(choiceList[strIndex]); + if (!choiceList[strIndex].empty()) { + _textShown = true; + _activeSpeaker->setText(choiceList[strIndex]); + } else if (!obj44._speakerMode) { + _delayFrames = 1; + } else { + _delayFrames = 0; + speaker->proc15(); + } + } else { + _textShown = true; + _activeSpeaker->setText(choiceList[strIndex]); + } } _obj44Index = getNewIndex(obj44._list[strIndex]._id); @@ -915,6 +1015,8 @@ Speaker *StripManager::getSpeaker(const char *speakerName) { int StripManager::getNewIndex(int id) { if (id == 10000) return id; + if ((g_vm->getGameID() == GType_Ringworld2) && (id < 0)) + return id; for (uint idx = 0; idx < _obj44List.size(); ++idx) { if (_obj44List[idx]._id == id) { diff --git a/engines/tsage/converse.h b/engines/tsage/converse.h index 0c4eb9539d..5aef0d8a7f 100644 --- a/engines/tsage/converse.h +++ b/engines/tsage/converse.h @@ -94,6 +94,7 @@ public: virtual void proc12(Action *action); virtual void setText(const Common::String &msg); virtual void removeText(); + virtual void proc16() {} void setTextPos(const Common::Point &pt) { _textPos = pt; } }; @@ -145,6 +146,10 @@ public: }; class ConversationChoiceDialog : public ModalDialog { +private: + int textLeft() const; + int textMaxWidth() const; + int numberLeft() const; public: int _stdColor; int _highlightColor; @@ -189,8 +194,9 @@ public: // Return to Ringworld specific field int _mode; - int _lookupValue, _lookupIndex, _field6; - int _field8, _field16; + int _lookupValue, _lookupIndex, _exitMode; + int _speakerMode; + int _field16[11]; public: void load(const byte *dataP); virtual void synchronize(Serializer &s); @@ -217,6 +223,7 @@ public: bool _textShown; bool _field2E6; int _field2E8; + int _exitMode; Common::Array<Obj44> _obj44List; Common::Array<byte> _script; StripProc _onBegin; diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp index 4a90e23a33..6b4e2963a5 100644 --- a/engines/tsage/core.cpp +++ b/engines/tsage/core.cpp @@ -2468,10 +2468,10 @@ void SceneObject::postInit(SceneObjectList *OwnerList) { if (!OwnerList) OwnerList = g_globals->_sceneObjects; - if (!OwnerList->contains(this)) { + if (!OwnerList->contains(this) || ((_flags & OBJFLAG_REMOVE) != 0)) { _percent = 100; _priority = 255; - _flags = 4; + _flags = OBJFLAG_ZOOMED; _visage = 0; _strip = 1; _frame = 1; @@ -2724,7 +2724,9 @@ void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, i } void SceneObject::setup(int visage, int stripFrameNum, int frameNum) { - postInit(); + if (g_vm->getGameID() != GType_Ringworld2) + postInit(); + setVisage(visage); setStrip(stripFrameNum); setFrame(frameNum); @@ -2760,8 +2762,8 @@ void BackgroundSceneObject::setup2(int visage, int stripFrameNum, int frameNum, fixPriority(priority); } -void BackgroundSceneObject::proc27() { - warning("STUB: BackgroundSceneObject::proc27()"); +void BackgroundSceneObject::copySceneToBackground() { + GLOBALS._sceneManager._scene->_backSurface.copyFrom(g_globals->gfxManager().getSurface(), 0, 0); } /*--------------------------------------------------------------------------*/ @@ -3103,6 +3105,7 @@ Visage::Visage() { _rlbNum = -1; _data = NULL; _flipHoriz = false; + _flipVert = false; } Visage::Visage(const Visage &v) { @@ -3112,6 +3115,7 @@ Visage::Visage(const Visage &v) { if (_data) g_vm->_memoryManager.incLocks(_data); _flipHoriz = false; + _flipVert = false; } Visage &Visage::operator=(const Visage &s) { @@ -3155,8 +3159,11 @@ void Visage::setVisage(int resNum, int rlbNum) { rlbNum = (int)(v & 0xff); } _flipHoriz = flags & 1; + _flipVert = flags & 2; _data = g_resourceManager->getResource(RES_VISAGE, resNum, rlbNum); + + DEALLOCATE(indexData); } } @@ -3179,7 +3186,9 @@ GfxSurface Visage::getFrame(int frameNum) { byte *frameData = _data + offset; GfxSurface result = surfaceFromRes(frameData); - if (_flipHoriz) flip(result); + if (_flipHoriz) flipHorizontal(result); + if (_flipVert) flipVertical(result); + return result; } @@ -3187,7 +3196,7 @@ int Visage::getFrameCount() const { return READ_LE_UINT16(_data); } -void Visage::flip(GfxSurface &gfxSurface) { +void Visage::flipHorizontal(GfxSurface &gfxSurface) { Graphics::Surface s = gfxSurface.lockSurface(); for (int y = 0; y < s.h; ++y) { @@ -3200,6 +3209,21 @@ void Visage::flip(GfxSurface &gfxSurface) { gfxSurface.unlockSurface(); } +void Visage::flipVertical(GfxSurface &gfxSurface) { + Graphics::Surface s = gfxSurface.lockSurface(); + + for (int y = 0; y < s.h / 2; ++y) { + // Flip the lines1 + byte *line1P = (byte *)s.getBasePtr(0, y); + byte *line2P = (byte *)s.getBasePtr(0, s.h - y - 1); + + for (int x = 0; x < s.w; ++x) + SWAP(line1P[x], line2P[x]); + } + + gfxSurface.unlockSurface(); +} + /*--------------------------------------------------------------------------*/ Player::Player(): SceneObject() { @@ -4267,10 +4291,15 @@ void SceneHandler::dispatch() { GUIErrorMessage(SAVE_ERROR_MSG); } if (_loadGameSlot != -1) { + int priorSceneBeforeLoad = GLOBALS._sceneManager._previousScene; + int currentSceneBeforeLoad = GLOBALS._sceneManager._sceneNumber; + int loadSlot = _loadGameSlot; _loadGameSlot = -1; g_saver->restore(loadSlot); g_globals->_events.setCursorFromFlag(); + + postLoad(priorSceneBeforeLoad, currentSceneBeforeLoad); } g_globals->_soundManager.dispatch(); diff --git a/engines/tsage/core.h b/engines/tsage/core.h index 296754011e..f7a5a43b16 100644 --- a/engines/tsage/core.h +++ b/engines/tsage/core.h @@ -472,11 +472,13 @@ class Visage { private: byte *_data; - void flip(GfxSurface &s); + void flipHorizontal(GfxSurface &s); + void flipVertical(GfxSurface &s); public: int _resNum; int _rlbNum; bool _flipHoriz; + bool _flipVert; public: Visage(); Visage(const Visage &v); @@ -611,7 +613,7 @@ public: virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void draw(); void setup2(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority, int32 arg10); - void proc27(); + static void copySceneToBackground(); }; class SceneText : public SceneObject { @@ -898,6 +900,7 @@ public: protected: virtual void playerAction(Event &event) {} virtual void processEnd(Event &event) {} + virtual void postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) {} public: SceneHandler(); void registerHandler(); diff --git a/engines/tsage/dialogs.cpp b/engines/tsage/dialogs.cpp index 77ac0a25d7..43833f53b9 100644 --- a/engines/tsage/dialogs.cpp +++ b/engines/tsage/dialogs.cpp @@ -137,43 +137,47 @@ void ModalDialog::drawFrame() { Rect origRect = _bounds; _bounds.collapse(-10, -10); - // Fill the dialog area - g_globals->gfxManager().fillRect(origRect, 54); - - // Draw top line - GfxSurface surface = surfaceFromRes(8, 1, 7); - for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) - surface.draw(Common::Point(xp, _bounds.top)); - surface.draw(Common::Point(_bounds.right - 20, _bounds.top)); - - surface = surfaceFromRes(8, 1, 1); - surface.draw(Common::Point(_bounds.left, _bounds.top)); - - surface = surfaceFromRes(8, 1, 4); - surface.draw(Common::Point(_bounds.right - 10, _bounds.top)); - - // Draw vertical edges - surface = surfaceFromRes(8, 1, 2); - for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) - surface.draw(Common::Point(_bounds.left, yp)); - surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20)); - - surface = surfaceFromRes(8, 1, 5); - for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) - surface.draw(Common::Point(_bounds.right - 10, yp)); - surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20)); - - // Draw bottom line - surface = surfaceFromRes(8, 1, 8); - for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) - surface.draw(Common::Point(xp, _bounds.bottom - 10)); - surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10)); - - surface = surfaceFromRes(8, 1, 3); - surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10)); - - surface = surfaceFromRes(8, 1, 6); - surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10)); + if (g_vm->getGameID() == GType_Ringworld2) { + GfxElement::drawFrame(); + } else { + // Fill the dialog area + g_globals->gfxManager().fillRect(origRect, 54); + + // Draw top line + GfxSurface surface = surfaceFromRes(8, 1, 7); + for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) + surface.draw(Common::Point(xp, _bounds.top)); + surface.draw(Common::Point(_bounds.right - 20, _bounds.top)); + + surface = surfaceFromRes(8, 1, 1); + surface.draw(Common::Point(_bounds.left, _bounds.top)); + + surface = surfaceFromRes(8, 1, 4); + surface.draw(Common::Point(_bounds.right - 10, _bounds.top)); + + // Draw vertical edges + surface = surfaceFromRes(8, 1, 2); + for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) + surface.draw(Common::Point(_bounds.left, yp)); + surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20)); + + surface = surfaceFromRes(8, 1, 5); + for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) + surface.draw(Common::Point(_bounds.right - 10, yp)); + surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20)); + + // Draw bottom line + surface = surfaceFromRes(8, 1, 8); + for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) + surface.draw(Common::Point(xp, _bounds.bottom - 10)); + surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10)); + + surface = surfaceFromRes(8, 1, 3); + surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10)); + + surface = surfaceFromRes(8, 1, 6); + surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10)); + } // Set the dialog's manager bounds _gfxManager._bounds = origRect; diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp index 8f07a8243b..5ca531fdb9 100644 --- a/engines/tsage/events.cpp +++ b/engines/tsage/events.cpp @@ -277,7 +277,7 @@ void EventsClass::setCursor(CursorType cursorType) { GfxSurface s = surfaceFromRes(cursor); Graphics::Surface surface = s.lockSurface(); - const byte *cursorData = (const byte *)surface.getBasePtr(0, 0); + const byte *cursorData = (const byte *)surface.getPixels(); CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor); s.unlockSurface(); @@ -333,7 +333,7 @@ void EventsClass::pushCursor(CursorType cursorType) { GfxSurface s = surfaceFromRes(cursor); Graphics::Surface surface = s.lockSurface(); - const byte *cursorData = (const byte *)surface.getBasePtr(0, 0); + const byte *cursorData = (const byte *)surface.getPixels(); CursorMan.pushCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColor); s.unlockSurface(); @@ -346,7 +346,7 @@ void EventsClass::popCursor() { } void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Common::Point &hotspot, CursorType cursorId) { - const byte *cursorData = (const byte *)cursor.getBasePtr(0, 0); + const byte *cursorData = (const byte *)cursor.getPixels(); CursorMan.replaceCursor(cursorData, cursor.w, cursor.h, hotspot.x, hotspot.y, transColor); _currentCursor = cursorId; @@ -355,7 +355,7 @@ void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Com void EventsClass::setCursor(GfxSurface &cursor) { Graphics::Surface s = cursor.lockSurface(); - const byte *cursorData = (const byte *)s.getBasePtr(0, 0); + const byte *cursorData = (const byte *)s.getPixels(); CursorMan.replaceCursor(cursorData, cursor.getBounds().width(), cursor.getBounds().height(), cursor._centroid.x, cursor._centroid.y, cursor._transColor); diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp index 4589a926c9..5c4fa967e5 100644 --- a/engines/tsage/globals.cpp +++ b/engines/tsage/globals.cpp @@ -3,7 +3,7 @@ * 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 @@ -366,30 +366,47 @@ bool BlueForceGlobals::removeFlag(int flagNum) { namespace Ringworld2 { +Ringworld2Globals::Ringworld2Globals() { + _scannerDialog = new ScannerDialog(); +} + +Ringworld2Globals::~Ringworld2Globals() { + delete _scannerDialog; +} + void Ringworld2Globals::reset() { Globals::reset(); + if (!_scannerDialog) + _scannerDialog = new ScannerDialog(); + // Reset the inventory R2_INVENTORY.reset(); T2_GLOBALS._uiElements.updateInventory(); T2_GLOBALS._uiElements._active = false; + // Set the screen to track the player + _scrollFollower = &_player; + // Reset fields - Common::fill(&_v1000[0], &_v1000[0x1000], 0); - _v1000Flag = false; + Common::fill(&_fadePaletteMap[0][0], &_fadePaletteMap[10][256], 0); + Common::fill(&_paletteMap[0], &_paletteMap[4096], 0); + + _fadePaletteFlag = false; _v5589E.set(0, 0, 0, 0); _v558B6.set(0, 0, 0, 0); _v558C2 = 0; _animationCtr = 0; _v5657C = 0; - _v565E1 = 0; - _v565E3 = 0; + _electromagnetChangeAmount = 0; + _electromagnetZoom = 0; _v565E5 = 0; _v565E7 = 0; _v565E9 = -5; _v565EB = 26; _v565F5 = 0; _v565F6 = 0; + _v565F8 = 0; _v565FA = 0; _v565AE = 0; _v56605[0] = 0; @@ -463,7 +480,7 @@ void Ringworld2Globals::reset() { _v565EC[2] = 27; _v565EC[3] = 4; _v565EC[4] = 4; - Common::fill(&_v565F1[0], &_v565F1[MAX_CHARACTERS], 1); + Common::fill(&_scannerFrequencies[0], &_scannerFrequencies[MAX_CHARACTERS], 1); _speechSubtitles = SPEECH_VOICE | SPEECH_TEXT; _insetUp = 0; _frameEdgeColour = 2; @@ -496,14 +513,15 @@ void Ringworld2Globals::synchronize(Serializer &s) { s.syncAsSint16LE(_v558C2); s.syncAsSint16LE(_animationCtr); s.syncAsSint16LE(_v5657C); - s.syncAsSint16LE(_v565E1); - s.syncAsSint16LE(_v565E3); + s.syncAsSint16LE(_electromagnetChangeAmount); + s.syncAsSint16LE(_electromagnetZoom); s.syncAsSint16LE(_v565E5); s.syncAsSint16LE(_v565E7); s.syncAsSint16LE(_v565E9); s.syncAsSint16LE(_v565EB); s.syncAsSint16LE(_v565F5); s.syncAsSint16LE(_v565F6); + s.syncAsSint16LE(_v565F8); s.syncAsSint16LE(_v565FA); s.syncAsSint16LE(_v566A3); s.syncAsSint16LE(_v566A6); @@ -525,7 +543,7 @@ void Ringworld2Globals::synchronize(Serializer &s) { s.syncAsByte(_v565EC[i]); for (i = 0; i < MAX_CHARACTERS; ++i) - s.syncAsByte(_v565F1[i]); + s.syncAsByte(_scannerFrequencies[i]); s.syncAsByte(_v565AE); s.syncAsByte(_v566A4); diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h index d190b6a2a4..ed27ff0556 100644 --- a/engines/tsage/globals.h +++ b/engines/tsage/globals.h @@ -247,28 +247,31 @@ namespace Ringworld2 { #define k5A790 18 #define k5A791 17 +class ScannerDialog; + class Ringworld2Globals: public TsAGE2Globals { public: ASoundExt _sound1, _sound2, _sound3, _sound4; PlayStream _playStream; StripProxy _stripProxy; - bool _v1000Flag; - byte _v1000[0x1000]; - byte _palIndexList[10][256]; + bool _fadePaletteFlag; + byte _fadePaletteMap[10][256]; + byte _paletteMap[4096]; int _insetUp; int _frameEdgeColour; // _v421e Rect _v5589E; Rect _v558B6; int _v558C2; int _animationCtr; - int _v565E1; - int _v565E3; + int _electromagnetChangeAmount; + int _electromagnetZoom; int _v565E5; int _v565E7; int _v565E9; int _v565EB; int _v565F5; int _v565F6; + int _v565F8; int _v565FA; int _v5657C; byte _v565AE; @@ -302,9 +305,12 @@ public: int _v57C2C; int _speechSubtitles; byte _v565EC[5]; - byte _v565F1[4]; + byte _scannerFrequencies[4]; byte _stripManager_lookupList[12]; + ScannerDialog *_scannerDialog; + Ringworld2Globals(); + virtual ~Ringworld2Globals(); virtual void reset(); virtual void synchronize(Serializer &s); }; diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp index fb0b0b0cbb..1815c3d751 100644 --- a/engines/tsage/graphics.cpp +++ b/engines/tsage/graphics.cpp @@ -47,7 +47,7 @@ GfxSurface *surfaceGetArea(GfxSurface &src, const Rect &bounds) { Graphics::Surface destSurface = dest->lockSurface(); byte *srcP = (byte *)srcSurface.getBasePtr(bounds.left, bounds.top); - byte *destP = (byte *)destSurface.getBasePtr(0, 0); + byte *destP = (byte *)destSurface.getPixels(); for (int y = bounds.top; y < bounds.bottom; ++y, srcP += srcSurface.pitch, destP += destSurface.pitch) Common::copy(srcP, srcP + destSurface.pitch, destP); @@ -76,7 +76,7 @@ GfxSurface surfaceFromRes(const byte *imgData) { const byte *srcP = imgData + 10; Graphics::Surface destSurface = s.lockSurface(); - byte *destP = (byte *)destSurface.getBasePtr(0, 0); + byte *destP = (byte *)destSurface.getPixels(); if (!rleEncoded) { Common::copy(srcP, srcP + (r.width() * r.height()), destP); @@ -234,9 +234,14 @@ GfxSurface::GfxSurface(const GfxSurface &s) { } GfxSurface::~GfxSurface() { + clear(); +} + +void GfxSurface::clear() { if (_customSurface) { _customSurface->free(); delete _customSurface; + _customSurface = NULL; } } @@ -289,8 +294,11 @@ void GfxSurface::addDirtyRect(const Rect &r) { r2.translate(_bounds.left, _bounds.top); // Add to the dirty rect list - _dirtyRects.push_back(Rect(r2.left, r2.top, - MIN(r2.right + 1, SCREEN_WIDTH), MIN(r2.bottom + 1, SCREEN_HEIGHT))); + r2.right = MIN(r2.right + 1, SCREEN_WIDTH); + r2.bottom = MIN(r2.bottom + 1, SCREEN_HEIGHT); + + if (r2.isValidRect()) + _dirtyRects.push_back(r2); } } @@ -308,7 +316,7 @@ void GfxSurface::create(int width, int height) { } _customSurface = new Graphics::Surface(); _customSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); - Common::fill((byte *)_customSurface->pixels, (byte *)_customSurface->pixels + (width * height), 0); + Common::fill((byte *)_customSurface->getPixels(), (byte *)_customSurface->getBasePtr(0, height), 0); _bounds = Rect(0, 0, width, height); } @@ -324,12 +332,7 @@ Graphics::Surface GfxSurface::lockSurface() { // Setup the returned surface either as one pointing to the same pixels as the source, or // as a subset of the source one based on the currently set bounds Graphics::Surface result; - result.w = _bounds.width(); - result.h = _bounds.height(); - result.pitch = src->pitch; - result.format = src->format; - result.pixels = src->getBasePtr(_bounds.left, _bounds.top); - + result.init(_bounds.width(), _bounds.height(), src->pitch, src->getBasePtr(_bounds.left, _bounds.top), src->format); return result; } @@ -355,7 +358,7 @@ void GfxSurface::synchronize(Serializer &s) { if (_customSurface) { s.syncAsSint16LE(_customSurface->w); s.syncAsSint16LE(_customSurface->h); - s.syncBytes((byte *)_customSurface->pixels, _customSurface->w * _customSurface->h); + s.syncBytes((byte *)_customSurface->getPixels(), _customSurface->w * _customSurface->h); } else { int zero = 0; s.syncAsSint16LE(zero); @@ -372,7 +375,7 @@ void GfxSurface::synchronize(Serializer &s) { _customSurface = NULL; } else { create(w, h); - s.syncBytes((byte *)_customSurface->pixels, w * h); + s.syncBytes((byte *)_customSurface->getPixels(), w * h); } } } @@ -409,8 +412,8 @@ GfxSurface &GfxSurface::operator=(const GfxSurface &s) { // Surface owns the internal data, so replicate it so new surface owns it's own _customSurface = new Graphics::Surface(); _customSurface->create(s._customSurface->w, s._customSurface->h, Graphics::PixelFormat::createFormatCLUT8()); - const byte *srcP = (const byte *)s._customSurface->getBasePtr(0, 0); - byte *destP = (byte *)_customSurface->getBasePtr(0, 0); + const byte *srcP = (const byte *)s._customSurface->getPixels(); + byte *destP = (byte *)_customSurface->getPixels(); Common::copy(srcP, srcP + (_bounds.width() * _bounds.height()), destP); } @@ -573,7 +576,7 @@ void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Regi Graphics::Surface destSurface = srcImage.lockSurface(); const byte *srcP = (const byte *)srcSurface.getBasePtr(srcBounds.left, srcBounds.top); - byte *destP = (byte *)destSurface.pixels; + byte *destP = (byte *)destSurface.getPixels(); for (int yp = srcBounds.top; yp < srcBounds.bottom; ++yp, srcP += srcSurface.pitch, destP += destSurface.pitch) { Common::copy(srcP, srcP + srcBounds.width(), destP); } @@ -790,35 +793,58 @@ void GfxElement::drawFrame() { lineP++; } } + + // Draw the edge frame + // Outer frame border + surface.hLine(tempRect.left + 2, tempRect.top, tempRect.right - 2, 0); + surface.hLine(tempRect.left + 2, tempRect.bottom, tempRect.right - 2, 0); + surface.vLine(tempRect.left, tempRect.top + 2, tempRect.bottom - 2, 0); + surface.vLine(tempRect.right, tempRect.top + 2, tempRect.bottom - 2, 0); + *((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.top + 1)) = 0; + *((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.top + 1)) = 0; + *((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.bottom - 1)) = 0; + *((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.bottom - 1)) = 0; + + // Inner frame border + surface.hLine(tempRect.left + 2, tempRect.top + 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColour); + surface.hLine(tempRect.left + 2, tempRect.bottom - 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColour); + surface.vLine(tempRect.left + 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColour); + surface.vLine(tempRect.right - 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColour); + *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColour; + *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColour; + *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColour; + *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColour; + gfxManager.unlockSurface(); + gfxManager.getSurface().addDirtyRect(tempRect); } else { // Fill dialog content with specified background colour gfxManager.fillRect(tempRect, _colors.background); - } - --tempRect.bottom; --tempRect.right; - gfxManager.fillArea(tempRect.left, tempRect.top, bgColor); - gfxManager.fillArea(tempRect.left, tempRect.bottom, fgColor); - gfxManager.fillArea(tempRect.right, tempRect.top, fgColor); - gfxManager.fillArea(tempRect.right, tempRect.bottom, fgColor); - - tempRect.collapse(-1, -1); - gfxManager.fillRect2(tempRect.left + 1, tempRect.top, tempRect.width() - 1, 1, bgColor); - gfxManager.fillRect2(tempRect.left, tempRect.top + 1, 1, tempRect.height() - 1, bgColor); - gfxManager.fillRect2(tempRect.left + 1, tempRect.bottom, tempRect.width() - 1, 1, fgColor); - gfxManager.fillRect2(tempRect.right, tempRect.top + 1, 1, tempRect.height() - 1, fgColor); - - gfxManager.fillArea(tempRect.left, tempRect.top, 0); - gfxManager.fillArea(tempRect.left, tempRect.bottom, 0); - gfxManager.fillArea(tempRect.right, tempRect.top, 0); - gfxManager.fillArea(tempRect.right, tempRect.bottom, 0); - - tempRect.collapse(-1, -1); - gfxManager.fillRect2(tempRect.left + 2, tempRect.top, tempRect.width() - 3, 1, 0); - gfxManager.fillRect2(tempRect.left, tempRect.top + 2, 1, tempRect.height() - 3, 0); - gfxManager.fillRect2(tempRect.left + 2, tempRect.bottom, tempRect.width() - 3, 1, 0); - gfxManager.fillRect2(tempRect.right, tempRect.top + 2, 1, tempRect.height() - 3, 0); + --tempRect.bottom; --tempRect.right; + gfxManager.fillArea(tempRect.left, tempRect.top, bgColor); + gfxManager.fillArea(tempRect.left, tempRect.bottom, fgColor); + gfxManager.fillArea(tempRect.right, tempRect.top, fgColor); + gfxManager.fillArea(tempRect.right, tempRect.bottom, fgColor); + + tempRect.collapse(-1, -1); + gfxManager.fillRect2(tempRect.left + 1, tempRect.top, tempRect.width() - 1, 1, bgColor); + gfxManager.fillRect2(tempRect.left, tempRect.top + 1, 1, tempRect.height() - 1, bgColor); + gfxManager.fillRect2(tempRect.left + 1, tempRect.bottom, tempRect.width() - 1, 1, fgColor); + gfxManager.fillRect2(tempRect.right, tempRect.top + 1, 1, tempRect.height() - 1, fgColor); + + gfxManager.fillArea(tempRect.left, tempRect.top, 0); + gfxManager.fillArea(tempRect.left, tempRect.bottom, 0); + gfxManager.fillArea(tempRect.right, tempRect.top, 0); + gfxManager.fillArea(tempRect.right, tempRect.bottom, 0); + + tempRect.collapse(-1, -1); + gfxManager.fillRect2(tempRect.left + 2, tempRect.top, tempRect.width() - 3, 1, 0); + gfxManager.fillRect2(tempRect.left, tempRect.top + 2, 1, tempRect.height() - 3, 0); + gfxManager.fillRect2(tempRect.left + 2, tempRect.bottom, tempRect.width() - 3, 1, 0); + gfxManager.fillRect2(tempRect.right, tempRect.top + 2, 1, tempRect.height() - 3, 0); + } gfxManager.unlockSurface(); } @@ -1322,6 +1348,12 @@ void GfxManager::copyFrom(GfxSurface &src, int destX, int destY) { _surface.copyFrom(src, destX, destY); } +void GfxManager::copyFrom(GfxSurface &src, const Rect &srcBounds, const Rect &destBounds) { + _surface.setBounds(_bounds); + + _surface.copyFrom(src, srcBounds, destBounds); +} + /*--------------------------------------------------------------------------*/ diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h index 826f2fef6f..7239a99a68 100644 --- a/engines/tsage/graphics.h +++ b/engines/tsage/graphics.h @@ -100,6 +100,7 @@ public: void unlockSurface(); void synchronize(Serializer &s); void create(int width, int height); + void clear(); void setBounds(const Rect &bounds) { _bounds = bounds; } const Rect &getBounds() const { return _bounds; } @@ -302,6 +303,7 @@ public: } void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL); void copyFrom(GfxSurface &src, int destX, int destY); + void copyFrom(GfxSurface &src, const Rect &srcBounds, const Rect &destBounds); GfxSurface &getSurface() { _surface.setBounds(_bounds); diff --git a/engines/tsage/ringworld/ringworld_scenes1.cpp b/engines/tsage/ringworld/ringworld_scenes1.cpp index 4d9d565705..89c07273fc 100644 --- a/engines/tsage/ringworld/ringworld_scenes1.cpp +++ b/engines/tsage/ringworld/ringworld_scenes1.cpp @@ -2273,6 +2273,7 @@ void Scene60::Item1::doAction(int action) { } else { scene->setAction(&scene->_action2); } + break; default: SceneHotspot::doAction(action); break; diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp index 478fdcf5a5..57fdef6405 100644 --- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp +++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp @@ -236,7 +236,7 @@ void CharacterDialog::show() { // Play a transition sound as the character is changed if (R2_GLOBALS._player._characterScene[0] != 300) { - switch (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex]) { + switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex]) { case 0: R2_GLOBALS._sound4.stop(); break; @@ -255,8 +255,8 @@ void CharacterDialog::show() { default: break; } - } else if (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex] > 1) { - switch (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex]) { + } else if (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] > 1) { + switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex]) { case 2: R2_GLOBALS._sound4.play(45); break; @@ -272,8 +272,8 @@ void CharacterDialog::show() { default: break; } - } else if ((R2_GLOBALS._player._characterScene[1] == 300) && (R2_GLOBALS._v565F1[1] != 1)) { - switch (R2_GLOBALS._v565F1[1]) { + } else if ((R2_GLOBALS._player._characterScene[1] == 300) && (R2_GLOBALS._scannerFrequencies[1] != 1)) { + switch (R2_GLOBALS._scannerFrequencies[1]) { case 2: R2_GLOBALS._sound4.play(45); break; @@ -291,10 +291,10 @@ void CharacterDialog::show() { } } else if (R2_GLOBALS._player._characterScene[2] != 300) { R2_GLOBALS._sound4.stop(); - } else if (R2_GLOBALS._v565F1[2] == 1) { + } else if (R2_GLOBALS._scannerFrequencies[2] == 1) { R2_GLOBALS._sound4.stop(); } else { - switch (R2_GLOBALS._v565F1[1]) { + switch (R2_GLOBALS._scannerFrequencies[1]) { case 2: R2_GLOBALS._sound4.play(45); break; diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp index 97042cb621..2a8e50bd67 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.cpp +++ b/engines/tsage/ringworld2/ringworld2_logic.cpp @@ -21,6 +21,8 @@ */ #include "common/config-manager.h" +#include "common/rect.h" +#include "tsage/graphics.h" #include "tsage/scenes.h" #include "tsage/tsage.h" #include "tsage/staticres.h" @@ -86,8 +88,10 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { // Cutscene - Walking in hall return new Scene525(); case 600: + // Drive Room return new Scene600(); case 700: + // Lander Bay 2 return new Scene700(); case 800: // Sick bay @@ -99,11 +103,13 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { // Deck #5 - By Lift return new Scene850(); case 900: + // Lander Bay 2 - Crane Controls return new Scene900(); /* Scene group #1 */ // case 1000: - error("Missing scene %d from group 1", sceneNumber); + // Cutscene scene + return new Scene1000(); case 1010: // Cutscene - trip in space return new Scene1010(); @@ -166,7 +172,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { // Ice Maze: Large empty room return new Scene2400(); case 2425: - // Ice Maze: + // Ice Maze: The Hall of Records return new Scene2425(); case 2430: // Ice Maze: Bedroom @@ -213,7 +219,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { case 2900: error("Missing scene %d from group 2", sceneNumber); /* Scene group #3 */ - // + // ARM Base Hanager case 3100: return new Scene3100(); case 3125: @@ -258,16 +264,22 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { // Cutscene - Ship landing return new Scene3350(); case 3375: + // Outer walkway return new Scene3375(); case 3385: + // Corridor return new Scene3385(); case 3395: + // Walkway return new Scene3395(); case 3400: + // Confrontation return new Scene3400(); case 3500: + // Maze action sequencec return new Scene3500(); case 3600: + // Cutscene - walking at gunpoint return new Scene3600(); case 3700: // Cutscene - Teleport outside @@ -311,6 +323,12 @@ SceneExt::SceneExt(): Scene() { _savedUiEnabled = false; _savedCanWalk = false; _focusObject = NULL; + + // WORKAROUND: In the original, playing animations don't reset the global _animationCtr + // counter as scene changes unless the playing animation explicitly finishes. For now, + // to make inter-scene debugging easier, I'm explicitly resetting the _animationCtr + // on scene start, since scene objects aren't drawn while it's non-zero + R2_GLOBALS._animationCtr = 0; } void SceneExt::postInit(SceneObjectList *OwnerList) { @@ -328,8 +346,7 @@ void SceneExt::postInit(SceneObjectList *OwnerList) { int sceneNumber = R2_GLOBALS._sceneManager._sceneNumber; if (((prevScene == -1) && (sceneNumber != 180) && (sceneNumber != 205) && (sceneNumber != 50)) || (sceneNumber == 50) - || ((prevScene == 205) && (sceneNumber == 100)) - || ((prevScene == 180) && (sceneNumber == 100))) { + || ((sceneNumber == 100) && (prevScene == 0 || prevScene == 180 || prevScene == 205))) { static_cast<SceneHandlerExt *>(R2_GLOBALS._sceneHandler)->setupPaletteMaps(); R2_GLOBALS._uiElements._active = true; R2_GLOBALS._uiElements.show(); @@ -341,6 +358,7 @@ void SceneExt::postInit(SceneObjectList *OwnerList) { void SceneExt::remove() { _sceneAreas.clear(); Scene::remove(); + R2_GLOBALS._uiElements._active = true; } void SceneExt::process(Event &event) { @@ -407,17 +425,19 @@ bool SceneExt::display(CursorType action, Event &event) { SceneItem::display2(5, 0); break; case R2_SONIC_STUNNER: - if ((R2_GLOBALS._v565F1[1] == 2) || ((R2_GLOBALS._v565F1[1] == 1) && - (R2_GLOBALS._v565F1[2] == 2) && (R2_GLOBALS._sceneManager._previousScene == 300))) { + if ((R2_GLOBALS._scannerFrequencies[R2_QUINN] == 2) + || ((R2_GLOBALS._scannerFrequencies[R2_QUINN] == 1) && + (R2_GLOBALS._scannerFrequencies[R2_SEEKER] == 2) && + (R2_GLOBALS._sceneManager._previousScene == 300))) { R2_GLOBALS._sound4.stop(); R2_GLOBALS._sound3.play(46); SceneItem::display2(5, 15); + + R2_GLOBALS._sound4.play(45); } else { R2_GLOBALS._sound3.play(43, 0); - SceneItem::display2(2, 0); + SceneItem::display2(2, R2_SONIC_STUNNER); } - - R2_GLOBALS._sound4.play(45); break; case R2_COM_SCANNER: case R2_COM_SCANNER_2: @@ -509,7 +529,7 @@ void SceneExt::refreshBackground(int xAmount, int yAmount) { assert(screenSize == (s.w * s.h)); // Copy the data - byte *destP = (byte *)s.getBasePtr(0, 0); + byte *destP = (byte *)s.getPixels(); Common::copy(dataP, dataP + (s.w * s.h), destP); _backSurface.unlockSurface(); @@ -557,6 +577,13 @@ void SceneExt::scalePalette(int RFactor, int GFactor, int BFactor) { } } +void SceneExt::loadBlankScene() { + _backSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT * 3 / 2); + _backSurface.fillRect(_backSurface.getBounds(), 0); + + R2_GLOBALS._screenSurface.fillRect(R2_GLOBALS._screenSurface.getBounds(), 0); +} + /*--------------------------------------------------------------------------*/ void SceneHandlerExt::postInit(SceneObjectList *OwnerList) { @@ -573,7 +600,7 @@ void SceneHandlerExt::process(Event &event) { SceneExt *scene = static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene); if (scene && R2_GLOBALS._player._uiEnabled) { // Handle any scene areas that have been registered - SynchronizedList<SceneArea *>::iterator saIter; + SynchronizedList<EventHandler *>::iterator saIter; for (saIter = scene->_sceneAreas.begin(); saIter != scene->_sceneAreas.end() && !event.handled; ++saIter) { (*saIter)->process(event); } @@ -583,11 +610,32 @@ void SceneHandlerExt::process(Event &event) { SceneHandler::process(event); } +void SceneHandlerExt::postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) { + if (priorSceneBeforeLoad == -1 || priorSceneBeforeLoad == 50 + || priorSceneBeforeLoad == 180 || priorSceneBeforeLoad == 205) + setupPaletteMaps(); + + if (currentSceneBeforeLoad == 2900) { + R2_GLOBALS._gfxFontNumber = 50; + R2_GLOBALS._gfxColors.background = 0; + R2_GLOBALS._gfxColors.foreground = 59; + R2_GLOBALS._fontColors.background = 4; + R2_GLOBALS._fontColors.foreground = 15; + R2_GLOBALS._frameEdgeColour = 2; + + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._scenePalette.setEntry(255, 0xff, 0xff, 0xff); + R2_GLOBALS._fadePaletteFlag = false; + setupPaletteMaps(); + } +} + void SceneHandlerExt::setupPaletteMaps() { byte *palP = &R2_GLOBALS._scenePalette._palette[0]; - if (!R2_GLOBALS._v1000Flag) { - R2_GLOBALS._v1000Flag = true; + // Set up the mapping table for giving faded versions of pixels at different fade percentages + if (!R2_GLOBALS._fadePaletteFlag) { + R2_GLOBALS._fadePaletteFlag = true; for (int idx = 0; idx < 10; ++idx) { for (int palIndex = 0; palIndex < 224; ++palIndex) { @@ -637,18 +685,19 @@ void SceneHandlerExt::setupPaletteMaps() { foundIndex = pIndex2; } - R2_GLOBALS._palIndexList[idx][palIndex] = foundIndex; + R2_GLOBALS._fadePaletteMap[idx][palIndex] = foundIndex; } } } for (int palIndex = 0; palIndex < 224; ++palIndex) { - int r = palP[palIndex * 3] >> 2; - int g = palP[palIndex * 3 + 1] >> 2; - int b = palP[palIndex * 3 + 2] >> 2; + int r = palP[palIndex * 3] >> 4; + int g = palP[palIndex * 3 + 1] >> 4; + int b = palP[palIndex * 3 + 2] >> 4; - int idx = (((r << 4) | g) << 4) | b; - R2_GLOBALS._v1000[idx] = palIndex; + int v = (r << 8) | (g << 4) | b; + assert(v < 0x1000); + R2_GLOBALS._paletteMap[v] = palIndex; } int vdx = 0; @@ -656,9 +705,9 @@ void SceneHandlerExt::setupPaletteMaps() { int palIndex = 224; for (int vIndex = 0; vIndex < 4096; ++vIndex) { - int v = R2_GLOBALS._v1000[vIndex]; + int v = R2_GLOBALS._paletteMap[vIndex]; if (!v) { - R2_GLOBALS._v1000[vIndex] = idx; + R2_GLOBALS._paletteMap[vIndex] = idx; } else { idx = v; } @@ -842,6 +891,7 @@ Ringworld2InvObjectList::Ringworld2InvObjectList(): _itemList.push_back(&_inv52); _selectedItem = NULL; + } void Ringworld2InvObjectList::reset() { @@ -904,6 +954,9 @@ void Ringworld2InvObjectList::reset() { setObjectScene(R2_ALCOHOL_LAMP_3, 2435); setObjectScene(R2_BROKEN_DISPLAY, 1580); setObjectScene(R2_TOOLBOX, 3260); + + // Set up the select item handler method + T2_GLOBALS._onSelectItem = SelectItem; } void Ringworld2InvObjectList::setObjectScene(int objectNum, int sceneNumber) { @@ -921,6 +974,127 @@ void Ringworld2InvObjectList::setObjectScene(int objectNum, int sceneNumber) { T2_GLOBALS._uiElements.updateInventory(); } +/** + * When an inventory item is selected, in Return to Ringworld two objects can be combined + */ +bool Ringworld2InvObjectList::SelectItem(int objectNumber) { + // If no existing item selected, don't go any further + int currentItem = R2_GLOBALS._events.getCursor(); + if (currentItem >= 256) + return false; + + switch (objectNumber) { + case R2_NEGATOR_GUN: + switch (currentItem) { + case R2_SENSOR_PROBE: + if (R2_GLOBALS.getFlag(1)) + SceneItem::display2(5, 1); + else if (R2_INVENTORY.getObjectScene(R2_SPENT_POWER_CAPSULE) != 100) + SceneItem::display2(5, 3); + else { + R2_GLOBALS._sound3.play(48); + SceneItem::display2(5, 2); + R2_INVENTORY.setObjectScene(R2_SPENT_POWER_CAPSULE, 1); + } + break; + case R2_COM_SCANNER: + R2_GLOBALS._sound3.play(44); + if (R2_GLOBALS.getFlag(1)) + SceneItem::display2(5, 9); + else if (R2_INVENTORY.getObjectScene(R2_SPENT_POWER_CAPSULE) == 100) + SceneItem::display2(5, 8); + else + SceneItem::display2(5, 10); + + R2_GLOBALS._sound3.stop(); + break; + case R2_CHARGED_POWER_CAPSULE: + if (R2_INVENTORY.getObjectScene(R2_SPENT_POWER_CAPSULE) == 1) { + R2_GLOBALS._sound3.play(49); + R2_INVENTORY.setObjectScene(R2_CHARGED_POWER_CAPSULE, 100); + R2_GLOBALS.setFlag(1); + SceneItem::display2(5, 4); + } else { + SceneItem::display2(5, 5); + } + break; + default: + selectDefault(objectNumber); + break; + } + break; + case R2_STEPPING_DISKS: + switch (currentItem) { + case R2_SENSOR_PROBE: + if (R2_INVENTORY.getObjectScene(R2_CHARGED_POWER_CAPSULE) == 400) { + R2_GLOBALS._sound3.play(48); + SceneItem::display2(5, 6); + R2_INVENTORY.setObjectScene(R2_CHARGED_POWER_CAPSULE, 1); + } else { + SceneItem::display2(5, 7); + } + break; + case R2_COM_SCANNER: + R2_GLOBALS._sound3.play(44); + if (R2_INVENTORY.getObjectScene(R2_CHARGED_POWER_CAPSULE) == 400) + SceneItem::display2(5, 16); + else + SceneItem::display2(5, 17); + R2_GLOBALS._sound3.stop(); + break; + default: + selectDefault(objectNumber); + break; + } + break; + case R2_ATTRACTOR_UNIT: + case R2_CABLE_HARNESS: + if (currentItem == R2_CABLE_HARNESS || + currentItem == R2_ATTRACTOR_UNIT) { + R2_INVENTORY.setObjectScene(R2_CABLE_HARNESS, 0); + R2_INVENTORY.setObjectScene(R2_ATTRACTOR_UNIT, 0); + R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 1); + } else { + selectDefault(objectNumber); + } + break; + case R2_TANNER_MASK: + case R2_PURE_GRAIN_ALCOHOL: + if (currentItem == R2_TANNER_MASK || + currentItem == R2_PURE_GRAIN_ALCOHOL) { + R2_INVENTORY.setObjectScene(R2_TANNER_MASK, 0); + R2_INVENTORY.setObjectScene(R2_PURE_GRAIN_ALCOHOL, 0); + R2_INVENTORY.setObjectScene(R2_SOAKED_FACEMASK, 1); + } else { + selectDefault(objectNumber); + } + break; + default: + // Standard item selection + return false; + } + + return true; +} + +void Ringworld2InvObjectList::selectDefault(int objectNumber) { + Common::String msg1 = g_resourceManager->getMessage(4, 53); + Common::String msg2 = g_resourceManager->getMessage(4, R2_GLOBALS._events.getCursor()); + Common::String msg3 = g_resourceManager->getMessage(4, 54); + Common::String msg4 = g_resourceManager->getMessage(4, objectNumber); + Common::String line = Common::String::format("%.5s%.5s%.5s%.5s%s %s %s %s.", + msg1.c_str(), msg2.c_str(), msg3.c_str(), msg4.c_str(), + msg1.c_str() + 5, msg2.c_str() + 5, msg3.c_str() + 5, msg4.c_str() + 5); + + SceneItem::display(-1, -1, line.c_str(), + SET_WIDTH, 280, + SET_X, 160, + SET_Y, 20, + SET_POS_MODE, 1, + SET_EXT_BGCOLOR, 7, + LIST_END); +} + /*--------------------------------------------------------------------------*/ void Ringworld2Game::start() { @@ -1083,6 +1257,14 @@ void SceneActor::postInit(SceneObjectList *OwnerList) { SceneObject::postInit(); } +void SceneActor::remove() { + R2_GLOBALS._sceneItems.remove(this); + _field9C = NULL; + _linkedActor = NULL; + + SceneObject::remove(); +} + bool SceneActor::startAction(CursorType action, Event &event) { bool handled = true; @@ -1115,6 +1297,32 @@ bool SceneActor::startAction(CursorType action, Event &event) { return handled; } +GfxSurface SceneActor::getFrame() { + GfxSurface frame = SceneObject::getFrame(); + + // TODO: Proper effects handling + switch (_effect) { + case 0: + case 5: + // TODO: Figure out purpose of setting image flags to 64, and getting + // scene priorities -1 or _shade + break; + case 1: + // TODO: Transposing using R2_GLOBALS._pixelArrayMap + break; + case 2: + // No effect + break; + case 4: + break; + default: + // TODO: Default effect + break; + } + + return frame; +} + /*--------------------------------------------------------------------------*/ SceneArea::SceneArea(): EventHandler() { @@ -1268,287 +1476,206 @@ void SceneAreaObject::setDetails(int resNum, int lookLineNum, int talkLineNum, i /*****************************************************************************/ -UnkObject1200::UnkObject1200() { - _field16 = _field3A = NULL; - _field12 = _field14 = 0; - _field26 = _field28 = _field2A = _field2C = _field2E = _field30 = 0; - _field32 = _field34 = _field36 = _field38 = _field3E = _field40 = 0; +MazeUI::MazeUI() { + _mapData = NULL; + _cellsVisible.x = _cellsVisible.y = 0; + _mapCells.x = _mapCells.y = 0; + _cellSize.x = _cellSize.y = 0; + _mapOffset.x = _mapOffset.y = 0; + _resNum = _cellsResNum = 0; + _frameCount = _resCount = _mapImagePitch = _unused = 0; } -void UnkObject1200::synchronize(Serializer &s) { - SavedObject::synchronize(s); +MazeUI::~MazeUI() { + DEALLOCATE(_mapData); +} - _rect1.synchronize(s); - _rect2.synchronize(s); +void MazeUI::synchronize(Serializer &s) { + SavedObject::synchronize(s); - // FIXME: syncrhonize _field16 and _field3A + s.syncAsSint16LE(_resNum); + if (s.isLoading()) + load(_resNum); - s.syncAsSint16LE(_field12); - s.syncAsSint16LE(_field14); - s.syncAsSint16LE(_field26); - s.syncAsSint16LE(_field28); - s.syncAsSint16LE(_field2A); - s.syncAsSint16LE(_field2C); - s.syncAsSint16LE(_field2E); - s.syncAsSint16LE(_field30); - s.syncAsSint16LE(_field32); - s.syncAsSint16LE(_field34); - s.syncAsSint16LE(_field36); - s.syncAsSint16LE(_field38); - s.syncAsSint16LE(_field3E); - s.syncAsSint16LE(_field40); + s.syncAsSint16LE(_mapOffset.x); + s.syncAsSint16LE(_mapOffset.y); + s.syncAsSint16LE(_unused); } -void UnkObject1200::sub51AE9(int arg1) { - warning("STUB: UnkObject1200::sub51AE9()"); -} +void MazeUI::load(int resNum) { + postInit(); + clear(); + _resNum = resNum; -int UnkObject1200::sub51AF8(Common::Point pt) { - if (!_rect1.contains(pt)) - return -1; + const byte *header = g_resourceManager->getResource(RT17, resNum, 0); - int tmp1 = (pt.x - _rect1.left + _field2E) / _field2A; - int tmp2 = (pt.y - _rect1.top + _field30) / _field2C; + _cellsResNum = resNum + 1000; + _mapCells.x = READ_LE_UINT16(header + 2); + _mapCells.y = READ_LE_UINT16(header + 4); + _frameCount = 10; + _resCount = _frameCount << 3; - if ((tmp1 >= 0) && (tmp2 >= 0) && (_field26 > tmp1) && (_field28 > tmp2)) - return _field16[(((_field26 * tmp2) + tmp1)* 2)]; + Visage visage; + visage.setVisage(_cellsResNum, 1); - return -1; + GfxSurface frame = visage.getFrame(2); + _cellSize.x = frame.getBounds().width(); + _cellSize.y = frame.getBounds().height(); + + _mapData = g_resourceManager->getResource(RT17, resNum, 1); + + _mapOffset.y = _mapOffset.x = 0; + _cellsVisible.x = (_bounds.width() + _cellSize.x - 1) / _cellSize.x; + _cellsVisible.y = (_bounds.height() + _cellSize.y - 1) / _cellSize.y; + + _mapImagePitch = (_cellsVisible.x + 1) * _cellSize.x; + _mapImage.create(_mapImagePitch, _cellSize.y); + + _mapBounds = Rect(0, 0, _cellSize.x * _mapCells.x, _cellSize.y * _mapCells.y); } -bool UnkObject1200::sub51AFD(Common::Point pt) { - int retval = false; +void MazeUI::clear() { + if (!_resNum) + _resNum = 1; - _field2E = pt.x; - _field30 = pt.y; + if (_mapData) + DEALLOCATE(_mapData); + _mapData = NULL; + + _mapImage.clear(); +} - if (_field2E < _rect2.top) { - _field2E = _rect2.top; +bool MazeUI::setMazePosition(const Common::Point &pt) { + bool retval = false; + + _mapOffset = pt; + + if (_mapOffset.x < _mapBounds.top) { + _mapOffset.x = _mapBounds.top; retval = true; } - if (_field30 < _rect2.left) { - _field30 = _rect2.left; + if (_mapOffset.y < _mapBounds.left) { + _mapOffset.y = _mapBounds.left; retval = true; } - if (_field2E + _rect1.width() > _rect2.right) { - _field2E = _rect2.right - _rect1.width(); + if (_mapOffset.x + _bounds.width() > _mapBounds.right) { + _mapOffset.x = _mapBounds.right - _bounds.width(); retval = true; } - if (_field30 + _rect1.height() > _rect2.bottom) { - _field30 = _rect2.bottom - _rect1.height(); + if (_mapOffset.y + _bounds.height() > _mapBounds.bottom) { + _mapOffset.y = _mapBounds.bottom - _bounds.height(); retval = true; } return retval; } -void UnkObject1200::sub51B02() { - warning("STUB: UnkObject1200::sub51B02()"); +void MazeUI::reposition() { } -void UnkObject1200::sub9EDE8(Rect rect) { - _rect1 = rect; - warning("FIXME: UnkObject1200::sub9EDE8()"); -// _rect1.clip(g_globals->gfxManager()._bounds); -} +void MazeUI::draw() { + int yPos = 0; + int ySize; + Visage visage; -int UnkObject1200::sub9EE22(int &arg1, int &arg2) { - arg1 /= _field2A; - arg2 /= _field2C; + _cellsVisible.y = ((_mapOffset.y % _cellSize.y) + _bounds.height() + + (_cellSize.y - 1)) / _cellSize.y; - if ((arg1 >= 0) && (arg2 >= 0) && (_field26 > arg1) && (_field28 > arg2)) { - return _field16[(((_field26 * arg2) + arg1) * 2)]; - } + // Loop to handle the cell rows of the visible display area one at a time + for (int yCtr = 0; yCtr < _cellsVisible.y; ++yCtr, yPos += ySize) { + int cellY = _mapOffset.y / _cellSize.y + yCtr; - return -1; -} + // Loop to iterate through the horizontal visible cells to build up + // an entire cell high horizontal slice of the map + for (int xCtr = 0; xCtr < _cellsVisible.x; ++xCtr) { + int cellX = _mapOffset.x / _cellSize.x + xCtr; -void Scene1200::sub9DAD6(int indx) { - _object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4); + // Get the type of content to display in the cell + int cell = getCellFromCellXY(Common::Point(cellX, cellY)) - 1; + if (cell >= 0) { + int frameNum = (cell % _frameCount) + 1; + int rlbNum = (cell % _resCount) / _frameCount + 1; + int resNum = _cellsResNum + (cell / _resCount); - switch (indx) { - case 0: - if ( ((_object1.sub51AF8(Common::Point(200, 50)) > 36) || (_object1.sub51AF8(Common::Point(200, 88)) > 36)) - && ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33) && (_field418 != 4)) - || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21) && (_field418 != 2)) - || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17) && (_field418 != 1)) - || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41)) ) - ) { - R2_GLOBALS._player.disableControl(); - _sceneMode = 1200; - setAction(&_sequenceManager, this, 1200, &_actor1, NULL); - } else if (_object1.sub51AF8(Common::Point(200, 69)) == 36) { - switch (_field412 - 1) { - case 0: - if (R2_GLOBALS._player._visage == 3155) - _sceneMode = 15; - else - _sceneMode = 10; - break; - case 1: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 76; - else - _sceneMode = 75; - break; - case 2: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 101; - else - _sceneMode = 100; - break; - case 3: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 111; - else - _sceneMode = 110; - break; - default: - break; - } - R2_GLOBALS._player.disableControl(); - _field412 = 1; - signal(); - } - break; - case 1: - if ( ((_object1.sub51AF8(Common::Point(120, 50)) > 36) || (_object1.sub51AF8(Common::Point(120, 88)) > 36)) - && ( ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33) && (_field418 != 4)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21) && (_field418 != 2)) - || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17) && (_field418 != 1)) - || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5)) ) - ) { - R2_GLOBALS._player.disableControl(); - _sceneMode = 1201; - setAction(&_sequenceManager, this, 1201, &_actor1, NULL); - } else if (_object1.sub51AF8(Common::Point(120, 69)) == 36) { - switch (_field412 - 1) { - case 0: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 56; - else - _sceneMode = 55; - break; - case 1: - if (R2_GLOBALS._player._visage == 3155) - _sceneMode = 25; - else - _sceneMode = 20; - break; - case 2: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 91; - else - _sceneMode = 90; - break; - case 3: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 121; - else - _sceneMode = 120; - break; - default: - break; - } - R2_GLOBALS._player.disableControl(); - _field412 = 2; - signal(); - } - break; - case 2: - if ( ((_object1.sub51AF8(Common::Point(140, 110)) > 36) || (_object1.sub51AF8(Common::Point(178, 110)) > 36)) - && ( ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5) && (_field418 != 3)) - || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) ) - ) { - R2_GLOBALS._player.disableControl(); - _sceneMode = 1203; - setAction(&_sequenceManager, this, 1203, &_actor1, NULL); - } else if (_object1.sub51AF8(Common::Point(160, 110)) == 36) { - switch (_field412 - 1) { - case 0: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 51; - else - _sceneMode = 50; - break; - case 1: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 81; - else - _sceneMode = 80; - break; - case 2: - if (R2_GLOBALS._player._visage == 3155) - _sceneMode = 35; - else - _sceneMode = 30; - break; - case 3: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 116; - else - _sceneMode = 115; - break; - default: - break; + visage.setVisage(resNum, rlbNum); + GfxSurface frame = visage.getFrame(frameNum); + + _mapImage.copyFrom(frame, xCtr * _cellSize.x, 0); + } else { + GfxSurface emptyRect; + emptyRect.create(_cellSize.x, _cellSize.y); + + _mapImage.copyFrom(emptyRect, xCtr * _cellSize.x, 0); } - R2_GLOBALS._player.disableControl(); - _field412 = 3; - signal(); } - break; - case 3: - if ( ((_object1.sub51AF8(Common::Point(140, 30)) > 36) || (_object1.sub51AF8(Common::Point(178, 30)) > 36)) - && ( ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9) && (_field418 != 3)) - || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17)) ) - ) { - R2_GLOBALS._player.disableControl(); - _sceneMode = 1202; - setAction(&_sequenceManager, this, 1202, &_actor1, NULL); - } else if (_object1.sub51AF8(Common::Point(160, 30)) == 36) { - switch (_field412 - 1) { - case 0: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 61; - else - _sceneMode = 60; - break; - case 1: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 71; - else - _sceneMode = 70; - break; - case 2: - if (R2_GLOBALS._player._visage == 3156) - _sceneMode = 96; - else - _sceneMode = 95; - break; - case 3: - if (R2_GLOBALS._player._visage == 3155) - _sceneMode = 45; - else - _sceneMode = 40; - break; - default: - _sceneMode = 1; - R2_GLOBALS._player.setup(3156, 4, 6); - break; + + if (yPos == 0) { + // First line of the map to be displayed - only the bottom portion of that + // first cell row may be visible + yPos = _bounds.top; + ySize = _cellSize.y - (_mapOffset.y % _cellSize.y); + + Rect srcBounds(_mapOffset.x % _cellSize.x, _mapOffset.y % _cellSize.y, + (_mapOffset.x % _cellSize.x) + _bounds.width(), _cellSize.y); + Rect destBounds(_bounds.left, yPos, _bounds.right, yPos + ySize); + + R2_GLOBALS.gfxManager().copyFrom(_mapImage, srcBounds, destBounds); + } else { + if ((yPos + _cellSize.y) < _bounds.bottom) { + ySize = _cellSize.y; + } else { + ySize = _bounds.bottom - yPos; } - R2_GLOBALS._player.disableControl(); - _field412 = 4; - signal(); + + Rect srcBounds(_mapOffset.x % _cellSize.x, 0, + (_mapOffset.x % _cellSize.x) + _bounds.width(), ySize); + Rect destBounds(_bounds.left, yPos, _bounds.right, yPos + ySize); + + R2_GLOBALS.gfxManager().copyFrom(_mapImage, srcBounds, destBounds); } - break; - default: - break; } } +int MazeUI::getCellFromPixelXY(const Common::Point &pt) { + if (!_bounds.contains(pt)) + return -1; + + int cellX = (pt.x - _bounds.left + _mapOffset.x) / _cellSize.x; + int cellY = (pt.y - _bounds.top + _mapOffset.y) / _cellSize.y; + + if ((cellX >= 0) && (cellY >= 0) && (cellX < _mapCells.x) && (cellY < _mapCells.y)) + return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * cellY + cellX) * 2); + + return -1; +} + +int MazeUI::getCellFromCellXY(const Common::Point &p) { + if (p.x < 0 || p.y < 0 || p.x >= _mapCells.x || p.y >= _mapCells.y) { + return -1; + } else { + return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * p.y + p.x) * 2); + } +} + +int MazeUI::pixelToCellXY(Common::Point &pt) { + pt.x /= _cellSize.x; + pt.y /= _cellSize.y; + + if ((pt.x >= 0) && (pt.y >= 0) && (pt.x < _mapCells.x) && (pt.y < _mapCells.y)) { + return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * pt.y + pt.x) * 2); + } + + return -1; +} + +void MazeUI::setDisplayBounds(const Rect &r) { + _bounds = r; + _bounds.clip(g_globals->gfxManager()._bounds); +} + /*--------------------------------------------------------------------------*/ void AnimationSlice::load(Common::File &f) { @@ -1637,7 +1764,7 @@ AnimationPlayer::~AnimationPlayer() { void AnimationPlayer::synchronize(Serializer &s) { EventHandler::synchronize(s); - warning("TODO AnimationPlayer::load"); + warning("TODO AnimationPlayer::synchronize"); } void AnimationPlayer::remove() { @@ -2001,6 +2128,349 @@ void AnimationPlayerExt::synchronize(Serializer &s) { s.syncAsSint16LE(_v); } +/*--------------------------------------------------------------------------*/ + +ModalWindow::ModalWindow() { + _field20 = 0; +} + +void ModalWindow::remove() { + R2_GLOBALS._sceneItems.remove(&_object1); + _object1.remove(); + + SceneArea::remove(); + + --R2_GLOBALS._insetUp; +} + +void ModalWindow::synchronize(Serializer &s) { + SceneArea::synchronize(s); + + s.syncAsByte(_field20); +} + +void ModalWindow::process(Event &event) { + if (_field20 != R2_GLOBALS._insetUp) + return; + + CursorType cursor = R2_GLOBALS._events.getCursor(); + + if (_object1._bounds.contains(event.mousePos.x + g_globals->gfxManager()._bounds.left , event.mousePos.y)) { + if (cursor == _cursorNum) { + R2_GLOBALS._events.setCursor(_savedCursorNum); + } + } else if (event.mousePos.y < 168) { + if (cursor != _cursorNum) { + _savedCursorNum = cursor; + R2_GLOBALS._events.setCursor(CURSOR_INVALID); + } + if (event.eventType == EVENT_BUTTON_DOWN) { + event.handled = true; + R2_GLOBALS._events.setCursor(_savedCursorNum); + remove(); + } + } +} + +void ModalWindow::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) { + Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; + + _object1.postInit(); + _object1.setup(visage, stripFrameNum, frameNum); + _object1.setPosition(Common::Point(posX, posY)); + _object1.fixPriority(250); + _cursorNum = CURSOR_INVALID; + scene->_sceneAreas.push_front(this); + ++R2_GLOBALS._insetUp; + _field20 = R2_GLOBALS._insetUp; +} + +void ModalWindow::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) { + _object1.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL); +} + +/*--------------------------------------------------------------------------*/ + +ScannerDialog::Button::Button() { + _buttonId = 0; + _buttonDown = false; +} + +void ScannerDialog::Button::setup(int buttonId) { + _buttonId = buttonId; + _buttonDown = false; + SceneActor::postInit(); + + SceneObject::setup(4, 2, 2); + fixPriority(255); + + if (_buttonId == 1) + setPosition(Common::Point(141, 99)); + else if (_buttonId == 2) + setPosition(Common::Point(141, 108)); + + static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene)->_sceneAreas.push_front(this); +} + +void ScannerDialog::Button::synchronize(Serializer &s) { + SceneActor::synchronize(s); + s.syncAsSint16LE(_buttonId); +} + +void ScannerDialog::Button::process(Event &event) { + if (event.eventType == EVENT_BUTTON_DOWN && R2_GLOBALS._events.getCursor() == CURSOR_USE + && _bounds.contains(event.mousePos) && !_buttonDown) { + setFrame(3); + _buttonDown = true; + event.handled = true; + } + + if (event.eventType == EVENT_BUTTON_UP && _buttonDown) { + setFrame(2); + _buttonDown = false; + event.handled = true; + + reset(); + } +} + +bool ScannerDialog::Button::startAction(CursorType action, Event &event) { + if (action == CURSOR_USE) + return false; + + return startAction(action, event); +} + +void ScannerDialog::Button::reset() { + Scene *scene = R2_GLOBALS._sceneManager._scene; + ScannerDialog &scanner = *R2_GLOBALS._scannerDialog; + + switch (_buttonId) { + case 1: + // Talk button + switch (R2_GLOBALS._sceneManager._sceneNumber) { + case 1550: + scene->_sceneMode = 80; + scene->signal(); + break; + case 1700: + scene->_sceneMode = 30; + scene->signal(); + remove(); + break; + default: + break; + } + break; + case 2: + // Scan button + switch (R2_GLOBALS._sceneManager._sceneNumber) { + case 1550: + scanner._obj4.setup(4, 3, 1); + + scanner._obj5.postInit(); + scanner._obj5.setup(4, 4, 1); + scanner._obj5.setPosition(Common::Point(R2_GLOBALS._v565EC[1] + 145, + R2_GLOBALS._v565EC[3] + 59)); + scanner._obj5.fixPriority(257); + + scanner._obj6.postInit(); + scanner._obj6.setup(4, 4, 2); + scanner._obj6.setPosition(Common::Point(R2_GLOBALS._v565EC[2] + 145, + R2_GLOBALS._v565EC[4] + 59)); + scanner._obj6.fixPriority(257); + break; + case 1700: + case 1800: + if (R2_GLOBALS._v565F8 < 0 || (R2_GLOBALS._v565F8 == 0 && R2_GLOBALS._v565F6 < 1201)) + scanner._obj4.setup(4, 3, 3); + else if (R2_GLOBALS._v565F8 > 0 || (R2_GLOBALS._v565F8 == 0 && R2_GLOBALS._v565F6 < 1201)) + scanner._obj4.setup(4, 3, 4); + else + scanner._obj4.setup(4, 3, 5); + break; + case 3800: + case 3900: + if ((R2_GLOBALS._v56A93 + 1) == 0 && R2_GLOBALS._v566A9 == 0) { + do { + R2_GLOBALS._v566A9 = R2_GLOBALS._randomSource.getRandomNumber(3); + } while (R2_GLOBALS._v566A9 == R2_GLOBALS._v566AA); + } + + scanner._obj4.setup(4, 7, R2_GLOBALS._v566A9); + if (!R2_GLOBALS.getFlag(46)) + R2_GLOBALS.setFlag(46); + break; + default: + scanner._obj4.setup(4, 3, 2); + break; + } + break; + default: + break; + } +} + +/*--------------------------------------------------------------------------*/ + +ScannerDialog::Slider::Slider() { + _initial = _xStart = _yp = 0; + _width = _xInc = 0; + _sliderDown = false; +} + +void ScannerDialog::Slider::synchronize(Serializer &s) { + SceneActor::synchronize(s); + + s.syncAsSint16LE(_initial); + s.syncAsSint16LE(_xStart); + s.syncAsSint16LE(_yp); + s.syncAsSint16LE(_width); + s.syncAsSint16LE(_xInc); +} + +void ScannerDialog::Slider::remove() { + static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene)->_sceneAreas.remove(this); + SceneActor::remove(); +} + +void ScannerDialog::Slider::process(Event &event) { + if (event.eventType == EVENT_BUTTON_DOWN && R2_GLOBALS._events.getCursor() == CURSOR_USE + && _bounds.contains(event.mousePos)) { + _sliderDown = true; + } + + if (event.eventType == EVENT_BUTTON_UP && _sliderDown) { + _sliderDown = false; + event.handled = true; + update(); + } + + if (_sliderDown) { + event.handled = true; + if (event.mousePos.x < _xStart) { + setPosition(Common::Point(_xStart, _yp)); + } else if (event.mousePos.x >= (_xStart + _width)) { + setPosition(Common::Point(_xStart + _width, _yp)); + } else { + setPosition(Common::Point(event.mousePos.x, _yp)); + } + } +} + +bool ScannerDialog::Slider::startAction(CursorType action, Event &event) { + if (action == CURSOR_USE) + return false; + + return startAction(action, event); +} + +void ScannerDialog::Slider::update() { + int incHalf = (_width / (_xInc - 1)) / 2; + int newFrequency = ((_position.x - _xStart + incHalf) * _xInc) / (_width + incHalf * 2); + setPosition(Common::Point(_xStart + ((_width * newFrequency) / (_xInc - 1)), _yp)); + + R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] = newFrequency + 1; + + switch (newFrequency) { + case 0: + R2_GLOBALS._sound4.stop(); + break; + case 1: + R2_GLOBALS._sound4.play(45); + break; + case 2: + R2_GLOBALS._sound4.play(4); + break; + case 3: + R2_GLOBALS._sound4.play(5); + break; + case 4: + R2_GLOBALS._sound4.play(6); + break; + default: + break; + } +} + +void ScannerDialog::Slider::setup(int initial, int xStart, int yp, int width, int xInc) { + _initial = initial; + _xStart = xStart; + _yp = yp; + _width = width; + _xInc = xInc; + _sliderDown = false; + SceneActor::postInit(); + SceneObject::setup(4, 2, 1); + fixPriority(255); + setPosition(Common::Point(_width * (_initial - 1) / (_xInc - 1) + _xStart, yp)); + + static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene)->_sceneAreas.push_front(this); +} + +/*--------------------------------------------------------------------------*/ + +ScannerDialog::ScannerDialog() { +} + +void ScannerDialog::remove() { + switch (R2_GLOBALS._sceneManager._sceneNumber) { + case 1550: + case 1700: + R2_GLOBALS._events.setCursor(R2_GLOBALS._player._canWalk ? CURSOR_ARROW : CURSOR_USE); + break; + case 3800: + case 3900: { + Scene *scene = R2_GLOBALS._sceneManager._scene; + scene->_sceneMode = 3806; + scene->signal(); + break; + } + default: + break; + } + + SceneExt *scene = static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene); + scene->_sceneAreas.remove(&_talkButton); + scene->_sceneAreas.remove(&_scanButton); + _talkButton.remove(); + _scanButton.remove(); + _slider.remove(); + _obj4.remove(); + _obj5.remove(); + _obj6.remove(); + _obj7.remove(); + + ModalWindow::remove(); +} + +void ScannerDialog::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) { + // Stop player moving if currently doing so + if (R2_GLOBALS._player._mover) + R2_GLOBALS._player.addMover(NULL); + + R2_GLOBALS._events.setCursor(CURSOR_USE); + ModalWindow::proc12(visage, stripFrameNum, frameNum, posX, posY); + + proc13(100, -1, -1, -1); + _talkButton.setup(1); + _scanButton.setup(2); + _slider.setup(R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex], 142, 124, 35, 5); + + _obj4.postInit(); + _obj4.setup(4, 3, 2); + _obj4.setPosition(Common::Point(160, 83)); + _obj4.fixPriority(256); + + if (R2_GLOBALS._sceneManager._sceneNumber == 3800 || R2_GLOBALS._sceneManager._sceneNumber == 3900) { + Scene *scene = R2_GLOBALS._sceneManager._scene; + scene->_sceneMode = 3805; + scene->signal(); + } +} + +/*--------------------------------------------------------------------------*/ + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h index 0b573bf7f0..1b4b7fca1f 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.h +++ b/engines/tsage/ringworld2/ringworld2_logic.h @@ -88,7 +88,7 @@ public: SceneObject *_focusObject; Visage _cursorVisage; - SynchronizedList<SceneArea *> _sceneAreas; + SynchronizedList<EventHandler *> _sceneAreas; Rect _v51C34; public: @@ -108,12 +108,14 @@ public: void fadeOut(); void clearScreen(); void scalePalette(int RFactor, int GFactor, int BFactor); + void loadBlankScene(); }; class SceneHandlerExt: public SceneHandler { public: virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void process(Event &event); + virtual void postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad); void setupPaletteMaps(); }; @@ -159,6 +161,9 @@ public: /*--------------------------------------------------------------------------*/ class Ringworld2InvObjectList : public InvObjectList { +private: + static bool SelectItem(int objectNumber); + static void selectDefault(int obectNumber); public: InvObject _none; InvObject _inv1; @@ -260,7 +265,9 @@ class SceneActor: public SceneObject { public: virtual Common::String getClassName() { return "SceneActor"; } virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void remove(); virtual bool startAction(CursorType action, Event &event); + virtual GfxSurface getFrame(); }; class SceneActorExt: public SceneActor { @@ -276,6 +283,49 @@ public: } }; +enum MazeDirection { MAZEDIR_NONE = 0, MAZEDIR_NORTH = 1, MAZEDIR_NORTHEAST = 2, MAZEDIR_EAST = 3, + MAZEDIR_SOUTHEAST = 4, MAZEDIR_SOUTH = 5, MAZEDIR_SOUTHWEST = 6, MAZEDIR_WEST = 7, + MAZEDIR_NORTHWEST = 8 }; + +class MazeUI: public SceneObject { +private: + void clear(); +public: + // The dimensions (in cells) of the entire maze map + Rect _mapBounds; + + // Encoded cell map specifying the features of the maze + byte *_mapData; + // Image surface used to store a line of the map for rendering + GfxSurface _mapImage; + + Common::Point _cellsVisible; + Common::Point _mapCells; + Common::Point _cellSize; + Common::Point _mapOffset; + int _resNum; + int _cellsResNum; + int _frameCount; + int _resCount; + int _mapImagePitch; + int _unused; +public: + MazeUI(); + virtual ~MazeUI(); + + void setDisplayBounds(const Rect &r); + bool setMazePosition(const Common::Point &pt); + void load(int resNum); + int getCellFromPixelXY(const Common::Point &pt); + int getCellFromCellXY(const Common::Point &p); + int pixelToCellXY(Common::Point &pt); + + virtual Common::String getClassName() { return "MazeUI"; } + void synchronize(Serializer &s); + virtual void reposition(); + virtual void draw(); +}; + class SceneAreaObject: public SceneArea { class Object1: public SceneActor { public: @@ -290,41 +340,6 @@ public: void setDetails(int resNum, int lookLineNum, int talkLineNum, int useLineNum); }; -class UnkObject1200 : public SavedObject { -public: - Rect _rect1; - Rect _rect2; - - int *_field16; - int *_field3A; - - int _field12; - int _field14; - int _field26; - int _field28; - int _field2A; - int _field2C; - int _field2E; - int _field30; - int _field32; - int _field34; - int _field36; - int _field38; - int _field3E; - int _field40; - - UnkObject1200(); - void synchronize(Serializer &s); - - void sub51AE9(int arg1); - int sub51AF8(Common::Point pt); - bool sub51AFD(Common::Point pt); - void sub51B02(); - void sub9EDE8(Rect rect); - int sub9EE22(int &arg1, int &arg2); - virtual Common::String getClassName() { return "UnkObject1200"; } -}; - /*--------------------------------------------------------------------------*/ class AnimationSlice { @@ -378,6 +393,8 @@ public: enum AnimationPaletteMode { ANIMPALMODE_REPLACE_PALETTE = 0, ANIMPALMODE_CURR_PALETTE = 1, ANIMPALMODE_NONE = 2 }; +enum AnimationObjectMode { ANIMOBJMODE_1 = 1, ANIMOBJMODE_2 = 2, ANIMOBJMODE_42 = 42 }; + class AnimationPlayer: public EventHandler { private: void rleDecode(const byte *pSrc, byte *pDest, int size); @@ -392,8 +409,9 @@ public: Common::File _resourceFile; Rect _rect1, _screenBounds; int _field38; - int _field3A, _paletteMode; - int _objectMode; + int _field3A; + AnimationPaletteMode _paletteMode; + AnimationObjectMode _objectMode; int _field58, _sliceHeight; byte _palIndexes[256]; ScenePalette _palette; @@ -418,6 +436,7 @@ public: virtual void changePane() {} virtual void closing() {} + bool load(int animId, Action *endAction = NULL); bool isCompleted(); void close(); @@ -432,6 +451,74 @@ public: virtual void synchronize(Serializer &s); }; +class ModalWindow: public SceneArea { +public: + SceneActor _object1; + byte _field20; +public: + ModalWindow(); + + virtual void remove(); + virtual void synchronize(Serializer &s); + virtual Common::String getClassName() { return "ModalWindow"; } + virtual void process(Event &event); + virtual void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY); + virtual void proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum); +}; + +class ScannerDialog: public ModalWindow { + + class Button: public SceneActor { + private: + void reset(); + public: + int _buttonId; + bool _buttonDown; + public: + Button(); + void setup(int buttonId); + + virtual void synchronize(Serializer &s); + virtual Common::String getClassName() { return "ScannerButton"; } + virtual void process(Event &event); + virtual bool startAction(CursorType action, Event &event); + }; + class Slider: public SceneActor { + private: + void update(); + public: + int _initial; + int _xStart; + int _yp; + int _width; + int _xInc; + bool _sliderDown; + public: + Slider(); + void setup(int initial, int xStart, int yp, int width, int xInc); + + virtual void synchronize(Serializer &s); + virtual Common::String getClassName() { return "ScannerSlider"; } + virtual void remove(); + virtual void process(Event &event); + virtual bool startAction(CursorType action, Event &event); + }; +public: + Button _talkButton; + Button _scanButton; + Slider _slider; + SceneActor _obj4; + SceneActor _obj5; + SceneActor _obj6; + SceneActor _obj7; +public: + ScannerDialog(); + + virtual Common::String getClassName() { return "ScannerDialog"; } + virtual void remove(); + void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY); +}; + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp index 3b7d283e44..63bb24f384 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp @@ -226,9 +226,9 @@ bool Scene100::Terminal::startAction(CursorType action, Event &event) { /*--------------------------------------------------------------------------*/ void Scene100::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(100); R2_GLOBALS._scenePalette.loadPalette(0); + SceneExt::postInit(); if (R2_GLOBALS._sceneManager._previousScene != 125) R2_GLOBALS._sound1.play(10); @@ -573,23 +573,23 @@ void Scene125::Icon::hideIcon() { /*--------------------------------------------------------------------------*/ -bool Scene125::Item4::startAction(CursorType action, Event &event) { +bool Scene125::DiskSlot::startAction(CursorType action, Event &event) { Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene; switch (action) { case CURSOR_USE: if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._player._oldCharacterScene[1]) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 126; - scene->setAction(&scene->_sequenceManager, scene, 126, &scene->_object7, NULL); + scene->setAction(&scene->_sequenceManager, scene, 126, &scene->_infoDisk, NULL); return true; } break; case R2_OPTO_DISK: if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == 1) { R2_GLOBALS._player.disableControl(); - scene->_object7.postInit(); + scene->_infoDisk.postInit(); scene->_sceneMode = 125; - scene->setAction(&scene->_sequenceManager, scene, 125, &scene->_object7, NULL); + scene->setAction(&scene->_sequenceManager, scene, 125, &scene->_infoDisk, NULL); return true; } break; @@ -626,16 +626,16 @@ void Scene125::postInit(SceneObjectList *OwnerList) { R2_GLOBALS._player.disableControl(); if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._player._oldCharacterScene[1]) { - _object7.postInit(); - _object7.setup(160, 3, 5); - _object7.setPosition(Common::Point(47, 167)); + _infoDisk.postInit(); + _infoDisk.setup(160, 3, 5); + _infoDisk.setPosition(Common::Point(47, 167)); } _object6.postInit(); _object6.setup(162, 1, 1); _object6.setPosition(Common::Point(214, 168)); - _item4.setDetails(Rect(27, 145, 81, 159), 126, 9, -1, -1, 1, NULL); + _diskSlot.setDetails(Rect(27, 145, 81, 159), 126, 9, -1, -1, 1, NULL); _item3.setDetails(Rect(144, 119, 286, 167), 126, 6, 7, 8, 1, NULL); _item2.setDetails(1, 126, 3, 4, 5); _background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 126, 0, 1, -1, 1, NULL); @@ -782,10 +782,11 @@ void Scene125::signal() { break; case 125: R2_INVENTORY.setObjectScene(R2_OPTO_DISK, R2_GLOBALS._player._oldCharacterScene[1]); + R2_GLOBALS._player.enableControl(); break; case 126: R2_INVENTORY.setObjectScene(R2_OPTO_DISK, 1); - _object7.remove(); + _infoDisk.remove(); R2_GLOBALS._player.enableControl(); R2_GLOBALS._player._canWalk = false; break; @@ -1553,7 +1554,7 @@ void Scene180::signal() { R2_GLOBALS._sceneManager._hasPalette = true; _animationPlayer._paletteMode = ANIMPALMODE_NONE; _animationPlayer._v = 1; - _animationPlayer._objectMode = 1; + _animationPlayer._objectMode = ANIMOBJMODE_1; R2_GLOBALS._scene180Mode = 1; _animationPlayer.load(1); @@ -1596,7 +1597,7 @@ void Scene180::signal() { case 5: _animationPlayer._paletteMode = ANIMPALMODE_NONE; _animationPlayer._v = 1; - _animationPlayer._objectMode = 1; + _animationPlayer._objectMode = ANIMOBJMODE_1; R2_GLOBALS._scene180Mode = 2; _animationPlayer.load(2); @@ -1701,7 +1702,7 @@ void Scene180::signal() { _field412 = 1; _animationPlayer._paletteMode = ANIMPALMODE_REPLACE_PALETTE; _animationPlayer._v = 1; - _animationPlayer._objectMode = 42; + _animationPlayer._objectMode = ANIMOBJMODE_42; R2_GLOBALS._scene180Mode = 3; _animationPlayer.load(3); break; @@ -1800,7 +1801,7 @@ void Scene180::signal() { case 40: _animationPlayer._paletteMode = ANIMPALMODE_NONE; - _animationPlayer._objectMode = 1; + _animationPlayer._objectMode = ANIMOBJMODE_1; R2_GLOBALS._scene180Mode = 4; if (_animationPlayer.load(4)) { _animationPlayer.dispatch(); @@ -1839,7 +1840,7 @@ void Scene180::signal() { _field412 = 1; _animationPlayer._paletteMode = ANIMPALMODE_NONE; _animationPlayer._v = 1; - _animationPlayer._objectMode = 1; + _animationPlayer._objectMode = ANIMOBJMODE_1; R2_GLOBALS._scene180Mode = 15; _animationPlayer.load(15, NULL); @@ -2025,7 +2026,7 @@ void Scene200::EastExit::changeScene() { Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene; _enabled = false; - R2_GLOBALS._player.disableControl(); + R2_GLOBALS._player.disableControl(CURSOR_WALK); scene->_sceneMode = 206; scene->setAction(&scene->_sequenceManager, scene, 206, &R2_GLOBALS._player, NULL); } @@ -2034,7 +2035,7 @@ void Scene200::WestExit::changeScene() { Scene200 *scene = (Scene200 *)R2_GLOBALS._sceneManager._scene; _enabled = false; - R2_GLOBALS._player.disableControl(); + R2_GLOBALS._player.disableControl(CURSOR_WALK); scene->_sceneMode = 208; scene->setAction(&scene->_sequenceManager, scene, 208, &R2_GLOBALS._player, NULL); } @@ -2042,8 +2043,8 @@ void Scene200::WestExit::changeScene() { /*--------------------------------------------------------------------------*/ void Scene200::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(200); + SceneExt::postInit(); _westExit.setDetails(Rect(94, 0, 123, 58), EXITCURSOR_W, 175); _westExit.setDest(Common::Point(125, 52)); @@ -2311,19 +2312,6 @@ void Scene205::Action1::textLoop() { /*--------------------------------------------------------------------------*/ -Scene205::Object::Object(): SceneObject() { - _x100 = _y100 = 0; -} - -void Scene205::Object::synchronize(Serializer &s) { - EventHandler::synchronize(s); - - s.syncAsSint32LE(_x100); - s.syncAsSint32LE(_y100); -} - -/*--------------------------------------------------------------------------*/ - Scene205::Scene205(): SceneExt() { _yp = 0; _textIndex = 1; @@ -2597,8 +2585,8 @@ void Scene250::synchronize(Serializer &s) { } void Scene250::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(250); + SceneExt::postInit(); R2_GLOBALS._player.postInit(); R2_GLOBALS._player.setVisage(10); @@ -2708,6 +2696,8 @@ void Scene250::signal() { case 7: _field418 = 1; if ((_field414 + 12) == _field412) + _sceneMode = 9; + else _sceneMode = 8; signal(); break; @@ -2741,7 +2731,7 @@ void Scene250::signal() { R2_GLOBALS._sceneManager.changeScene(300); break; case 139: - R2_GLOBALS._sceneManager.changeScene(139); + R2_GLOBALS._sceneManager.changeScene(700); break; case 91: R2_GLOBALS._sceneManager.changeScene(850); @@ -2986,7 +2976,7 @@ bool Scene300::Miranda::startAction(CursorType action, Event &event) { } else if (!R2_GLOBALS.getFlag(55)) { R2_GLOBALS._events.setCursor(CURSOR_ARROW); scene->_sceneMode = 10; - scene->_stripManager.start3(scene->_stripId, scene, R2_GLOBALS._stripManager_lookupList); + scene->_stripManager.start3(201, scene, R2_GLOBALS._stripManager_lookupList); } else { scene->_sceneMode = 16; @@ -3048,7 +3038,7 @@ bool Scene300::Seeker::startAction(CursorType action, Event &event) { R2_GLOBALS._player.disableControl(); if (R2_GLOBALS._player._characterIndex == R2_QUINN) { - if (R2_GLOBALS.getFlag(44)) { + if (!R2_GLOBALS.getFlag(44)) { if (!R2_GLOBALS.getFlag(38)) { R2_GLOBALS._sound1.play(69); scene->_stripId = 181; @@ -3090,10 +3080,10 @@ bool Scene300::Seeker::startAction(CursorType action, Event &event) { } else { R2_GLOBALS._player.disableControl(); scene->_stripId = 171; - } - scene->_sceneMode = 310; - scene->setAction(&scene->_sequenceManager1, scene, 310, &R2_GLOBALS._player, NULL); + scene->_sceneMode = 310; + scene->setAction(&scene->_sequenceManager1, scene, 310, &R2_GLOBALS._player, NULL); + } return true; case R2_READER: @@ -3152,7 +3142,7 @@ bool Scene300::Doorway::startAction(CursorType action, Event &event) { if (action == CURSOR_USE) { if ((R2_GLOBALS._player._characterIndex == R2_QUINN) && - (!R2_GLOBALS.getFlag(44) || R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500)) { + (!R2_GLOBALS.getFlag(44) || R2_GLOBALS._player._characterScene[R2_SEEKER] == 500)) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 301; scene->setAction(&scene->_sequenceManager1, scene, 301, &R2_GLOBALS._player, this, NULL); @@ -3171,6 +3161,9 @@ bool Scene300::Doorway::startAction(CursorType action, Event &event) { Scene300::Scene300(): SceneExt() { _stripId = 0; _rotation = NULL; + + _stripManager.setColors(60, 255); + _stripManager.setFontNumber(3); } void Scene300::synchronize(Serializer &s) { @@ -3181,8 +3174,9 @@ void Scene300::synchronize(Serializer &s) { } void Scene300::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(300); + SceneExt::postInit(); + _sound1.play(23); setZoomPercents(75, 93, 120, 100); @@ -3191,8 +3185,6 @@ void Scene300::postInit(SceneObjectList *OwnerList) { R2_GLOBALS._player._characterIndex = R2_QUINN; } - _stripManager.setColors(60, 255); - _stripManager.setFontNumber(3); _stripManager.addSpeaker(&_mirandaSpeaker); _stripManager.addSpeaker(&_seekerSpeaker); _stripManager.addSpeaker(&_quinnSpeaker); @@ -3233,7 +3225,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) { _protocolDisplay.postInit(); _protocolDisplay.setup(300, 6, 1); _protocolDisplay.setPosition(Common::Point(287, 71)); - _protocolDisplay.animate(ANIM_MODE_7, NULL); + _protocolDisplay.animate(ANIM_MODE_7, 0, NULL); _protocolDisplay._numFrames = 5; _object6.postInit(); @@ -3365,7 +3357,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) { break; case 325: if (!R2_GLOBALS.getFlag(44) || R2_GLOBALS.getFlag(25)) - setAction(&_sequenceManager1, this, 309, &R2_GLOBALS._player, NULL); + setAction(&_sequenceManager1, this, 307, &R2_GLOBALS._player, NULL); else { R2_GLOBALS.setFlag(60); R2_GLOBALS._player.setup(302, 3, 1); @@ -3402,9 +3394,11 @@ void Scene300::postInit(SceneObjectList *OwnerList) { R2_GLOBALS._events.setCursor(CURSOR_ARROW); if (R2_GLOBALS.getFlag(51)) { + // Things don't seem right _sceneMode = 13; _stripManager.start3(300, this, R2_GLOBALS._stripManager_lookupList); } else { + // Back in Ringworld space _sceneMode = 11; _stripManager.start3(200, this, R2_GLOBALS._stripManager_lookupList); } @@ -3484,27 +3478,27 @@ void Scene300::remove() { void Scene300::signal() { switch (_sceneMode) { case 10: - switch (_stripManager._field2E8) { - case 0: + switch (_stripManager._exitMode) { + case 1: R2_GLOBALS._sound1.changeSound(10); R2_GLOBALS.setFlag(38); break; - case 1: + case 2: R2_GLOBALS.setFlag(3); break; - case 2: + case 3: R2_GLOBALS.setFlag(4); break; - case 3: + case 4: R2_GLOBALS.setFlag(13); if (R2_GLOBALS._stripManager_lookupList[1] == 6) R2_GLOBALS.setFlag(40); break; - case 4: + case 5: if (R2_GLOBALS._stripManager_lookupList[1] == 6) R2_GLOBALS.setFlag(40); break; - case 5: + case 6: R2_GLOBALS._sceneManager.changeScene(1000); break; default: @@ -3565,7 +3559,7 @@ void Scene300::signal() { break; case 16: - if (_stripManager._field2E8 == 1) { + if (_stripManager._exitMode == 1) { R2_GLOBALS._player.setAction(NULL); R2_GLOBALS._sceneManager.changeScene(1000); } else { @@ -3624,6 +3618,8 @@ void Scene300::signal() { case 309: signal309(); R2_GLOBALS._events.setCursor(CURSOR_ARROW); + R2_GLOBALS._events._currentCursor = CURSOR_ARROW; + _sceneMode = 10; _stripManager.start3(_stripId, this, R2_GLOBALS._stripManager_lookupList); break; @@ -3891,7 +3887,7 @@ Scene325::Scene325(): SceneExt() { _field412 = 7; _iconFontNumber = 50; _field416 = _field418 = 0; - _field41A = _field41C = _field41E = _field420 = 0; + _field41A = _field41C = _field41E = _scannerLocation = 0; _soundCount = _soundIndex = 0; for (int idx = 0; idx < 10; ++idx) @@ -3899,8 +3895,8 @@ Scene325::Scene325(): SceneExt() { } void Scene325::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(325); + SceneExt::postInit(); R2_GLOBALS.clearFlag(50); _stripManager.addSpeaker(&_quinnSpeaker); @@ -3926,7 +3922,7 @@ void Scene325::synchronize(Serializer &s) { s.syncAsSint16LE(_field41A); s.syncAsSint16LE(_field41C); s.syncAsSint16LE(_field41E); - s.syncAsSint16LE(_field420); + s.syncAsSint16LE(_scannerLocation); s.syncAsSint16LE(_soundCount); s.syncAsSint16LE(_soundIndex); @@ -4027,19 +4023,19 @@ void Scene325::signal() { if (R2_GLOBALS.getFlag(44) && !R2_GLOBALS.getFlag(51)) { if (v != 13) { - setMessage(328, 0); + setMessage(328, v); } else { - _field420 = 864; + _scannerLocation = 864; _object12.postInit(); - _object2.setup(326, 4, 1); + _object12.setup(326, 4, 1); _object12.setPosition(Common::Point(149, 128)); _object12.fixPriority(20); - _object13.postInit(); - _object13.setup(326, 4, 2); - _object13.setPosition(Common::Point(149, (int)(_field420 * ADJUST_FACTOR))); - _object13.fixPriority(21); + _scannerTab.postInit(); + _scannerTab.setup(326, 4, 2); + _scannerTab.setPosition(Common::Point(149, 22 + (int)(_scannerLocation * ADJUST_FACTOR))); + _scannerTab.fixPriority(21); _object10.postInit(); _object10.setup(326, 1, 1); @@ -4049,7 +4045,7 @@ void Scene325::signal() { _object1.postInit(); _object1.setup(326, 1, 1); _object1.setPosition(Common::Point(210, 32)); - _object10.fixPriority(10); + _object1.fixPriority(10); _object2.postInit(); _object2.setup(326, 1, 1); @@ -4099,7 +4095,7 @@ void Scene325::signal() { } else if (R2_GLOBALS.getFlag(51)) { setMessage(329, (v == 12) ? 10 : v); } else { - setMessage(327, (v < 15) ? 1 : v); + setMessage(327, (v >= 15) ? 1 : v); } break; } @@ -4140,12 +4136,12 @@ void Scene325::signal() { setMessage(128, _field416); break; default: - R2_GLOBALS._player.enableControl(); - R2_GLOBALS._player._canWalk = false; - _field416 = 105; - setMessage(128, _field416); + _field416 = 0; break; } + + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; break; case 10: R2_GLOBALS._player.enableControl(); @@ -4227,31 +4223,50 @@ void Scene325::consoleAction(int id) { _icon1.hideIcon(); _icon2.hideIcon(); _icon3.hideIcon(); - // TODO: Finish - break; - case 3: - _icon1.setIcon(5); - _icon2.setIcon(6); - _icon3.setIcon(R2_GLOBALS.getFlag(50) ? 16 : 15); - break; - case 4: - case 5: - _field418 = id; - _icon1.setIcon(17); - _icon2.setIcon(18); - _icon3.setIcon(19); - break; - case 7: - consoleAction(((_field412 == 5) || (_field412 == 6) || (_field412 == 15)) ? 4 : 7); + + if (id == 2 || (id == 19 && _field418 == 5 && R2_GLOBALS.getFlag(50) && + R2_GLOBALS.getFlag(44) && !R2_GLOBALS.getFlag(51))) { + _icon5.setIcon(13); + _icon4.setPosition(Common::Point(52, 107)); + _icon4._sceneRegionId = 9; + _icon4.setIcon(14); + _icon4._object2.hide(); + + } else { + _icon4.hideIcon(); + _icon5.hideIcon(); + } + + _icon6.setIcon(12); + _sceneMode = 10; + _palette.loadPalette(161); + BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this); break; - case 8: - R2_GLOBALS._sceneManager.changeScene(300); - case 9: - case 10: - _iconFontNumber = (id - 1) == 9 ? 50 : 52; - _text1.remove(); - _icon6.setIcon(7); + + case 22: + case 23: + case 24: + case 25: + R2_GLOBALS._player.disableControl(); + consoleAction(2); + _field412 = id; + _icon1.hideIcon(); + _icon2.hideIcon(); + _icon3.hideIcon(); + _icon4.hideIcon(); + + _icon5.setIcon(13); + _icon4.setPosition(Common::Point(52, 107)); + _icon4._sceneRegionId = 9; + _icon4.setIcon(14); + _icon4._object2.hide(); + + _icon6.setIcon(12); + _sceneMode = 10; + _palette.loadPalette(161); + BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this); break; + case 11: if (R2_GLOBALS.getFlag(57) && (R2_GLOBALS._player._characterIndex == 1) && !R2_GLOBALS.getFlag(25)) { R2_GLOBALS._player.disableControl(); @@ -4260,6 +4275,7 @@ void Scene325::consoleAction(int id) { _stripManager.start(403, this); } else { R2_GLOBALS._player.disableControl(); + id = 8; _text1.remove(); _icon4.setPosition(Common::Point(80, 62)); @@ -4267,7 +4283,7 @@ void Scene325::consoleAction(int id) { _icon4.hideIcon(); _object12.remove(); - _object13.remove(); + _scannerTab.remove(); _object10.remove(); _object1.remove(); _object2.remove(); @@ -4286,6 +4302,31 @@ void Scene325::consoleAction(int id) { BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this); } break; + + case 3: + _icon1.setIcon(5); + _icon2.setIcon(6); + _icon3.setIcon(R2_GLOBALS.getFlag(50) ? 16 : 15); + break; + case 4: + case 5: + _field418 = id; + _icon1.setIcon(17); + _icon2.setIcon(18); + _icon3.setIcon(19); + _icon4.setIcon(20); + break; + case 7: + consoleAction(((_field412 == 5) || (_field412 == 6) || (_field412 == 15)) ? 4 : 7); + break; + case 8: + R2_GLOBALS._sceneManager.changeScene(300); + case 9: + case 10: + _iconFontNumber = (id - 1) == 9 ? 50 : 52; + _text1.remove(); + _icon6.setIcon(7); + break; case 12: _icon4.setIcon(14); _icon4._object2.hide(); @@ -4295,7 +4336,7 @@ void Scene325::consoleAction(int id) { case 18: case 19: case 20: - if (_field420) { + if (_scannerLocation) { R2_GLOBALS._player.disableControl(); _field41A = 1296; _field41E = 1; @@ -4315,7 +4356,7 @@ void Scene325::consoleAction(int id) { case 18: case 19: case 20: - if (_field420 < 1620) { + if (_scannerLocation < 1620) { R2_GLOBALS._player.disableControl(); _field41A = 1296; _field41E = -1; @@ -4337,31 +4378,6 @@ void Scene325::consoleAction(int id) { consoleAction(4); id = 4; break; - case 22: - case 23: - case 24: - case 25: - R2_GLOBALS._player.disableControl(); - consoleAction(2); - _field412 = id; - - _icon1.hideIcon(); - _icon2.hideIcon(); - _icon3.hideIcon(); - _icon4.hideIcon(); - - _icon5.setIcon(13); - _icon4.setPosition(Common::Point(52, 107)); - _icon4._sceneRegionId = 9; - _icon4.setIcon(14); - _icon4._object2.hide(); - - _icon6.setIcon(12); - _sceneMode = 10; - _palette.loadPalette(161); - - BF_GLOBALS._scenePalette.addFader(&_palette._palette[0], 256, 5, this); - break; case 6: default: _icon1.setIcon(1); @@ -4436,21 +4452,21 @@ void Scene325::dispatch() { if (yp >= 30) { yp -= 12; - --_field420; + --_scannerLocation; flag = true; } if (yp <= 10) { yp += 12; - ++_field420; + ++_scannerLocation; flag = true; } - _object3.setPosition(Common::Point(149, (int)(_field420 * ADJUST_FACTOR) + 22)); + _scannerTab.setPosition(Common::Point(149, 22 + (int)(_scannerLocation * ADJUST_FACTOR))); for (int idx = 0; idx < 4; ++idx) _objList[idx].remove(); if (flag) { - int v = _field420 - 758; + int v = _scannerLocation - 758; _object10.setFrame((v++ <= 0) ? 1 : v); _object1.setFrame((v++ <= 0) ? 1 : v); _object2.setFrame((v++ <= 0) ? 1 : v); @@ -4490,7 +4506,7 @@ void Scene325::dispatch() { R2_GLOBALS._sound3.stop(); _field41C = 0; - if (_field420 == 756) { + if (_scannerLocation == 756) { R2_GLOBALS._player.disableControl(); R2_GLOBALS._events.setCursor(CURSOR_USE); _sceneMode = 12; @@ -4908,7 +4924,7 @@ bool Scene500::Doorway::startAction(CursorType action, Event &event) { scene->setAction(&scene->_sequenceManager1, scene, 524, &R2_GLOBALS._player, NULL); } else { scene->_sceneMode = 500; - scene->setAction(&scene->_sequenceManager1, scene, 500, &R2_GLOBALS._player, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 500, &R2_GLOBALS._player, this, NULL); } return true; @@ -4986,7 +5002,7 @@ bool Scene500::SonicStunner::startAction(CursorType action, Event &event) { if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = R2_GLOBALS.getFlag(26) ? 520 : 502; - scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL); + scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, this, NULL); return true; } else { return SceneActor::startAction(action, event); @@ -5075,7 +5091,7 @@ void Scene500::postInit(SceneObjectList *OwnerList) { } } - if ((R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) != 500) && R2_GLOBALS.getFlag(27)) { + if ((R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) == 500) && R2_GLOBALS.getFlag(27)) { _tanks1.postInit(); _tanks1.setup(502, 7, 1); _tanks1.setPosition(Common::Point(281, 120)); @@ -5230,7 +5246,7 @@ void Scene500::signal() { R2_GLOBALS._sceneManager.changeScene(700); break; case 501: - if (R2_GLOBALS._player._characterScene[R2_QUINN] == 500) { + if (R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500) { _stripNumber = 1100; _sceneMode = 523; setAction(&_sequenceManager1, this, 523, &R2_GLOBALS._player, NULL); @@ -5338,28 +5354,16 @@ void Scene525::signal() { } /*-------------------------------------------------------------------------- - * Scene 600 - + * Scene 600 - Drive Room * *--------------------------------------------------------------------------*/ -Scene600::Scene600() { - _field412 = 0; - for (int i = 0; i < 256; i++) - _fieldAD2[i] = 0; -} - -void Scene600::synchronize(Serializer &s) { - SceneExt::synchronize(s); - s.syncAsSint16LE(_field412); - for (int i = 0; i < 256; i++) - s.syncAsByte(_fieldAD2[i]); -} - -bool Scene600::Item1::startAction(CursorType action, Event &event) { +bool Scene600::CompartmentHotspot::startAction(CursorType action, Event &event) { if ((action != R2_NEGATOR_GUN) || (!R2_GLOBALS.getFlag(5)) || (R2_GLOBALS.getFlag(8))) return SceneHotspot::startAction(action, event); - SceneItem::display(600, 32, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + SceneItem::display(600, 32, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, ALIGN_CENTER, + SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END); return true; } @@ -5368,12 +5372,14 @@ bool Scene600::Item4::startAction(CursorType action, Event &event) { return SceneHotspot::startAction(action, event); if ((R2_GLOBALS.getFlag(5)) && (!R2_GLOBALS.getFlag(8))) { - SceneItem::display(600, 32, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + SceneItem::display(600, 32, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, ALIGN_CENTER, + SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END); return true; } - if (R2_GLOBALS.getFlag(5)) { - SceneItem::display(600, 30, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + if (!R2_GLOBALS.getFlag(5)) { + SceneItem::display(600, 30, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, ALIGN_CENTER, + SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END); return true; } @@ -5389,30 +5395,46 @@ bool Scene600::Item4::startAction(CursorType action, Event &event) { scene->_actor2.postInit(); scene->_sceneMode = 612; - setAction(&scene->_sequenceManager1, this, 612, &scene->_actor3, &scene->_actor2, &R2_GLOBALS._player, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 612, &scene->_actor3, &scene->_actor2, &R2_GLOBALS._player, NULL); return true; } void Scene600::Actor4::signal() { - Common::Point pt(36, 177 + R2_GLOBALS._randomSource.getRandomNumber(5)); + Common::Point pt(177 + R2_GLOBALS._randomSource.getRandomNumber(5), + 108 + R2_GLOBALS._randomSource.getRandomNumber(3)); NpcMover *mover = new NpcMover(); addMover(mover, &pt, this); } bool Scene600::Actor4::startAction(CursorType action, Event &event) { - if ((action >= CURSOR_WALK) && (action < R2CURSORS_START)) + if (action >= CURSOR_WALK) // Only action cursors return SceneActor::startAction(action, event); return false; } -void Scene600::Actor4::draw() { - warning("TODO: Actor4::draw()"); - SceneActor::draw(); +GfxSurface Scene600::Actor4::getFrame() { + GfxSurface frame = SceneActor::getFrame(); + + if (_effect) { + // Translate the frame using the scene's pixel map + byte *pixelMap = static_cast<Scene600 *>(R2_GLOBALS._sceneManager._scene)->_pixelMap; + Graphics::Surface surface = frame.lockSurface(); + byte *srcP = (byte *)surface.getPixels(); + + while (srcP < ((byte *)surface.getBasePtr(0, surface.h))) { + *srcP = pixelMap[*srcP]; + srcP++; + } + + frame.unlockSurface(); + } + + return frame; } -bool Scene600::Actor5::startAction(CursorType action, Event &event) { +bool Scene600::Doorway::startAction(CursorType action, Event &event) { if ((action < CURSOR_WALK) && (action >= R2CURSORS_START)) return false; @@ -5423,10 +5445,10 @@ bool Scene600::Actor5::startAction(CursorType action, Event &event) { if ((R2_INVENTORY.getObjectScene(R2_CLAMP) == 600) && (!R2_GLOBALS.getFlag(6))) { R2_GLOBALS._player.disableControl(); - scene->_actor6.setDetails(600, 11, -1, -1, 3, (SceneItem *) NULL); + scene->_laser.setDetails(600, 11, -1, -1, 3, (SceneItem *) NULL); R2_GLOBALS.setFlag(6); scene->_sceneMode = 609; - scene->setAction(&scene->_sequenceManager1, scene, 609, &R2_GLOBALS._player, &scene->_actor5, &scene->_actor6, &scene->_actor1, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 609, &R2_GLOBALS._player, &scene->_doorway, &scene->_laser, &scene->_actor1, NULL); return true; } @@ -5436,7 +5458,7 @@ bool Scene600::Actor5::startAction(CursorType action, Event &event) { if (!R2_GLOBALS.getFlag(6)) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 616; - scene->setAction(&scene->_sequenceManager1, scene, 616, &R2_GLOBALS._player, &scene->_actor5, &scene->_actor6, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 616, &R2_GLOBALS._player, &scene->_doorway, &scene->_laser, NULL); return true; } @@ -5445,15 +5467,15 @@ bool Scene600::Actor5::startAction(CursorType action, Event &event) { else { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 601; - scene->setAction(&scene->_sequenceManager1, scene, 601, &R2_GLOBALS._player, &scene->_actor5, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 601, &R2_GLOBALS._player, &scene->_doorway, NULL); } return true; } -bool Scene600::Actor6::startAction(CursorType action, Event &event) { +bool Scene600::Laser::startAction(CursorType action, Event &event) { Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene; - if ((action < CURSOR_WALK) && (action >= R2CURSORS_START)) { + if (action < CURSOR_WALK) { switch (action) { case R2_COM_SCANNER: if (R2_GLOBALS.getFlag(6)) { @@ -5463,7 +5485,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) { } else { R2_GLOBALS._player.disableControl(); scene->_actor8.postInit(); - scene->_actor8.setDetails(600, 20, -1, -1, 4, &scene->_actor6); + scene->_actor8.setDetails(600, 20, -1, -1, 4, &scene->_laser); scene->_sceneMode = 607; scene->setAction(&scene->_sequenceManager1, scene, 607, &R2_GLOBALS._player, &scene->_actor8, NULL); return true; @@ -5478,8 +5500,8 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) { return true; } else { R2_GLOBALS._player.disableControl(); - scene->_actor7.postInit(); - scene->_actor7.setDetails(600, 27, -1, -1, 5, &scene->_actor6); + scene->_aerosol.postInit(); + scene->_aerosol.setDetails(600, 27, -1, -1, 5, &scene->_laser); scene->_actor4.postInit(); scene->_actor4.setup(601, 3, 1); @@ -5487,11 +5509,11 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) { scene->_actor4._moveDiff = Common::Point(1, 1); scene->_actor4._moveRate = 2; scene->_actor4._numFrames = 3; - scene->_actor4.setDetails(600, 24, 25, 26, 5, &scene->_actor7); + scene->_actor4.setDetails(600, 24, 25, 26, 5, &scene->_aerosol); scene->_sceneMode = 605; - scene->setAction(&scene->_sequenceManager1, scene, 605, &R2_GLOBALS._player, &scene->_actor7, &scene->_actor4, &scene->_actor5, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 605, &R2_GLOBALS._player, &scene->_aerosol, &scene->_actor4, &scene->_doorway, NULL); return true; } break; @@ -5499,7 +5521,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) { if (R2_GLOBALS.getFlag(5)) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 606; - scene->setAction(&scene->_sequenceManager1, scene, 606, &R2_GLOBALS._player, &scene->_actor6, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 606, &R2_GLOBALS._player, &scene->_laser, NULL); return true; } else { return SceneActor::startAction(action, event); @@ -5509,7 +5531,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) { return false; break; } - } else if (action != CURSOR_USE) { + } else if (action == CURSOR_USE) { if (R2_GLOBALS.getFlag(5)) { return SceneActor::startAction(action, event); } else { @@ -5522,7 +5544,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) { return SceneActor::startAction(action, event); } -bool Scene600::Actor7::startAction(CursorType action, Event &event) { +bool Scene600::Aerosol::startAction(CursorType action, Event &event) { Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene; if ((action < CURSOR_WALK) && (action >= R2CURSORS_START)) { @@ -5530,13 +5552,28 @@ bool Scene600::Actor7::startAction(CursorType action, Event &event) { } else if (action == CURSOR_USE) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 614; - scene->setAction(&scene->_sequenceManager1, scene, 614, &R2_GLOBALS._player, &scene->_actor7, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 614, &R2_GLOBALS._player, &scene->_aerosol, NULL); return true; } else { return SceneActor::startAction(action, event); } } +/*--------------------------------------------------------------------------*/ + +Scene600::Scene600() { + _field412 = 0; + Common::fill(&_pixelMap[0], &_pixelMap[256], 0); +} + +void Scene600::synchronize(Serializer &s) { + SceneExt::synchronize(s); + + s.syncAsSint16LE(_field412); + for (int i = 0; i < 256; i++) + s.syncAsByte(_pixelMap[i]); +} + bool Scene600::Actor8::startAction(CursorType action, Event &event) { Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene; @@ -5544,7 +5581,7 @@ bool Scene600::Actor8::startAction(CursorType action, Event &event) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 615; scene->setAction(&scene->_sequenceManager1, scene, 615, &R2_GLOBALS._player, &scene->_actor8, NULL); - } else if ((action == R2_SONIC_STUNNER) && (R2_INVENTORY.getObjectScene(9) == 600) && (R2_GLOBALS._v565F1[1] == 2) && (!R2_GLOBALS.getFlag(8))){ + } else if ((action == R2_SONIC_STUNNER) && (R2_INVENTORY.getObjectScene(9) == 600) && (R2_GLOBALS._scannerFrequencies[1] == 2) && (!R2_GLOBALS.getFlag(8))){ R2_GLOBALS._player.disableControl(); scene->_sceneMode = 608; scene->setAction(&scene->_sequenceManager1, scene, 608, &R2_GLOBALS._player, &scene->_actor4, NULL); @@ -5562,23 +5599,31 @@ void Scene600::postInit(SceneObjectList *OwnerList) { R2_GLOBALS._walkRegions.enableRegion(3); _field412 = 0; - warning("FIXME: loop to initialize _fieldAD2[]"); + // Initialise pixel map for the obscuring effect + ScenePalette &pal = R2_GLOBALS._scenePalette; + uint r, g, b; + for (int i = 0; i < 256; ++i) { + pal.getEntry(i, &r, &g, &b); + int av = ((r + g + b) / 48); - _actor5.postInit(); - _actor5.setVisage(600); - _actor5.setPosition(Common::Point(29, 147)); - _actor5.fixPriority(10); - _actor5.setDetails(300, 3, -1, -1, 1, (SceneItem *) NULL); + _pixelMap[i] = R2_GLOBALS._paletteMap[(av << 8) | (av << 4) | av]; + } - _actor6.postInit(); - _actor6.setPosition(Common::Point(246, 41)); + _doorway.postInit(); + _doorway.setVisage(600); + _doorway.setPosition(Common::Point(29, 147)); + _doorway.fixPriority(10); + _doorway.setDetails(300, 3, -1, -1, 1, (SceneItem *) NULL); + + _laser.postInit(); + _laser.setPosition(Common::Point(246, 41)); if (R2_INVENTORY.getObjectScene(9) == 600) { _actor8.postInit(); _actor8.setup(602, 5, 1); _actor8.setPosition(Common::Point(246, 41)); _actor8.setDetails(600, 20, -1, -1, 1, (SceneItem *) NULL); - switch (R2_GLOBALS._v565F1[1] - 2) { + switch (R2_GLOBALS._scannerFrequencies[1] - 2) { case 0: R2_GLOBALS._sound4.play(45); break; @@ -5597,11 +5642,11 @@ void Scene600::postInit(SceneObjectList *OwnerList) { } if (R2_GLOBALS.getFlag(6)) { - _actor6.setup(602, 7, 1); - _actor6.setDetails(600, 11, -1, -1, 1, (SceneItem *) NULL); + _laser.setup(602, 7, 1); + _laser.setDetails(600, 11, -1, -1, 1, (SceneItem *) NULL); } else { - _actor6.setup(600, 2, 1); - _actor6.setDetails(600, 10, -1, -1, 1, (SceneItem *) NULL); + _laser.setup(600, 2, 1); + _laser.setDetails(600, 10, -1, -1, 1, (SceneItem *) NULL); _actor1.postInit(); _actor1.setup(600, 3, 5); @@ -5614,10 +5659,10 @@ void Scene600::postInit(SceneObjectList *OwnerList) { if (R2_GLOBALS.getFlag(5)) { if (R2_INVENTORY.getObjectScene(12) == 600) { - _actor7.postInit(); - _actor7.setup(602, 2, 2); - _actor7.setPosition(Common::Point(189, 95)); - _actor7.setDetails(600, 27, -1, -1, 1, (SceneItem *) NULL); + _aerosol.postInit(); + _aerosol.setup(602, 2, 2); + _aerosol.setPosition(Common::Point(189, 95)); + _aerosol.setDetails(600, 27, -1, -1, 1, (SceneItem *) NULL); } if (R2_GLOBALS.getFlag(8)) { @@ -5651,30 +5696,30 @@ void Scene600::postInit(SceneObjectList *OwnerList) { _item3.setDetails(11, 600, 14, -1, -1); if (R2_GLOBALS.getFlag(9)) { - _item1.setDetails(Rect(159, 3, 315, 95), 600, 7, -1, -1, 1, NULL); + _background.setDetails(Rect(159, 3, 315, 95), 600, 7, -1, -1, 1, NULL); } else { _item4.setDetails(Rect(173, 15, 315, 45), 600, 21, -1, 23, 1, NULL); - _item1.setDetails(Rect(159, 3, 315, 95), 600, 6, -1, -1, 1, NULL); + _background.setDetails(Rect(159, 3, 315, 95), 600, 6, -1, -1, 1, NULL); } _item5.setDetails(Rect(0, 0, 320, 200), 600, 0, -1, -1, 1, NULL); _sceneMode = 600; if (R2_GLOBALS._sceneManager._previousScene == 700) { if (R2_GLOBALS.getFlag(6)) { - setAction(&_sequenceManager1, this, 600, &R2_GLOBALS._player, &_actor5, NULL); + setAction(&_sequenceManager1, this, 600, &R2_GLOBALS._player, &_doorway, NULL); } else if (R2_GLOBALS.getFlag(5)) { - setAction(&_sequenceManager1, this, 603, &R2_GLOBALS._player, &_actor5, &_actor6, &_actor1, NULL); + setAction(&_sequenceManager1, this, 603, &R2_GLOBALS._player, &_doorway, &_laser, &_actor1, NULL); } else { - setAction(&_sequenceManager1, this, 602, &R2_GLOBALS._player, &_actor5, &_actor6, &_actor1, NULL); + setAction(&_sequenceManager1, this, 602, &R2_GLOBALS._player, &_doorway, &_laser, &_actor1, NULL); } } else if (R2_GLOBALS.getFlag(5)) { R2_GLOBALS._player.setPosition(Common::Point(50, 140)); R2_GLOBALS._player.setStrip(3); - _actor6.setFrame(_actor6.getFrameCount()); + _laser.setFrame(_laser.getFrameCount()); signal(); } else { - _actor5.setFrame(7); - _actor6.setFrame(7); + _doorway.setFrame(7); + _laser.setFrame(7); R2_GLOBALS._player.setPosition(Common::Point(28, 140)); R2_GLOBALS._player.setStrip(5); signal(); @@ -5703,7 +5748,7 @@ void Scene600::signal() { R2_GLOBALS._walkRegions.enableRegion(9); R2_GLOBALS._walkRegions.enableRegion(10); - R2_INVENTORY.setObjectScene(12, 600); + R2_INVENTORY.setObjectScene(R2_AEROSOL, 600); R2_GLOBALS.setFlag(5); _actor4._effect = 3; @@ -5730,12 +5775,12 @@ void Scene600::signal() { _actor3.remove(); R2_GLOBALS._sceneItems.remove(&_item4); _actor2.setDetails(600, 21, -1, 23, 4, &_item4); - _item1.setDetails(600, 7, -1, -1, 3, (SceneItem *) NULL); + _background.setDetails(600, 7, -1, -1, 3, (SceneItem *) NULL); R2_GLOBALS._player.enableControl(CURSOR_USE); break; case 614: R2_GLOBALS._player.enableControl(); - _actor7.remove(); + _aerosol.remove(); R2_INVENTORY.setObjectScene(12, 1); R2_GLOBALS._walkRegions.disableRegion(7); break; @@ -5753,8 +5798,9 @@ void Scene600::signal() { } void Scene600::process(Event &event) { - if ((!R2_GLOBALS._player._canWalk) && (!R2_GLOBALS.getFlag(6)) && (event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN)) { - if (!_actor5.contains(event.mousePos) || (_actor5._frame <= 1)) { + if (R2_GLOBALS._player._canWalk && (!R2_GLOBALS.getFlag(6)) && (event.eventType == EVENT_BUTTON_DOWN) + && (R2_GLOBALS._events.getCursor() == CURSOR_WALK)) { + if (!_doorway.contains(event.mousePos) || (_doorway._frame <= 1)) { if (R2_GLOBALS.getFlag(5)) { _field412 += 10; } else { @@ -5766,7 +5812,7 @@ void Scene600::process(Event &event) { } else { R2_GLOBALS._player.disableControl(); _sceneMode = 613; - setAction(&_sequenceManager1, this, 613, &R2_GLOBALS._player, &_actor6, NULL); + setAction(&_sequenceManager1, this, 613, &R2_GLOBALS._player, &_laser, NULL); event.handled = true; } } else if ((!R2_GLOBALS.getFlag(6)) && (R2_GLOBALS._player._mover) && (_field412 < 10)){ @@ -5778,9 +5824,9 @@ void Scene600::process(Event &event) { void Scene600::dispatch() { if ((_field412 != 0) && (_sceneMode != 600) && (_sceneMode != 603) && (_sceneMode != 602)) { - if ( ((_actor6._strip == 4) && (_actor6._frame > 1)) + if ( ((_laser._strip == 4) && (_laser._frame > 1)) || (_sceneMode == 601) - || ((_sceneMode == 616) && (_actor5._frame > 1)) ) + || ((_sceneMode == 616) && (_doorway._frame > 1)) ) _field412 = 0; else { _field412--; @@ -5803,7 +5849,7 @@ void Scene600::dispatch() { } /*-------------------------------------------------------------------------- - * Scene 700 - + * Scene 700 - Lander Bay 2 * *--------------------------------------------------------------------------*/ Scene700::Scene700() { @@ -5849,7 +5895,7 @@ bool Scene700::Item12::startAction(CursorType action, Event &event) { break; } - scene->setAction(&scene->_sequenceManager, this, 707, &R2_GLOBALS._player, &scene->_actor5, NULL); + scene->setAction(&scene->_sequenceManager, scene, 707, &R2_GLOBALS._player, &scene->_actor5, NULL); return true; } @@ -5910,7 +5956,7 @@ bool Scene700::Actor5::startAction(CursorType action, Event &event) { case 0: if ((_strip == 2) && (_frame == 1)) { R2_GLOBALS._player.disableControl(); - if (R2_GLOBALS._player._position.x <= 100) { + if (R2_GLOBALS._player._position.y <= 100) { scene->_sceneMode = 710; scene->setAction(&scene->_sequenceManager, scene, 710, &R2_GLOBALS._player, this, NULL); } else { @@ -5969,10 +6015,10 @@ bool Scene700::Actor6::startAction(CursorType action, Event &event) { } void Scene700::postInit(SceneObjectList *OwnerList) { + loadScene(700); if (R2_GLOBALS._sceneManager._previousScene == 900) - g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0)); + _sceneBounds = Rect(160, 0, 480, 200); - loadScene(700); R2_GLOBALS._v558B6.set(60, 0, 260, 200); SceneExt::postInit(); @@ -5994,7 +6040,7 @@ void Scene700::postInit(SceneObjectList *OwnerList) { _actor1.postInit(); _actor1.setup(700, 4, 1); - _actor1.setPosition(Common::Point(355 - ((R2_GLOBALS._v565E3 * 8) / 5), ((R2_GLOBALS._v565E1 + 20 ) / 5) - 12)); + _actor1.setPosition(Common::Point(355 - ((R2_GLOBALS._electromagnetZoom * 8) / 5), ((R2_GLOBALS._electromagnetChangeAmount + 20 ) / 5) - 12)); _actor1.fixPriority(10); _actor1.setDetails(700, 12, -1, 14, 1, (SceneItem *) NULL); @@ -6041,7 +6087,7 @@ void Scene700::postInit(SceneObjectList *OwnerList) { case 700: switch (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS)) { case 0: - if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) + if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) _actor5.setup(701, 2, 1); else _actor5.setup(701, 2, 8); @@ -6158,9 +6204,7 @@ void Scene700::signal() { } break; case 3: - R2_INVENTORY.setObjectScene(5, 600); - R2_INVENTORY.setObjectScene(16, 700); - R2_GLOBALS._player.enableControl(); + R2_GLOBALS._sceneManager.changeScene(600); break; case 4: _sceneMode = 5; @@ -6206,7 +6250,7 @@ void Scene700::signal() { _sceneMode = 17; _actor5.setup(701, 1, 8); _actor5.setDetails(700, 38, -1, -1, 3, (SceneItem *) NULL); - if ((R2_GLOBALS._v565E5 != 0) && (_actor5._position.x == _actor1._position.x + 1) && (_actor5._position.x == 148 - (((R2_GLOBALS._v565E1 + 10) / 5) * 4))) { + if ((R2_GLOBALS._v565E5 != 0) && (_actor5._position.x == _actor1._position.x + 1) && (_actor5._position.x == 148 - (((R2_GLOBALS._electromagnetChangeAmount + 10) / 5) * 4))) { _actor5.animate(ANIM_MODE_6, NULL); Common::Point pt(_actor5._position.x, _actor1._position.y + 120); NpcMover *mover = new NpcMover(); @@ -6231,7 +6275,7 @@ void Scene700::signal() { break; case 21: _actor5.fixPriority(77); - if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) + if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) _actor5.animate(ANIM_MODE_6, NULL); R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 700); @@ -6249,7 +6293,7 @@ void Scene700::signal() { case 706: _actor5.setDetails(700, 38, -1, -1, 3, (SceneItem *) NULL); _actor5.fixPriority(77); - if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) + if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) _actor5.animate(ANIM_MODE_6, NULL); R2_INVENTORY.setObjectScene(R2_ATTRACTOR_UNIT, 0); R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 700); @@ -6317,12 +6361,26 @@ bool Scene800::DeviceSlot::startAction(CursorType action, Event &event) { break; R2_GLOBALS._player.disableControl(); - scene->_reader.postInit(); + _lookLineNum = 27; + scene->_sceneMode = 809; if (R2_INVENTORY.getObjectScene(R2_OPTICAL_FIBRE) == 800) - scene->setAction(&scene->_sequenceManager1, scene, 814, &R2_GLOBALS._player, &scene->_reader, &scene->_opticalFibre, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 815, &R2_GLOBALS._player, &scene->_reader, &scene->_opticalFibre, NULL); else - scene->setAction(&scene->_sequenceManager1, scene, 804, &R2_GLOBALS._player, &scene->_reader, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 809, &R2_GLOBALS._player, &scene->_reader, NULL); + return true; + case R2_READER: + R2_GLOBALS._player.disableControl(); + scene->_reader.postInit(); + scene->_sceneMode = 804; + + if (R2_INVENTORY.getObjectScene(R2_OPTICAL_FIBRE) == 800) { + scene->setAction(&scene->_sequenceManager1, scene, 814, &R2_GLOBALS._player, + &scene->_reader, &scene->_opticalFibre, NULL); + } else { + scene->setAction(&scene->_sequenceManager1, scene, 804, &R2_GLOBALS._player, + &scene->_reader, NULL); + } return true; default: break; @@ -6416,8 +6474,8 @@ bool Scene800::Cabinet::startAction(CursorType action, Event &event) { /*--------------------------------------------------------------------------*/ void Scene800::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(800); + SceneExt::postInit(); _door.postInit(); _door.setVisage(800); @@ -6826,8 +6884,9 @@ void Scene825::doButtonPress(int buttonId) { _sceneText.setup(NO_TREATMENT_REQUIRED); } else { _button6._buttonId = 5; - + _sceneMode = 827; _object5.postInit(); + setAction(&_sequenceManager1, this, 827, &_object5, NULL); } } else { @@ -7006,8 +7065,8 @@ bool Scene850::Panel::startAction(CursorType action, Event &event) { /*--------------------------------------------------------------------------*/ void Scene850::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); loadScene(850); + SceneExt::postInit(); _liftDoor.postInit(); _liftDoor.setup(850, 2, 1); @@ -7103,44 +7162,47 @@ void Scene850::signal() { } /*-------------------------------------------------------------------------- - * Scene 900 - + * Scene 900 - Lander Bay 2 - Crane Controls * *--------------------------------------------------------------------------*/ -Scene900::Actor4::Actor4() { - _fieldA4 = 0; + +Scene900::Button::Button() { + _buttonId = 0; } -void Scene900::Actor4::synchronize(Serializer &s) { +void Scene900::Button::synchronize(Serializer &s) { SceneActor::synchronize(s); - s.syncAsSint16LE(_fieldA4); + s.syncAsSint16LE(_buttonId); } -void Scene900::Actor4::sub96135(int arg1) { - _fieldA4 = arg1; + +void Scene900::Button::initButton(int buttonId) { + _buttonId = buttonId; + postInit(); setDetails(900, -1, -1, -1, 2, (SceneItem *) NULL); } Scene900::Scene900() { _field412 = 0; - _field414 = 0; - _field416 = 0; + _magnetChangeAmount.x = 0; + _magnetChangeAmount.y = 0; } void Scene900::synchronize(Serializer &s) { SceneExt::synchronize(s); s.syncAsSint16LE(_field412); - s.syncAsSint16LE(_field414); - s.syncAsSint16LE(_field416); + s.syncAsSint16LE(_magnetChangeAmount.x); + s.syncAsSint16LE(_magnetChangeAmount.y); } -bool Scene900::Actor4::startAction(CursorType action, Event &event) { +bool Scene900::Button::startAction(CursorType action, Event &event) { Scene900 *scene = (Scene900 *)R2_GLOBALS._sceneManager._scene; if (action == CURSOR_USE) { R2_GLOBALS._sound2.play(14); - switch (_fieldA4) { + switch (_buttonId) { case 2: if (scene->_field412 == 1) { scene->_sceneMode = 2; @@ -7150,15 +7212,15 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) { scene->_aSound1.play(30); setup(900, 3, 11); R2_GLOBALS._v565E5 = 1; - if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS == 700)) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70) && (scene->_actor2._animateMode != ANIM_MODE_6)) { + if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS == 700)) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70) && (scene->_actor2._animateMode != ANIM_MODE_6)) { scene->_actor2.animate(ANIM_MODE_6, NULL); } else { - if (((scene->_actor3._percent * 49) / 100) + scene->_actor3._position.x == scene->_actor2._position.x) { - if (scene->_actor2._position.x == 166 - (R2_GLOBALS._v565E3 / 15)) { + if (((scene->_electromagnet._percent * 49) / 100) + scene->_electromagnet._position.x == scene->_actor2._position.x) { + if (scene->_actor2._position.x == 166 - (R2_GLOBALS._electromagnetZoom / 15)) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 4; - scene->_actor2._moveDiff.y = (scene->_actor2._position.y - (scene->_actor3._position.y + ((scene->_actor3._percent * 3) / 10) - 2)) / 9; - Common::Point pt(scene->_actor3._position.x + ((scene->_actor3._percent * 49) / 100), scene->_actor3._position.y + ((scene->_actor3._percent * 3) / 10) - 2); + scene->_actor2._moveDiff.y = (scene->_actor2._position.y - (scene->_electromagnet._position.y + ((scene->_electromagnet._percent * 3) / 10) - 2)) / 9; + Common::Point pt(scene->_electromagnet._position.x + ((scene->_electromagnet._percent * 49) / 100), scene->_electromagnet._position.y + ((scene->_electromagnet._percent * 3) / 10) - 2); NpcMover *mover = new NpcMover(); scene->_actor2.addMover(mover, &pt, this); scene->_actor2.animate(ANIM_MODE_6, NULL); @@ -7179,7 +7241,7 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) { scene->_sceneMode = 5; scene->_actor2.animate(ANIM_MODE_5, NULL); scene->_actor2._moveDiff.y = (166 - scene->_actor2._position.y) / 9; - Common::Point pt(scene->_actor2._position.x, 166 - (R2_GLOBALS._v565E3 / 15)); + Common::Point pt(scene->_actor2._position.x, 166 - (R2_GLOBALS._electromagnetZoom / 15)); NpcMover *mover = new NpcMover(); scene->_actor2.addMover(mover, &pt, this); } @@ -7196,30 +7258,30 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) { return true; break; case 4: - if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E3 != 0)) { + if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetZoom != 0)) { scene->_aSound1.play(38); - scene->_field416 = -5; + scene->_magnetChangeAmount.y = -5; } return true; break; case 5: - if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E3 < 135)) { + if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetZoom < 135)) { scene->_aSound1.play(38); - scene->_field416 = 5; + scene->_magnetChangeAmount.y = 5; } return true; break; case 6: - if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E1 > -10)) { + if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetChangeAmount > -10)) { scene->_aSound1.play(38); - scene->_field414 = -5; + scene->_magnetChangeAmount.x = -5; } return true; break; case 7: - if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E1 < 20)) { + if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetChangeAmount < 20)) { scene->_aSound1.play(38); - scene->_field414 = 5; + scene->_magnetChangeAmount.x = 5; } return true; break; @@ -7234,12 +7296,12 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) { default: if (scene->_field412 == 1) { R2_GLOBALS._player.disableControl(); - scene->_actor5.remove(); - scene->_actor6.remove(); - scene->_actor7.remove(); - scene->_actor8.remove(); - scene->_actor9.remove(); - scene->_actor10.remove(); + scene->_button2.remove(); + scene->_button3.remove(); + scene->_button4.remove(); + scene->_button5.remove(); + scene->_button6.remove(); + scene->_button7.remove(); R2_GLOBALS._sound2.play(37); scene->_sceneMode = 901; scene->setAction(&scene->_sequenceManager1, scene, 901, &scene->_actor1, this ,NULL); @@ -7252,10 +7314,8 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) { break; } } else if (action == CURSOR_LOOK) { - if ((_fieldA4 == 2) && (scene->_field412 == 2)) - SceneItem::display(900, 21, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); - else - SceneItem::display(900, _fieldA4, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); + SceneItem::display(900, ((_buttonId == 2) && (scene->_field412 == 2)) ? 21 : _buttonId + 11, + SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, 1, SET_Y, 20, SET_EXT_BGCOLOR, 7, -999); return true; } else { return SceneActor::startAction(action, event); @@ -7275,16 +7335,15 @@ void Scene900::postInit(SceneObjectList *OwnerList) { _actor1.postInit(); _actor1.setDetails(900, 3, -1, -1, 1, (SceneItem *) NULL); - _field414 = 0; - _field416 = 0; + _magnetChangeAmount.x = 0; + _magnetChangeAmount.y = 0; - _actor3.postInit(); - _actor3.fixPriority(1); - // useless, the original use it for debugging purposes: strcpy(_actor3._actorName, "Crane"); - _actor3.setup(900, 1, 2); - _actor3.setPosition(Common::Point(89, 0)); - _actor3._effect = 1; - _actor3.setDetails(900, 6, -1, 8, 1, (SceneItem *) NULL); + _electromagnet.postInit(); + _electromagnet.fixPriority(1); + _electromagnet.setup(900, 1, 2); + _electromagnet.setPosition(Common::Point(89, 0)); + _electromagnet._effect = 1; + _electromagnet.setDetails(900, 6, -1, 8, 1, (SceneItem *) NULL); if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) != 1) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) != 1)) { _actor2.postInit(); @@ -7294,7 +7353,7 @@ void Scene900::postInit(SceneObjectList *OwnerList) { if (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) { if (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) != 700) { _actor2.setup(901, 3, 2); - } else if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) { + } else if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) { _actor2.setup(901, 2, 1); } else { _actor2.setup(901, 2, 8); @@ -7306,7 +7365,7 @@ void Scene900::postInit(SceneObjectList *OwnerList) { if (R2_GLOBALS._v565E7 == 0) { _actor2.setup(901, 1, 8); // Original set two times the same values: skipped - _actor2.setPosition(Common::Point((((100 - ((R2_GLOBALS._v565EB * 350) / 100)) * 49) / 100) + ((R2_GLOBALS._v565E9 * _actor3._percent * 6) / 100) + 89, 166 - (R2_GLOBALS._v565EB / 3))); + _actor2.setPosition(Common::Point((((100 - ((R2_GLOBALS._v565EB * 350) / 100)) * 49) / 100) + ((R2_GLOBALS._v565E9 * _electromagnet._percent * 6) / 100) + 89, 166 - (R2_GLOBALS._v565EB / 3))); _actor2.changeZoom(((100 - ((R2_GLOBALS._v565EB * 350) / 100) + 52) / 10) * 10); } } @@ -7329,68 +7388,68 @@ void Scene900::signal() { _field412 = 1; R2_GLOBALS._sound2.play(37); - _actor5.remove(); - _actor6.remove(); - _actor7.remove(); - _actor8.remove(); - _actor9.remove(); - _actor10.remove(); + _button2.remove(); + _button3.remove(); + _button4.remove(); + _button5.remove(); + _button6.remove(); + _button7.remove(); - _actor5.sub96135(2); - _actor5.setup(900, 2, 1); - _actor5.setPosition(Common::Point(36, 166)); + _button2.initButton(2); + _button2.setup(900, 2, 1); + _button2.setPosition(Common::Point(36, 166)); - _actor6.sub96135(3); - _actor6.setup(900, 2, 5); - _actor6.setPosition(Common::Point(117, 166)); + _button3.initButton(3); + _button3.setup(900, 2, 5); + _button3.setPosition(Common::Point(117, 166)); break; case 2: _field412 = 2; - _actor5.remove(); - _actor6.remove(); + _button2.remove(); + _button3.remove(); - _actor5.sub96135(2); + _button2.initButton(2); if (R2_GLOBALS._v565E5 == 0) - _actor5.setup(900, 3, 9); + _button2.setup(900, 3, 9); else - _actor5.setup(900, 3, 11); - _actor5.setPosition(Common::Point(36, 166)); + _button2.setup(900, 3, 11); + _button2.setPosition(Common::Point(36, 166)); - _actor7.sub96135(5); - _actor7.setup(900, 3, 3); - _actor7.setPosition(Common::Point(76, 134)); + _button4.initButton(5); + _button4.setup(900, 3, 3); + _button4.setPosition(Common::Point(76, 134)); - _actor8.sub96135(4); - _actor8.setup(900, 3, 7); - _actor8.setPosition(Common::Point(76, 156)); + _button5.initButton(4); + _button5.setup(900, 3, 7); + _button5.setPosition(Common::Point(76, 156)); - _actor9.sub96135(6); - _actor9.setup(900, 3, 1); - _actor9.setPosition(Common::Point(55, 144)); + _button6.initButton(6); + _button6.setup(900, 3, 1); + _button6.setPosition(Common::Point(55, 144)); - _actor10.sub96135(7); - _actor10.setup(900, 3, 5); - _actor10.setPosition(Common::Point(99, 144)); + _button7.initButton(7); + _button7.setup(900, 3, 5); + _button7.setPosition(Common::Point(99, 144)); break; case 3: _field412 = 3; - _actor5.remove(); - _actor6.remove(); - _actor7.remove(); - _actor8.remove(); - _actor9.remove(); - _actor10.remove(); + _button2.remove(); + _button3.remove(); + _button4.remove(); + _button5.remove(); + _button6.remove(); + _button7.remove(); - _actor5.sub96135(8); - _actor5.setup(900, 4, 1); - _actor5.setPosition(Common::Point(36, 166)); + _button2.initButton(8); + _button2.setup(900, 4, 1); + _button2.setPosition(Common::Point(36, 166)); - _actor6.sub96135(9); - _actor6.setup(900, 4, 5); - _actor6.setPosition(Common::Point(117, 166)); + _button3.initButton(9); + _button3.setup(900, 4, 5); + _button3.setPosition(Common::Point(117, 166)); break; case 4: _sceneMode = 0; @@ -7404,9 +7463,9 @@ void Scene900::signal() { _actor1.setup(900, 1, 1); - _actor4.sub96135(1); - _actor4.setup(900, 1, 3); - _actor4.setPosition(Common::Point(77, 168)); + _button1.initButton(1); + _button1.setup(900, 1, 3); + _button1.setPosition(Common::Point(77, 168)); _sceneMode = 1; signal(); @@ -7425,26 +7484,28 @@ void Scene900::signal() { } void Scene900::dispatch() { - if (_field416 != 0) { - if (_field416 < 0) { - R2_GLOBALS._v565E3--; - ++_field416; + if (_magnetChangeAmount.y != 0) { + if (_magnetChangeAmount.y < 0) { + R2_GLOBALS._electromagnetZoom--; + ++_magnetChangeAmount.y; } else { - ++R2_GLOBALS._v565E3; - _field416--; + ++R2_GLOBALS._electromagnetZoom; + _magnetChangeAmount.y--; } } - if (_field414 != 0) { - R2_GLOBALS._v565E1--; - ++_field414; - } else { - ++R2_GLOBALS._v565E1; - _field414++; + if (_magnetChangeAmount.x != 0) { + if (_magnetChangeAmount.x < 0) { + R2_GLOBALS._electromagnetChangeAmount--; + ++_magnetChangeAmount.x; + } else { + ++R2_GLOBALS._electromagnetChangeAmount; + _magnetChangeAmount.x--; + } } if (R2_GLOBALS._sceneObjects->contains(&_actor2)) { - if ((R2_GLOBALS._v565E5 != 0) && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) { + if ((R2_GLOBALS._v565E5 != 0) && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) { if ((_actor2._frame > 1) && (_actor2._animateMode != ANIM_MODE_6)) _actor2.animate(ANIM_MODE_6, NULL); } else { @@ -7453,17 +7514,17 @@ void Scene900::dispatch() { } } - _actor3.changeZoom(100 - ((R2_GLOBALS._v565E3 * 70) / 100)); - _actor3.setPosition(Common::Point(((_actor3._percent * R2_GLOBALS._v565E1 * 6) / 100) + 89, R2_GLOBALS._v565E3)); + _electromagnet.changeZoom(100 - ((R2_GLOBALS._electromagnetZoom * 70) / 100)); + _electromagnet.setPosition(Common::Point(((_electromagnet._percent * R2_GLOBALS._electromagnetChangeAmount * 6) / 100) + 89, R2_GLOBALS._electromagnetZoom)); if ((R2_GLOBALS._sceneObjects->contains(&_actor2)) && (R2_GLOBALS._v565E7 != 0) && (!_actor2._mover) && (_actor2._animateMode == ANIM_MODE_NONE)) { - _actor2.setPosition(Common::Point(_actor3._position.x + ((_actor3._percent * 49) / 100), _actor3._position.y + ((_actor3._percent * 3) / 10))); - if (R2_GLOBALS._v565E3 >= 75) { + _actor2.setPosition(Common::Point(_electromagnet._position.x + ((_electromagnet._percent * 49) / 100), _electromagnet._position.y + ((_electromagnet._percent * 3) / 10))); + if (R2_GLOBALS._electromagnetZoom >= 75) { _actor2.setup(901, 1, 1); - _actor2.changeZoom(((_actor3._percent + 52) / 10) * 10); + _actor2.changeZoom(((_electromagnet._percent + 52) / 10) * 10); } else { _actor2.setup(901, 5, 1); - _actor2.changeZoom(((_actor3._percent / 10) * 10) + 30); + _actor2.changeZoom(((_electromagnet._percent / 10) * 10) + 30); } } Scene::dispatch(); diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.h b/engines/tsage/ringworld2/ringworld2_scenes0.h index 2f52f9578f..bc30743aca 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.h +++ b/engines/tsage/ringworld2/ringworld2_scenes0.h @@ -126,7 +126,7 @@ class Scene125: public SceneExt { }; /* Items */ - class Item4: public NamedHotspot { + class DiskSlot: public NamedHotspot { public: virtual bool startAction(CursorType action, Event &event); }; @@ -135,8 +135,8 @@ public: ScenePalette _palette; ASoundExt _sound1; NamedHotspot _background, _item2, _item3; - Item4 _item4; - SceneActor _object1, _object2, _object3, _object4, _object5, _object6, _object7; + DiskSlot _diskSlot; + SceneActor _object1, _object2, _object3, _object4, _object5, _object6, _infoDisk; Icon _icon1, _icon2, _icon3, _icon4, _icon5, _icon6; SequenceManager _sequenceManager; SceneText _sceneText; @@ -277,9 +277,7 @@ class Scene205: public SceneExt { public: int _x100, _y100; public: - Object(); - - virtual void synchronize(Serializer &s); + // TODO: Check if this derives from DataManager? and flesh out }; private: void setup(); @@ -453,7 +451,7 @@ private: Common::String parseMessage(const Common::String &msg); public: int _field412, _iconFontNumber, _field416, _field418; - int _field41A, _field41C, _field41E, _field420; + int _field41A, _field41C, _field41E, _scannerLocation; int _soundCount, _soundIndex; int _soundQueue[10]; SpeakerQuinn _quinnSpeaker; @@ -461,7 +459,7 @@ public: SceneHotspot _background, _item2; SceneObject _object1, _object2, _object3, _object4, _object5; SceneObject _object6, _object7, _object8, _object9, _object10; - SceneObject _object11, _object12, _object13; + SceneObject _object11, _object12, _scannerTab; SceneObject _objList[4]; Icon _icon1, _icon2, _icon3, _icon4, _icon5, _icon6; ASoundExt _sound1; @@ -615,7 +613,7 @@ public: }; class Scene600 : public SceneExt { - class Item1 : public NamedHotspot { + class CompartmentHotspot : public NamedHotspot { public: virtual bool startAction(CursorType action, Event &event); }; @@ -628,17 +626,17 @@ class Scene600 : public SceneExt { public: virtual void signal(); virtual bool startAction(CursorType action, Event &event); - virtual void draw(); + virtual GfxSurface getFrame(); }; - class Actor5 : public SceneActor { + class Doorway : public SceneActor { public: virtual bool startAction(CursorType action, Event &event); }; - class Actor6 : public SceneActor { + class Laser : public SceneActor { public: virtual bool startAction(CursorType action, Event &event); }; - class Actor7 : public SceneActor { + class Aerosol : public SceneActor { public: virtual bool startAction(CursorType action, Event &event); }; @@ -648,24 +646,24 @@ class Scene600 : public SceneExt { }; public: int _field412; - Item1 _item1; - Item1 _item2; - Item1 _item3; + CompartmentHotspot _background; + CompartmentHotspot _item2; + CompartmentHotspot _item3; Item4 _item4; - Item1 _item5; + CompartmentHotspot _item5; BackgroundSceneObject _object1; SceneActor _actor1; SceneActor _actor2; SceneActor _actor3; Actor4 _actor4; - Actor5 _actor5; - Actor6 _actor6; - Actor7 _actor7; + Doorway _doorway; + Laser _laser; + Aerosol _aerosol; Actor8 _actor8; ASoundExt _aSound1; SequenceManager _sequenceManager1; SequenceManager _sequenceManager2; - byte _fieldAD2[256]; + byte _pixelMap[256]; Scene600(); virtual void postInit(SceneObjectList *OwnerList = NULL); @@ -865,30 +863,29 @@ public: }; class Scene900 : public SceneExt { - class Actor4 : public SceneActor { + class Button : public SceneActor { public: - int _fieldA4; + int _buttonId; - Actor4(); - void sub96135(int arg1); + Button(); + void initButton(int buttonId); virtual void synchronize(Serializer &s); virtual bool startAction(CursorType action, Event &event); }; public: int _field412; - int _field414; - int _field416; + Common::Point _magnetChangeAmount; NamedHotspot _item1; SceneActor _actor1; SceneActor _actor2; - SceneActor _actor3; - Actor4 _actor4; - Actor4 _actor5; - Actor4 _actor6; - Actor4 _actor7; - Actor4 _actor8; - Actor4 _actor9; - Actor4 _actor10; + SceneActor _electromagnet; + Button _button1; + Button _button2; + Button _button3; + Button _button4; + Button _button5; + Button _button6; + Button _button7; ASoundExt _aSound1; SequenceManager _sequenceManager1; diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp index af62ab6916..4e9d019f01 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp @@ -30,9 +30,452 @@ namespace TsAGE { namespace Ringworld2 { /*-------------------------------------------------------------------------- + * Scene 1000 - Cutscene scene + * + *--------------------------------------------------------------------------*/ + +Scene1000::Scene1000(): SceneExt() { + R2_GLOBALS._sceneManager._hasPalette = false; + R2_GLOBALS._uiElements._active = false; + _gameTextSpeaker._displayMode = 9; + _fieldD2E = 0; +} + +void Scene1000::postInit(SceneObjectList *OwnerList) { + loadBlankScene(); + SceneExt::postInit(); + + _stripManager.addSpeaker(&_gameTextSpeaker); + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player.hide(); + R2_GLOBALS._player.disableControl(); + + switch (R2_GLOBALS._sceneManager._previousScene) { + case 300: + _sceneMode = R2_GLOBALS.getFlag(57) ? 40 : 0; + break; + case 1010: + _sceneMode = 30; + break; + case 1100: + _sceneMode = 10; + break; + case 1530: + _sceneMode = 20; + break; + case 2500: + _sceneMode = 100; + break; + case 2800: + _sceneMode = 2800; + break; + case 3100: + if (R2_GLOBALS._player._oldCharacterScene[R2_QUINN] == 1000) + _sceneMode = 90; + else + _sceneMode = 80; + break; + case 3500: + _sceneMode = 50; + break; + case 3700: + _sceneMode = 60; + break; + default: + _sceneMode = 999; + break; + } + + R2_GLOBALS._uiElements._active = false; + setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL); +} + +void Scene1000::remove() { + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._scenePalette.setEntry(255, 0xff, 0xff, 0xff); + SceneExt::remove(); +} + +void Scene1000::signal() { + ScenePalette scenePalette1, scenePalette2; + uint32 black = 0; + + switch (_sceneMode++) { + case 0: + // TODO: Sort out values + R2_GLOBALS._gfxColors.foreground = 191; + R2_GLOBALS._gfxColors.background = 144; + R2_GLOBALS._fontColors.background = 224; + R2_GLOBALS._fontColors.foreground = 119; + + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer.load(5, this); + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + + _animationPlayer.dispatch(); + _fieldD2E = 1; + + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound1.play(67); + break; + + case 1: + R2_GLOBALS._sound1.fadeOut2(NULL); + + // TODO: Sort out values + R2_GLOBALS._gfxColors.foreground = 191; + R2_GLOBALS._gfxColors.background = 144; + R2_GLOBALS._fontColors.background = 224; + R2_GLOBALS._fontColors.foreground = 119; + + R2_GLOBALS._scenePalette.loadPalette(0); + loadScene(9999); + + R2_GLOBALS._player.setup(1140, 1, 1); + R2_GLOBALS._player.setPosition(Common::Point(160, 100)); + R2_GLOBALS._player.show(); + + _field412 = 0; + _stripManager.start(29, this); + break; + + case 2: + if (R2_GLOBALS._speechSubtitles & SPEECH_TEXT) { + setAction(&_sequenceManager1, this, 1, &R2_GLOBALS._player, NULL); + } else { + if (++_field412 < 3) + _sceneMode = 2; + + setAction(&_sequenceManager1, this, 2, &R2_GLOBALS._player, NULL); + } + break; + + case 3: + // TODO: Sort out values + R2_GLOBALS._gfxColors.foreground = 191; + R2_GLOBALS._gfxColors.background = 144; + R2_GLOBALS._fontColors.background = 224; + R2_GLOBALS._fontColors.foreground = 119; + + for (int percent = 100; percent >= 0; percent -= 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(7, this); + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound2.play(81); + R2_GLOBALS._sound1.play(80); + break; + + case 4: + // TODO: Sort out values + R2_GLOBALS._gfxColors.foreground = 191; + R2_GLOBALS._gfxColors.background = 144; + R2_GLOBALS._fontColors.background = 224; + R2_GLOBALS._fontColors.foreground = 119; + + R2_GLOBALS._sound2.fadeOut2(NULL); + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._sceneManager.changeScene(1100); + break; + + case 10: + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(6, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound1.play(55); + break; + + case 11: + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(300); + break; + + case 20: + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(8, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + break; + + case 21: + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(1530); + break; + + case 30: + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(17, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound2.play(91); + break; + + case 31: + R2_GLOBALS._sound2.fadeOut2(NULL); + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS.setFlag(51); + R2_GLOBALS._sceneManager.changeScene(300); + break; + + case 40: + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(18, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound2.play(90); + break; + + case 41: + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(1010); + break; + + case 50: + R2_GLOBALS._sound2.play(306); + for (int percent = 100; percent >= 0; percent -= 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(13, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + break; + + case 51: + R2_GLOBALS._sound2.stop(); + R2_GLOBALS._sound2.play(307); + R2_GLOBALS._sound1.play(308); + + for (int percent = 100; percent >= 0; percent -= 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(14, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + break; + + case 52: + R2_GLOBALS._sound2.fadeOut2(NULL); + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(3350); + break; + + case 60: + R2_GLOBALS._sound1.play(333); + + for (int percent = 100; percent >= 0; percent -= 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(12, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + break; + + case 61: + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(160); + break; + + case 70: + R2_GLOBALS._sound2.play(113); + for (int percent = 100; percent >= 0; percent -= 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(9, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + break; + + case 71: + case 81: + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._sound2.fadeOut2(NULL); + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(3100); + break; + + case 80: + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(10, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound1.play(242); + R2_GLOBALS._sound2.play(286); + break; + + case 90: + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(11, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + + R2_GLOBALS._sound1.play(277); + break; + + case 91: + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._player._characterIndex = R2_SEEKER; + R2_GLOBALS._player._oldCharacterScene[R2_SEEKER] = 3100; + R2_GLOBALS._sceneManager.changeScene(2500); + break; + + case 100: + R2_GLOBALS._sound1.play(304); + R2_GLOBALS._sound2.play(82); + + _animationPlayer._paletteMode = ANIMPALMODE_NONE; + _animationPlayer._objectMode = ANIMOBJMODE_2; + _animationPlayer.load(19, this); + + R2_GLOBALS._scenePalette.loadPalette(_animationPlayer._subData._palData, 0, 256); + R2_GLOBALS._sceneManager._hasPalette = false; + _animationPlayer.dispatch(); + + _fieldD2E = 1; + R2_GLOBALS._scenePalette.fade((const byte *)&black, 1, 0); + for (int percent = 0; percent < 100; percent += 5) + R2_GLOBALS._scenePalette.fade((const byte *)&black, true, percent); + break; + + case 101: + R2_GLOBALS._sound1.fadeOut2(NULL); + R2_GLOBALS._sound2.fadeOut2(NULL); + R2_GLOBALS._scenePalette.loadPalette(0); + R2_GLOBALS._sceneManager.changeScene(3500); + break; + } +} + +void Scene1000::dispatch() { + if (_fieldD2E) { + if (_animationPlayer.isCompleted()) { + _fieldD2E = 0; + _animationPlayer.close(); + _animationPlayer.remove(); + + if (_sceneMode == 52) + _endHandler = this; + } else { + _animationPlayer.dispatch(); + } + } + + Scene::dispatch(); +} + + +/*-------------------------------------------------------------------------- * Scene 1010 - Cutscene: A pixel lost in space! * *--------------------------------------------------------------------------*/ + void Scene1010::postInit(SceneObjectList *OwnerList) { SceneExt::postInit(); loadScene(1010); @@ -229,7 +672,7 @@ void Scene1100::synchronize(Serializer &s) { s.syncAsSint16LE(_field414); } -bool Scene1100::Actor16::startAction(CursorType action, Event &event) { +bool Scene1100::Seeker::startAction(CursorType action, Event &event) { Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene; if (action != CURSOR_TALK) @@ -263,7 +706,7 @@ bool Scene1100::Actor16::startAction(CursorType action, Event &event) { return true; } -bool Scene1100::Actor17::startAction(CursorType action, Event &event) { +bool Scene1100::Trooper::startAction(CursorType action, Event &event) { Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene; switch (action) { @@ -271,7 +714,7 @@ bool Scene1100::Actor17::startAction(CursorType action, Event &event) { if (_visage == 1105) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 1114; - scene->setAction(&scene->_sequenceManager1, scene, 1114, &R2_GLOBALS._player, &scene->_actor17, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 1114, &R2_GLOBALS._player, &scene->_trooper, NULL); return true; } else { return SceneActor::startAction(action, event); @@ -284,19 +727,19 @@ bool Scene1100::Actor17::startAction(CursorType action, Event &event) { R2_GLOBALS._player.disableControl(); if (R2_GLOBALS._player._characterIndex == 1) { scene->_sceneMode = 1112; - scene->setAction(&scene->_sequenceManager1, scene, 1112, &R2_GLOBALS._player, &scene->_actor17, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 1112, &R2_GLOBALS._player, &scene->_trooper, NULL); } else { scene->_sceneMode = 1115; - scene->setAction(&scene->_sequenceManager1, scene, 1115, &R2_GLOBALS._player, &scene->_actor17, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 1115, &R2_GLOBALS._player, &scene->_trooper, NULL); } return true; } else if (_strip == 2) { R2_GLOBALS._player.disableControl(); scene->_sceneMode = 1113; if (R2_GLOBALS._player._characterIndex == 1) { - scene->setAction(&scene->_sequenceManager1, scene, 1113, &R2_GLOBALS._player, &scene->_actor17, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 1113, &R2_GLOBALS._player, &scene->_trooper, NULL); } else { - scene->setAction(&scene->_sequenceManager1, scene, 1118, &R2_GLOBALS._player, &scene->_actor17, NULL); + scene->setAction(&scene->_sequenceManager1, scene, 1118, &R2_GLOBALS._player, &scene->_trooper, NULL); } return true; } else { @@ -309,7 +752,7 @@ bool Scene1100::Actor17::startAction(CursorType action, Event &event) { } } -bool Scene1100::Actor18::startAction(CursorType action, Event &event) { +bool Scene1100::Chief::startAction(CursorType action, Event &event) { Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene; if ((action == CURSOR_TALK) && (!R2_GLOBALS.getFlag(54)) && (R2_GLOBALS.getFlag(52))) { @@ -381,28 +824,28 @@ void Scene1100::postInit(SceneObjectList *OwnerList) { R2_GLOBALS._player.hide(); R2_GLOBALS._player.disableControl(); - _actor16.postInit(); - _actor16.hide(); + _seeker.postInit(); + _seeker.hide(); if (R2_GLOBALS._player._characterIndex == 1) - _actor16.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL); + _seeker.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL); else - _actor16.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL); + _seeker.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL); - _actor18.postInit(); - _actor18.setup(1113, 3, 1); - _actor18.setPosition(Common::Point(181, 125)); - _actor18.fixPriority(110); + _chief.postInit(); + _chief.setup(1113, 3, 1); + _chief.setPosition(Common::Point(181, 125)); + _chief.fixPriority(110); if (R2_GLOBALS.getFlag(54)) - _actor18.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL); + _chief.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL); else - _actor18.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL); + _chief.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL); - _actor17.postInit(); - _actor17.setup(1105, 3, 1); - _actor17.setPosition(Common::Point(312, 165)); - _actor17._numFrames = 5; - _actor17.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL); + _trooper.postInit(); + _trooper.setup(1105, 3, 1); + _trooper.setPosition(Common::Point(312, 165)); + _trooper._numFrames = 5; + _trooper.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL); _actor1.postInit(); _actor1.setup(1512, 1, 1); @@ -464,66 +907,66 @@ void Scene1100::postInit(SceneObjectList *OwnerList) { R2_GLOBALS._player.postInit(); R2_GLOBALS._player.animate(ANIM_MODE_1, NULL); - _actor16.postInit(); + _seeker.postInit(); if (R2_GLOBALS.getFlag(52)) { if (R2_GLOBALS._player._characterIndex == 1) { R2_GLOBALS._player.setup(19, 7, 1); - _actor16.setup(29, 6, 1); + _seeker.setup(29, 6, 1); } else { R2_GLOBALS._player.setup(29, 7, 1); - _actor16.setup(19, 6, 1); + _seeker.setup(19, 6, 1); } R2_GLOBALS._player.setPosition(Common::Point(140, 124)); - _actor16.setPosition(Common::Point(237, 134)); + _seeker.setPosition(Common::Point(237, 134)); R2_GLOBALS._player.enableControl(); } else { if (R2_GLOBALS._player._characterIndex == 1) { R2_GLOBALS._player.setup(1107, 2, 1); - _actor16.setup(1107, 4, 1); + _seeker.setup(1107, 4, 1); R2_GLOBALS._player.setPosition(Common::Point(247, 169)); - _actor16.setPosition(Common::Point(213, 169)); + _seeker.setPosition(Common::Point(213, 169)); } else { R2_GLOBALS._player.setup(1107, 4, 1); - _actor16.setup(1107, 2, 1); + _seeker.setup(1107, 2, 1); R2_GLOBALS._player.setPosition(Common::Point(213, 169)); - _actor16.setPosition(Common::Point(247, 169)); + _seeker.setPosition(Common::Point(247, 169)); } R2_GLOBALS._player.enableControl(); R2_GLOBALS._player._canWalk = false; } if (R2_GLOBALS._player._characterIndex == 1) - _actor16.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL); + _seeker.setDetails(9002, 0, 4, 3, 1, (SceneItem *) NULL); else - _actor16.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL); + _seeker.setDetails(9001, 0, 5, 3, 1, (SceneItem *) NULL); - _actor18.postInit(); - _actor18.setup(1113, 3, 1); - _actor18.setPosition(Common::Point(181, 125)); - _actor18.fixPriority(110); + _chief.postInit(); + _chief.setup(1113, 3, 1); + _chief.setPosition(Common::Point(181, 125)); + _chief.fixPriority(110); if (R2_GLOBALS.getFlag(54)) - _actor18.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL); + _chief.setDetails(1100, 4, -1, -1, 1, (SceneItem *) NULL); else - _actor18.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL); + _chief.setDetails(1100, 3, -1, -1, 1, (SceneItem *) NULL); if (!R2_GLOBALS.getFlag(52)) { - _actor17.postInit(); + _trooper.postInit(); if (R2_GLOBALS.getFlag(53)) - _actor17.setup(1106, 2, 4); + _trooper.setup(1106, 2, 4); else - _actor17.setup(1105, 4, 4); + _trooper.setup(1105, 4, 4); - _actor17.setPosition(Common::Point(17, 54)); - _actor17._numFrames = 5; + _trooper.setPosition(Common::Point(17, 54)); + _trooper._numFrames = 5; if (R2_GLOBALS.getFlag(53)) - _actor17.setDetails(1100, 28, -1, -1, 1, (SceneItem *) NULL); + _trooper.setDetails(1100, 28, -1, -1, 1, (SceneItem *) NULL); else - _actor17.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL); + _trooper.setDetails(1100, 22, 23, 24, 1, (SceneItem *) NULL); - _actor17.fixPriority(200); + _trooper.fixPriority(200); } _actor1.postInit(); _actor1.setup(1512, 1, 1); @@ -583,9 +1026,9 @@ void Scene1100::signal() { } break; case 4: - _actor18.postInit(); - _actor18.show(); - setAction(&_sequenceManager1, this, 1101, &_actor18, &_actor10, NULL); + _chief.postInit(); + _chief.show(); + setAction(&_sequenceManager1, this, 1101, &_chief, &_actor10, NULL); break; case 5: _actor13.postInit(); @@ -611,15 +1054,15 @@ void Scene1100::signal() { } break; case 7: - setAction(&_sequenceManager1, this, 1103, &_actor18, &_actor10); + setAction(&_sequenceManager1, this, 1103, &_chief, &_actor10); break; case 8: R2_GLOBALS._player._effect = 0; _actor11.postInit(); - setAction(&_sequenceManager1, this, 1105, &R2_GLOBALS._player, &_actor10, &_actor11, &_actor18, NULL); + setAction(&_sequenceManager1, this, 1105, &R2_GLOBALS._player, &_actor10, &_actor11, &_chief, NULL); break; case 9: - _object1.proc27(); + _object1.copySceneToBackground(); _actor15.postInit(); _actor15.setup(1103, 2, 1); @@ -633,7 +1076,7 @@ void Scene1100::signal() { _actor13.setAction(&_sequenceManager2, this, 1108, &_actor13, NULL); break; case 11: { - setAction(&_sequenceManager1, this, 1116, &_actor11, &_actor10, &_actor12, NULL); + setAction(&_sequenceManager1, this, 1106, &_actor11, &_actor10, &_actor12, NULL); R2_GLOBALS._player._effect = 5; R2_GLOBALS._player.setup(1102, 3, 2); R2_GLOBALS._player.setPosition(Common::Point(-50, 131)); @@ -647,8 +1090,8 @@ void Scene1100::signal() { // Really nothing break; case 13: - _actor17.postInit(); - R2_GLOBALS._scrollFollower = &_actor17; + _trooper.postInit(); + R2_GLOBALS._scrollFollower = &_trooper; _actor11.setup(1100, 2, 1); _actor11.setPosition(Common::Point(408, 121)); @@ -656,7 +1099,7 @@ void Scene1100::signal() { _actor10.setup(1100, 3, 5); _actor10.setPosition(Common::Point(409, 121)); - setAction(&_sequenceManager1, this, 1104, &_actor17, NULL); + setAction(&_sequenceManager1, this, 1104, &_trooper, NULL); break; case 14: setAction(&_sequenceManager1, this, 1100, &_actor11, &_actor10, NULL); @@ -672,14 +1115,14 @@ void Scene1100::signal() { break; case 21: { R2_GLOBALS._sound2.play(92); - _actor17.animate(ANIM_MODE_5, NULL); + _trooper.animate(ANIM_MODE_5, NULL); Common::Point pt(187, 45); NpcMover *mover = new NpcMover(); _actor1.addMover(mover, &pt, this); } break; case 22: - setAction(&_sequenceManager1, this, 1110, &_actor16, &R2_GLOBALS._player, NULL); + setAction(&_sequenceManager1, this, 1110, &_seeker, &R2_GLOBALS._player, NULL); break; case 23: R2_GLOBALS._player.disableControl(); @@ -693,34 +1136,37 @@ void Scene1100::signal() { break; case 25: R2_GLOBALS._player.disableControl(); - _stripManager._lookupList[9] = 1; - _stripManager._lookupList[10] = 1; - _stripManager._lookupList[11] = 1; + R2_GLOBALS._stripManager_lookupList[9] = 1; + R2_GLOBALS._stripManager_lookupList[10] = 1; + R2_GLOBALS._stripManager_lookupList[11] = 1; R2_GLOBALS._sound1.play(95); - setAction(&_sequenceManager1, this, 1111, &_actor17, &R2_GLOBALS._player, &_actor16, NULL); + setAction(&_sequenceManager1, this, 1111, &_trooper, &R2_GLOBALS._player, &_seeker, NULL); break; case 26: R2_GLOBALS._player.disableControl(); - R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + R2_GLOBALS._events.setCursor(CURSOR_ARROW); _stripManager.start(302, this); break; case 27: R2_GLOBALS._player.disableControl(); - setAction(&_sequenceManager1, this, 1120, &_actor16, &R2_GLOBALS._player, NULL); + setAction(&_sequenceManager1, this, 1120, &_seeker, &R2_GLOBALS._player, NULL); break; case 28: R2_GLOBALS._player.disableControl(); - R2_GLOBALS._events.setCursor(CURSOR_CROSSHAIRS); + R2_GLOBALS._events.setCursor(CURSOR_ARROW); _stripManager.start(303, this); break; + case 29: + case 50: + R2_GLOBALS._player.enableControl(CURSOR_USE); + R2_GLOBALS._player._canWalk = false; + break; case 51: R2_GLOBALS.setFlag(53); - _actor17.setDetails(1100, 28, -1, -1, 3, (SceneItem *) NULL); - // No break on purpose - case 50: - // No break on purpose - case 29: + _trooper.setDetails(1100, 28, -1, -1, 3, (SceneItem *) NULL); + R2_GLOBALS._player.enableControl(CURSOR_USE); + R2_GLOBALS._player._canWalk = false; break; case 52: R2_GLOBALS._sound1.play(98); @@ -729,10 +1175,10 @@ void Scene1100::signal() { _sceneMode = 1116; if (R2_GLOBALS._player._characterIndex == 1) { setAction(&_sequenceManager1, this, 1116, &R2_GLOBALS._player, NULL); - _actor16.setAction(&_sequenceManager2, NULL, 1123, &_actor16, NULL); + _seeker.setAction(&_sequenceManager2, NULL, 1123, &_seeker, NULL); } else { setAction(&_sequenceManager1, this, 1124, &R2_GLOBALS._player, NULL); - _actor16.setAction(&_sequenceManager2, NULL, 1117, &_actor16, NULL); + _seeker.setAction(&_sequenceManager2, NULL, 1117, &_seeker, NULL); } break; case 53: @@ -757,10 +1203,10 @@ void Scene1100::signal() { } break; case 54: - if (_stripManager._field2E8 == 1) { + if (_stripManager._exitMode == 1) { R2_GLOBALS._player.disableControl(); _sceneMode = 1125; - setAction(&_sequenceManager1, this, 1125, &R2_GLOBALS._player, &_actor16, NULL); + setAction(&_sequenceManager1, this, 1125, &R2_GLOBALS._player, &_seeker, NULL); } else R2_GLOBALS._player.enableControl(CURSOR_TALK); break; @@ -801,9 +1247,9 @@ void Scene1100::signal() { break; case 1116: R2_GLOBALS._player.enableControl(CURSOR_ARROW); - _stripManager._lookupList[9] = 1; - _stripManager._lookupList[10] = 1; - _stripManager._lookupList[11] = 1; + R2_GLOBALS._stripManager_lookupList[9] = 1; + R2_GLOBALS._stripManager_lookupList[10] = 1; + R2_GLOBALS._stripManager_lookupList[11] = 1; break; case 1125: { _sceneMode = 99; @@ -858,16 +1304,17 @@ void Scene1100::saveCharacter(int characterIndex) { } /*-------------------------------------------------------------------------- - * Scene 1200 - + * Scene 1200 - Air Ducts Maze * *--------------------------------------------------------------------------*/ + Scene1200::Scene1200() { _field412 = 0; _field414 = 0; _field416 = 0; _field418 = 0; _field41A = 0; - _field41C = 1; //CHECKME: Only if fixup_flag == 6?? + _fixupMaze = false; } void Scene1200::synchronize(Serializer &s) { @@ -878,20 +1325,13 @@ void Scene1200::synchronize(Serializer &s) { s.syncAsSint16LE(_field416); s.syncAsSint16LE(_field418); s.syncAsSint16LE(_field41A); - s.syncAsSint16LE(_field41C); + s.syncAsSint16LE(_fixupMaze); } -Scene1200::Area1::Area1() { - _field20 = 0; -} - -void Scene1200::Area1::synchronize(Serializer &s) { - SceneArea::synchronize(s); - - s.syncAsByte(_field20); +Scene1200::LaserPanel::LaserPanel() { } -void Scene1200::Area1::Actor3::init(int state) { +void Scene1200::LaserPanel::Jumper::init(int state) { _state = state; SceneActor::postInit(); @@ -912,6 +1352,7 @@ void Scene1200::Area1::Actor3::init(int state) { default: break; } + break; case 2: switch (R2_GLOBALS._v56AA7) { case 1: @@ -929,6 +1370,7 @@ void Scene1200::Area1::Actor3::init(int state) { default: break; } + break; case 3: switch (R2_GLOBALS._v56AA8) { case 1: @@ -942,6 +1384,7 @@ void Scene1200::Area1::Actor3::init(int state) { default: break; } + break; default: break; } @@ -949,7 +1392,7 @@ void Scene1200::Area1::Actor3::init(int state) { setDetails(1200, 12, -1, -1, 2, (SceneItem *) NULL); } -bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) { +bool Scene1200::LaserPanel::Jumper::startAction(CursorType action, Event &event) { if (action != CURSOR_USE) return SceneActor::startAction(action, event); @@ -1018,7 +1461,7 @@ bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) { return true; } -void Scene1200::Area1::postInit(SceneObjectList *OwnerList) { +void Scene1200::LaserPanel::postInit(SceneObjectList *OwnerList) { Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; scene->_field41A = 1; @@ -1026,81 +1469,35 @@ void Scene1200::Area1::postInit(SceneObjectList *OwnerList) { proc12(1003, 1, 1, 100, 40); proc13(1200, 11, -1, -1); R2_GLOBALS._sound2.play(259); - _actor3.init(1); - _actor4.init(2); - _actor5.init(3); + _jumper1.init(1); + _jumper2.init(2); + _jumper3.init(3); R2_GLOBALS._player._canWalk = false; } -void Scene1200::Area1::remove() { +void Scene1200::LaserPanel::remove() { Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; scene->_field41A = 0; warning("Unexpected _sceneAreas.remove() call"); -// scene->_sceneAreas.remove(&_actor3); -// scene->_sceneAreas.remove(&_actor4); -// scene->_sceneAreas.remove(&_actor5); - _actor3.remove(); - _actor4.remove(); - _actor5.remove(); +// scene->_sceneAreas.remove(&_jumper1); +// scene->_sceneAreas.remove(&_jumper2); +// scene->_sceneAreas.remove(&_jumper3); + _jumper1.remove(); + _jumper2.remove(); + _jumper3.remove(); // sub201EA R2_GLOBALS._sceneItems.remove((SceneItem *)this); - _actor2.remove(); + _object1.remove(); SceneArea::remove(); R2_GLOBALS._insetUp--; - // R2_GLOBALS._player._canWalk = true; } -void Scene1200::Area1::process(Event &event) { - if (_field20 != R2_GLOBALS._insetUp) - return; - - CursorType cursor = R2_GLOBALS._events.getCursor(); - - if (_actor2._bounds.contains(event.mousePos.x + g_globals->gfxManager()._bounds.left , event.mousePos.y)) { - if (cursor == _cursorNum) { - warning("TODO: _cursorState = ???"); - R2_GLOBALS._events.setCursor(_savedCursorNum); //, _cursorState); - } - } else if (event.mousePos.y < 168) { - if (cursor != _cursorNum) { - _savedCursorNum = cursor; - warning("TODO: _cursorState = ???"); - R2_GLOBALS._events.setCursor(CURSOR_INVALID); - } - if (event.eventType == EVENT_BUTTON_DOWN) { - event.handled = true; - warning("TODO: _cursorState = ???"); - R2_GLOBALS._events.setCursor(_savedCursorNum); //, _cursorState); - remove(); - } - } -} - -void Scene1200::Area1::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) { - Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene; - - _actor2.postInit(); - _actor2.setup(visage, stripFrameNum, frameNum); - _actor2.setPosition(Common::Point(posX, posY)); - _actor2.fixPriority(250); - _cursorNum = CURSOR_INVALID; - scene->_sceneAreas.push_front(this); - ++R2_GLOBALS._insetUp; - _field20 = R2_GLOBALS._insetUp; -} - -void Scene1200::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) { - _actor2.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL); -} - void Scene1200::postInit(SceneObjectList *OwnerList) { - Rect tmpRect; - loadScene(1200); SceneExt::postInit(); @@ -1112,7 +1509,6 @@ void Scene1200::postInit(SceneObjectList *OwnerList) { _field416 = 0; _field418 = 0; _field41A = 0; - _field41C = 0; if ((R2_GLOBALS._v56AA6 == 1) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1)) _field418 = 1; @@ -1133,14 +1529,10 @@ void Scene1200::postInit(SceneObjectList *OwnerList) { _actor1.postInit(); _actor1.hide(); - tmpRect.set(110, 20, 210, 120); - _object1.sub9EDE8(tmpRect); + _mazeUI.setDisplayBounds(Rect(110, 20, 210, 120)); - _object1.sub51AE9(1); - _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); - warning("int unk = set_pane_p(_paneNumber);"); - _object1.sub51B02(); - warning("set_pane_p(unk);"); + _mazeUI.load(1); + _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); R2_GLOBALS._player.enableControl(); _item1.setDetails(Rect(0, 0, 320, 200), 1200, 0, 1, 2, 1, NULL); @@ -1337,7 +1729,7 @@ void Scene1200::signal() { case 111: // No break on purpose case 116: - R2_GLOBALS._player.setup(3157, 3, 1); + R2_GLOBALS._player.setup(3157, 4, 1); R2_GLOBALS._player.animate(ANIM_MODE_5, this); break; case 78: @@ -1396,50 +1788,52 @@ void Scene1200::process(Event &event) { return; if (event.eventType == EVENT_BUTTON_DOWN) { - _object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4); - int unk = _object1.sub51AF8(event.mousePos); + Common::Point cellPos(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4); + _mazeUI.pixelToCellXY(cellPos); + + int cellId = _mazeUI.getCellFromPixelXY(event.mousePos); switch (R2_GLOBALS._events.getCursor()) { - case CURSOR_ARROW: + case CURSOR_WALK: event.handled = true; if ((event.mousePos.x > 179) && (event.mousePos.x < 210) && (event.mousePos.y > 50) && (event.mousePos.y < 89)) - sub9DAD6(1); + startCrawling(CRAWL_EAST); if ((event.mousePos.x > 109) && (event.mousePos.x < 140) && (event.mousePos.y > 50) && (event.mousePos.y < 89)) - sub9DAD6(2); + startCrawling(CRAWL_WEST); if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 89) && (event.mousePos.y < 120)) - sub9DAD6(3); + startCrawling(CRAWL_SOUTH); if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 19) && (event.mousePos.y < 50)) - sub9DAD6(4); + startCrawling(CRAWL_NORTH); break; case CURSOR_USE: - if (unk > 36) { - if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33)) - || ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33)) - || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41)) - || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5)) - || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9)) - || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17)) - || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17)) - || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17)) - || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) ) { - _area1.postInit(); + if (cellId > 36) { + if ( ((cellPos.x == 3) && (cellPos.y == 33)) + || ((cellPos.x == 7) && (cellPos.y == 33)) + || ((cellPos.x == 33) && (cellPos.y == 41)) + || ((cellPos.x == 5) && (cellPos.y == 5)) + || ((cellPos.x == 13) && (cellPos.y == 21)) + || ((cellPos.x == 17) && (cellPos.y == 21)) + || ((cellPos.x == 17) && (cellPos.y == 5)) + || ((cellPos.x == 17) && (cellPos.y == 9)) + || ((cellPos.x == 29) && (cellPos.y == 17)) + || ((cellPos.x == 33) && (cellPos.y == 17)) + || ((cellPos.x == 35) && (cellPos.y == 17)) + || ((cellPos.x == 41) && (cellPos.y == 21)) ) { + _laserPanel.postInit(); event.handled = true; } } - if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) { - if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 9)) - || ((R2_GLOBALS._v56AA2 == 11) && (R2_GLOBALS._v56AA4 == 27)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 7)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 27)) - || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 33)) - || (R2_GLOBALS._v56AA2 == 33) ) { - switch (R2_GLOBALS._v56AA2) { + if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) { + if ( ((cellPos.x == 3) && (cellPos.y == 9)) + || ((cellPos.x == 11) && (cellPos.y == 27)) + || ((cellPos.x == 17) && (cellPos.y == 7)) + || ((cellPos.x == 17) && (cellPos.y == 27)) + || ((cellPos.x == 17) && (cellPos.y == 33)) + || (cellPos.x == 33) ) { + switch (cellPos.x) { case 3: R2_GLOBALS._sceneManager.changeScene(3150); break; @@ -1458,23 +1852,25 @@ void Scene1200::process(Event &event) { } break; case CURSOR_LOOK: - if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) { + if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) { event.handled = true; - switch (R2_GLOBALS._v56AA2) { + switch (cellPos.x) { case 3: + // It was your cell. SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); break; case 9: R2_GLOBALS._sceneManager.changeScene(3240); break; case 11: - if (R2_GLOBALS._v56AA4 == 27) + if (cellPos.y == 27) R2_GLOBALS._sceneManager.changeScene(3210); else + // A vent grill SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); break; case 17: - switch (R2_GLOBALS._v56AA4) { + switch (cellPos.y) { case 5: R2_GLOBALS._sceneManager.changeScene(3230); break; @@ -1485,6 +1881,7 @@ void Scene1200::process(Event &event) { R2_GLOBALS._sceneManager.changeScene(3200); break; default: + // A vent grill SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); break; } @@ -1496,7 +1893,8 @@ void Scene1200::process(Event &event) { break; } } - if (unk > 36) { + if (cellId > 36) { + // "An anti-pest laser" event.handled = true; SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999); } @@ -1516,19 +1914,19 @@ void Scene1200::process(Event &event) { switch (event.kbd.keycode) { case Common::KEYCODE_1: warning("FIXME: keycode = 0x4800"); - sub9DAD6(4); + startCrawling(CRAWL_NORTH); break; case Common::KEYCODE_2: warning("FIXME: keycode = 0x4B00"); - sub9DAD6(2); + startCrawling(CRAWL_WEST); break; case Common::KEYCODE_3: warning("FIXME: keycode = 0x4D00"); - sub9DAD6(1); + startCrawling(CRAWL_EAST); break; case Common::KEYCODE_4: warning("FIXME: keycode = 0x5000"); - sub9DAD6(3); + startCrawling(CRAWL_SOUTH); break; default: event.handled = false; @@ -1543,13 +1941,13 @@ void Scene1200::process(Event &event) { void Scene1200::dispatch() { Rect tmpRect; Scene::dispatch(); - if (_field41C != 0) { - _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); - warning("int unk = set_pane_p(_paneNumber);"); - _object1.sub51B02(); + + if (_fixupMaze) { + _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); + warning("_gfxManager.sub294AC(unk);"); warning("tmpRect.sub14DF3();"); - _field41C = 0; + _fixupMaze = false; } if (_field414 != 0) { @@ -1571,11 +1969,10 @@ void Scene1200::dispatch() { default: break; } - _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); - warning("int unk = set_pane_p(_paneNumber);"); - _object1.sub51B02(); - warning("_gfxManager.sub294AC(unk);"); - warning("tmpRect.sub14DF3();"); + _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4)); + + debug("_gfxManager.sub294AC(unk);"); + debug("tmpRect.sub14DF3();"); if (_field416 != 0) { switch(_field412 - 1) { @@ -1608,6 +2005,190 @@ void Scene1200::saveCharacter(int characterIndex) { SceneExt::saveCharacter(characterIndex); } +void Scene1200::startCrawling(CrawlDirection dir) { + Common::Point cellPos = Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4); + _mazeUI.pixelToCellXY(cellPos); + + switch (dir) { + case CRAWL_EAST: + if ( ((_mazeUI.getCellFromPixelXY(Common::Point(200, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(200, 88)) > 36)) + && ( ((cellPos.x == 3) && (cellPos.y == 33) && (_field418 != 4)) + || ((cellPos.x == 13) && (cellPos.y == 21) && (_field418 != 2)) + || ((cellPos.x == 29) && (cellPos.y == 17) && (_field418 != 1)) + || ((cellPos.x == 33) && (cellPos.y == 41)) ) + ) { + R2_GLOBALS._player.disableControl(); + _sceneMode = 1200; + setAction(&_sequenceManager, this, 1200, &_actor1, NULL); + } else if (_mazeUI.getCellFromPixelXY(Common::Point(200, 69)) == 36) { + switch (_field412 - 1) { + case 0: + if (R2_GLOBALS._player._visage == 3155) + _sceneMode = 15; + else + _sceneMode = 10; + break; + case 1: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 76; + else + _sceneMode = 75; + break; + case 2: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 101; + else + _sceneMode = 100; + break; + case 3: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 111; + else + _sceneMode = 110; + break; + default: + break; + } + R2_GLOBALS._player.disableControl(); + _field412 = 1; + signal(); + } + break; + case CRAWL_WEST: + if ( ((_mazeUI.getCellFromPixelXY(Common::Point(120, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(120, 88)) > 36)) + && ( ((cellPos.x == 7) && (cellPos.y == 33) && (_field418 != 4)) + || ((cellPos.x == 17) && (cellPos.y == 21) && (_field418 != 2)) + || ((cellPos.x == 33) && (cellPos.y == 17) && (_field418 != 1)) + || ((cellPos.x == 5) && (cellPos.y == 5)) ) + ) { + R2_GLOBALS._player.disableControl(); + _sceneMode = 1201; + setAction(&_sequenceManager, this, 1201, &_actor1, NULL); + } else if (_mazeUI.getCellFromPixelXY(Common::Point(120, 69)) == 36) { + switch (_field412 - 1) { + case 0: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 56; + else + _sceneMode = 55; + break; + case 1: + if (R2_GLOBALS._player._visage == 3155) + _sceneMode = 25; + else + _sceneMode = 20; + break; + case 2: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 91; + else + _sceneMode = 90; + break; + case 3: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 121; + else + _sceneMode = 120; + break; + default: + break; + } + R2_GLOBALS._player.disableControl(); + _field412 = 2; + signal(); + } + break; + case CRAWL_SOUTH: + if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 110)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 110)) > 36)) + && ( ((cellPos.x == 17) && (cellPos.y == 5) && (_field418 != 3)) + || ((cellPos.x == 41) && (cellPos.y == 21)) ) + ) { + R2_GLOBALS._player.disableControl(); + _sceneMode = 1203; + setAction(&_sequenceManager, this, 1203, &_actor1, NULL); + } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 110)) == 36) { + switch (_field412 - 1) { + case 0: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 51; + else + _sceneMode = 50; + break; + case 1: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 81; + else + _sceneMode = 80; + break; + case 2: + if (R2_GLOBALS._player._visage == 3155) + _sceneMode = 35; + else + _sceneMode = 30; + break; + case 3: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 116; + else + _sceneMode = 115; + break; + default: + break; + } + R2_GLOBALS._player.disableControl(); + _field412 = 3; + signal(); + } + break; + case CRAWL_NORTH: + if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 30)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 30)) > 36)) + && ( ((cellPos.x == 17) && (cellPos.y == 9) && (_field418 != 3)) + || ((cellPos.x == 35) && (cellPos.y == 17)) ) + ) { + R2_GLOBALS._player.disableControl(); + _sceneMode = 1202; + setAction(&_sequenceManager, this, 1202, &_actor1, NULL); + } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 30)) == 36) { + switch (_field412 - 1) { + case 0: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 61; + else + _sceneMode = 60; + break; + case 1: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 71; + else + _sceneMode = 70; + break; + case 2: + if (R2_GLOBALS._player._visage == 3156) + _sceneMode = 96; + else + _sceneMode = 95; + break; + case 3: + if (R2_GLOBALS._player._visage == 3155) + _sceneMode = 45; + else + _sceneMode = 40; + break; + default: + _sceneMode = 1; + R2_GLOBALS._player.setup(3156, 4, 6); + break; + } + R2_GLOBALS._player.disableControl(); + _field412 = 4; + signal(); + } + break; + default: + break; + } +} + /*-------------------------------------------------------------------------- * Scene 1337 - Card game * @@ -6924,7 +7505,7 @@ void Scene1550::UnkArea1550::remove() { } void Scene1550::UnkArea1550::process(Event &event) { -// This is a copy of Scene1200::Area1::process +// This is a copy of Scene1200::LaserPanel::process if (_field20 != R2_GLOBALS._insetUp) return; @@ -6988,7 +7569,7 @@ void Scene1550::UnkArea1550::proc12(int visage, int stripFrameNum, int frameNum, } void Scene1550::UnkArea1550::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) { - // Copy of Scene1200::Area1::proc13 + // Copy of Scene1200::LaserPanel::proc13 _areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL); } @@ -8751,7 +9332,7 @@ void Scene1575::Hotspot1::process(Event &event) { di -= 2; scene->_field41A -= 2; - for (int i = 0; i < 178; i++) + for (int i = 0; i < 17; i++) scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x - 2, scene->_arrActor[i]._position.y)); scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x - 2, scene->_actor13._position.y)); @@ -12947,7 +13528,7 @@ void Scene1950::Area1::remove() { } void Scene1950::Area1::process(Event &event) { -// This is a copy of Scene1200::Area1::process +// This is a copy of Scene1200::LaserPanel::process if (_field20 != R2_GLOBALS._insetUp) return; @@ -13000,7 +13581,7 @@ void Scene1950::Area1::proc12(int visage, int stripFrameNum, int frameNum, int p } void Scene1950::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) { - // Copy of Scene1200::Area1::proc13() + // Copy of Scene1200::LaserPanel::proc13() _areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL); } diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h index f65a89972d..eaca667377 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes1.h +++ b/engines/tsage/ringworld2/ringworld2_scenes1.h @@ -39,6 +39,24 @@ namespace Ringworld2 { using namespace TsAGE; +class Scene1000 : public SceneExt { +public: + SequenceManager _sequenceManager1; + SequenceManager _sequenceManager2; + SpeakerGameText _gameTextSpeaker; + AnimationPlayer _animationPlayer; + + int _field412; + int _fieldD2E; +public: + Scene1000(); + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void remove(); + virtual void signal(); + virtual void dispatch(); +}; + class Scene1010 : public SceneExt { public: SequenceManager _sequenceManager; @@ -57,15 +75,15 @@ public: }; class Scene1100 : public SceneExt { - class Actor16 : public SceneActor { + class Seeker : public SceneActor { public: virtual bool startAction(CursorType action, Event &event); }; - class Actor17 : public SceneActor { + class Trooper : public SceneActor { public: virtual bool startAction(CursorType action, Event &event); }; - class Actor18 : public SceneActor { + class Chief : public SceneActor { public: virtual bool startAction(CursorType action, Event &event); }; @@ -100,9 +118,9 @@ public: SceneActor _actor15; BackgroundSceneObject _object1; BackgroundSceneObject _object2; - Actor16 _actor16; - Actor17 _actor17; - Actor18 _actor18; + Seeker _seeker; + Trooper _trooper; + Chief _chief; SequenceManager _sequenceManager1; SequenceManager _sequenceManager2; SequenceManager _sequenceManager3; @@ -118,36 +136,31 @@ public: }; class Scene1200 : public SceneExt { - class Area1: public SceneArea { + enum CrawlDirection { CRAWL_EAST = 1, CRAWL_WEST = 2, CRAWL_SOUTH = 3, CRAWL_NORTH = 4 }; + + class LaserPanel: public ModalWindow { public: - class Actor3 : public SceneActorExt { + class Jumper : public SceneActorExt { public: void init(int state); virtual bool startAction(CursorType action, Event &event); }; - SceneActor _actor2; - Actor3 _actor3; - Actor3 _actor4; - Actor3 _actor5; + Jumper _jumper1; + Jumper _jumper2; + Jumper _jumper3; - byte _field20; - - Area1(); - void synchronize(Serializer &s); + LaserPanel(); virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void remove(); - virtual void process(Event &event); - virtual void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY); - virtual void proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum); }; public: NamedHotspot _item1; SceneActor _actor1; - Area1 _area1; - UnkObject1200 _object1; + LaserPanel _laserPanel; + MazeUI _mazeUI; SequenceManager _sequenceManager; int _field412; @@ -155,12 +168,12 @@ public: int _field416; int _field418; int _field41A; - int _field41C; + bool _fixupMaze; Scene1200(); void synchronize(Serializer &s); - void sub9DAD6(int indx); + void startCrawling(CrawlDirection dir); virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void signal(); diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp index 6a030e5b44..9246c4b6a4 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp @@ -630,6 +630,7 @@ void Scene2000::Exit3::changeScene() { break; } } + void Scene2000::Exit4::changeScene() { Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene; @@ -756,19 +757,21 @@ void Scene2000::Exit5::changeScene() { } } -void Scene2000::postInit(SceneObjectList *OwnerList) { - SceneExt::postInit(); - loadScene(2000); - +Scene2000::Scene2000(): SceneExt() { if (R2_GLOBALS._sceneManager._previousScene != -1) { R2_GLOBALS._v56605[1] = 21; R2_GLOBALS._v56605[2] = 21; } - if ((R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex] != R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex]) && (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 2350)) { + if ((R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex] + != R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex]) + && (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 2350)) { R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 0; } + _exitingFlag = false; +} +void Scene2000::postInit(SceneObjectList *OwnerList) { _exit1.setDetails(Rect(0, 100, 14, 140), EXITCURSOR_W, 2000); _exit1.setDest(Common::Point(14, 129)); _exit2.setDetails(Rect(305, 100, 320, 140), EXITCURSOR_E, 2000); @@ -917,6 +920,8 @@ void Scene2000::postInit(SceneObjectList *OwnerList) { initPlayer(); _item1.setDetails(Rect(0, 0, 320, 200), 2000, 0, -1, 23, 1, NULL); + + SceneExt::postInit(); } void Scene2000::remove() { @@ -998,6 +1003,8 @@ void Scene2000::signal() { g_globals->_sceneManager.changeScene(2350); break; default: + R2_GLOBALS._v56AAB = 0; + R2_GLOBALS._player.enableControl(); break; } } diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.h b/engines/tsage/ringworld2/ringworld2_scenes2.h index 281d1da366..feceaa1537 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes2.h +++ b/engines/tsage/ringworld2/ringworld2_scenes2.h @@ -80,6 +80,7 @@ public: Action1 _action1, _action2, _action3, _action4, _action5; SequenceManager _sequenceManager; + Scene2000(); virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void remove(); virtual void signal(); diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp index 61711d0a4f..6af2a0cad4 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp @@ -2885,9 +2885,10 @@ void Scene3400::signal() { } /*-------------------------------------------------------------------------- - * Scene 3500 - + * Scene 3500 - Cavern Maze * *--------------------------------------------------------------------------*/ + Scene3500::Action1::Action1() { _field1E = 0; _field20 = 0; @@ -2919,9 +2920,10 @@ void Scene3500::Action1::sub108670(int arg1) { else scene->_actor5.show(); - if (scene->_actor1._frame % 2 == 0) - scene->_actor1._frameChange = _field1E; - scene->_actor1.setFrame(scene->_actor1.changeFrame()); + if (scene->_actor1._frame % 2 == 0) { + scene->_actor1._frameChange = _field1E; + scene->_actor1.setFrame(scene->_actor1.changeFrame()); + } setActionIndex(0); } @@ -2977,219 +2979,6 @@ void Scene3500::Action1::sub108732(int arg1) { } } -Scene3500::Action2::Action2() { - _field1E = 0; -} - -void Scene3500::Action2::synchronize(Serializer &s) { - Action::synchronize(s); - - s.syncAsSint16LE(_field1E); -} - -Scene3500::Item4::Item4() { - _field34 = 0; -} - -void Scene3500::Item4::synchronize(Serializer &s) { - NamedHotspot::synchronize(s); - - s.syncAsSint16LE(_field34); -} - -Scene3500::Actor7::Actor7() { - _fieldA4 = 0; - _fieldA6 = 0; - _fieldA8 = 0; - _fieldAA = 0; - _fieldAC = 0; - _fieldAE = 0; -} - -void Scene3500::Actor7::synchronize(Serializer &s) { - SceneActor::synchronize(s); - - s.syncAsSint16LE(_fieldA4); - s.syncAsSint16LE(_fieldA6); - s.syncAsSint16LE(_fieldA8); - s.syncAsSint16LE(_fieldAA); - s.syncAsSint16LE(_fieldAC); - s.syncAsSint16LE(_fieldAE); -} - -void Scene3500::Actor7::sub109466(int arg1, int arg2, int arg3, int arg4, int arg5) { - _fieldAE = 0; - _fieldA4 = arg1; - _fieldA6 = arg2; - _fieldA8 = arg3; - _fieldAA = arg4; - _fieldAC = _fieldAA / _fieldA8; - - postInit(); - setup(10501, 3, 1); - fixPriority(255); - sub109663(arg5); -} - -void Scene3500::Actor7::sub1094ED() { - Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene; - - scene->_field1270 = _position.x - _fieldA4; -} - -void Scene3500::Actor7::sub109663(int arg1){ - sub109693(Common::Point(_fieldA4 + arg1, _fieldA6 - (_fieldAC * arg1))); -} - -void Scene3500::Actor7::sub109693(Common::Point Pt) { - setPosition(Pt); -} - -int Scene3500::UnkObject3500::sub1097C9(int arg1) { - return (_field2A / 2) + arg1 - (arg1 % _field2A); -} - -int Scene3500::UnkObject3500::sub1097EF(int arg1) { - return (_field2C / 2) + arg1 - (arg1 % _field2C); -} - -int Scene3500::UnkObject3500::sub109C09(Common::Point pt) { - int vx = pt.x / _field2A; - int vy = pt.y / _field2C; - - if ((vx >= 0) && (_field26 > vx) && (_field28 > vy)) { - return _field16[((_field26 * vy) + vx) * 2]; - } else - return -1; -} - -int Scene3500::UnkObject3500::sub109C5E(int &x, int &y) { - int retVal = sub51AFD(Common::Point(x, y)); - x = _field2E; - y = _field30; - - return retVal; -} - -Scene3500::Scene3500() { - _fieldAF8 = 0; - _fieldB9E = 0; - _rotation = NULL; - _field126E = 0; - _field1270 = 0; - _field1272 = 0; - _field1274 = 0; - _field1276 = 0; - _field1278 = 0; - _field127A = 0; - _field127C = 0; - _field127E = 0; - _field1280 = 0; - _field1282 = 0; - _field1284 = 0; - _field1286 = 0; -} - -void Scene3500::synchronize(Serializer &s) { - SceneExt::synchronize(s); - SYNC_POINTER(_rotation); - - s.syncAsSint16LE(_fieldAF8); - s.syncAsSint16LE(_fieldB9E); - s.syncAsSint16LE(_field126E); - s.syncAsSint16LE(_field1270); - s.syncAsSint16LE(_field1272); - s.syncAsSint16LE(_field1274); - s.syncAsSint16LE(_field1276); - s.syncAsSint16LE(_field1278); - s.syncAsSint16LE(_field127A); - s.syncAsSint16LE(_field127C); - s.syncAsSint16LE(_field127E); - s.syncAsSint16LE(_field1280); - s.syncAsSint16LE(_field1282); - s.syncAsSint16LE(_field1284); - s.syncAsSint16LE(_field1286); -} - -void Scene3500::sub107F71(int arg1) { - switch (arg1) { - case -1: - _actor7.sub1094ED(); - if (_field1270 != 0) { - _field1270--; - _actor7.sub109663(_field1270); - } - if (_action1._field24 != 0) - _field1270 = 0; - break; - case 1: - _actor7.sub1094ED(); - if (_field1270 < 16) { - ++_field1270; - _actor7.sub109663(_field1270); - } - if (_action1._field24 != 0) - _field1270 = 0; - break; - case 88: - if ((_action == 0) || (_action1._field24 == 0)) { - // The original makes a second useless check on action, skipped - _action2.sub10831F(2); - if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != 2))) { - _action2.signal(); - } else { - _actor9.setAction(&_action2, &_actor9, NULL); - } - } - break; - case 96: - if ((_action) && (_action1._field24 != 0) && (_action2._field1E != 1)) { - _field1278 = 0; - _action1.sub108732(0); - } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) { - _field1278 = arg1; - } else if ((_action) && (_action1._field24 == 0)) { - _action1.sub108670(1); - _action1.signal(); - } else if (_action == 0) { - _action1.sub108670(1); - setAction(&_action1, &_actor1, NULL); - } - break; - case 104: - if ((_action == 0) || (_action1._field24 == 0)) { - _action2.sub10831F(-1); - if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != -1))) { - _action2.signal(); - } else { - _actor9.setAction(&_action2, &_actor9, NULL); - } - } - break; - case 112: - if ((_action) && (_action1._field24 != 0) && (_action2._field1E != -1)) { - _field1278 = 0; - _action1.sub108732(0); - } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) { - _field1278 = arg1; - } else if ((_action) && (_action1._field24 == 0)) { - _action1.sub108670(-1); - _action1.signal(); - } else if (_action == 0) { - _action1.sub108670(-1); - setAction(&_action1, &_actor1, NULL); - } - break; - default: - _field1270 = arg1; - _actor7.sub109663(arg1); - if (_action1._field24 != 0) { - _field1270 = 0; - } - break; - } -} - void Scene3500::Action1::signal() { Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene; @@ -3199,13 +2988,13 @@ void Scene3500::Action1::signal() { scene->_field1286 = 0; if (scene->_field1270 != 0) { scene->_field1270 = 0; - scene->_field126E = 0; + scene->_mazeChangeAmount = 0; scene->_field1272 = 0; scene->_rotation->_idxChange = 0; } break; case 1: - if ((scene->_actor1._frame % 2) == 0) { + if ((scene->_actor1._frame % 2) == 1) { setDelay(1); return; } @@ -3216,25 +3005,28 @@ void Scene3500::Action1::signal() { setDelay(1); break; case 4: { - int si = scene->_unkObj1.sub109C09(Common::Point(scene->_field127A + 70, scene->_field127C + 46)); - int var2 = scene->_unkObj1.sub1097C9(scene->_field127A + 70) - 70; - int var4 = scene->_unkObj1.sub1097EF(scene->_field127C + 46) - 46; - int di = abs(var2 - scene->_field127A); - int var6 = abs(var4 - scene->_field127C); + int si = scene->_mazeUI.getCellFromMapXY(Common::Point(scene->_mazePosition.x + 70, scene->_mazePosition.y + 46)); + int var2 = scene->_mazeUI.cellFromX(scene->_mazePosition.x + 70) - 70; + int var4 = scene->_mazeUI.cellFromY(scene->_mazePosition.y + 46) - 46; + int di = abs(var2 - scene->_mazePosition.x); + int var6 = abs(var4 - scene->_mazePosition.y); if ((scene->_actor1._frame % 2) != 0) { scene->_actor1._frameChange = _field1E; scene->_actor1.setFrame(scene->_actor1.changeFrame()); } - int var8 = (scene->_action1._field1E * 2 + scene->_field1276); - if (var8 > 7) - var8 = 1; - else if (var8 < 1) - var8 = 7; + // Get the new direction starting on + int var8 = (scene->_action1._field1E * 2 + scene->_mazeDirection); + if (var8 > MAZEDIR_NORTHWEST) + var8 = MAZEDIR_NORTH; + else if (var8 < MAZEDIR_NORTH) + var8 = MAZEDIR_WEST; + // Check whether movement is allowed in that direction. If so, then + // movement is started again switch (var8) { - case 0: + case MAZEDIR_NORTH: if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 23) && (si != 24) && (si != 4) && (si != 11)) || (var6 != 0)) { if ((si != 25) && (si != 26) && (si != 5) && (si != 14) && (si != 15)) @@ -3246,7 +3038,7 @@ void Scene3500::Action1::signal() { } else _field20 = 1; break; - case 2: + case MAZEDIR_EAST: if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 26) && (si != 24) && (si != 15) && (si != 6) && (si != 31)) || (di != 0)) { if ((si != 25) && (si != 23) && (si != 14) && (si != 5) && (si != 4)) @@ -3258,7 +3050,7 @@ void Scene3500::Action1::signal() { } else _field20 = 1; break; - case 4: + case MAZEDIR_SOUTH: if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 25) && (si != 26) && (si != 5) && (si != 16) && (si != 31)) || (var6 != 0)) { if ((si != 23) && (si != 24) && (si != 4) && (si != 14) && (si != 15)) @@ -3270,7 +3062,7 @@ void Scene3500::Action1::signal() { } else _field20 = 1; break; - case 6: + case MAZEDIR_WEST: if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 25) && (si != 23) && (si != 14) && (si != 1) && (si != 31)) || (var6 != 0)) { if ((si != 26) && (si != 24) && (si != 15) && (si != 5) && (si != 4)) @@ -3288,14 +3080,14 @@ void Scene3500::Action1::signal() { // No break on purpose case 2: { scene->_actor8.setPosition(Common::Point(160, 73)); - scene->_actor8._moveDiff.x = 160 - scene->_field126E; + scene->_actor8._moveDiff.x = 160 - scene->_mazeChangeAmount; scene->_fieldAF8 = 160 - ((_field1E * 2) * 160); Common::Point pt(scene->_fieldAF8, 73); NpcMover *mover = new NpcMover(); scene->_actor8.addMover(mover, &pt, this); scene->_actor9.setPosition(Common::Point(160 + ((_field1E * 2) * 160), 73)); - scene->_actor9._moveDiff.x = 160 - scene->_field126E; + scene->_actor9._moveDiff.x = 160 - scene->_mazeChangeAmount; scene->_fieldB9E = 160; Common::Point pt2(scene->_fieldB9E, 73); NpcMover *mover2 = new NpcMover(); @@ -3304,8 +3096,8 @@ void Scene3500::Action1::signal() { break; case 5: scene->_actor1._frameChange = _field1E; - scene->_field1276 = scene->_actor1.changeFrame(); - scene->_actor1.setFrame(scene->_field1276); + scene->_mazeDirection = scene->_actor1.changeFrame(); + scene->_actor1.setFrame(scene->_mazeDirection); setDelay(1); break; case 6: @@ -3325,8 +3117,8 @@ void Scene3500::Action1::signal() { case 7: if ((scene->_actor1._frame % 2) == 0) { scene->_actor1._frameChange = _field1E; - scene->_field1276 = scene->_actor1.changeFrame(); - scene->_actor1.setFrame(scene->_field1276); + scene->_mazeDirection = scene->_actor1.changeFrame(); + scene->_actor1.setFrame(scene->_mazeDirection); } setDelay(1); break; @@ -3342,7 +3134,7 @@ void Scene3500::Action1::signal() { // but it's clearly a cut and paste error from case 4. // The following code allows the switch to work properly. warning("Checkme: fix for dead code"); - int var_8 = (_field1E * 2 + scene->_field1276); + int var_8 = (_field1E * 2 + scene->_mazeDirection); if (var_8 > 7) var_8 = 1; else if (var_8 < 1) @@ -3353,12 +3145,12 @@ void Scene3500::Action1::signal() { case 0: // No break on purpose case 4: - scene->_field127A = scene->_unkObj1.sub1097C9(scene->_field127A + 70) - 70; + scene->_mazePosition.x = scene->_mazeUI.cellFromX(scene->_mazePosition.x + 70) - 70; break; case 2: // No break on purpose case 6: - scene->_field127C = scene->_unkObj1.sub1097EF(scene->_field127C + 46) - 46; + scene->_mazePosition.y = scene->_mazeUI.cellFromY(scene->_mazePosition.y + 46) - 46; break; default: break; @@ -3368,7 +3160,7 @@ void Scene3500::Action1::signal() { _field24 = 0; if (_field20 == 0) { scene->_actor7.sub1094ED(); - if (scene->_field126E == scene->_field1270) + if (scene->_mazeChangeAmount == scene->_field1270) scene->_aSound1.play(276); } break; @@ -3416,12 +3208,232 @@ void Scene3500::Action1::dispatch() { Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene; Action::dispatch(); - if ((_actionIndex == 1) && (scene->_field126E <= 4)) { + if ((_actionIndex == 1) && (scene->_mazeChangeAmount <= 4)) { scene->_rotation->_idxChange = 0; signal(); } } +/*--------------------------------------------------------------------------*/ + +Scene3500::Action2::Action2() { + _field1E = 0; +} + +void Scene3500::Action2::synchronize(Serializer &s) { + Action::synchronize(s); + + s.syncAsSint16LE(_field1E); +} + +/*--------------------------------------------------------------------------*/ + +Scene3500::Item4::Item4() { + _field34 = 0; +} + +void Scene3500::Item4::synchronize(Serializer &s) { + NamedHotspot::synchronize(s); + + s.syncAsSint16LE(_field34); +} + +/*--------------------------------------------------------------------------*/ + +Scene3500::Actor7::Actor7() { + _fieldA4 = 0; + _fieldA6 = 0; + _fieldA8 = 0; + _fieldAA = 0; + _fieldAC = 0; + _fieldAE = 0; +} + +void Scene3500::Actor7::synchronize(Serializer &s) { + SceneActor::synchronize(s); + + s.syncAsSint16LE(_fieldA4); + s.syncAsSint16LE(_fieldA6); + s.syncAsSint16LE(_fieldA8); + s.syncAsSint16LE(_fieldAA); + s.syncAsSint16LE(_fieldAC); + s.syncAsSint16LE(_fieldAE); +} + +void Scene3500::Actor7::sub109466(int arg1, int arg2, int arg3, int arg4, int arg5) { + _fieldAE = 0; + _fieldA4 = arg1; + _fieldA6 = arg2; + _fieldA8 = arg3; + _fieldAA = arg4; + _fieldAC = _fieldAA / _fieldA8; + + postInit(); + setup(1050, 3, 1); + fixPriority(255); + sub109663(arg5); +} + +void Scene3500::Actor7::sub1094ED() { + Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene; + + scene->_field1270 = _position.x - _fieldA4; +} + +void Scene3500::Actor7::sub109663(int arg1){ + sub109693(Common::Point(_fieldA4 + arg1, _fieldA6 - (_fieldAC * arg1))); +} + +void Scene3500::Actor7::sub109693(Common::Point Pt) { + setPosition(Pt); +} + +/*--------------------------------------------------------------------------*/ + +int Scene3500::MazeUI3500::cellFromX(int x) { + return (_cellSize.x / 2) + x - (x % _cellSize.x); +} + +int Scene3500::MazeUI3500::cellFromY(int y) { + return (_cellSize.y / 2) + y - (y % _cellSize.y) - 1; +} + +int Scene3500::MazeUI3500::getCellFromMapXY(Common::Point pt) { + int cellX = pt.x / _cellSize.x; + int cellY = pt.y / _cellSize.y; + + if ((cellX >= 0) && (cellY >= 0) && (cellX < _mapCells.x) && (cellY < _mapCells.y)) { + return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * cellY + cellX) * 2); + } else + return -1; +} + +bool Scene3500::MazeUI3500::setMazePosition2(Common::Point &p) { + bool retVal = setMazePosition(p); + p = _mapOffset; + + return retVal; +} + +Scene3500::Scene3500() { + _fieldAF8 = 0; + _fieldB9E = 0; + _rotation = NULL; + _mazeChangeAmount = 0; + _field1270 = 0; + _field1272 = 0; + _field1274 = 0; + _mazeDirection = MAZEDIR_NONE; + _field1278 = 0; + _mazePosition.x = 0; + _mazePosition.y = 0; + _field127E = 0; + _field1280 = 0; + _field1282 = 0; + _field1284 = 0; + _field1286 = 0; +} + +void Scene3500::synchronize(Serializer &s) { + SceneExt::synchronize(s); + SYNC_POINTER(_rotation); + + s.syncAsSint16LE(_fieldAF8); + s.syncAsSint16LE(_fieldB9E); + s.syncAsSint16LE(_mazeChangeAmount); + s.syncAsSint16LE(_field1270); + s.syncAsSint16LE(_field1272); + s.syncAsSint16LE(_field1274); + s.syncAsSint16LE(_mazeDirection); + s.syncAsSint16LE(_field1278); + s.syncAsSint16LE(_mazePosition.x); + s.syncAsSint16LE(_mazePosition.y); + s.syncAsSint16LE(_field127E); + s.syncAsSint16LE(_field1280); + s.syncAsSint16LE(_field1282); + s.syncAsSint16LE(_field1284); + s.syncAsSint16LE(_field1286); +} + +void Scene3500::sub107F71(int arg1) { + switch (arg1) { + case -1: + _actor7.sub1094ED(); + if (_field1270 != 0) { + _field1270--; + _actor7.sub109663(_field1270); + } + if (_action1._field24 != 0) + _field1270 = 0; + break; + case 1: + _actor7.sub1094ED(); + if (_field1270 < 16) { + ++_field1270; + _actor7.sub109663(_field1270); + } + if (_action1._field24 != 0) + _field1270 = 0; + break; + case 88: + if ((_action == 0) || (_action1._field24 == 0)) { + // The original makes a second useless check on action, skipped + _action2.sub10831F(2); + if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != 2))) { + _action2.signal(); + } else { + _actor9.setAction(&_action2, &_actor9, NULL); + } + } + break; + case 96: + if ((_action) && (_action1._field24 != 0) && (_action2._field1E != 1)) { + _field1278 = 0; + _action1.sub108732(0); + } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) { + _field1278 = arg1; + } else if ((_action) && (_action1._field24 == 0)) { + _action1.sub108670(1); + _action1.signal(); + } else if (_action == 0) { + _action1.sub108670(1); + setAction(&_action1, &_actor1, NULL); + } + break; + case 104: + if ((_action == 0) || (_action1._field24 == 0)) { + _action2.sub10831F(-1); + if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != -1))) { + _action2.signal(); + } else { + _actor9.setAction(&_action2, &_actor9, NULL); + } + } + break; + case 112: + if ((_action) && (_action1._field24 != 0) && (_action2._field1E != -1)) { + _field1278 = 0; + _action1.sub108732(0); + } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) { + _field1278 = arg1; + } else if ((_action) && (_action1._field24 == 0)) { + _action1.sub108670(-1); + _action1.signal(); + } else if (_action == 0) { + _action1.sub108670(-1); + setAction(&_action1, &_actor1, NULL); + } + break; + default: + _field1270 = arg1; + _actor7.sub109663(arg1); + if (_action1._field24 != 0) { + _field1270 = 0; + } + break; + } +} + void Scene3500::Action2::sub10831F(int arg1) { Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene; @@ -3452,17 +3464,17 @@ void Scene3500::Action2::signal() { di = scene->_fieldB9E; } - scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2); + scene->_actor8._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2); Common::Point pt(si, 73 - (_field1E * 12)); NpcMover *mover = new NpcMover(); scene->_actor8.addMover(mover, &pt, NULL); - scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2); + scene->_actor9._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2); Common::Point pt2(di, 73 - (_field1E * 12)); NpcMover *mover2 = new NpcMover(); scene->_actor9.addMover(mover2, &pt2, NULL); - scene->_field126E = (scene->_field126E / 2) + (scene->_field126E % 2); - setDelay(17 - scene->_field126E); + scene->_mazeChangeAmount = (scene->_mazeChangeAmount / 2) + (scene->_mazeChangeAmount % 2); + setDelay(17 - scene->_mazeChangeAmount); } break; case 1: { @@ -3477,12 +3489,12 @@ void Scene3500::Action2::signal() { scene->_actor7.sub1094ED(); - scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2); + scene->_actor8._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2); Common::Point pt(si, 73); NpcMover *mover = new NpcMover(); scene->_actor8.addMover(mover, &pt, NULL); - scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2); + scene->_actor9._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2); Common::Point pt2(di, 73); NpcMover *mover2 = new NpcMover(); scene->_actor9.addMover(mover2, &pt2, NULL); @@ -3559,7 +3571,6 @@ bool Scene3500::Actor7::startAction(CursorType action, Event &event) { void Scene3500::postInit(SceneObjectList *OwnerList) { byte tmpPal[768]; - Rect tmpRect; loadScene(1050); R2_GLOBALS._uiElements._active = false; @@ -3574,9 +3585,8 @@ void Scene3500::postInit(SceneObjectList *OwnerList) { _field1278 = 0; _field1272 = 1; _field1270 = 4; - _field126E = 4; - _field127A = 860; - _field127C = 891; + _mazeChangeAmount = 4; + _mazePosition = Common::Point(860, 891); _rotation = R2_GLOBALS._scenePalette.addRotation(240, 254, -1); _rotation->setDelay(0); _rotation->_idxChange = 1; @@ -3615,7 +3625,7 @@ void Scene3500::postInit(SceneObjectList *OwnerList) { _item7.setDetails(96, 3500, 12, 10, -1); _actor8.postInit(); - _actor8.setup(10501, 1, 1); + _actor8.setup(1050, 1, 1); _actor8.setPosition(Common::Point(160, 73)); _actor8.fixPriority(1); @@ -3630,8 +3640,8 @@ void Scene3500::postInit(SceneObjectList *OwnerList) { _item1.setDetails(Rect(0, 0, 320, 200), 3500, 0, -1, 2, 1, NULL); _actor1.postInit(); - _field1276 = 1; - _actor1.setup(1004, 1, _field1276); + _mazeDirection = MAZEDIR_NORTH; + _actor1.setup(1004, 1, _mazeDirection); _actor1.setPosition(Common::Point(230, 135)); _actor1.fixPriority(200); _actor1._frameChange = 1; @@ -3654,7 +3664,7 @@ void Scene3500::postInit(SceneObjectList *OwnerList) { _actor6.hide(); _actor2.postInit(); - _actor2.setup(1004, 4, _field126E + 1); + _actor2.setup(1004, 4, _mazeChangeAmount + 1); _actor2.setPosition(Common::Point(126, 137)); _actor2.fixPriority(200); @@ -3663,15 +3673,12 @@ void Scene3500::postInit(SceneObjectList *OwnerList) { _actor3.setPosition(Common::Point(126, 108)); _actor3.fixPriority(200); - tmpRect.set(160, 89, 299, 182); - _unkObj1.sub9EDE8(tmpRect); - _unkObj1.sub51AE9(2); - _unkObj1.sub51AFD(Common::Point(_field127A, _field127C)); + _mazeUI.setDisplayBounds(Rect(160, 89, 299, 182)); + _mazeUI.load(2); + _mazeUI.setMazePosition(_mazePosition); _action1._field24 = 0; - warning("gfx_set_pane_p()"); - _unkObj1.sub51B02(); - warning("gfx_set_pane_p()"); + _mazeUI.draw(); _field1286 = 1; R2_GLOBALS._player.postInit(); @@ -3682,7 +3689,6 @@ void Scene3500::postInit(SceneObjectList *OwnerList) { } void Scene3500::remove() { - _rotation->remove(); R2_GLOBALS._sound2.fadeOut2(NULL); SceneExt::remove(); } @@ -3699,64 +3705,58 @@ void Scene3500::process(Event &event) { if (event.eventType == EVENT_KEYPRESS) { switch (event.kbd.keycode) { - case Common::KEYCODE_1: - warning("FIXME: keycode = 0x4700"); + case Common::KEYCODE_KP7: R2_GLOBALS._sound2.play(338); sub107F71(16); event.handled = true; break; - case Common::KEYCODE_2: - warning("FIXME: keycode = 0x4800"); + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: R2_GLOBALS._sound2.play(14, NULL, 63); sub107F71(88); event.handled = true; break; - case Common::KEYCODE_3: - warning("FIXME: keycode = 0x4900"); + case Common::KEYCODE_KP9: if (_field1270 < 16) R2_GLOBALS._sound2.play(338); sub107F71(1); event.handled = true; break; - case Common::KEYCODE_4: - warning("FIXME: keycode = 0x4B00"); + case Common::KEYCODE_KP4: + case Common::KEYCODE_LEFT: R2_GLOBALS._sound2.play(14, NULL, 63); sub107F71(112); event.handled = true; break; - case Common::KEYCODE_5: - warning("FIXME: keycode = 0x4D00"); + case Common::KEYCODE_KP6: + case Common::KEYCODE_RIGHT: R2_GLOBALS._sound2.play(14, NULL, 63); sub107F71(96); event.handled = true; break; - case Common::KEYCODE_6: - warning("FIXME: keycode = 0x4F00"); + case Common::KEYCODE_KP1: R2_GLOBALS._sound2.play(338); sub107F71(0); event.handled = true; break; - case Common::KEYCODE_7: - warning("FIXME: keycode = 0x5000"); + case Common::KEYCODE_KP2: + case Common::KEYCODE_DOWN: R2_GLOBALS._sound2.play(14, NULL, 63); sub107F71(104); event.handled = true; break; - case Common::KEYCODE_8: - warning("FIXME: keycode = 0x5100"); + case Common::KEYCODE_KP3: if (_field1270 != 0) R2_GLOBALS._sound2.play(338); sub107F71(-1); event.handled = true; break; - case Common::KEYCODE_9: - warning("FIXME: keycode = 0x5200"); + case Common::KEYCODE_KP0: R2_GLOBALS._sound2.play(338); sub107F71(8); event.handled = true; break; - case Common::KEYCODE_0: - warning("FIXME: keycode = 0x5300"); + case Common::KEYCODE_KP_PERIOD: R2_GLOBALS._sound2.play(338); sub107F71(4); event.handled = true; @@ -3787,9 +3787,10 @@ void Scene3500::process(Event &event) { void Scene3500::dispatch() { Rect tmpRect; Scene::dispatch(); + if (((_actor1._frame % 2) == 0) && (_action1._field24 == 0)) { _actor1.setFrame(_actor1.changeFrame()); - _field1276 = _actor1._frame; + _mazeDirection = _actor1._frame; } int oldField1278; if ((_field1278 != 0) && (_action1._field24 == 0)) { @@ -3801,90 +3802,90 @@ void Scene3500::dispatch() { if (!_rotation) return; - int var_field127A = 0; - int di = 0; + int newMazeX = 0; + int newMazeY = 0; int var_4 = 0; int var_6 = 0; int var_8 = 0; int var_a = 0; int dx = 0; - int tmpVar = 0; + int cellId = 0; - if ((_field126E == 0) && (_field1282 == 0)) { + if ((_mazeChangeAmount == 0) && (_field1282 == 0)) { if (_field1284 == 2) R2_GLOBALS._sceneManager.changeScene(1000); } else { _field1282 = 0; tmpRect.set(160, 89, 299, 182); - var_field127A = _field127A; - di = _field127C; - var_4 = _unkObj1.sub1097C9(70) - 70; - var_6 = _unkObj1.sub1097EF(_field127C + 46) - 46; - var_8 = abs(var_4 - var_field127A); - var_a = abs(var_6 - di); + newMazeX = _mazePosition.x; + newMazeY = _mazePosition.y; + var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70; + var_6 = _mazeUI.cellFromY(_mazePosition.y + 46) - 46; + var_8 = abs(var_4 - newMazeX); + var_a = abs(var_6 - newMazeY); dx = 0; - switch (_field1276) { - case 0: - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, 46)); - if ( ((tmpVar == 2) || (tmpVar == 3) || (tmpVar == 6) || (tmpVar == 1)) - || (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 > 3)) ) { + switch (_mazeDirection) { + case MAZEDIR_NORTH: + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if (((cellId == 2) || (cellId == 3) || (cellId == 6) || (cellId == 1)) || + ((cellId == 25 || cellId == 26 || cellId == 5 || cellId == 14 || cellId == 15) && var_8 > 3)) { R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_6 = _unkObj1.sub1097EF(di + 46) - 46; - di = _field127C - _field126E; - dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4)) && (tmpVar != dx)) { - di = var_6; + var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46; + newMazeY = _mazePosition.y - _mazeChangeAmount; + dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (cellId != dx)) { + newMazeY = var_6; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 11) && (tmpVar != dx)) { - di = var_6 + 3; + } else if ((cellId == 11) && (cellId != dx)) { + newMazeY = var_6 + 3; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_6 = _unkObj1.sub1097EF(di + 46) - 46; - var_a = abs(var_6 - di); - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - - if ( (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4)) && (di <= var_6) && (_field127C>= var_6)) - || (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (_field126E >= var_a) && (_field126E > 3) && (_action1._field24 != 0)) ) { - di = var_6; - if ((tmpVar != 25) && (tmpVar != 26) && (tmpVar != 5) && (tmpVar != 14) && (tmpVar == 15)) + var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46; + var_a = abs(var_6 - newMazeY); + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + + if ( (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (newMazeY <= var_6) && (_mazePosition.y>= var_6)) + || (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= var_a) && (_mazeChangeAmount > 3) && (_action1._field24 != 0)) ) { + newMazeY = var_6; + if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId == 15)) R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 11) && (var_6 + 3 >= di) && (_field127C >= var_6 + 3)) { + } else if ((cellId == 11) && (var_6 + 3 >= newMazeY) && (_mazePosition.y >= var_6 + 3)) { R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 != 0) && (var_8 <= 3)) { - var_field127A = var_4; + } else if (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (var_8 != 0) && (var_8 <= 3)) { + newMazeX = var_4; R2_GLOBALS._sound2.play(339); } else { // Nothing @@ -3892,65 +3893,65 @@ void Scene3500::dispatch() { } } break; - case 2: - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if ( ((tmpVar == 12) || (tmpVar == 13) || (tmpVar == 11) || (tmpVar == 16) || (tmpVar == 31)) - || (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (var_a > 3)) ) { + case MAZEDIR_EAST: + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if ( ((cellId == 12) || (cellId == 13) || (cellId == 11) || (cellId == 16) || (cellId == 31)) + || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (var_a > 3)) ) { R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70; - var_field127A = _field127A + _field126E; - dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15)) && (tmpVar != dx)) { - var_field127A = var_4; + var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70; + newMazeX = _mazePosition.x + _mazeChangeAmount; + dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (cellId != dx)) { + newMazeX = var_4; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 6) && (tmpVar != dx)) { - var_field127A = var_4 - 5; + } else if ((cellId == 6) && (cellId != dx)) { + newMazeX = var_4 - 5; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70; - var_8 = abs(var_field127A - var_4); - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, tmpVar + 46)); - if ( (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15)) && (var_field127A >= var_4) && (_field127A <= var_4)) - || (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (_field126E >= var_8) && (_field126E <= 3) && (_action1._field24 != 0)) ) { - var_field127A = var_4; - if ((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) + var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70; + var_8 = abs(newMazeX - var_4); + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if ( (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (newMazeX >= var_4) && (_mazePosition.x <= var_4)) + || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= var_8) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) { + newMazeX = var_4; + if ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 6) && (var_4 - 5 <= var_field127A) && (_field127A <= var_4 - 5)) { - var_field127A = var_4 - 5; + } else if ((cellId == 6) && (var_4 - 5 <= newMazeX) && (_mazePosition.x <= var_4 - 5)) { + newMazeX = var_4 - 5; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (var_a != 0) && (var_a <= 3)) { - di = var_6; + } else if (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (var_a != 0) && (var_a <= 3)) { + newMazeY = var_6; R2_GLOBALS._sound2.play(339); } else { // Nothing @@ -3958,84 +3959,87 @@ void Scene3500::dispatch() { } } break; - case 4: - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if ( ((tmpVar == 2) || (tmpVar == 3) || (tmpVar == 6) || (tmpVar == 1)) - || (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 > 3)) ) { + case MAZEDIR_SOUTH: + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if ( ((cellId == 2) || (cellId == 3) || (cellId == 6) || (cellId == 1)) + || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (var_8 > 3)) ) { R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_6 = _unkObj1.sub1097EF(di + 46) - 46; - di = _field127C + _field126E; - dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5)) && (tmpVar == dx)) { + var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46; + newMazeY = _mazePosition.y + _mazeChangeAmount; + dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + + if (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (cellId != dx)) { R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 16) && (tmpVar == dx)) { - di = var_6 - 3; + } else if ((cellId == 16) && (cellId != dx)) { + newMazeY = var_6 - 3; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 31) && (tmpVar == dx)) { - di = var_6 + 4; + } else if ((cellId == 31) && (cellId != dx)) { + newMazeY = var_6 + 4; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_6 = _unkObj1.sub1097EF(di + 46) - 46; - var_a = abs(di - var_6); - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if ( (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5)) && (di >= var_6) && (_field127C <= var_6)) - || (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (_field126E >= var_a) && (_field126E <= 3) && (_action1._field24 != 0)) ){ - if ((tmpVar != 23) && (tmpVar != 24) && (tmpVar != 4) && (tmpVar != 14) && (tmpVar != 15)) + var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46; + var_a = abs(newMazeY - var_6); + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if ( (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (newMazeY >= var_6) && (_mazePosition.y <= var_6)) + || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= var_a) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ){ + newMazeY = var_6; + + if ((cellId != 23) && (cellId != 24) && (cellId != 4) && (cellId != 14) && (cellId != 15)) R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 16) && (var_6 - 3 <= di) && (_field127C <= var_6 - 3)) { - di = var_6 - 3; + } else if ((cellId == 16) && (var_6 - 3 <= newMazeY) && (_mazePosition.y <= var_6 - 3)) { + newMazeY = var_6 - 3; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 31) && (var_6 + 4 <= di) && (_field127C <= var_6 + 4)) { - di = var_6 + 4; + } else if ((cellId == 31) && (var_6 + 4 <= newMazeY) && (_mazePosition.y <= var_6 + 4)) { + newMazeY = var_6 + 4; _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - if ((var_field127A == 660) && (_field126E + 306 <= di) && (di <= 307)) + if ((newMazeX == 660) && (_mazeChangeAmount + 306 <= newMazeY) && (newMazeY <= 307)) ++_field1284; else R2_GLOBALS._sound2.play(339); - } else if (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 != 0) && (var_8 <= 3)) { - var_field127A = var_4; + } else if (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (var_8 != 0) && (var_8 <= 3)) { + newMazeX = var_4; R2_GLOBALS._sound2.play(339); } else { // Nothing @@ -4043,65 +4047,65 @@ void Scene3500::dispatch() { } } break; - case 6: - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if ( ((tmpVar == 12) || (tmpVar == 13) || (tmpVar == 11) || (tmpVar == 16) || (tmpVar == 31)) - || (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (var_a > 3)) ) { + case MAZEDIR_WEST: + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if ( ((cellId == 12) || (cellId == 13) || (cellId == 11) || (cellId == 16) || (cellId == 31)) + || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (var_a > 3)) ) { R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70; - var_field127A = _field127A - _field126E; - dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14)) && (tmpVar != dx)) { - var_field127A = var_4; + var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70; + newMazeX = _mazePosition.x - _mazeChangeAmount; + dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (cellId != dx)) { + newMazeX = var_4; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 1) && (tmpVar != dx)) { - var_field127A = var_4 + 5; + } else if ((cellId == 1) && (cellId != dx)) { + newMazeX = var_4 + 5; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); } else { - var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70; - var_8 = abs(var_4 - var_field127A); - tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46)); - if ( (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14)) && (var_field127A <= var_4) && (_field127A >= var_4)) - || (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (_field126E >= var_8) && (_field126E <= 3) && (_action1._field24 != 0)) ) { - var_field127A = var_4; - if ((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) + var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70; + var_8 = abs(var_4 - newMazeX); + cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46)); + if ( (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (newMazeX <= var_4) && (_mazePosition.x >= var_4)) + || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= var_8) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) { + newMazeX = var_4; + if ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if ((tmpVar == 1) && (var_field127A >= var_4 + 5) && (_field127A >= var_4 + 5)) { - var_field127A = var_4 + 5; + } else if ((cellId == 1) && (newMazeX >= var_4 + 5) && (_mazePosition.x >= var_4 + 5)) { + newMazeX = var_4 + 5; R2_GLOBALS._sound2.play(339); _rotation->_idxChange = 0; _field1270 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1272 = 0; if (_action1._field24 == 0) _actor8.hide(); - } else if (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (var_a != 0) && (var_a <= 3)) { - di = var_6; + } else if (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (var_a != 0) && (var_a <= 3)) { + newMazeY = var_6; R2_GLOBALS._sound2.play(339); } else { // Nothing @@ -4114,49 +4118,49 @@ void Scene3500::dispatch() { } if (_field1284 < 2) { - _field127A = var_field127A; - _field127C = di; - if (_unkObj1.sub109C5E(_field127A, _field127C) != 0) { + _mazePosition.x = newMazeX; + _mazePosition.y = newMazeY; + if (_mazeUI.setMazePosition2(_mazePosition) != 0) { _field1272 = 0; - _field126E = 0; + _mazeChangeAmount = 0; _field1270 = 0; _rotation->setDelay(0); _rotation->_idxChange = 0; } - warning("gfx_set_pane_p"); - _unkObj1.sub51B02(); + + _mazeUI.draw(); if (_field1284 != 0) ++_field1284; } } if (_field1272 == 0) { - if (_field126E != _field1270) { - if (_field126E >= _field1270) { - if (_field126E == 1) { + if (_mazeChangeAmount != _field1270) { + if (_mazeChangeAmount >= _field1270) { + if (_mazeChangeAmount == 1) { if (_action1._field24 != 0) { - if ( ((_field1276 == 1) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15))) - || ((_field1276 == 3) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4))) - || ((_field1276 == 5) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15))) - || ((_field1276 == 7) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4))) ){ - _field126E = 1; + if ( ((_mazeDirection == 1) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15))) + || ((_mazeDirection == 3) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4))) + || ((_mazeDirection == 5) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15))) + || ((_mazeDirection == 7) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))) ){ + _mazeChangeAmount = 1; } else - _field126E--; + _mazeChangeAmount--; } else - _field126E--; + _mazeChangeAmount--; } else - _field126E--; + _mazeChangeAmount--; } else - ++_field126E; + ++_mazeChangeAmount; _field1272 = 1; } - _actor2.setFrame2(_field126E); + _actor2.setFrame2(_mazeChangeAmount + 1); } if (_field1272 == 1) { - if (_field126E == 0) + if (_mazeChangeAmount == 0) _rotation->_idxChange = 0; - else if (_field126E > 8) + else if (_mazeChangeAmount > 8) _rotation->_idxChange = 2; else _rotation->_idxChange = 1; @@ -4165,9 +4169,9 @@ void Scene3500::dispatch() { if (_field1272 != 0) _field1272--; - if (_field126E != 0) { - R2_GLOBALS._player._uiEnabled = false; - if (_field126E != _field1270) + if (_mazeChangeAmount != 0) { + R2_GLOBALS._player._uiEnabled = false; + if (_mazeChangeAmount != _field1270) _aSound1.play(276); } else { R2_GLOBALS._player._uiEnabled = true; diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.h b/engines/tsage/ringworld2/ringworld2_scenes3.h index 44787b9eef..85e5674433 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes3.h +++ b/engines/tsage/ringworld2/ringworld2_scenes3.h @@ -633,12 +633,12 @@ class Scene3500 : public SceneExt { // TODO: double check if nothing specific is present, then remove this class }; - class UnkObject3500 : public UnkObject1200 { + class MazeUI3500 : public MazeUI { public: - int sub1097C9(int arg1); - int sub1097EF(int arg1); - int sub109C09(Common::Point pt); - int sub109C5E(int &x, int &y); + int cellFromX(int arg1); + int cellFromY(int arg1); + int getCellFromMapXY(Common::Point pt); + bool setMazePosition2(Common::Point &p); }; public: Action1 _action1; @@ -650,6 +650,7 @@ public: Item4 _item5; Item4 _item6; Item4 _item7; + // Glyph of vessel on top of the maze ui SceneActor _actor1; SceneActor _actor2; SceneActor _actor3; @@ -660,20 +661,19 @@ public: Actor8 _actor8; Actor8 _actor9; ASoundExt _aSound1; - UnkObject3500 _unkObj1; + MazeUI3500 _mazeUI; SequenceManager _sequenceManager; int _fieldAF8; int _fieldB9E; PaletteRotation *_rotation; - int _field126E; + int _mazeChangeAmount; int _field1270; int _field1272; int _field1274; - int _field1276; + int _mazeDirection; int _field1278; - int _field127A; - int _field127C; + Common::Point _mazePosition; int _field127E; int _field1280; int _field1282; diff --git a/engines/tsage/ringworld2/ringworld2_speakers.cpp b/engines/tsage/ringworld2/ringworld2_speakers.cpp index da1449efdf..8d91787272 100644 --- a/engines/tsage/ringworld2/ringworld2_speakers.cpp +++ b/engines/tsage/ringworld2/ringworld2_speakers.cpp @@ -40,7 +40,7 @@ VisualSpeaker::VisualSpeaker(): Speaker() { _color1 = 8; _color2 = 0; _displayMode = 0; - _fieldF6 = 0; + _speakerMode = 0; } void VisualSpeaker::remove() { @@ -49,27 +49,104 @@ void VisualSpeaker::remove() { _fieldF8 = 0; _object1.setStrip(_object1._strip - 1); _object1.setFrame(_object1.getFrameCount()); - _object1.animate(ANIM_MODE_6, (_fieldF6 == 0xff) ? this : NULL); + _object1.animate(ANIM_MODE_6, (_speakerMode == 0xff) ? this : NULL); } else { - _object1.animate(ANIM_MODE_6, (_fieldF6 == 0xff) ? this : NULL); + _object1.animate(ANIM_MODE_6, (_speakerMode == 0xff) ? this : NULL); } } Speaker::remove(); } +void VisualSpeaker::signal() { + // TODO: _action->_field18 = 1; + if (_speakerMode == 0xff) + proc16(); + + _speakerMode = 0; + if (_numFrames) { + if (_object2) { + _object1.setStrip(_object1._strip + 1); + _object1.animate(ANIM_MODE_2, NULL); + _fieldF8 = 1; + } + + if ((R2_GLOBALS._speechSubtitles & SPEECH_TEXT) || _soundId) + _sceneText.show(); + + if ((R2_GLOBALS._speechSubtitles & SPEECH_VOICE) && _soundId) { + // TODO: Check global that is passed + setFrame2(/* word_55F90 */ 1); + } + } else if (_action && _object2) { + _action->setDelay(1); + _sceneText.remove(); + + R2_GLOBALS._playStream.stop(); + } +} + +void VisualSpeaker::dispatch() { + uint32 frameNumber = R2_GLOBALS._events.getFrameNumber(); + + // Delay check for character animation + if (_delayAmount) { + if (frameNumber >= _frameNumber) { + _delayAmount = _delayAmount - (_frameNumber - frameNumber); + _frameNumber = frameNumber; + + if (_delayAmount <= 0) { + _delayAmount = 0; + _object1.animate(ANIM_MODE_NONE, NULL); + _object1.setFrame(1); + } + } + } + + // Delay check for voice + if (_delayAmount2) { + if (frameNumber >= _frameNumber2) { + _delayAmount2 = _delayAmount2 - (_frameNumber2 - frameNumber); + _frameNumber2 = frameNumber; + + if (_delayAmount2 <= 0) { + _delayAmount2 = 0; + if (R2_GLOBALS._playStream.play(0, NULL)) { + _numFrames = 2; + _soundId = 0; + } else { + _sceneText.show(); + } + } + } + } + + if ((R2_GLOBALS._speechSubtitles & SPEECH_VOICE) && (_numFrames == 2) && + !R2_GLOBALS._playStream.isPlaying()) { + _numFrames = 0; + _object1.animate(ANIM_MODE_NONE); + _object1.setFrame(1); + + if (!(R2_GLOBALS._speechSubtitles & SPEECH_TEXT)) { + _action->setDelay(1); + } + } +} + void VisualSpeaker::synchronize(Serializer &s) { Speaker::synchronize(s); SYNC_POINTER(_object2); - s.syncAsSint16LE(_fieldF6); + s.syncAsSint16LE(_speakerMode); s.syncAsSint16LE(_fieldF8); s.syncAsSint16LE(_displayMode); s.syncAsSint16LE(_soundId); - s.syncAsSint16LE(_delayAmount); s.syncAsByte(_removeObject); - s.syncAsSint32LE(_frameNumber); s.syncAsSint16LE(_numFrames); + s.syncAsSint16LE(_delayAmount); + s.syncAsUint32LE(_frameNumber); + s.syncAsSint16LE(_delayAmount2); + s.syncAsUint32LE(_frameNumber2); } void VisualSpeaker::setText(const Common::String &msg) { @@ -159,8 +236,7 @@ void VisualSpeaker::setText(const Common::String &msg) { if (s.empty()) _numFrames = 0; - - if (_fieldF6) { + if (_speakerMode) { if ((R2_GLOBALS._speechSubtitles & SPEECH_TEXT) || !_soundId) _sceneText.hide(); } else { @@ -173,11 +249,11 @@ void VisualSpeaker::setText(const Common::String &msg) { void VisualSpeaker::proc16() { R2_GLOBALS._playStream.stop(); - _fieldF6 = 0; + _speakerMode = 0; _object1.remove(); - assert(_object2); - _object2->show(); + if (_object2) + _object2->show(); _object2 = NULL; _fieldF8 = 0; } @@ -187,6 +263,11 @@ void VisualSpeaker::setFrame(int numFrames) { _frameNumber = R2_GLOBALS._events.getFrameNumber(); } +void VisualSpeaker::setFrame2(int numFrames) { + _delayAmount2 = numFrames; + _frameNumber2 = R2_GLOBALS._events.getFrameNumber(); +} + void VisualSpeaker::setDelay(int delay) { _delayAmount = delay; _frameNumber = R2_GLOBALS._events.getFrameNumber(); @@ -211,7 +292,7 @@ SpeakerCaptain3210::SpeakerCaptain3210() { _speakerName = "Captain"; _color1 = 5; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -220,7 +301,7 @@ SpeakerCaptain3210::SpeakerCaptain3210() { } void SpeakerCaptain3210::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3210 *scene = (Scene3210 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -250,7 +331,7 @@ SpeakerCaretaker2450::SpeakerCaretaker2450() { _speakerName = "CARETAKER"; _color1 = 43; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -266,7 +347,7 @@ SpeakerChief1100::SpeakerChief1100() { _speakerName = "CHIEF"; _color1 = 8; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -275,11 +356,11 @@ SpeakerChief1100::SpeakerChief1100() { } void SpeakerChief1100::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { - _object2 = &scene->_actor18; + _object2 = &scene->_chief; _object2->hide(); _object1.postInit(); _object1.setPosition(_object2->_position); @@ -324,7 +405,7 @@ SpeakerGuard::SpeakerGuard() { _speakerName = "GUARD"; _color1 = 5; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -333,7 +414,7 @@ SpeakerGuard::SpeakerGuard() { } void SpeakerGuard2800::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -364,7 +445,7 @@ SpeakerJocko::SpeakerJocko() { _speakerName = "Jocko"; _color1 = 45; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -373,7 +454,7 @@ SpeakerJocko::SpeakerJocko() { } void SpeakerJocko3200::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -396,7 +477,7 @@ void SpeakerJocko3200::proc15() { } void SpeakerJocko3220::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3220 *scene = (Scene3220 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -419,7 +500,7 @@ void SpeakerJocko3220::proc15() { } void SpeakerJocko3230::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3230 *scene = (Scene3230 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -449,7 +530,7 @@ SpeakerMiranda::SpeakerMiranda(): VisualSpeaker() { _speakerName = "MIRANDA"; _color1 = 154; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -458,7 +539,7 @@ SpeakerMiranda::SpeakerMiranda(): VisualSpeaker() { } void SpeakerMiranda300::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) { @@ -498,7 +579,7 @@ void SpeakerMiranda300::proc15() { } void SpeakerMiranda1625::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { Scene1625 *scene = (Scene1625 *)R2_GLOBALS._sceneManager._scene; @@ -521,7 +602,7 @@ void SpeakerMiranda1625::proc15() { } void SpeakerMiranda3255::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &R2_GLOBALS._player; @@ -544,7 +625,7 @@ void SpeakerMiranda3255::proc15() { void SpeakerMiranda3375::proc15() { Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) @@ -594,7 +675,7 @@ void SpeakerMiranda3375::proc15() { void SpeakerMiranda3385::proc15() { Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) @@ -643,7 +724,7 @@ void SpeakerMiranda3385::proc15() { void SpeakerMiranda3395::proc15() { Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) @@ -693,7 +774,7 @@ void SpeakerMiranda3395::proc15() { void SpeakerMiranda3400::proc15() { Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) @@ -737,7 +818,7 @@ void SpeakerMiranda3400::proc15() { void SpeakerMiranda3600::proc15() { Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) @@ -783,7 +864,7 @@ void SpeakerMiranda3600::proc15() { void SpeakerMiranda3700::proc15() { Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor3; @@ -840,7 +921,7 @@ SpeakerNej::SpeakerNej() { _speakerName = "NEJ"; _color1 = 171; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -849,7 +930,7 @@ SpeakerNej::SpeakerNej() { } void SpeakerNej2700::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -884,7 +965,7 @@ void SpeakerNej2700::proc15() { } void SpeakerNej2750::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -916,7 +997,7 @@ void SpeakerNej2750::proc15() { } void SpeakerNej2800::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -948,7 +1029,7 @@ SpeakerPharisha::SpeakerPharisha(): VisualSpeaker() { _speakerName = "PHARISHA"; _color1 = 151; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -957,7 +1038,7 @@ SpeakerPharisha::SpeakerPharisha(): VisualSpeaker() { } void SpeakerPharisha2435::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -984,7 +1065,7 @@ SpeakerPrivate3210::SpeakerPrivate3210() { _speakerName = "Private"; _color1 = 45; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -993,7 +1074,7 @@ SpeakerPrivate3210::SpeakerPrivate3210() { } void SpeakerPrivate3210::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3210 *scene = (Scene3210 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -1023,7 +1104,7 @@ SpeakerProtector3600::SpeakerProtector3600() { _speakerName = "Protector"; _color1 = 170; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -1032,7 +1113,7 @@ SpeakerProtector3600::SpeakerProtector3600() { } void SpeakerProtector3600::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -1084,7 +1165,7 @@ SpeakerQuinn::SpeakerQuinn(): VisualSpeaker() { _speakerName = "QUINN"; _color1 = 60; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -1093,7 +1174,7 @@ SpeakerQuinn::SpeakerQuinn(): VisualSpeaker() { } void SpeakerQuinn300::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 3) { @@ -1140,7 +1221,7 @@ void SpeakerQuinn300::proc15() { } void SpeakerQuinn1100::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (v == 0) @@ -1150,7 +1231,7 @@ void SpeakerQuinn1100::proc15() { _object2 = &R2_GLOBALS._player; } else { Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene; - _object2 = &scene->_actor16; + _object2 = &scene->_seeker; } _object2->hide(); @@ -1188,7 +1269,7 @@ void SpeakerQuinn1100::proc15() { } void SpeakerQuinn2435::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) { @@ -1214,7 +1295,7 @@ void SpeakerQuinn2435::proc15() { } void SpeakerQuinn2450::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) { @@ -1242,7 +1323,7 @@ void SpeakerQuinn2450::proc15() { } void SpeakerQuinn2700::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &R2_GLOBALS._player; @@ -1273,7 +1354,7 @@ void SpeakerQuinn2700::proc15() { } void SpeakerQuinn2750::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &R2_GLOBALS._player; @@ -1304,7 +1385,7 @@ void SpeakerQuinn2750::proc15() { } void SpeakerQuinn2800::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &R2_GLOBALS._player; @@ -1345,7 +1426,7 @@ void SpeakerQuinn2800::proc15() { void SpeakerQuinn3255::proc15() { Scene3255 *scene = (Scene3255 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor4; @@ -1368,7 +1449,7 @@ void SpeakerQuinn3255::proc15() { void SpeakerQuinn3375::proc15() { Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) @@ -1419,7 +1500,7 @@ void SpeakerQuinn3375::proc15() { void SpeakerQuinn3385::proc15() { Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) @@ -1474,7 +1555,7 @@ void SpeakerQuinn3385::proc15() { void SpeakerQuinn3395::proc15() { Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) @@ -1529,7 +1610,7 @@ void SpeakerQuinn3395::proc15() { void SpeakerQuinn3400::proc15() { Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) @@ -1578,7 +1659,7 @@ void SpeakerQuinn3400::proc15() { void SpeakerQuinn3600::proc15() { Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 1) @@ -1626,7 +1707,7 @@ void SpeakerQuinn3600::proc15() { void SpeakerQuinn3700::setText(const Common::String &msg) { Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene; - switch (_fieldF6) { + switch (_speakerMode) { case 2: scene->_actor3.setup(30, 1, 1); R2_GLOBALS._sound2.play(44); @@ -1644,7 +1725,7 @@ void SpeakerQuinn3700::setText(const Common::String &msg) { void SpeakerQuinn3700::proc15() { Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor1; @@ -1701,7 +1782,7 @@ SpeakerQuinnL::SpeakerQuinnL(): VisualSpeaker() { _speakerName = "QUINNL"; _color1 = 35; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -1718,7 +1799,7 @@ SpeakerRalf3245::SpeakerRalf3245() { _speakerName = "Ralf"; _color1 = 5; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -1727,7 +1808,7 @@ SpeakerRalf3245::SpeakerRalf3245() { } void SpeakerRalf3245::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3245 *scene = (Scene3245 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -1770,7 +1851,7 @@ SpeakerRocko::SpeakerRocko() { _speakerName = "Rocko"; _color1 = 5; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -1779,7 +1860,7 @@ SpeakerRocko::SpeakerRocko() { } void SpeakerRocko3200::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -1802,7 +1883,7 @@ void SpeakerRocko3200::proc15() { } void SpeakerRocko3220::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3220 *scene = (Scene3220 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -1825,7 +1906,7 @@ void SpeakerRocko3220::proc15() { } void SpeakerRocko3230::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3230 *scene = (Scene3230 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -1855,7 +1936,7 @@ SpeakerSeeker::SpeakerSeeker(): VisualSpeaker() { _speakerName = "SEEKER"; _color1 = 35; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -1864,10 +1945,10 @@ SpeakerSeeker::SpeakerSeeker(): VisualSpeaker() { } void SpeakerSeeker300::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { - if (R2_GLOBALS._player._characterIndex == 3) { + if (R2_GLOBALS._player._characterIndex == 2) { _object2 = &R2_GLOBALS._player; } else { Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene; @@ -1900,7 +1981,7 @@ void SpeakerSeeker300::proc15() { } void SpeakerSeeker1100::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (v == 0) @@ -1910,7 +1991,7 @@ void SpeakerSeeker1100::proc15() { _object2 = &R2_GLOBALS._player; } else { Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene; - _object2 = &scene->_actor16; + _object2 = &scene->_seeker; } _object2->hide(); @@ -1959,7 +2040,7 @@ void SpeakerSeeker1100::proc15() { } void SpeakerSeeker1900::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) { @@ -1989,7 +2070,7 @@ void SpeakerSeeker1900::proc15() { } void SpeakerSeeker2435::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) { @@ -2015,7 +2096,7 @@ void SpeakerSeeker2435::proc15() { } void SpeakerSeeker2450::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) { @@ -2042,7 +2123,7 @@ void SpeakerSeeker2450::proc15() { void SpeakerSeeker3375::proc15() { Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) @@ -2091,7 +2172,7 @@ void SpeakerSeeker3375::proc15() { void SpeakerSeeker3385::proc15() { Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) @@ -2140,7 +2221,7 @@ void SpeakerSeeker3385::proc15() { void SpeakerSeeker3395::proc15() { Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) @@ -2189,7 +2270,7 @@ void SpeakerSeeker3395::proc15() { void SpeakerSeeker3400::proc15() { Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) @@ -2248,7 +2329,7 @@ void SpeakerSeeker3400::proc15() { void SpeakerSeeker3600::proc15() { Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { if (R2_GLOBALS._player._characterIndex == 2) @@ -2295,7 +2376,7 @@ void SpeakerSeeker3600::proc15() { void SpeakerSeeker3700::setText(const Common::String &msg) { Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene; - if (_fieldF6 == 1) { + if (_speakerMode == 1) { R2_GLOBALS._sound2.play(44); scene->_actor3.setup(30, 8, 1); } else { @@ -2307,7 +2388,7 @@ void SpeakerSeeker3700::setText(const Common::String &msg) { void SpeakerSeeker3700::proc15() { Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor2; @@ -2359,7 +2440,7 @@ SpeakerSeekerL::SpeakerSeekerL(): VisualSpeaker() { _speakerName = "SEEKERL"; _color1 = 35; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2376,7 +2457,7 @@ SpeakerSocko3200::SpeakerSocko3200() { _speakerName = "Socko"; _color1 = 10; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2385,7 +2466,7 @@ SpeakerSocko3200::SpeakerSocko3200() { } void SpeakerSocko3200::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -2415,7 +2496,7 @@ SpeakerSoldier::SpeakerSoldier(int colour) { _speakerName = "SOLDIER"; _color1 = colour; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2424,7 +2505,7 @@ SpeakerSoldier::SpeakerSoldier(int colour) { } void SpeakerSoldier300::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene; @@ -2455,7 +2536,7 @@ SpeakerTeal::SpeakerTeal(): VisualSpeaker() { _speakerName = "TEAL"; _color1 = 22; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2468,7 +2549,7 @@ SpeakerTealMode7::SpeakerTealMode7(): SpeakerTeal() { } void SpeakerTeal300::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene; @@ -2492,7 +2573,7 @@ void SpeakerTeal300::proc15() { } void SpeakerTeal1625::proc15() { - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { Scene1625 *scene = (Scene1625 *)R2_GLOBALS._sceneManager._scene; @@ -2516,7 +2597,7 @@ void SpeakerTeal1625::proc15() { } void SpeakerTeal3240::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3240 *scene = (Scene3240 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -2541,7 +2622,7 @@ void SpeakerTeal3240::proc15() { void SpeakerTeal3400::proc15() { Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor4; @@ -2598,7 +2679,7 @@ void SpeakerTeal3400::proc15() { void SpeakerTeal3600::proc15() { Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor5; @@ -2659,7 +2740,7 @@ SpeakerTomko3245::SpeakerTomko3245() { _speakerName = "Tomko"; _color1 = 10; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2668,7 +2749,7 @@ SpeakerTomko3245::SpeakerTomko3245() { } void SpeakerTomko3245::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3245 *scene = (Scene3245 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -2711,7 +2792,7 @@ SpeakerWebbster::SpeakerWebbster(int colour) { _speakerName = "WEBBSTER"; _color1 = colour; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2720,7 +2801,7 @@ SpeakerWebbster::SpeakerWebbster(int colour) { } void SpeakerWebbster3240::proc15() { - int v = _fieldF6; + int v = _speakerMode; Scene3240 *scene = (Scene3240 *)R2_GLOBALS._sceneManager._scene; if (!_object2) { @@ -2745,7 +2826,7 @@ void SpeakerWebbster3240::proc15() { void SpeakerWebbster3375::proc15() { Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor3; @@ -2789,7 +2870,7 @@ void SpeakerWebbster3375::proc15() { void SpeakerWebbster3385::proc15() { Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor3; @@ -2833,7 +2914,7 @@ void SpeakerWebbster3385::proc15() { void SpeakerWebbster3395::proc15() { Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor3; @@ -2877,7 +2958,7 @@ void SpeakerWebbster3395::proc15() { void SpeakerWebbster3400::proc15() { Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_actor3; @@ -2925,7 +3006,7 @@ SpeakerDutyOfficer::SpeakerDutyOfficer(): VisualSpeaker() { _speakerName = "DUTYOFFICER"; _color1 = 5; _color2 = 0; - _fieldF6 = 0; + _speakerMode = 0; _textWidth = 300; _hideObjects = false; _object2 = NULL; @@ -2936,7 +3017,7 @@ SpeakerDutyOfficer::SpeakerDutyOfficer(): VisualSpeaker() { void SpeakerDutyOfficer::proc15() { Scene180 *scene = (Scene180 *)R2_GLOBALS._sceneManager._scene; - int v = _fieldF6; + int v = _speakerMode; if (!_object2) { _object2 = &scene->_object2; diff --git a/engines/tsage/ringworld2/ringworld2_speakers.h b/engines/tsage/ringworld2/ringworld2_speakers.h index fa2946d56c..532e02576c 100644 --- a/engines/tsage/ringworld2/ringworld2_speakers.h +++ b/engines/tsage/ringworld2/ringworld2_speakers.h @@ -41,21 +41,27 @@ class VisualSpeaker : public Speaker { public: SceneActor _object1; SceneObject *_object2; - int _fieldF6, _fieldF8; + int _speakerMode; + int _fieldF8; int _displayMode; int _soundId; int _delayAmount; bool _removeObject; - int _frameNumber; + uint32 _frameNumber; int _numFrames; + int _delayAmount2; + uint32 _frameNumber2; private: void setFrame(int numFrames); + void setFrame2(int numFrames); public: VisualSpeaker(); virtual Common::String getClassName() { return "VisualSpeaker"; } virtual void synchronize(Serializer &s); virtual void remove(); + virtual void signal(); + virtual void dispatch(); virtual void setText(const Common::String &msg); virtual void proc15() {} virtual void proc16(); diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp index af2f3566ad..7143305586 100644 --- a/engines/tsage/saveload.cpp +++ b/engines/tsage/saveload.cpp @@ -289,7 +289,7 @@ void Saver::writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &h // Create a thumbnail and save it Graphics::Surface *thumb = new Graphics::Surface(); Graphics::Surface s = g_globals->_screenSurface.lockSurface(); - ::createThumbnail(thumb, (const byte *)s.pixels, SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette); + ::createThumbnail(thumb, (const byte *)s.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette); Graphics::saveThumbnail(*out, *thumb); g_globals->_screenSurface.unlockSurface(); thumb->free(); diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h index 4126e31822..d43ef792bc 100644 --- a/engines/tsage/saveload.h +++ b/engines/tsage/saveload.h @@ -150,6 +150,16 @@ public: if (i != this->end()) ++i; this->insert(i, newItem); } + + bool contains(T item) { + typename SynchronizedList<T>::iterator i = this->begin(); + for (; i != this->end(); ++i) { + if (*i == item) + return true; + } + + return false; + } }; /** diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp index 4bd9e49875..c0ebb804d2 100644 --- a/engines/tsage/user_interface.cpp +++ b/engines/tsage/user_interface.cpp @@ -84,7 +84,10 @@ void UIQuestion::showDescription(CursorType cursor) { case GType_Ringworld2: if ((cursor == R2_COM_SCANNER) || (cursor == R2_COM_SCANNER_2)) { // Show communicator - warning("TODO: Communicator"); + Ringworld2::SceneExt *scene = static_cast<Ringworld2::SceneExt *> + (R2_GLOBALS._sceneManager._scene); + if (!scene->_sceneAreas.contains(R2_GLOBALS._scannerDialog)) + R2_GLOBALS._scannerDialog->proc12(4, 1, 1, 160, 125); } else { // Show object description SceneItem::display2(3, (int)cursor); @@ -399,7 +402,7 @@ void UIElements::setup(const Common::Point &pt) { } // Setup bottom-right hand buttons - xp += 62; + xp = (g_vm->getGameID() == GType_Ringworld2) ? 255 : 253; int yp = (g_vm->getGameID() == GType_BlueForce) ? 16 : 17; _question.setup(1, 4, 7, xp, yp, 255); _question.setEnabled(false); @@ -410,7 +413,7 @@ void UIElements::setup(const Common::Point &pt) { add(&_scrollLeft); _scrollLeft._isLeft = true; - xp += 22; + xp += (g_vm->getGameID() == GType_Ringworld2) ? 21 : 22; _scrollRight.setup(1, 4, 4, xp, yp, 255); add(&_scrollRight); _scrollRight._isLeft = false; diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index 16c4f4f6f0..bd03eed00b 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -763,7 +763,7 @@ bool AnimationSequencePlayer::decodeNextAnimationFrame(int index, bool copyDirty if (!copyDirtyRects) { for (uint16 y = 0; (y < surface->h) && (y < kScreenHeight); y++) - memcpy(_offscreenBuffer + y * kScreenWidth, (byte *)surface->pixels + y * surface->pitch, surface->w); + memcpy(_offscreenBuffer + y * kScreenWidth, (const byte *)surface->getBasePtr(0, y), surface->w); } else { _flicPlayer[index].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth); } @@ -811,7 +811,7 @@ void AnimationSequencePlayer::playIntroSeq19_20() { if (surface) for (int i = 0; i < kScreenWidth * kScreenHeight; ++i) if (_offscreenBuffer[i] == 0) - _offscreenBuffer[i] = *((byte *)surface->pixels + i); + _offscreenBuffer[i] = *((const byte *)surface->getPixels() + i); if (!framesLeft) _changeToNextSequence = true; diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index 2bd7c47b62..04e83efbe5 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -941,7 +941,7 @@ void TuckerEngine::fadeOutPalette(int colorsCount) { _system->getPaletteManager()->grabPalette(pal, 0, colorsCount); for (int color = 0; color < colorsCount; ++color) { for (int i = 0; i < 3; ++i) { - const int c = int(pal[color * 3 + i]) + kFadePaletteStep * 3; + const int c = int(pal[color * 3 + i]) + kFadePaletteStep * 4; pal[color * 3 + i] = MIN<int>(c, _currentPalette[color * 3 + i]); } } @@ -954,7 +954,7 @@ void TuckerEngine::fadeInPalette(int colorsCount) { _system->getPaletteManager()->grabPalette(pal, 0, colorsCount); for (int color = 0; color < colorsCount; ++color) { for (int i = 0; i < 3; ++i) { - const int c = int(pal[color * 3 + i]) - kFadePaletteStep * 3; + const int c = int(pal[color * 3 + i]) - kFadePaletteStep * 4; pal[color * 3 + i] = MAX<int>(c, 0); } } @@ -2991,6 +2991,7 @@ enum TableInstructionCode { kCode_gfg, kCode_gv, kCode_loc, + kCode_mof, kCode_opt, kCode_opf, kCode_ofg, @@ -3041,6 +3042,7 @@ static const struct { { "gfg", kCode_gfg }, { "gv", kCode_gv }, { "loc", kCode_loc }, + { "mof", kCode_mof }, { "opt", kCode_opt }, { "opf", kCode_opf }, { "ofg", kCode_ofg }, @@ -3062,8 +3064,9 @@ static const struct { int TuckerEngine::readTableInstructionCode(int *index) { bool match = false; + int nameLen = 0; for (int i = 0; _instructions[i].name; ++i) { - const int nameLen = strlen(_instructions[i].name); + nameLen = strlen(_instructions[i].name); if (_instructions[i].name[1] == '0') { if (_instructions[i].name[0] == _tableInstructionsPtr[0] && _instructions[i].name[2] == _tableInstructionsPtr[2]) { const char digit = _tableInstructionsPtr[1]; @@ -3083,6 +3086,7 @@ int TuckerEngine::readTableInstructionCode(int *index) { } } warning("Unhandled instruction '%c%c%c'", _tableInstructionsPtr[0], _tableInstructionsPtr[1], _tableInstructionsPtr[2]); + _tableInstructionsPtr += nameLen + 1; return kCode_invalid; } @@ -3232,6 +3236,9 @@ int TuckerEngine::executeTableInstruction() { case kCode_loc: _nextLocationNum = readTableInstructionParam(2); return 1; + case kCode_mof: + // TODO: Unknown opcode in Spanish version. Identify if this has any function. + return 0; case kCode_opt: _conversationOptionsCount = readTableInstructionParam(2); for (i = 0; i < _conversationOptionsCount; ++i) { diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp index e4c18d6287..94df17c543 100644 --- a/engines/wintermute/ad/ad_actor.cpp +++ b/engines/wintermute/ad/ad_actor.cpp @@ -1457,4 +1457,4 @@ bool AdActor::playAnim(const char *filename) { return AdTalkHolder::playAnim(filename); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_actor.h b/engines/wintermute/ad/ad_actor.h index 3630c6665b..582b41b8b0 100644 --- a/engines/wintermute/ad/ad_actor.h +++ b/engines/wintermute/ad/ad_actor.h @@ -103,6 +103,6 @@ private: int32 _pFCount; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp index c43f74b620..388accf34f 100644 --- a/engines/wintermute/ad/ad_entity.cpp +++ b/engines/wintermute/ad/ad_entity.cpp @@ -1134,4 +1134,4 @@ bool AdEntity::setSprite(const char *filename) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_entity.h b/engines/wintermute/ad/ad_entity.h index c23b37366d..bdbd271667 100644 --- a/engines/wintermute/ad/ad_entity.h +++ b/engines/wintermute/ad/ad_entity.h @@ -68,6 +68,6 @@ private: TEntityType _subtype; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_game.cpp b/engines/wintermute/ad/ad_game.cpp index ead68f7729..d5799e851b 100644 --- a/engines/wintermute/ad/ad_game.cpp +++ b/engines/wintermute/ad/ad_game.cpp @@ -2282,4 +2282,4 @@ bool AdGame::onScriptShutdown(ScScript *script) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_game.h b/engines/wintermute/ad/ad_game.h index 2032a1723f..cb5147501d 100644 --- a/engines/wintermute/ad/ad_game.h +++ b/engines/wintermute/ad/ad_game.h @@ -158,6 +158,6 @@ private: AdInventoryBox *_inventoryBox; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_inventory.cpp b/engines/wintermute/ad/ad_inventory.cpp index e9b6e56f16..544d8310d0 100644 --- a/engines/wintermute/ad/ad_inventory.cpp +++ b/engines/wintermute/ad/ad_inventory.cpp @@ -133,4 +133,4 @@ bool AdInventory::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_inventory.h b/engines/wintermute/ad/ad_inventory.h index 999200b465..9de831b2a0 100644 --- a/engines/wintermute/ad/ad_inventory.h +++ b/engines/wintermute/ad/ad_inventory.h @@ -47,6 +47,6 @@ public: int32 _scrollOffset; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_inventory_box.cpp b/engines/wintermute/ad/ad_inventory_box.cpp index 110359917b..d703de1714 100644 --- a/engines/wintermute/ad/ad_inventory_box.cpp +++ b/engines/wintermute/ad/ad_inventory_box.cpp @@ -386,4 +386,4 @@ bool AdInventoryBox::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_inventory_box.h b/engines/wintermute/ad/ad_inventory_box.h index 9792b1ea66..f65bd8d8f0 100644 --- a/engines/wintermute/ad/ad_inventory_box.h +++ b/engines/wintermute/ad/ad_inventory_box.h @@ -60,6 +60,6 @@ private: int32 _itemWidth; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp index 1a46eb783b..7d05461169 100644 --- a/engines/wintermute/ad/ad_item.cpp +++ b/engines/wintermute/ad/ad_item.cpp @@ -810,4 +810,4 @@ bool AdItem::getExtendedFlag(const char *flagName) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_item.h b/engines/wintermute/ad/ad_item.h index b8351448a7..dd7039db43 100644 --- a/engines/wintermute/ad/ad_item.h +++ b/engines/wintermute/ad/ad_item.h @@ -64,6 +64,6 @@ private: char *_amountString; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_layer.cpp b/engines/wintermute/ad/ad_layer.cpp index 7bf79e4ae5..c833b59163 100644 --- a/engines/wintermute/ad/ad_layer.cpp +++ b/engines/wintermute/ad/ad_layer.cpp @@ -561,4 +561,4 @@ bool AdLayer::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_layer.h b/engines/wintermute/ad/ad_layer.h index 8fe4d4f91e..b260b919fd 100644 --- a/engines/wintermute/ad/ad_layer.h +++ b/engines/wintermute/ad/ad_layer.h @@ -53,6 +53,6 @@ public: virtual const char *scToString() override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_node_state.cpp b/engines/wintermute/ad/ad_node_state.cpp index d52201a08d..876c5a8bb4 100644 --- a/engines/wintermute/ad/ad_node_state.cpp +++ b/engines/wintermute/ad/ad_node_state.cpp @@ -192,4 +192,4 @@ bool AdNodeState::transferEntity(AdEntity *entity, bool includingSprites, bool s return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_node_state.h b/engines/wintermute/ad/ad_node_state.h index e2050815a7..4b5b46ee60 100644 --- a/engines/wintermute/ad/ad_node_state.h +++ b/engines/wintermute/ad/ad_node_state.h @@ -55,6 +55,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_object.cpp b/engines/wintermute/ad/ad_object.cpp index 741d6e6fc6..0d5011f92d 100644 --- a/engines/wintermute/ad/ad_object.cpp +++ b/engines/wintermute/ad/ad_object.cpp @@ -1299,4 +1299,4 @@ bool AdObject::updatePartEmitter() { return _partEmitter->update(); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_object.h b/engines/wintermute/ad/ad_object.h index c6573315da..9e30f69855 100644 --- a/engines/wintermute/ad/ad_object.h +++ b/engines/wintermute/ad/ad_object.h @@ -123,6 +123,6 @@ private: AdInventory *_inventory; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_path.cpp b/engines/wintermute/ad/ad_path.cpp index 5b36ed6471..91a24cbf7d 100644 --- a/engines/wintermute/ad/ad_path.cpp +++ b/engines/wintermute/ad/ad_path.cpp @@ -117,4 +117,4 @@ bool AdPath::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_path.h b/engines/wintermute/ad/ad_path.h index 3f38355b94..9de0bcad2c 100644 --- a/engines/wintermute/ad/ad_path.h +++ b/engines/wintermute/ad/ad_path.h @@ -51,6 +51,6 @@ public: bool _ready; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_path_point.cpp b/engines/wintermute/ad/ad_path_point.cpp index be4b487466..d5108ad8c1 100644 --- a/engines/wintermute/ad/ad_path_point.cpp +++ b/engines/wintermute/ad/ad_path_point.cpp @@ -72,4 +72,4 @@ bool AdPathPoint::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_path_point.h b/engines/wintermute/ad/ad_path_point.h index 04648b1733..5e6b8c61ea 100644 --- a/engines/wintermute/ad/ad_path_point.h +++ b/engines/wintermute/ad/ad_path_point.h @@ -45,6 +45,6 @@ public: int32 _distance; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_region.cpp b/engines/wintermute/ad/ad_region.cpp index acd5f13397..bc9ac903c6 100644 --- a/engines/wintermute/ad/ad_region.cpp +++ b/engines/wintermute/ad/ad_region.cpp @@ -404,9 +404,9 @@ bool AdRegion::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_alpha)); persistMgr->transfer(TMEMBER(_blocked)); persistMgr->transfer(TMEMBER(_decoration)); - persistMgr->transfer(TMEMBER(_zoom)); + persistMgr->transferFloat(TMEMBER(_zoom)); return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_region.h b/engines/wintermute/ad/ad_region.h index bc9eab085e..637c742c9c 100644 --- a/engines/wintermute/ad/ad_region.h +++ b/engines/wintermute/ad/ad_region.h @@ -59,6 +59,6 @@ private: bool _decoration; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_response.cpp b/engines/wintermute/ad/ad_response.cpp index 4483bbc667..fa05224b06 100644 --- a/engines/wintermute/ad/ad_response.cpp +++ b/engines/wintermute/ad/ad_response.cpp @@ -166,7 +166,7 @@ BaseFont *AdResponse::getFont() const { int32 AdResponse::getID() const { return _iD; } - + const char *AdResponse::getText() const { return _text; } @@ -175,4 +175,4 @@ const char *AdResponse::getTextOrig() const { return _textOrig; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response.h b/engines/wintermute/ad/ad_response.h index 57cd302e9d..00ebafbdb0 100644 --- a/engines/wintermute/ad/ad_response.h +++ b/engines/wintermute/ad/ad_response.h @@ -68,6 +68,6 @@ private: char *_textOrig; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_response_box.cpp b/engines/wintermute/ad/ad_response_box.cpp index a589bf3a30..9d7c17ac74 100644 --- a/engines/wintermute/ad/ad_response_box.cpp +++ b/engines/wintermute/ad/ad_response_box.cpp @@ -737,4 +737,4 @@ bool AdResponseBox::getObjects(BaseArray<UIObject *> &objects, bool interactiveO return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response_box.h b/engines/wintermute/ad/ad_response_box.h index cb57b98924..7598e8b569 100644 --- a/engines/wintermute/ad/ad_response_box.h +++ b/engines/wintermute/ad/ad_response_box.h @@ -94,6 +94,6 @@ private: UIWindow *_window; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_response_context.cpp b/engines/wintermute/ad/ad_response_context.cpp index 663ef49a24..0b58f5ba0c 100644 --- a/engines/wintermute/ad/ad_response_context.cpp +++ b/engines/wintermute/ad/ad_response_context.cpp @@ -68,4 +68,4 @@ void AdResponseContext::setContext(const char *context) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response_context.h b/engines/wintermute/ad/ad_response_context.h index dd0008a728..bc30b4a1c9 100644 --- a/engines/wintermute/ad/ad_response_context.h +++ b/engines/wintermute/ad/ad_response_context.h @@ -47,6 +47,6 @@ private: char *_context; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp index 4d7f27aec7..d925b0d57a 100644 --- a/engines/wintermute/ad/ad_rot_level.cpp +++ b/engines/wintermute/ad/ad_rot_level.cpp @@ -153,9 +153,9 @@ bool AdRotLevel::persist(BasePersistenceManager *persistMgr) { BaseObject::persist(persistMgr); - persistMgr->transfer(TMEMBER(_rotation)); + persistMgr->transferFloat(TMEMBER(_rotation)); return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_rot_level.h b/engines/wintermute/ad/ad_rot_level.h index 3466e46ba5..fe2d1691cd 100644 --- a/engines/wintermute/ad/ad_rot_level.h +++ b/engines/wintermute/ad/ad_rot_level.h @@ -45,6 +45,6 @@ public: bool loadBuffer(byte *buffer, bool complete = true); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_scale_level.cpp b/engines/wintermute/ad/ad_scale_level.cpp index e80f38bd0f..59e6d57787 100644 --- a/engines/wintermute/ad/ad_scale_level.cpp +++ b/engines/wintermute/ad/ad_scale_level.cpp @@ -154,9 +154,9 @@ bool AdScaleLevel::persist(BasePersistenceManager *persistMgr) { BaseObject::persist(persistMgr); - persistMgr->transfer(TMEMBER(_scale)); + persistMgr->transferFloat(TMEMBER(_scale)); return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scale_level.h b/engines/wintermute/ad/ad_scale_level.h index 516f507a5a..b2dd7aa91f 100644 --- a/engines/wintermute/ad/ad_scale_level.h +++ b/engines/wintermute/ad/ad_scale_level.h @@ -47,6 +47,6 @@ private: float _scale; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp index 4d0068fad1..668b39853b 100644 --- a/engines/wintermute/ad/ad_scene.cpp +++ b/engines/wintermute/ad/ad_scene.cpp @@ -2989,4 +2989,4 @@ bool AdScene::getRegionObjects(AdRegion *region, BaseArray<AdObject *> &objects, return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene.h b/engines/wintermute/ad/ad_scene.h index cd144b77ef..5beb10e546 100644 --- a/engines/wintermute/ad/ad_scene.h +++ b/engines/wintermute/ad/ad_scene.h @@ -176,6 +176,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_scene_node.cpp b/engines/wintermute/ad/ad_scene_node.cpp index e9b80b3cc8..8548da91db 100644 --- a/engines/wintermute/ad/ad_scene_node.cpp +++ b/engines/wintermute/ad/ad_scene_node.cpp @@ -79,4 +79,4 @@ bool AdSceneNode::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene_state.cpp b/engines/wintermute/ad/ad_scene_state.cpp index 8e022ab115..58cb5f514a 100644 --- a/engines/wintermute/ad/ad_scene_state.cpp +++ b/engines/wintermute/ad/ad_scene_state.cpp @@ -95,4 +95,4 @@ AdNodeState *AdSceneState::getNodeState(const char *name, bool saving) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene_state.h b/engines/wintermute/ad/ad_scene_state.h index 600aa4b581..067c737b2e 100644 --- a/engines/wintermute/ad/ad_scene_state.h +++ b/engines/wintermute/ad/ad_scene_state.h @@ -48,6 +48,6 @@ private: BaseArray<AdNodeState *> _nodeStates; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_sentence.cpp b/engines/wintermute/ad/ad_sentence.cpp index 70a57a624d..d5baa8291f 100644 --- a/engines/wintermute/ad/ad_sentence.cpp +++ b/engines/wintermute/ad/ad_sentence.cpp @@ -358,4 +358,4 @@ bool AdSentence::canSkip() { return (_gameRef->getTimer()->getTime() - _startTime) > 300; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_sentence.h b/engines/wintermute/ad/ad_sentence.h index 6f255578f7..c491ad99a2 100644 --- a/engines/wintermute/ad/ad_sentence.h +++ b/engines/wintermute/ad/ad_sentence.h @@ -80,6 +80,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_sprite_set.cpp b/engines/wintermute/ad/ad_sprite_set.cpp index 6c802c4863..9eb3bd0686 100644 --- a/engines/wintermute/ad/ad_sprite_set.cpp +++ b/engines/wintermute/ad/ad_sprite_set.cpp @@ -353,4 +353,4 @@ bool AdSpriteSet::containsSprite(BaseSprite *sprite) { return false; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_sprite_set.h b/engines/wintermute/ad/ad_sprite_set.h index 61043aa3d6..ef5ef3a94f 100644 --- a/engines/wintermute/ad/ad_sprite_set.h +++ b/engines/wintermute/ad/ad_sprite_set.h @@ -48,6 +48,6 @@ public: BaseSprite *_sprites[NUM_DIRECTIONS]; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_talk_def.cpp b/engines/wintermute/ad/ad_talk_def.cpp index bf72b2916b..f10a0e2fb9 100644 --- a/engines/wintermute/ad/ad_talk_def.cpp +++ b/engines/wintermute/ad/ad_talk_def.cpp @@ -282,4 +282,4 @@ BaseSprite *AdTalkDef::getDefaultSprite(TDirection dir) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_talk_def.h b/engines/wintermute/ad/ad_talk_def.h index 2375360d89..726eefbe4c 100644 --- a/engines/wintermute/ad/ad_talk_def.h +++ b/engines/wintermute/ad/ad_talk_def.h @@ -53,6 +53,6 @@ public: virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0) override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_talk_holder.cpp b/engines/wintermute/ad/ad_talk_holder.cpp index 33deab7805..6041105b93 100644 --- a/engines/wintermute/ad/ad_talk_holder.cpp +++ b/engines/wintermute/ad/ad_talk_holder.cpp @@ -399,4 +399,4 @@ bool AdTalkHolder::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_talk_holder.h b/engines/wintermute/ad/ad_talk_holder.h index 501acbc885..ab48c3aaf4 100644 --- a/engines/wintermute/ad/ad_talk_holder.h +++ b/engines/wintermute/ad/ad_talk_holder.h @@ -52,6 +52,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_talk_node.cpp b/engines/wintermute/ad/ad_talk_node.cpp index f03c24ea94..ce86dccd8e 100644 --- a/engines/wintermute/ad/ad_talk_node.cpp +++ b/engines/wintermute/ad/ad_talk_node.cpp @@ -292,4 +292,4 @@ BaseSprite *AdTalkNode::getSprite(TDirection dir) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_talk_node.h b/engines/wintermute/ad/ad_talk_node.h index 012fa2133e..01dfb6b4ff 100644 --- a/engines/wintermute/ad/ad_talk_node.h +++ b/engines/wintermute/ad/ad_talk_node.h @@ -58,6 +58,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_types.h b/engines/wintermute/ad/ad_types.h index ae5882f4ee..dc1a54b91d 100644 --- a/engines/wintermute/ad/ad_types.h +++ b/engines/wintermute/ad/ad_types.h @@ -102,6 +102,6 @@ typedef enum { GEOM_GENERIC } TGeomNodeType; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp index 96dece34b8..cc7982cb9d 100644 --- a/engines/wintermute/ad/ad_waypoint_group.cpp +++ b/engines/wintermute/ad/ad_waypoint_group.cpp @@ -196,7 +196,7 @@ bool AdWaypointGroup::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_active)); persistMgr->transfer(TMEMBER(_editorSelectedPoint)); - persistMgr->transfer(TMEMBER(_lastMimicScale)); + persistMgr->transferFloat(TMEMBER(_lastMimicScale)); persistMgr->transfer(TMEMBER(_lastMimicX)); persistMgr->transfer(TMEMBER(_lastMimicY)); _points.persist(persistMgr); @@ -267,4 +267,4 @@ bool AdWaypointGroup::mimic(AdWaypointGroup *wpt, float scale, int argX, int arg return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ad/ad_waypoint_group.h b/engines/wintermute/ad/ad_waypoint_group.h index 79b28e0d22..af97a21290 100644 --- a/engines/wintermute/ad/ad_waypoint_group.h +++ b/engines/wintermute/ad/ad_waypoint_group.h @@ -56,6 +56,6 @@ private: int32 _lastMimicY; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base.cpp b/engines/wintermute/base/base.cpp index d01972b82f..a64770c577 100644 --- a/engines/wintermute/base/base.cpp +++ b/engines/wintermute/base/base.cpp @@ -183,4 +183,4 @@ bool BaseClass::saveAsText(BaseDynamicBuffer *buffer, int indent) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base.h b/engines/wintermute/base/base.h index 7f2796c6e0..48ebe49a97 100644 --- a/engines/wintermute/base/base.h +++ b/engines/wintermute/base/base.h @@ -57,6 +57,6 @@ protected: Common::HashMap<Common::String, Common::String>::iterator _editorPropsIter; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_active_rect.cpp b/engines/wintermute/base/base_active_rect.cpp index 7a91854c57..abeaa18d54 100644 --- a/engines/wintermute/base/base_active_rect.cpp +++ b/engines/wintermute/base/base_active_rect.cpp @@ -109,4 +109,4 @@ void BaseActiveRect::clipRect() { BasePlatform::intersectRect(&_rect, &_rect, &rc); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_active_rect.h b/engines/wintermute/base/base_active_rect.h index 982a0902d0..a3c0746618 100644 --- a/engines/wintermute/base/base_active_rect.h +++ b/engines/wintermute/base/base_active_rect.h @@ -55,6 +55,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_dynamic_buffer.cpp b/engines/wintermute/base/base_dynamic_buffer.cpp index f684420b1e..5334ae46c4 100644 --- a/engines/wintermute/base/base_dynamic_buffer.cpp +++ b/engines/wintermute/base/base_dynamic_buffer.cpp @@ -201,4 +201,4 @@ void BaseDynamicBuffer::putTextForm(const char *format, va_list argptr) { putBytes((byte *)buff, strlen(buff)); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_dynamic_buffer.h b/engines/wintermute/base/base_dynamic_buffer.h index ad78ebad00..2804d78895 100644 --- a/engines/wintermute/base/base_dynamic_buffer.h +++ b/engines/wintermute/base/base_dynamic_buffer.h @@ -60,6 +60,6 @@ private: void putTextForm(const char *format, va_list argptr); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp index d4b17a0a64..acb12bbe5f 100644 --- a/engines/wintermute/base/base_engine.cpp +++ b/engines/wintermute/base/base_engine.cpp @@ -44,10 +44,11 @@ BaseEngine::BaseEngine() { _classReg = nullptr; _rnd = nullptr; _gameId = ""; + _language = Common::UNK_LANG; } -void BaseEngine::init(Common::Language lang) { - _fileManager = new BaseFileManager(lang); +void BaseEngine::init() { + _fileManager = new BaseFileManager(_language); // Don't forget to register your random source _rnd = new Common::RandomSource("Wintermute"); _classReg = new SystemClassRegistry(); @@ -60,9 +61,11 @@ BaseEngine::~BaseEngine() { delete _classReg; } -void BaseEngine::createInstance(const Common::String &gameid, Common::Language lang) { - instance()._gameId = gameid; - instance().init(lang); +void BaseEngine::createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang) { + instance()._targetName = targetName; + instance()._gameId = gameId; + instance()._language = lang; + instance().init(); } void BaseEngine::LOG(bool res, const char *fmt, ...) { @@ -122,4 +125,4 @@ const Timer *BaseEngine::getLiveTimer() { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h index d972e6ebbc..a5eafd3597 100644 --- a/engines/wintermute/base/base_engine.h +++ b/engines/wintermute/base/base_engine.h @@ -44,17 +44,19 @@ class BaseRenderer; class SystemClassRegistry; class Timer; class BaseEngine : public Common::Singleton<Wintermute::BaseEngine> { - void init(Common::Language lang); + void init(); BaseFileManager *_fileManager; Common::String _gameId; + Common::String _targetName; BaseGame *_gameRef; // We need random numbers Common::RandomSource *_rnd; SystemClassRegistry *_classReg; + Common::Language _language; public: BaseEngine(); ~BaseEngine(); - static void createInstance(const Common::String &gameid, Common::Language lang); + static void createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang); void setGameRef(BaseGame *gameRef) { _gameRef = gameRef; } Common::RandomSource *getRandomSource() { return _rnd; } @@ -68,9 +70,11 @@ public: static const Timer *getTimer(); static const Timer *getLiveTimer(); static void LOG(bool res, const char *fmt, ...); - const char *getGameId() { return _gameId.c_str(); } + const char *getGameTargetName() const { return _targetName.c_str(); } + Common::String getGameId() const { return _gameId; } + Common::Language getLanguage() const { return _language; } }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_fader.cpp b/engines/wintermute/base/base_fader.cpp index 0d17b07a9d..7978230964 100644 --- a/engines/wintermute/base/base_fader.cpp +++ b/engines/wintermute/base/base_fader.cpp @@ -193,4 +193,4 @@ bool BaseFader::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_fader.h b/engines/wintermute/base/base_fader.h index 845ce2f244..087b19bc44 100644 --- a/engines/wintermute/base/base_fader.h +++ b/engines/wintermute/base/base_fader.h @@ -58,6 +58,6 @@ private: uint32 _startTime; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp index 7d59b03684..bea7e53445 100644 --- a/engines/wintermute/base/base_file_manager.cpp +++ b/engines/wintermute/base/base_file_manager.cpp @@ -269,7 +269,7 @@ Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &f bool BaseFileManager::hasFile(const Common::String &filename) { if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) { - BasePersistenceManager pm(BaseEngine::instance().getGameId()); + BasePersistenceManager pm(BaseEngine::instance().getGameTargetName()); if (filename.size() <= 9) { return false; } @@ -360,4 +360,4 @@ BaseFileManager *BaseFileManager::getEngineInstance() { return nullptr; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h index 7ed3a6c7cb..8c2876f681 100644 --- a/engines/wintermute/base/base_file_manager.h +++ b/engines/wintermute/base/base_file_manager.h @@ -74,6 +74,6 @@ private: // the detector too, without launching the entire engine: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp index 9fb5770f79..eaad024120 100644 --- a/engines/wintermute/base/base_frame.cpp +++ b/engines/wintermute/base/base_frame.cpp @@ -764,4 +764,4 @@ const char *BaseFrame::scToString() { return "[frame]"; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h index 954851c77f..bf1e40daa1 100644 --- a/engines/wintermute/base/base_frame.h +++ b/engines/wintermute/base/base_frame.h @@ -70,6 +70,6 @@ private: BaseSound *_sound; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp index 4d8e79b5c2..b2c05d271d 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -81,7 +81,7 @@ IMPLEMENT_PERSISTENT(BaseGame, true) ////////////////////////////////////////////////////////////////////// -BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gameId), _timerNormal(), _timerLive() { +BaseGame::BaseGame(const Common::String &targetName) : BaseObject(this), _targetName(targetName), _timerNormal(), _timerLive() { _shuttingDown = false; _state = GAME_RUNNING; @@ -212,7 +212,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam #else*/ _touchInterface = false; _constrainedMemory = false; - + _settings = new BaseGameSettings(this); //#endif @@ -1276,11 +1276,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack stack->correctParams(2); const char *key = stack->pop()->getString(); const char *initVal = stack->pop()->getString(); - Common::String privKey = "wme_" + StringUtil::encodeSetting(key); - Common::String result = initVal; - if (ConfMan.hasKey(privKey)) { - result = StringUtil::decodeSetting(ConfMan.get(key)); - } + Common::String result = readRegistryString(key, initVal); stack->pushString(result.c_str()); return STATUS_OK; } @@ -3072,8 +3068,8 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_offsetX)); persistMgr->transfer(TMEMBER(_offsetY)); - persistMgr->transfer(TMEMBER(_offsetPercentX)); - persistMgr->transfer(TMEMBER(_offsetPercentY)); + persistMgr->transferFloat(TMEMBER(_offsetPercentX)); + persistMgr->transferFloat(TMEMBER(_offsetPercentY)); persistMgr->transfer(TMEMBER(_origInteractive)); persistMgr->transfer(TMEMBER_INT(_origState)); @@ -3734,7 +3730,7 @@ bool BaseGame::onWindowClose() { bool BaseGame::displayDebugInfo() { const uint32 strLength = 100; char str[strLength]; - + if (_debugShowFPS) { sprintf(str, "FPS: %d", _gameRef->_fps); _systemFont->drawText((byte *)str, 0, 0, 100, TAL_LEFT); @@ -3902,4 +3898,26 @@ char *BaseGame::getKeyFromStringTable(const char *str) const { return _settings->getKeyFromStringTable(str); } -} // end of namespace Wintermute +Common::String BaseGame::readRegistryString(const Common::String &key, const Common::String &initValue) const { + // Game specific hacks: + Common::String result = initValue; + // James Peris: + if (BaseEngine::instance().getGameId() == "jamesperis" && key == "Language") { + Common::Language language = BaseEngine::instance().getLanguage(); + if (language == Common::EN_ANY) { + result = "english"; + } else if (language == Common::ES_ESP) { + result = "spanish"; + } else { + error("Invalid language set for James Peris"); + } + } else { // Just fallback to using ConfMan for now + Common::String privKey = "wme_" + StringUtil::encodeSetting(key); + if (ConfMan.hasKey(privKey)) { + result = StringUtil::decodeSetting(ConfMan.get(key)); + } + } + return result; +} + +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h index d51255d013..d295bb6b1a 100644 --- a/engines/wintermute/base/base_game.h +++ b/engines/wintermute/base/base_game.h @@ -137,7 +137,7 @@ public: bool initialize2(); bool initialize3(); BaseTransitionMgr *_transMgr; - + // String Table void expandStringByStringTable(char **str) const; char *getKeyFromStringTable(const char *str) const; @@ -150,7 +150,7 @@ public: BaseScriptable *_mathClass; BaseSurfaceStorage *_surfaceStorage; BaseFontStorage *_fontStorage; - BaseGame(const Common::String &gameId); + BaseGame(const Common::String &targetName); virtual ~BaseGame(); bool _debugDebugMode; @@ -173,8 +173,8 @@ public: // compatibility bits bool _compatKillMethodThreads; - const char* getGameId() const { return _gameId.c_str(); } - void setGameId(const Common::String& gameId) { _gameId = gameId; } + const char* getGameTargetName() const { return _targetName.c_str(); } + void setGameTargetName(const Common::String& targetName) { _targetName = targetName; } uint32 _surfaceGCCycleTime; bool _smartCache; // RO bool _subtitles; // RO @@ -275,7 +275,7 @@ private: bool _mouseRightDown; bool _mouseMidlleDown; - + BaseGameSettings *_settings; int32 _soundBufferSizeSec; @@ -295,7 +295,7 @@ private: uint32 _lastTime; uint32 _fpsTime; uint32 _framesRendered; - Common::String _gameId; + Common::String _targetName; void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = nullptr, void *data = nullptr); ENGINE_LOG_CALLBACK _engineLogCallback; @@ -343,6 +343,8 @@ private: bool isDoubleClick(int32 buttonIndex); uint32 _usedMem; +// TODO: This should be expanded into a proper class eventually: + Common::String readRegistryString(const Common::String &key, const Common::String &initValue) const; protected: @@ -356,6 +358,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_game_music.cpp b/engines/wintermute/base/base_game_music.cpp index ac23801e4c..c50969df76 100644 --- a/engines/wintermute/base/base_game_music.cpp +++ b/engines/wintermute/base/base_game_music.cpp @@ -8,12 +8,12 @@ * 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. @@ -65,10 +65,10 @@ bool BaseGameMusic::playMusic(int channel, const char *filename, bool looping, u BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); return STATUS_FAILED; } - + delete _music[channel]; _music[channel] = nullptr; - + _music[channel] = new BaseSound(_gameRef); if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) { if (_musicStartTime[channel]) { @@ -93,7 +93,7 @@ bool BaseGameMusic::stopMusic(int channel) { BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); return STATUS_FAILED; } - + if (_music[channel]) { _music[channel]->stop(); delete _music[channel]; @@ -111,7 +111,7 @@ bool BaseGameMusic::pauseMusic(int channel) { BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); return STATUS_FAILED; } - + if (_music[channel]) { return _music[channel]->pause(); } else { @@ -126,7 +126,7 @@ bool BaseGameMusic::resumeMusic(int channel) { BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); return STATUS_FAILED; } - + if (_music[channel]) { return _music[channel]->resume(); } else { @@ -141,7 +141,7 @@ bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) { BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS); return STATUS_FAILED; } - + _musicStartTime[channel] = time; if (_music[channel] && _music[channel]->isPlaying()) { return _music[channel]->setPositionTime(time); @@ -153,14 +153,14 @@ bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) { ////////////////////////////////////////////////////////////////////////// bool BaseGameMusic::updateMusicCrossfade() { /* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */ - + if (!_musicCrossfadeRunning) { return STATUS_OK; } if (_gameRef->_state == GAME_FROZEN) { return STATUS_OK; } - + if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) { _musicCrossfadeRunning = false; return STATUS_OK; @@ -169,34 +169,34 @@ bool BaseGameMusic::updateMusicCrossfade() { _musicCrossfadeRunning = false; return STATUS_OK; } - + if (!_music[_musicCrossfadeChannel1]->isPlaying()) { _music[_musicCrossfadeChannel1]->play(); } if (!_music[_musicCrossfadeChannel2]->isPlaying()) { _music[_musicCrossfadeChannel2]->play(); } - + uint32 currentTime = _gameRef->getLiveTimer()->getTime() - _musicCrossfadeStartTime; - + if (currentTime >= _musicCrossfadeLength) { _musicCrossfadeRunning = false; //_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol); _music[_musicCrossfadeChannel2]->setVolumePercent(100); - + _music[_musicCrossfadeChannel1]->stop(); //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol); _music[_musicCrossfadeChannel1]->setVolumePercent(100); - - + + if (_musicCrossfadeSwap) { // swap channels BaseSound *dummy = _music[_musicCrossfadeChannel1]; int dummyInt = _musicStartTime[_musicCrossfadeChannel1]; - + _music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2]; _musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2]; - + _music[_musicCrossfadeChannel2] = dummy; _musicStartTime[_musicCrossfadeChannel2] = dummyInt; } @@ -205,10 +205,10 @@ bool BaseGameMusic::updateMusicCrossfade() { //_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol); _music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f)); _music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f)); - + //_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume()); } - + return STATUS_OK; } @@ -242,15 +242,15 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(4); channel = stack->pop()->getInt(); } - + const char *filename = stack->pop()->getString(); ScValue *valLooping = stack->pop(); bool looping = valLooping->isNULL() ? true : valLooping->getBool(); - + ScValue *valLoopStart = stack->pop(); uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt()); - - + + if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) { stack->pushBool(false); } else { @@ -258,20 +258,20 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // StopMusic / StopMusicChannel ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) { int channel = 0; - + if (strcmp(name, "StopMusic") == 0) { stack->correctParams(0); } else { stack->correctParams(1); channel = stack->pop()->getInt(); } - + if (DID_FAIL(stopMusic(channel))) { stack->pushBool(false); } else { @@ -279,20 +279,20 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // PauseMusic / PauseMusicChannel ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) { int channel = 0; - + if (strcmp(name, "PauseMusic") == 0) { stack->correctParams(0); } else { stack->correctParams(1); channel = stack->pop()->getInt(); } - + if (DID_FAIL(pauseMusic(channel))) { stack->pushBool(false); } else { @@ -300,7 +300,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // ResumeMusic / ResumeMusicChannel ////////////////////////////////////////////////////////////////////////// @@ -312,7 +312,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(1); channel = stack->pop()->getInt(); } - + if (DID_FAIL(resumeMusic(channel))) { stack->pushBool(false); } else { @@ -320,7 +320,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // GetMusic / GetMusicChannel ////////////////////////////////////////////////////////////////////////// @@ -343,7 +343,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // SetMusicPosition / SetMusicChannelPosition ////////////////////////////////////////////////////////////////////////// @@ -355,18 +355,18 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(2); channel = stack->pop()->getInt(); } - + uint32 time = stack->pop()->getInt(); - + if (DID_FAIL(setMusicStartTime(channel, time))) { stack->pushBool(false); } else { stack->pushBool(true); } - + return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // GetMusicPosition / GetMusicChannelPosition ////////////////////////////////////////////////////////////////////////// @@ -378,7 +378,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(1); channel = stack->pop()->getInt(); } - + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { stack->pushInt(0); } else { @@ -386,7 +386,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // IsMusicPlaying / IsMusicChannelPlaying ////////////////////////////////////////////////////////////////////////// @@ -398,7 +398,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(1); channel = stack->pop()->getInt(); } - + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { stack->pushBool(false); } else { @@ -406,7 +406,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // SetMusicVolume / SetMusicChannelVolume ////////////////////////////////////////////////////////////////////////// @@ -418,7 +418,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(2); channel = stack->pop()->getInt(); } - + int volume = stack->pop()->getInt(); if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { stack->pushBool(false); @@ -431,7 +431,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // GetMusicVolume / GetMusicChannelVolume ////////////////////////////////////////////////////////////////////////// @@ -443,16 +443,16 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this stack->correctParams(1); channel = stack->pop()->getInt(); } - + if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) { stack->pushInt(0); } else { stack->pushInt(_music[channel]->getVolumePercent()); } - + return STATUS_OK; } - + ////////////////////////////////////////////////////////////////////////// // MusicCrossfade ////////////////////////////////////////////////////////////////////////// @@ -462,34 +462,34 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this int channel2 = stack->pop()->getInt(0); uint32 fadeLength = (uint32)stack->pop()->getInt(0); bool swap = stack->pop()->getBool(true); - + if (_musicCrossfadeRunning) { script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress."); stack->pushBool(false); return STATUS_OK; } - + _musicCrossfadeStartTime = _gameRef->getLiveTimer()->getTime(); _musicCrossfadeChannel1 = channel1; _musicCrossfadeChannel2 = channel2; _musicCrossfadeLength = fadeLength; _musicCrossfadeSwap = swap; - + _musicCrossfadeRunning = true; - + stack->pushBool(true); return STATUS_OK; - } + } ////////////////////////////////////////////////////////////////////////// // GetSoundLength ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "GetSoundLength") == 0) { stack->correctParams(1); - + int length = 0; const char *filename = stack->pop()->getString(); - + BaseSound *sound = new BaseSound(_gameRef); if (sound && DID_SUCCEED(sound->setSound(filename, Audio::Mixer::kMusicSoundType, true))) { length = sound->getLength(); @@ -503,4 +503,4 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_game_music.h b/engines/wintermute/base/base_game_music.h index 0ac904b8c1..72c7a171a6 100644 --- a/engines/wintermute/base/base_game_music.h +++ b/engines/wintermute/base/base_game_music.h @@ -8,12 +8,12 @@ * 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. @@ -53,7 +53,7 @@ public: bool stopMusic(int channel); bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0); bool updateMusicCrossfade(); - + bool persistChannels(BasePersistenceManager *persistMgr); bool persistCrossfadeSettings(BasePersistenceManager *persistMgr); private: @@ -68,6 +68,6 @@ private: int32 _musicCrossfadeChannel2; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_game_settings.cpp b/engines/wintermute/base/base_game_settings.cpp index 55fbe39fd2..1de8b31ca7 100644 --- a/engines/wintermute/base/base_game_settings.cpp +++ b/engines/wintermute/base/base_game_settings.cpp @@ -8,12 +8,12 @@ * 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. @@ -47,7 +47,7 @@ BaseGameSettings::BaseGameSettings(BaseGame *gameRef) { _allowAccessTab = true; _allowAboutTab = true; _allowDesktopRes = false; - + _compressedSavegames = true; _richSavedGames = false; _savedGameExt = "dsv"; @@ -101,21 +101,21 @@ bool BaseGameSettings::loadSettings(const char *filename) { TOKEN_TABLE(SAVED_GAME_EXT) TOKEN_TABLE(GUID) TOKEN_TABLE_END - - + + byte *origBuffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); if (origBuffer == nullptr) { BaseEngine::LOG(0, "BaseGame::LoadSettings failed for file '%s'", filename); return STATUS_FAILED; } - + bool ret = STATUS_OK; - + byte *buffer = origBuffer; byte *params; int cmd; BaseParser parser; - + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SETTINGS) { BaseEngine::LOG(0, "'SETTINGS' keyword expected in game settings file."); return STATUS_FAILED; @@ -130,61 +130,61 @@ bool BaseGameSettings::loadSettings(const char *filename) { strcpy(_gameFile, (char *)params); } break; - + case TOKEN_STRING_TABLE: if (DID_FAIL(_stringTable->loadFile((char *)params))) { cmd = PARSERR_GENERIC; } break; - + case TOKEN_RESOLUTION: parser.scanStr((char *)params, "%d,%d", &_resWidth, &_resHeight); break; - + case TOKEN_REQUIRE_3D_ACCELERATION: parser.scanStr((char *)params, "%b", &_requireAcceleration); break; - + case TOKEN_REQUIRE_SOUND: parser.scanStr((char *)params, "%b", &_requireSound); break; - + case TOKEN_HWTL_MODE: parser.scanStr((char *)params, "%d", &_TLMode); break; - + case TOKEN_ALLOW_WINDOWED_MODE: parser.scanStr((char *)params, "%b", &_allowWindowed); break; - + case TOKEN_ALLOW_DESKTOP_RES: parser.scanStr((char *)params, "%b", &_allowDesktopRes); break; - + case TOKEN_ALLOW_ADVANCED: parser.scanStr((char *)params, "%b", &_allowAdvanced); break; - + case TOKEN_ALLOW_ACCESSIBILITY_TAB: parser.scanStr((char *)params, "%b", &_allowAccessTab); break; - + case TOKEN_ALLOW_ABOUT_TAB: parser.scanStr((char *)params, "%b", &_allowAboutTab); break; - + case TOKEN_REGISTRY_PATH: //BaseEngine::instance().getRegistry()->setBasePath((char *)params); break; - + case TOKEN_RICH_SAVED_GAMES: parser.scanStr((char *)params, "%b", &_richSavedGames); break; - + case TOKEN_SAVED_GAME_EXT: _savedGameExt = (char *)params; break; - + case TOKEN_GUID: break; } @@ -197,12 +197,12 @@ bool BaseGameSettings::loadSettings(const char *filename) { BaseEngine::LOG(0, "Error loading game settings '%s'", filename); ret = STATUS_FAILED; } - + _allowWindowed = true; // TODO: These two settings should probably be cleaned out altogether. _compressedSavegames = true; - + delete[] origBuffer; - + return ret; } @@ -219,4 +219,4 @@ char *BaseGameSettings::getKeyFromStringTable(const char *str) const { return _stringTable->getKey(str); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_game_settings.h b/engines/wintermute/base/base_game_settings.h index 1dfb0b50cc..38a2fd1042 100644 --- a/engines/wintermute/base/base_game_settings.h +++ b/engines/wintermute/base/base_game_settings.h @@ -8,12 +8,12 @@ * 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. @@ -66,6 +66,6 @@ private: bool _richSavedGames; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp index 072a1bb71b..aeb56ad282 100644 --- a/engines/wintermute/base/base_keyboard_state.cpp +++ b/engines/wintermute/base/base_keyboard_state.cpp @@ -310,4 +310,4 @@ Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) { } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h index b62ece02b7..14a57ee7b8 100644 --- a/engines/wintermute/base/base_keyboard_state.h +++ b/engines/wintermute/base/base_keyboard_state.h @@ -61,7 +61,7 @@ private: bool _currentPrintable; uint32 _currentKeyData; uint32 _currentCharCode; - + bool _currentShift; bool _currentAlt; bool _currentControl; @@ -71,6 +71,6 @@ private: Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_named_object.cpp b/engines/wintermute/base/base_named_object.cpp index f99ec2f5db..3d1df5ab84 100644 --- a/engines/wintermute/base/base_named_object.cpp +++ b/engines/wintermute/base/base_named_object.cpp @@ -68,4 +68,4 @@ void BaseNamedObject::setName(const char *name) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_named_object.h b/engines/wintermute/base/base_named_object.h index d25fec4a82..ee4a3bba6a 100644 --- a/engines/wintermute/base/base_named_object.h +++ b/engines/wintermute/base/base_named_object.h @@ -46,6 +46,6 @@ public: void setName(const char *name); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp index ad181b922e..ea754f8f23 100644 --- a/engines/wintermute/base/base_object.cpp +++ b/engines/wintermute/base/base_object.cpp @@ -968,9 +968,9 @@ bool BaseObject::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_movable)); persistMgr->transfer(TMEMBER(_posX)); persistMgr->transfer(TMEMBER(_posY)); - persistMgr->transfer(TMEMBER(_relativeScale)); + persistMgr->transferFloat(TMEMBER(_relativeScale)); persistMgr->transfer(TMEMBER(_rotatable)); - persistMgr->transfer(TMEMBER(_scale)); + persistMgr->transferFloat(TMEMBER(_scale)); persistMgr->transferPtr(TMEMBER_PTR(_sFX)); persistMgr->transfer(TMEMBER(_sFXStart)); persistMgr->transfer(TMEMBER(_sFXVolume)); @@ -982,21 +982,21 @@ bool BaseObject::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_soundEvent)); persistMgr->transfer(TMEMBER(_zoomable)); - persistMgr->transfer(TMEMBER(_scaleX)); - persistMgr->transfer(TMEMBER(_scaleY)); + persistMgr->transferFloat(TMEMBER(_scaleX)); + persistMgr->transferFloat(TMEMBER(_scaleY)); - persistMgr->transfer(TMEMBER(_rotate)); + persistMgr->transferFloat(TMEMBER(_rotate)); persistMgr->transfer(TMEMBER(_rotateValid)); - persistMgr->transfer(TMEMBER(_relativeRotate)); + persistMgr->transferFloat(TMEMBER(_relativeRotate)); persistMgr->transfer(TMEMBER(_saveState)); persistMgr->transfer(TMEMBER(_nonIntMouseEvents)); persistMgr->transfer(TMEMBER_INT(_sFXType)); - persistMgr->transfer(TMEMBER(_sFXParam1)); - persistMgr->transfer(TMEMBER(_sFXParam2)); - persistMgr->transfer(TMEMBER(_sFXParam3)); - persistMgr->transfer(TMEMBER(_sFXParam4)); + persistMgr->transferFloat(TMEMBER(_sFXParam1)); + persistMgr->transferFloat(TMEMBER(_sFXParam2)); + persistMgr->transferFloat(TMEMBER(_sFXParam3)); + persistMgr->transferFloat(TMEMBER(_sFXParam4)); persistMgr->transfer(TMEMBER_INT(_blendMode)); @@ -1242,4 +1242,4 @@ bool BaseObject::afterMove() { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h index 7afe9cf94c..42041c5e3c 100644 --- a/engines/wintermute/base/base_object.h +++ b/engines/wintermute/base/base_object.h @@ -142,6 +142,6 @@ public: virtual const char *scToString() override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_parser.cpp b/engines/wintermute/base/base_parser.cpp index a7e3bd5efb..0b677b6cb2 100644 --- a/engines/wintermute/base/base_parser.cpp +++ b/engines/wintermute/base/base_parser.cpp @@ -464,4 +464,4 @@ int32 BaseParser::scanStr(const char *in, const char *format, ...) { return num; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_parser.h b/engines/wintermute/base/base_parser.h index 4953ac3c0b..4bf48cc016 100644 --- a/engines/wintermute/base/base_parser.h +++ b/engines/wintermute/base/base_parser.h @@ -83,6 +83,6 @@ private: char *_whiteSpace; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp index 5dbacb157b..2e2726f361 100644 --- a/engines/wintermute/base/base_persistence_manager.cpp +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -94,7 +94,7 @@ BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool dele if (savePrefix) { _savePrefix = savePrefix; } else if (_gameRef) { - _savePrefix = _gameRef->getGameId(); + _savePrefix = _gameRef->getGameTargetName(); } else { _savePrefix = "wmesav"; } @@ -282,7 +282,7 @@ bool BasePersistenceManager::initSave(const char *desc) { } else { _saveStream->writeUint32LE(0); } - + thumbnailOK = true; } } @@ -637,7 +637,7 @@ bool BasePersistenceManager::transfer(const char *name, uint32 *val) { ////////////////////////////////////////////////////////////////////////// // float -bool BasePersistenceManager::transfer(const char *name, float *val) { +bool BasePersistenceManager::transferFloat(const char *name, float *val) { if (_saving) { putFloat(*val); if (_saveStream->err()) { @@ -887,4 +887,4 @@ bool BasePersistenceManager::checkVersion(byte verMajor, byte verMinor, byte ver return true; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h index 7b578085ba..c09b3345b7 100644 --- a/engines/wintermute/base/base_persistence_manager.h +++ b/engines/wintermute/base/base_persistence_manager.h @@ -76,7 +76,7 @@ public: bool transferPtr(const char *name, void *val); bool transfer(const char *name, int32 *val); bool transfer(const char *name, uint32 *val); - bool transfer(const char *name, float *val); + bool transferFloat(const char *name, float *val); bool transfer(const char *name, double *val); bool transfer(const char *name, bool *val); bool transfer(const char *name, byte *val); @@ -115,6 +115,6 @@ private: BaseGame *_gameRef; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_point.cpp b/engines/wintermute/base/base_point.cpp index fbd8960894..fe6ca941f3 100644 --- a/engines/wintermute/base/base_point.cpp +++ b/engines/wintermute/base/base_point.cpp @@ -60,4 +60,4 @@ bool BasePoint::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_point.h b/engines/wintermute/base/base_point.h index 26568d5d0b..cf8a5be336 100644 --- a/engines/wintermute/base/base_point.h +++ b/engines/wintermute/base/base_point.h @@ -45,6 +45,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_quick_msg.cpp b/engines/wintermute/base/base_quick_msg.cpp index 9f19dfd74a..ac0c107d3b 100644 --- a/engines/wintermute/base/base_quick_msg.cpp +++ b/engines/wintermute/base/base_quick_msg.cpp @@ -52,4 +52,4 @@ uint32 BaseQuickMsg::getStartTime() const { return _startTime; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_quick_msg.h b/engines/wintermute/base/base_quick_msg.h index 377f7733fd..b706424c18 100644 --- a/engines/wintermute/base/base_quick_msg.h +++ b/engines/wintermute/base/base_quick_msg.h @@ -44,6 +44,6 @@ private: uint32 _startTime; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp index 2dabe6ae44..36036a1f18 100644 --- a/engines/wintermute/base/base_region.cpp +++ b/engines/wintermute/base/base_region.cpp @@ -432,7 +432,7 @@ bool BaseRegion::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_active)); persistMgr->transfer(TMEMBER(_editorSelectedPoint)); - persistMgr->transfer(TMEMBER(_lastMimicScale)); + persistMgr->transferFloat(TMEMBER(_lastMimicScale)); persistMgr->transfer(TMEMBER(_lastMimicX)); persistMgr->transfer(TMEMBER(_lastMimicY)); _points.persist(persistMgr); @@ -532,4 +532,4 @@ bool BaseRegion::mimic(BaseRegion *region, float scale, int x, int y) { return createRegion() ? STATUS_OK : STATUS_FAILED; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_region.h b/engines/wintermute/base/base_region.h index 67ca158897..93ad6a6fbe 100644 --- a/engines/wintermute/base/base_region.h +++ b/engines/wintermute/base/base_region.h @@ -65,6 +65,6 @@ private: int32 _lastMimicY; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp index 036bac1dd8..25b8775a98 100644 --- a/engines/wintermute/base/base_script_holder.cpp +++ b/engines/wintermute/base/base_script_holder.cpp @@ -500,4 +500,4 @@ bool BaseScriptHolder::sendEvent(const char *eventName) { return DID_SUCCEED(applyEvent(eventName)); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_script_holder.h b/engines/wintermute/base/base_script_holder.h index 38a3f935d3..c34b0378a1 100644 --- a/engines/wintermute/base/base_script_holder.h +++ b/engines/wintermute/base/base_script_holder.h @@ -71,6 +71,6 @@ public: virtual bool sendEvent(const char *eventName); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_scriptable.cpp b/engines/wintermute/base/base_scriptable.cpp index 5753b0482b..be1e18c2c4 100644 --- a/engines/wintermute/base/base_scriptable.cpp +++ b/engines/wintermute/base/base_scriptable.cpp @@ -188,4 +188,4 @@ ScScript *BaseScriptable::invokeMethodThread(const char *methodName) { return nullptr; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_scriptable.h b/engines/wintermute/base/base_scriptable.h index f23d7faa5b..08fd32081a 100644 --- a/engines/wintermute/base/base_scriptable.h +++ b/engines/wintermute/base/base_scriptable.h @@ -78,6 +78,6 @@ BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack); BaseScriptable *makeSXStore(BaseGame *inGame); BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack); -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp index c920da9ee9..ab78c5ac7c 100644 --- a/engines/wintermute/base/base_sprite.cpp +++ b/engines/wintermute/base/base_sprite.cpp @@ -817,4 +817,4 @@ bool BaseSprite::killAllSounds() { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h index 05cb9fc936..1387796895 100644 --- a/engines/wintermute/base/base_sprite.h +++ b/engines/wintermute/base/base_sprite.h @@ -32,6 +32,7 @@ #include "engines/wintermute/coll_templ.h" #include "engines/wintermute/base/base_script_holder.h" +#include "engines/wintermute/graphics/transform_tools.h" namespace Wintermute { class BaseFrame; @@ -44,17 +45,17 @@ public: void setDefaults(); DECLARE_PERSISTENT(BaseSprite, BaseScriptHolder) - bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100); + bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = kDefaultZoomX, float scaleY = kDefaultZoomY); int32 _moveY; int32 _moveX; - bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); - bool getCurrentFrame(float zoomX = 100, float zoomY = 100); + bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod, float rotate = kDefaultAngle, TSpriteBlendMode blendMode = BLEND_NORMAL); + bool getCurrentFrame(float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY); void reset(); bool isChanged(); bool isFinished(); bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF); + bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod); bool _looping; int32 _currentFrame; bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = nullptr); @@ -88,6 +89,6 @@ private: bool killAllSounds(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp index 8207c32244..3d9cc4f8b3 100644 --- a/engines/wintermute/base/base_string_table.cpp +++ b/engines/wintermute/base/base_string_table.cpp @@ -253,4 +253,4 @@ bool BaseStringTable::loadFile(const char *filename, bool clearOld) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_string_table.h b/engines/wintermute/base/base_string_table.h index 128807bd1a..f8808f5b27 100644 --- a/engines/wintermute/base/base_string_table.h +++ b/engines/wintermute/base/base_string_table.h @@ -50,6 +50,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp index d93cf667f1..8a8f63240b 100644 --- a/engines/wintermute/base/base_sub_frame.cpp +++ b/engines/wintermute/base/base_sub_frame.cpp @@ -38,6 +38,8 @@ #include "engines/wintermute/base/gfx/base_renderer.h" #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/graphics/transform_tools.h" +#include "engines/wintermute/graphics/transform_struct.h" namespace Wintermute { @@ -46,8 +48,9 @@ IMPLEMENT_PERSISTENT(BaseSubFrame, false) ////////////////////////////////////////////////////////////////////////// BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) { _surface = nullptr; - _hotspotX = _hotspotY = 0; - _alpha = 0xFFFFFFFF; + _hotspotX = kDefaultHotspotX; + _hotspotY = kDefaultHotspotY; + _alpha = kDefaultRgbaMod; _transparent = 0xFFFF00FF; _wantsDefaultRect = false; @@ -233,12 +236,18 @@ const char* BaseSubFrame::getSurfaceFilename() { ////////////////////////////////////////////////////////////////////// bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, TSpriteBlendMode blendMode) { + + rotate = fmod(rotate, 360.0f); + if (rotate < 0) { + rotate += 360.0f; + } + if (!_surface) { return STATUS_OK; } if (registerOwner != nullptr && !_decoration) { - if (zoomX == 100 && zoomY == 100) { + if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) { BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, x - _hotspotX + getRect().left, y - _hotspotY + getRect().top, getRect().right - getRect().left, getRect().bottom - getRect().top, zoomX, zoomY, precise)); } else { BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + getRect().left) * (zoomX / 100)), (int)(y - (_hotspotY + getRect().top) * (zoomY / 100)), (int)((getRect().right - getRect().left) * (zoomX / 100)), (int)((getRect().bottom - getRect().top) * (zoomY / 100)), zoomX, zoomY, precise)); @@ -251,17 +260,24 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl bool res; //if (Alpha==0xFFFFFFFF) Alpha = _alpha; // TODO: better (combine owner's and self alpha) - if (_alpha != 0xFFFFFFFF) { + if (_alpha != kDefaultRgbaMod) { alpha = _alpha; } - if (rotate != 0.0f) { - res = _surface->displayTransform((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), _hotspotX, _hotspotY, getRect(), zoomX, zoomY, alpha, rotate, blendMode, _mirrorX, _mirrorY); + if (rotate != kDefaultAngle) { + Point32 boxOffset, rotatedHotspot, hotspotOffset, newOrigin; + Point32 origin(x, y); + Rect32 oldRect = getRect(); + Point32 newHotspot; + TransformStruct transform = TransformStruct(zoomX, zoomY, rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0); + Rect32 newRect = TransformTools::newRect (oldRect, transform, &newHotspot); + newOrigin = origin - newHotspot; + res = _surface->displayTransform(newOrigin.x, newOrigin.y, oldRect, newRect, transform); } else { - if (zoomX == 100 && zoomY == 100) { + if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) { res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, getRect(), alpha, blendMode, _mirrorX, _mirrorY); } else { - res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY); + res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / kDefaultZoomX)), (int)(y - _hotspotY * (zoomY / kDefaultZoomY)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY); } } @@ -657,4 +673,4 @@ bool BaseSubFrame::setSurfaceSimple() { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h index 37ba34b748..ba3d5b955a 100644 --- a/engines/wintermute/base/base_sub_frame.h +++ b/engines/wintermute/base/base_sub_frame.h @@ -88,6 +88,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_surface_storage.cpp b/engines/wintermute/base/base_surface_storage.cpp index 8dbd6a6d2a..f1d068674b 100644 --- a/engines/wintermute/base/base_surface_storage.cpp +++ b/engines/wintermute/base/base_surface_storage.cpp @@ -203,4 +203,4 @@ bool BaseSurfaceStorage::surfaceSortCB(const BaseSurface *s1, const BaseSurface } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_surface_storage.h b/engines/wintermute/base/base_surface_storage.h index 61738e69a2..c0049d676c 100644 --- a/engines/wintermute/base/base_surface_storage.h +++ b/engines/wintermute/base/base_surface_storage.h @@ -52,6 +52,6 @@ public: Common::Array<BaseSurface *> _surfaces; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_transition_manager.cpp b/engines/wintermute/base/base_transition_manager.cpp index 1c869e6a2b..eee5f1aae7 100644 --- a/engines/wintermute/base/base_transition_manager.cpp +++ b/engines/wintermute/base/base_transition_manager.cpp @@ -135,4 +135,4 @@ bool BaseTransitionMgr::update() { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_transition_manager.h b/engines/wintermute/base/base_transition_manager.h index edb3045a58..82edb9ff88 100644 --- a/engines/wintermute/base/base_transition_manager.h +++ b/engines/wintermute/base/base_transition_manager.h @@ -49,6 +49,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/base_viewport.cpp b/engines/wintermute/base/base_viewport.cpp index f79e5c9f13..09ac80e9de 100644 --- a/engines/wintermute/base/base_viewport.cpp +++ b/engines/wintermute/base/base_viewport.cpp @@ -97,4 +97,4 @@ int BaseViewport::getHeight() const { return _rect.bottom - _rect.top; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/base_viewport.h b/engines/wintermute/base/base_viewport.h index 584e5a78f9..0225c02c7c 100644 --- a/engines/wintermute/base/base_viewport.h +++ b/engines/wintermute/base/base_viewport.h @@ -52,6 +52,6 @@ private: Rect32 _rect; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp index 3c1ecc7a73..7391d819fc 100644 --- a/engines/wintermute/base/file/base_disk_file.cpp +++ b/engines/wintermute/base/file/base_disk_file.cpp @@ -66,12 +66,6 @@ static Common::FSNode getNodeForRelativePath(const Common::String &filename) { const Common::FSNode gameDataDir(ConfMan.get("path")); Common::FSNode curNode = gameDataDir; - Common::String fixedPath = ""; - while (!path.empty()) { - fixedPath += path.nextToken() + "/"; - } - fixedPath.deleteLastChar(); - // Parse all path-elements while (!path.empty()) { // Get the next path-component by slicing on '\\' @@ -198,4 +192,4 @@ Common::SeekableReadStream *openDiskFile(const Common::String &filename) { return nullptr; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/file/base_disk_file.h b/engines/wintermute/base/file/base_disk_file.h index c9f93b80d9..81cc22b86d 100644 --- a/engines/wintermute/base/file/base_disk_file.h +++ b/engines/wintermute/base/file/base_disk_file.h @@ -36,6 +36,6 @@ namespace Wintermute { Common::SeekableReadStream *openDiskFile(const Common::String &filename); bool diskFileExists(const Common::String &filename); -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/file/base_file.cpp b/engines/wintermute/base/file/base_file.cpp index f52a13211e..42eea69824 100644 --- a/engines/wintermute/base/file/base_file.cpp +++ b/engines/wintermute/base/file/base_file.cpp @@ -65,4 +65,4 @@ Common::SeekableReadStream *BaseFile::getMemStream() { } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/file/base_file.h b/engines/wintermute/base/file/base_file.h index 8eda6d51d9..9acda7ffce 100644 --- a/engines/wintermute/base/file/base_file.h +++ b/engines/wintermute/base/file/base_file.h @@ -62,6 +62,6 @@ public: virtual Common::SeekableReadStream *getMemStream(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/file/base_file_entry.cpp b/engines/wintermute/base/file/base_file_entry.cpp index 1968da6f47..846f56b55c 100644 --- a/engines/wintermute/base/file/base_file_entry.cpp +++ b/engines/wintermute/base/file/base_file_entry.cpp @@ -70,4 +70,4 @@ BaseFileEntry::~BaseFileEntry() { _package = nullptr; // ref only } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/file/base_file_entry.h b/engines/wintermute/base/file/base_file_entry.h index 6e4823d994..9d738c8c11 100644 --- a/engines/wintermute/base/file/base_file_entry.h +++ b/engines/wintermute/base/file/base_file_entry.h @@ -55,6 +55,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp index 73f767c3ef..512279b72c 100644 --- a/engines/wintermute/base/file/base_package.cpp +++ b/engines/wintermute/base/file/base_package.cpp @@ -273,4 +273,4 @@ Common::SeekableReadStream *PackageSet::createReadStreamForMember(const Common:: return nullptr; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/file/base_package.h b/engines/wintermute/base/file/base_package.h index bcf088aaea..18156c4f65 100644 --- a/engines/wintermute/base/file/base_package.h +++ b/engines/wintermute/base/file/base_package.h @@ -85,6 +85,6 @@ private: Common::HashMap<Common::String, Common::ArchiveMemberPtr>::iterator _filesIter; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/file/base_save_thumb_file.cpp b/engines/wintermute/base/file/base_save_thumb_file.cpp index 2c4ddf4875..bb172ca66a 100644 --- a/engines/wintermute/base/file/base_save_thumb_file.cpp +++ b/engines/wintermute/base/file/base_save_thumb_file.cpp @@ -150,4 +150,4 @@ bool BaseSaveThumbFile::seek(uint32 pos, int whence) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/file/base_save_thumb_file.h b/engines/wintermute/base/file/base_save_thumb_file.h index 3b217525fd..faf1af9255 100644 --- a/engines/wintermute/base/file/base_save_thumb_file.h +++ b/engines/wintermute/base/file/base_save_thumb_file.h @@ -47,6 +47,6 @@ private: byte *_data; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/file/dcpackage.h b/engines/wintermute/base/file/dcpackage.h index 2234139408..a2ec5d28d5 100644 --- a/engines/wintermute/base/file/dcpackage.h +++ b/engines/wintermute/base/file/dcpackage.h @@ -75,6 +75,6 @@ v2: uint32 TimeDate1 */ -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/font/base_font.cpp b/engines/wintermute/base/font/base_font.cpp index 596f9fb5c6..26bc0e7985 100644 --- a/engines/wintermute/base/font/base_font.cpp +++ b/engines/wintermute/base/font/base_font.cpp @@ -137,4 +137,4 @@ bool BaseFont::isTrueType(BaseGame *gameRef, const Common::String &filename) { return ret; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/font/base_font.h b/engines/wintermute/base/font/base_font.h index 50587fa7eb..d75d3f4fb5 100644 --- a/engines/wintermute/base/font/base_font.h +++ b/engines/wintermute/base/font/base_font.h @@ -56,6 +56,6 @@ private: static bool isTrueType(BaseGame *game, const Common::String &filename); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp index 03bd471636..890a9a2f83 100644 --- a/engines/wintermute/base/font/base_font_bitmap.cpp +++ b/engines/wintermute/base/font/base_font_bitmap.cpp @@ -587,4 +587,4 @@ int BaseFontBitmap::getLetterHeight() { return _tileHeight; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/font/base_font_bitmap.h b/engines/wintermute/base/font/base_font_bitmap.h index 0bdac64026..c810777446 100644 --- a/engines/wintermute/base/font/base_font_bitmap.h +++ b/engines/wintermute/base/font/base_font_bitmap.h @@ -66,6 +66,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/font/base_font_storage.cpp b/engines/wintermute/base/font/base_font_storage.cpp index 3286742478..8abd368b70 100644 --- a/engines/wintermute/base/font/base_font_storage.cpp +++ b/engines/wintermute/base/font/base_font_storage.cpp @@ -138,4 +138,4 @@ bool BaseFontStorage::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/font/base_font_storage.h b/engines/wintermute/base/font/base_font_storage.h index 60874167e7..f4ac490324 100644 --- a/engines/wintermute/base/font/base_font_storage.h +++ b/engines/wintermute/base/font/base_font_storage.h @@ -50,6 +50,6 @@ public: bool initLoop(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp index 2fcdebc117..3059a69047 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -644,4 +644,4 @@ void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight }*/ } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/font/base_font_truetype.h b/engines/wintermute/base/font/base_font_truetype.h index f93505921f..fdbae30684 100644 --- a/engines/wintermute/base/font/base_font_truetype.h +++ b/engines/wintermute/base/font/base_font_truetype.h @@ -148,6 +148,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp index 75de95128f..d0dbae352e 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -228,4 +228,4 @@ bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) { return true; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h index 017305e5d0..4b04fd1252 100644 --- a/engines/wintermute/base/gfx/base_image.h +++ b/engines/wintermute/base/gfx/base_image.h @@ -67,6 +67,6 @@ private: BaseFileManager *_fileManager; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp index c20881e425..1f171209d7 100644 --- a/engines/wintermute/base/gfx/base_renderer.cpp +++ b/engines/wintermute/base/gfx/base_renderer.cpp @@ -113,15 +113,21 @@ void BaseRenderer::setIndicatorVal(int value) { } void BaseRenderer::setLoadingScreen(const char *filename, int x, int y) { - // TODO: Handle NULL - _loadImageName = filename; + if (filename == nullptr) { + _saveImageName = ""; + } else { + _loadImageName = filename; + } _loadImageX = x; _loadImageY = y; } void BaseRenderer::setSaveImage(const char *filename, int x, int y) { - // TODO: Handle NULL - _saveImageName = filename; + if (filename == nullptr) { + _saveImageName = ""; + } else { + _saveImageName = filename; + } _saveImageX = x; _saveImageY = y; } @@ -395,4 +401,4 @@ bool BaseRenderer::displayIndicator() { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h index bfef29a5ed..31dc2a022d 100644 --- a/engines/wintermute/base/gfx/base_renderer.h +++ b/engines/wintermute/base/gfx/base_renderer.h @@ -228,6 +228,6 @@ private: BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp index 2002463ea4..19639c0c33 100644 --- a/engines/wintermute/base/gfx/base_surface.cpp +++ b/engines/wintermute/base/gfx/base_surface.cpp @@ -75,8 +75,8 @@ bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) { } ////////////////////////////////////////////////////////////////////////// -bool BaseSurface::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return displayTransZoom(x, y, rect, zoomX, zoomY, alpha, blendMode, mirrorX, mirrorY); +bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) { + return displayTransform(x, y, rect, newRect, transform); } ////////////////////////////////////////////////////////////////////////// @@ -146,4 +146,4 @@ void BaseSurface::setSize(int width, int height) { _height = height; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index b83efa0bb8..8a0603734e 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -32,6 +32,7 @@ #include "engines/wintermute/base/base.h" #include "engines/wintermute/math/rect32.h" #include "graphics/surface.h" +#include "engines/wintermute/graphics/transform_struct.h" namespace Wintermute { @@ -49,12 +50,12 @@ public: virtual bool displayHalfTrans(int x, int y, Rect32 rect); virtual bool isTransparentAt(int x, int y); - virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransZoom(int x, int y, Rect32 rect, int32 zoomX, int32 zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0; virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) = 0; + virtual bool displayZoom(int x, int y, Rect32 rect, int32 zoomX, int32 zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) = 0; virtual bool restore(); virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; @@ -95,6 +96,6 @@ protected: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index e1424cea87..668105457f 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -60,8 +60,7 @@ BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { _borderLeft = _borderRight = _borderTop = _borderBottom = 0; _ratioX = _ratioY = 1.0f; - setAlphaMod(255); - setColorMod(255, 255, 255); + _colorMod = kDefaultRgbaMod; _dirtyRect = nullptr; _disableDirtyRects = false; _tempDisableDirtyRects = 0; @@ -150,18 +149,6 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) { return STATUS_OK; } -void BaseRenderOSystem::setAlphaMod(byte alpha) { - byte r = RGBCOLGetR(_colorMod); - byte g = RGBCOLGetB(_colorMod); - byte b = RGBCOLGetB(_colorMod); - _colorMod = BS_ARGB(alpha, r, g, b); -} - -void BaseRenderOSystem::setColorMod(byte r, byte g, byte b) { - byte alpha = RGBCOLGetA(_colorMod); - _colorMod = BS_ARGB(alpha, r, g, b); -} - bool BaseRenderOSystem::indicatorFlip() { g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight); g_system->updateScreen(); @@ -200,9 +187,9 @@ bool BaseRenderOSystem::flip() { } if (_needsFlip || _disableDirtyRects || _tempDisableDirtyRects) { if (_disableDirtyRects || _tempDisableDirtyRects) { - g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); + g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); } - // g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); + // g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); delete _dirtyRect; _dirtyRect = nullptr; g_system->updateScreen(); @@ -256,7 +243,6 @@ void BaseRenderOSystem::fade(uint16 alpha) { return fadeToColor(0, 0, 0, dwAlpha); } - ////////////////////////////////////////////////////////////////////////// void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) { Common::Rect fillRect; @@ -279,14 +265,14 @@ void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect //TODO: This is only here until I'm sure about the final pixelformat uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b); - setAlphaMod(255); - setColorMod(255, 255, 255); Graphics::Surface surf; surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format); Common::Rect sizeRect(fillRect); sizeRect.translate(-fillRect.top, -fillRect.left); surf.fillRect(fillRect, col); - drawSurface(nullptr, &surf, &sizeRect, &fillRect, false, false); + TransformStruct temp = TransformStruct(); + temp._alphaDisable = false; + drawSurface(nullptr, &surf, &sizeRect, &fillRect, temp); surf.free(); //SDL_SetRenderDrawColor(_renderer, r, g, b, a); @@ -298,16 +284,18 @@ Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const { return _renderSurface->format; } -void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) { +void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) { + if (_tempDisableDirtyRects || _disableDirtyRects) { - RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); - ticket->_colorMod = _colorMod; + RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform); + ticket->_transform._rgbaMod = _colorMod; ticket->_wantsDraw = true; _renderQueue.push_back(ticket); _previousTicket = ticket; drawFromSurface(ticket); return; } + // Start searching from the beginning for the first and second items (since it's empty the first time around // then keep incrementing the start-position, to avoid comparing against already used tickets. if (_drawNum == 0 || _drawNum == 1) { @@ -320,12 +308,11 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S } if (owner) { // Fade-tickets are owner-less - RenderTicket compare(owner, nullptr, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); + RenderTicket compare(owner, nullptr, srcRect, dstRect, transform); compare._batchNum = _batchNum; if (_spriteBatch) { _batchNum++; } - compare._colorMod = _colorMod; RenderQueueIterator it; // Avoid calling end() and operator* every time, when potentially going through // LOTS of tickets. @@ -334,7 +321,7 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S for (it = _lastAddedTicket; it != endIterator; ++it) { compareTicket = *it; if (*(compareTicket) == compare && compareTicket->_isValid) { - compareTicket->_colorMod = _colorMod; + compareTicket->_transform._rgbaMod = transform._rgbaMod; if (_disableDirtyRects) { drawFromSurface(compareTicket); } else { @@ -349,8 +336,7 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S } } } - RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha); - ticket->_colorMod = _colorMod; + RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform); if (!_disableDirtyRects) { drawFromTicket(ticket); _previousTicket = ticket; @@ -385,12 +371,14 @@ void BaseRenderOSystem::repeatLastDraw(int offsetX, int offsetY, int numTimesX, int initLeft = dstRect.left; int initRight = dstRect.right; + TransformStruct temp = TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, BLEND_NORMAL, kDefaultRgbaMod, false, false, kDefaultOffsetX, kDefaultOffsetY); + for (int i = 0; i < numTimesY; i++) { if (i == 0) { dstRect.translate(offsetX, 0); } for (int j = (i == 0 ? 1 : 0); j < numTimesX; j++) { - drawSurface(origTicket->_owner, origTicket->getSurface(), &srcRect, &dstRect, false, false); + drawSurface(origTicket->_owner, origTicket->getSurface(), &srcRect, &dstRect, temp); dstRect.translate(offsetX, 0); } dstRect.left = initLeft; @@ -535,7 +523,7 @@ void BaseRenderOSystem::drawTickets() { // convert from screen-coords to surface-coords. dstClip.translate(-offsetX, -offsetY); - _colorMod = ticket->_colorMod; + _colorMod = ticket->_transform._rgbaMod; drawFromSurface(ticket, &pos, &dstClip); _needsFlip = true; } @@ -546,7 +534,7 @@ void BaseRenderOSystem::drawTickets() { // Revert the colorMod-state. _colorMod = oldColorMod; - + it = _renderQueue.begin(); // Clean out the old tickets decrement = 0; @@ -625,8 +613,8 @@ bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) { // TODO: Hopefully this is the same logic that ScummVM uses. rect.left = (int16)(left + _borderLeft); rect.top = (int16)(top + _borderTop); - rect.right = (int16)((right - left) * _ratioX); - rect.bottom = (int16)((bottom - top) * _ratioY); + rect.setWidth((int16)((right - left) * _ratioX)); + rect.setHeight((int16)((bottom - top) * _ratioY)); _renderRect = rect; return STATUS_OK; @@ -643,15 +631,13 @@ Rect32 BaseRenderOSystem::getViewPort() { ////////////////////////////////////////////////////////////////////////// void BaseRenderOSystem::modTargetRect(Common::Rect *rect) { - // FIXME: This is wrong in quite a few ways right now, and ends up - // breaking the notebook in Dirty Split, so we disable the correction - // for now, this will need fixing when a game with odd aspect-ratios - // show up. return; - rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft - _renderRect.left); - rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop - _renderRect.top); - rect->setWidth((int16)MathUtil::roundUp(rect->width() * _ratioX)); - rect->setHeight((int16)MathUtil::roundUp(rect->height() * _ratioY)); + int newWidth = (int16)MathUtil::roundUp(rect->width() * _ratioX); + int newHeight = (int16)MathUtil::roundUp(rect->height() * _ratioY); + rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft); + rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop); + rect->setWidth(newWidth); + rect->setHeight(newHeight); } ////////////////////////////////////////////////////////////////////////// @@ -694,7 +680,7 @@ void BaseRenderOSystem::endSaveLoad() { _drawNum = 1; _renderSurface->fillRect(Common::Rect(0, 0, _renderSurface->h, _renderSurface->w), _renderSurface->format.ARGBToColor(255, 0, 0, 0)); - g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); + g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); g_system->updateScreen(); } @@ -710,4 +696,4 @@ bool BaseRenderOSystem::endSpriteBatch() { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index 3cb0fa82a3..928a52d4fc 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -33,10 +33,30 @@ #include "common/rect.h" #include "graphics/surface.h" #include "common/list.h" +#include "engines/wintermute/graphics/transform_struct.h" namespace Wintermute { class BaseSurfaceOSystem; class RenderTicket; +/** + * A 2D-renderer implementation for WME. + * This renderer makes use of a "ticket"-system, where all draw-calls + * are stored as tickets until flip() is called, and compared against the tickets + * from last frame, to determine which calls were the same as last round + * (i.e. in the exact same order, with the exact same arguments), and thus + * figure out which parts of the screen need to be redrawn. + * + * Important concepts to handle here, is the ordered number of any ticket + * which is called the "drawNum", every frame this starts from scratch, and + * then the incoming tickets created from the draw-calls are checked to see whether + * they came before, on, or after the drawNum they had last frame. Everything else + * being equal, this information is then used to check whether the draw order changed, + * which will then create a need for redrawing, as we draw with an alpha-channel here. + * + * There is also a draw path that draws without tickets, for debugging purposes, + * as well as to accomodate situations with large enough amounts of draw calls, + * that there will be too much overhead involved with comparing the generated tickets. + */ class BaseRenderOSystem : public BaseRenderer { public: BaseRenderOSystem(BaseGame *inGame); @@ -56,10 +76,13 @@ public: BaseImage *takeScreenshot() override; - void setAlphaMod(byte alpha); - void setColorMod(byte r, byte g, byte b); void invalidateTicket(RenderTicket *renderTicket); void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf); + /** + * Insert a ticket into the queue, adding a dirty rect if it's + * new, or out-of-order from last draw from the ticket. + * param renderTicket the ticket to be added. + */ void drawFromTicket(RenderTicket *renderTicket); bool setViewport(int left, int top, int right, int bottom) override; @@ -80,11 +103,18 @@ public: virtual bool startSpriteBatch() override; virtual bool endSpriteBatch() override; void endSaveLoad(); - void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false) ; + void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform); void repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY); BaseSurface *createSurface() override; private: - void addDirtyRect(const Common::Rect &rect) ; + /** + * Mark a specified rect of the screen as dirty. + * @param rect the region to be marked as dirty + */ + void addDirtyRect(const Common::Rect &rect); + /** + * Traverse the tickets that are dirty, and draw them + */ void drawTickets(); // Non-dirty-rects: void drawFromSurface(RenderTicket *ticket); @@ -97,7 +127,7 @@ private: RenderTicket *_previousTicket; bool _needsFlip; - uint32 _drawNum; + uint32 _drawNum; ///< The global number of the current draw-operation. Common::Rect _renderRect; Graphics::Surface *_renderSurface; Graphics::Surface *_blankSurface; @@ -119,6 +149,6 @@ private: bool _skipThisFrame; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index 0572ef2f6e..d4c5905c4b 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -52,6 +52,7 @@ BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) { _lockPixels = nullptr; _lockPitch = 0; _loaded = false; + _rotation = 0; } ////////////////////////////////////////////////////////////////////////// @@ -163,7 +164,7 @@ bool BaseSurfaceOSystem::finishLoad() { needsColorKey = true; } } - + if (needsColorKey) { TransparentSurface trans(*_surface); trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha); @@ -233,7 +234,7 @@ uint32 BaseSurfaceOSystem::getPixelAt(Graphics::Surface *surface, int x, int y) warning("BaseSurfaceOSystem::GetPixel - Not ported yet"); int bpp = surface->format.bytesPerPixel; /* Here p is the address to the pixel we want to retrieve */ - uint8 *p = (uint8 *)surface->pixels + y * surface->pitch + x * bpp; + uint8 *p = (uint8 *)surface->getBasePtr(x, y); switch (bpp) { case 1: @@ -319,39 +320,56 @@ bool BaseSurfaceOSystem::endPixelOp() { ////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, 100, 100, 0xFFFFFFFF, true, blendMode, mirrorX, mirrorY); + _rotation = 0; + return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, mirrorX, mirrorY)); } ////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY); + _rotation = 0; + return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, blendMode, alpha, mirrorX, mirrorY)); } ////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { - return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY, offsetX, offsetY); + _rotation = 0; + return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY, offsetX, offsetY)); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY); +bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, int32 zoomX, int32 zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + _rotation = 0; + return drawSprite(x, y, &rect, nullptr, TransformStruct(zoomX, zoomY, blendMode, alpha, mirrorX, mirrorY)); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, zoomX, zoomY, alpha, !transparent, blendMode, mirrorX, mirrorY); +bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, int32 zoomX, int32 zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { + _rotation = 0; + TransformStruct transform; + if (transparent) { + transform = TransformStruct(zoomX, zoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY); + } else { + transform = TransformStruct(zoomX, zoomY, mirrorX, mirrorY); + } + return drawSprite(x, y, &rect, nullptr, transform); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { - return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY); +bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) { + _rotation = (uint32)transform._angle; + if (transform._angle < 0.0f) { + warning("Negative rotation: %d %d", transform._angle, _rotation); + _rotation = (uint32)(360.0f + transform._angle); + warning("Negative post rotation: %d %d", transform._angle, _rotation); + } + return drawSprite(x, y, &rect, &newRect, transform); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { +bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) { BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); if (!_loaded) { @@ -359,17 +377,9 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, flo } if (renderer->_forceAlphaColor != 0) { - alpha = renderer->_forceAlphaColor; + transform._rgbaMod = renderer->_forceAlphaColor; } - byte r = RGBCOLGetR(alpha); - byte g = RGBCOLGetG(alpha); - byte b = RGBCOLGetB(alpha); - byte a = RGBCOLGetA(alpha); - - renderer->setAlphaMod(a); - renderer->setColorMod(r, g, b); - #if 0 // These are kept for reference if BlendMode is reimplemented at some point. if (alphaDisable) { SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_NONE); @@ -386,8 +396,8 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, flo srcRect.setHeight(rect->bottom - rect->top); Common::Rect position; - position.left = x + offsetX; - position.top = y + offsetY; + position.left = x + transform._offset.x; + position.top = y + transform._offset.y; // Crop off-by-ones: if (position.left == -1) { @@ -396,31 +406,34 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, flo if (position.top == -1) { position.top = 0; // TODO: Something is wrong } - - position.setWidth((int16)((float)srcRect.width() * zoomX / 100.f)); - position.setHeight((int16)((float)srcRect.height() * zoomX / 100.f)); - + if (newRect) { + position.top = y; + position.left = x; + position.right = x + newRect->width(); + position.bottom = y + newRect->height(); + position.setWidth(newRect->width()); + position.setHeight(newRect->height()); + } else { + position.setWidth((int16)((float)srcRect.width() * transform._zoom.x / kDefaultZoomX)); + position.setHeight((int16)((float)srcRect.height() * transform._zoom.y / kDefaultZoomY)); + } renderer->modTargetRect(&position); - /* position.left += offsetX; - position.top += offsetY;*/ - // TODO: This actually requires us to have the SAME source-offsets every time, // But no checking is in place for that yet. // TODO: Optimize by not doing alpha-blits if we lack or disable alpha - bool hasAlpha; - if (_hasAlpha && !alphaDisable) { + + bool hasAlpha = false; + + if (_hasAlpha && !transform._alphaDisable) { hasAlpha = true; - } else { - hasAlpha = false; - } - if (alphaDisable) { + } + + if (transform._alphaDisable) { warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored"); } - - renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY, !hasAlpha); - + renderer->drawSurface(this, _surface, &srcRect, &position, transform); return STATUS_OK; } @@ -441,4 +454,4 @@ bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAl return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index 9091ec65b1..da86833517 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -51,12 +51,12 @@ public: bool endPixelOp() override; - bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override; + bool displayTransZoom(int x, int y, Rect32 rect, int32 zoomX, int32 zoomY, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override; bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayZoom(int x, int y, Rect32 rect, int32 zoomX, int32 zoomY, uint32 alpha = kDefaultRgbaMod, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) override; bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) override; virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override; /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); @@ -85,16 +85,17 @@ private: Graphics::Surface *_surface; bool _loaded; bool finishLoad(); - bool drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX = 0, int offsetY = 0); + bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transformStruct); void genAlphaMask(Graphics::Surface *surface); uint32 getPixelAt(Graphics::Surface *surface, int x, int y); + uint32 _rotation; bool _hasAlpha; void *_lockPixels; int _lockPitch; byte *_alphaMask; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index 36c5d7b740..98739e0778 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -8,12 +8,12 @@ * 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. @@ -26,22 +26,22 @@ * Copyright (c) 2011 Jan Nedoma */ -#include "engines/wintermute/graphics/transparent_surface.h" + #include "engines/wintermute/base/gfx/osystem/render_ticket.h" +#include "engines/wintermute/graphics/transform_tools.h" +#include "common/textconsole.h" namespace Wintermute { -RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner), -_srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) { - _colorMod = 0; +RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct transform) : + _owner(owner), + _srcRect(*srcRect), + _dstRect(*dstRect), + _drawNum(0), + _isValid(true), + _wantsDraw(true), + _transform(transform) { _batchNum = 0; - _mirror = TransparentSurface::FLIP_NONE; - if (mirrorX) { - _mirror |= TransparentSurface::FLIP_V; - } - if (mirrorY) { - _mirror |= TransparentSurface::FLIP_H; - } if (surf) { _surface = new Graphics::Surface(); _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format); @@ -51,7 +51,13 @@ _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw( memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); } // Then scale it if necessary - if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { + if (_transform._angle != kDefaultAngle) { + TransparentSurface src(*_surface, false); + Graphics::Surface *temp = src.rotoscale(transform); + _surface->free(); + delete _surface; + _surface = temp; + } else if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); _surface->free(); @@ -60,6 +66,14 @@ _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw( } } else { _surface = nullptr; + + if (transform._angle != kDefaultAngle) { // Make sure comparison-tickets get the correct width + Rect32 newDstRect; + Point32 newHotspot; + newDstRect = TransformTools::newRect(_srcRect, transform, &newHotspot); + _dstRect.setWidth(newDstRect.right - newDstRect.left); + _dstRect.setHeight(newDstRect.bottom - newDstRect.top); + } } } @@ -70,32 +84,31 @@ RenderTicket::~RenderTicket() { } } -bool RenderTicket::operator==(RenderTicket &t) { +bool RenderTicket::operator==(const RenderTicket &t) const { if ((t._owner != _owner) || (t._batchNum != _batchNum) || - (t._hasAlpha != _hasAlpha) || - (t._mirror != _mirror) || - (t._colorMod != _colorMod) || + (t._transform != _transform) || (t._dstRect != _dstRect) || - (t._srcRect != _srcRect)) { + (t._srcRect != _srcRect) + ) { return false; } return true; } // Replacement for SDL2's SDL_RenderCopy -void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) { +void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { TransparentSurface src(*getSurface(), false); Common::Rect clipRect; clipRect.setWidth(getSurface()->w); clipRect.setHeight(getSurface()->h); - src._enableAlphaBlit = _hasAlpha; - src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _mirror, &clipRect, _colorMod, clipRect.width(), clipRect.height()); + src._enableAlphaBlit = !_transform._alphaDisable; + src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); } -void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) { +void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const { TransparentSurface src(*getSurface(), false); bool doDelete = false; if (!clipRect) { @@ -105,11 +118,11 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect clipRect->setHeight(getSurface()->h); } - src._enableAlphaBlit = _hasAlpha; - src.blit(*_targetSurface, dstRect->left, dstRect->top, _mirror, clipRect, _colorMod, clipRect->width(), clipRect->height()); + src._enableAlphaBlit = !_transform._alphaDisable; + src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height()); if (doDelete) { delete clipRect; } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h index 968b42b5e1..875102d01c 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.h +++ b/engines/wintermute/base/gfx/osystem/render_ticket.h @@ -8,12 +8,12 @@ * 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. @@ -29,22 +29,36 @@ #ifndef WINTERMUTE_RENDER_TICKET_H #define WINTERMUTE_RENDER_TICKET_H +#include "engines/wintermute/graphics/transparent_surface.h" #include "graphics/surface.h" #include "common/rect.h" namespace Wintermute { class BaseSurfaceOSystem; +/** + * A single RenderTicket. + * A render ticket is a collection of the data and draw specifications made + * for a single draw-call in the OSystem-backend for WME. The ticket additionally + * holds the order in which this call was made, so that it can be detected if + * the same call is done in the following frame. Thus allowing us to potentially + * skip drawing the same region again, unless anything has changed. Since a surface + * can have a potentially large amount of draw-calls made to it, at varying rotation, + * zoom, and crop-levels we also need to hold a copy of the necessary data. + * (Video-surfaces may even change their data). The promise that is made when a ticket + * is created is that what the state was of the surface at THAT point, is what will end + * up on screen at flip() time. + */ class RenderTicket { public: - RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false); - RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {} + RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, TransformStruct transform); + RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0), _transform(TransformStruct()) {} ~RenderTicket(); - const Graphics::Surface *getSurface() { return _surface; } + const Graphics::Surface *getSurface() const { return _surface; } // Non-dirty-rects: - void drawToSurface(Graphics::Surface *_targetSurface); + void drawToSurface(Graphics::Surface *_targetSurface) const; // Dirty-rects: - void drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect); + void drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const; Common::Rect _dstRect; uint32 _batchNum; @@ -52,18 +66,17 @@ public: bool _isValid; bool _wantsDraw; uint32 _drawNum; - uint32 _colorMod; + TransformStruct _transform; + BaseSurfaceOSystem *_owner; - bool operator==(RenderTicket &a); - const Common::Rect *getSrcRect() { return &_srcRect; } + bool operator==(const RenderTicket &a) const; + const Common::Rect *getSrcRect() const { return &_srcRect; } private: Graphics::Surface *_surface; Common::Rect _srcRect; - bool _hasAlpha; - uint32 _mirror; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp index c86e1ce369..aaffa0965a 100644 --- a/engines/wintermute/base/particles/part_emitter.cpp +++ b/engines/wintermute/base/particles/part_emitter.cpp @@ -1163,12 +1163,12 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_angle1)); persistMgr->transfer(TMEMBER(_angle2)); - persistMgr->transfer(TMEMBER(_velocity1)); - persistMgr->transfer(TMEMBER(_velocity2)); + persistMgr->transferFloat(TMEMBER(_velocity1)); + persistMgr->transferFloat(TMEMBER(_velocity2)); persistMgr->transfer(TMEMBER(_velocityZBased)); - persistMgr->transfer(TMEMBER(_scale1)); - persistMgr->transfer(TMEMBER(_scale2)); + persistMgr->transferFloat(TMEMBER(_scale1)); + persistMgr->transferFloat(TMEMBER(_scale2)); persistMgr->transfer(TMEMBER(_scaleZBased)); persistMgr->transfer(TMEMBER(_maxParticles)); @@ -1196,14 +1196,14 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_alpha2)); persistMgr->transfer(TMEMBER(_alphaTimeBased)); - persistMgr->transfer(TMEMBER(_angVelocity1)); - persistMgr->transfer(TMEMBER(_angVelocity2)); + persistMgr->transferFloat(TMEMBER(_angVelocity1)); + persistMgr->transferFloat(TMEMBER(_angVelocity2)); - persistMgr->transfer(TMEMBER(_rotation1)); - persistMgr->transfer(TMEMBER(_rotation2)); + persistMgr->transferFloat(TMEMBER(_rotation1)); + persistMgr->transferFloat(TMEMBER(_rotation2)); - persistMgr->transfer(TMEMBER(_growthRate1)); - persistMgr->transfer(TMEMBER(_growthRate2)); + persistMgr->transferFloat(TMEMBER(_growthRate1)); + persistMgr->transferFloat(TMEMBER(_growthRate2)); persistMgr->transfer(TMEMBER(_exponentialGrowth)); persistMgr->transfer(TMEMBER(_useRegion)); @@ -1252,4 +1252,4 @@ bool PartEmitter::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/particles/part_emitter.h b/engines/wintermute/base/particles/part_emitter.h index a0d701f338..94b4dc8126 100644 --- a/engines/wintermute/base/particles/part_emitter.h +++ b/engines/wintermute/base/particles/part_emitter.h @@ -135,6 +135,6 @@ private: BaseArray<char *> _sprites; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/particles/part_force.cpp b/engines/wintermute/base/particles/part_force.cpp index df84162504..122cdf1afe 100644 --- a/engines/wintermute/base/particles/part_force.cpp +++ b/engines/wintermute/base/particles/part_force.cpp @@ -62,4 +62,4 @@ bool PartForce::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/particles/part_force.h b/engines/wintermute/base/particles/part_force.h index 27f4cb7d90..cdb1ce40f9 100644 --- a/engines/wintermute/base/particles/part_force.h +++ b/engines/wintermute/base/particles/part_force.h @@ -52,6 +52,6 @@ public: bool persist(BasePersistenceManager *PersistMgr); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/particles/part_particle.cpp b/engines/wintermute/base/particles/part_particle.cpp index f1aba114de..86cacacb5c 100644 --- a/engines/wintermute/base/particles/part_particle.cpp +++ b/engines/wintermute/base/particles/part_particle.cpp @@ -234,9 +234,9 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_alpha2)); persistMgr->transfer(TMEMBER(_border)); persistMgr->transfer(TMEMBER(_pos)); - persistMgr->transfer(TMEMBER(_posZ)); + persistMgr->transferFloat(TMEMBER(_posZ)); persistMgr->transfer(TMEMBER(_velocity)); - persistMgr->transfer(TMEMBER(_scale)); + persistMgr->transferFloat(TMEMBER(_scale)); persistMgr->transfer(TMEMBER(_creationTime)); persistMgr->transfer(TMEMBER(_lifeTime)); persistMgr->transfer(TMEMBER(_isDead)); @@ -244,9 +244,9 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_fadeStart)); persistMgr->transfer(TMEMBER(_fadeTime)); persistMgr->transfer(TMEMBER(_currentAlpha)); - persistMgr->transfer(TMEMBER(_angVelocity)); - persistMgr->transfer(TMEMBER(_rotation)); - persistMgr->transfer(TMEMBER(_growthRate)); + persistMgr->transferFloat(TMEMBER(_angVelocity)); + persistMgr->transferFloat(TMEMBER(_rotation)); + persistMgr->transferFloat(TMEMBER(_growthRate)); persistMgr->transfer(TMEMBER(_exponentialGrowth)); persistMgr->transfer(TMEMBER(_fadeStartAlpha)); @@ -266,4 +266,4 @@ bool PartParticle::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/particles/part_particle.h b/engines/wintermute/base/particles/part_particle.h index 8cca6b4057..281d87cf72 100644 --- a/engines/wintermute/base/particles/part_particle.h +++ b/engines/wintermute/base/particles/part_particle.h @@ -85,6 +85,6 @@ private: int32 _fadeStartAlpha; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/save_thumb_helper.cpp b/engines/wintermute/base/save_thumb_helper.cpp index bab29c5cf8..77514849a6 100644 --- a/engines/wintermute/base/save_thumb_helper.cpp +++ b/engines/wintermute/base/save_thumb_helper.cpp @@ -56,23 +56,23 @@ BaseImage *SaveThumbHelper::storeThumb(bool doFlip, int width, int height) { // works normally for direct3d _gameRef->displayContent(false); _gameRef->_renderer->flip(); - + _gameRef->displayContent(false); _gameRef->_renderer->flip(); } - + BaseImage *screenshot = _gameRef->_renderer->takeScreenshot(); if (!screenshot) { return nullptr; } - + // normal thumbnail if (_gameRef->getSaveThumbWidth() > 0 && _gameRef->getSaveThumbHeight() > 0) { thumbnail = new BaseImage(); thumbnail->copyFrom(screenshot, width, height); } - - + + delete screenshot; screenshot = nullptr; } @@ -99,7 +99,7 @@ bool SaveThumbHelper::storeThumbnail(bool doFlip) { bool SaveThumbHelper::storeScummVMThumbNail(bool doFlip) { delete _scummVMThumb; _scummVMThumb = nullptr; - + _scummVMThumb = storeThumb(doFlip, kThumbnailWidth, kThumbnailHeight2); if (!_scummVMThumb) { return STATUS_FAILED; @@ -107,4 +107,4 @@ bool SaveThumbHelper::storeScummVMThumbNail(bool doFlip) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/save_thumb_helper.h b/engines/wintermute/base/save_thumb_helper.h index d3bc5f5523..44792e3d75 100644 --- a/engines/wintermute/base/save_thumb_helper.h +++ b/engines/wintermute/base/save_thumb_helper.h @@ -47,6 +47,6 @@ private: BaseGame *_gameRef; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/saveload.cpp b/engines/wintermute/base/saveload.cpp index 1b7dfd42ed..8d37909bb4 100644 --- a/engines/wintermute/base/saveload.cpp +++ b/engines/wintermute/base/saveload.cpp @@ -201,4 +201,4 @@ bool SaveLoad::emptySaveSlot(int slot) { } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/saveload.h b/engines/wintermute/base/saveload.h index 722f7a89b6..15d4d86b26 100644 --- a/engines/wintermute/base/saveload.h +++ b/engines/wintermute/base/saveload.h @@ -52,6 +52,6 @@ private: static void afterLoadScript(void *script, void *data); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/dcscript.h b/engines/wintermute/base/scriptables/dcscript.h index 4aae897dc2..d6bb3cd176 100644 --- a/engines/wintermute/base/scriptables/dcscript.h +++ b/engines/wintermute/base/scriptables/dcscript.h @@ -136,6 +136,6 @@ typedef enum { ELEMENT_STRING = 0 } TElementType; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp index 1b945c2e1c..5aeff78c50 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -461,6 +461,7 @@ void ScScript::cleanup() { _parentScript = nullptr; // ref only delete _scriptStream; + _scriptStream = nullptr; } @@ -1464,4 +1465,4 @@ void ScScript::afterLoad() { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h index ee9f45e204..488ff63606 100644 --- a/engines/wintermute/base/scriptables/script.h +++ b/engines/wintermute/base/scriptables/script.h @@ -169,6 +169,6 @@ public: virtual const char *dbgGetFilename(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp index f83fb36843..dd24457d6c 100644 --- a/engines/wintermute/base/scriptables/script_engine.cpp +++ b/engines/wintermute/base/scriptables/script_engine.cpp @@ -605,4 +605,4 @@ void ScEngine::dumpStats() { }*/ } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_engine.h b/engines/wintermute/base/scriptables/script_engine.h index 639875ffb6..622b3c4b94 100644 --- a/engines/wintermute/base/scriptables/script_engine.h +++ b/engines/wintermute/base/scriptables/script_engine.h @@ -130,6 +130,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp index a466d361ec..7f1c769ec5 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.cpp +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -249,4 +249,4 @@ bool SXArray::push(ScValue *val) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_array.h b/engines/wintermute/base/scriptables/script_ext_array.h index 68f808641e..e6381a011e 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.h +++ b/engines/wintermute/base/scriptables/script_ext_array.h @@ -51,6 +51,6 @@ private: Common::String _strRep; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp index afca0c4bbf..d88bfc5851 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.cpp +++ b/engines/wintermute/base/scriptables/script_ext_date.cpp @@ -307,4 +307,4 @@ int SXDate::scCompare(BaseScriptable *Value) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_date.h b/engines/wintermute/base/scriptables/script_ext_date.h index 062b7c55c7..0ccf093a7b 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.h +++ b/engines/wintermute/base/scriptables/script_ext_date.h @@ -49,6 +49,6 @@ private: Common::String _strRep; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp index 29e032a759..18f7b8213a 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.cpp +++ b/engines/wintermute/base/scriptables/script_ext_file.cpp @@ -825,4 +825,4 @@ Common::WriteStream *SXFile::openForAppend(const Common::String &filename, bool error("SXFile::openForAppend - WriteFiles not supported"); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_file.h b/engines/wintermute/base/scriptables/script_ext_file.h index fa2384109f..a1298929f2 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.h +++ b/engines/wintermute/base/scriptables/script_ext_file.h @@ -61,6 +61,6 @@ private: Common::WriteStream *openForAppend(const Common::String &filename, bool binary); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_math.cpp b/engines/wintermute/base/scriptables/script_ext_math.cpp index d816fbec65..ec53b983e7 100644 --- a/engines/wintermute/base/scriptables/script_ext_math.cpp +++ b/engines/wintermute/base/scriptables/script_ext_math.cpp @@ -31,7 +31,6 @@ #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/persistent.h" #include "common/math.h" -#include <math.h> namespace Wintermute { @@ -292,4 +291,4 @@ bool SXMath::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_math.h b/engines/wintermute/base/scriptables/script_ext_math.h index 48c43ea7e8..1aa274a96f 100644 --- a/engines/wintermute/base/scriptables/script_ext_math.h +++ b/engines/wintermute/base/scriptables/script_ext_math.h @@ -48,6 +48,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp index 9de9905fea..6a47c09136 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp @@ -526,4 +526,4 @@ int SXMemBuffer::scCompare(BaseScriptable *val) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h index 6700a03f50..4aad8b6484 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h @@ -55,6 +55,6 @@ private: bool checkBounds(ScScript *script, int start, int length); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_object.cpp b/engines/wintermute/base/scriptables/script_ext_object.cpp index b87aac81f9..a72b244f0a 100644 --- a/engines/wintermute/base/scriptables/script_ext_object.cpp +++ b/engines/wintermute/base/scriptables/script_ext_object.cpp @@ -64,4 +64,4 @@ bool SXObject::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_object.h b/engines/wintermute/base/scriptables/script_ext_object.h index c85d16d44e..566111292a 100644 --- a/engines/wintermute/base/scriptables/script_ext_object.h +++ b/engines/wintermute/base/scriptables/script_ext_object.h @@ -41,6 +41,6 @@ public: virtual ~SXObject(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp index 7cb3b9360b..2f2422cdf9 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.cpp +++ b/engines/wintermute/base/scriptables/script_ext_string.cpp @@ -430,4 +430,4 @@ int SXString::scCompare(BaseScriptable *val) { return strcmp(_string, ((SXString *)val)->_string); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_string.h b/engines/wintermute/base/scriptables/script_ext_string.h index 50b61deba4..7a95c59b4c 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.h +++ b/engines/wintermute/base/scriptables/script_ext_string.h @@ -53,6 +53,6 @@ private: int32 _capacity; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_stack.cpp b/engines/wintermute/base/scriptables/script_stack.cpp index b53457c81b..801ac6ab52 100644 --- a/engines/wintermute/base/scriptables/script_stack.cpp +++ b/engines/wintermute/base/scriptables/script_stack.cpp @@ -192,4 +192,4 @@ bool ScStack::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_stack.h b/engines/wintermute/base/scriptables/script_stack.h index 82c3debefa..ee04485a51 100644 --- a/engines/wintermute/base/scriptables/script_stack.h +++ b/engines/wintermute/base/scriptables/script_stack.h @@ -61,6 +61,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp index 5e2923e029..3532e127d0 100644 --- a/engines/wintermute/base/scriptables/script_value.cpp +++ b/engines/wintermute/base/scriptables/script_value.cpp @@ -992,4 +992,4 @@ bool ScValue::setProperty(const char *propName) { return ret; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_value.h b/engines/wintermute/base/scriptables/script_value.h index a8e815023e..90ad9f182a 100644 --- a/engines/wintermute/base/scriptables/script_value.h +++ b/engines/wintermute/base/scriptables/script_value.h @@ -108,6 +108,6 @@ public: bool setProperty(const char *propName); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp index d027c03c8b..c1923b3ca8 100644 --- a/engines/wintermute/base/sound/base_sound.cpp +++ b/engines/wintermute/base/sound/base_sound.cpp @@ -289,4 +289,4 @@ bool BaseSound::applyFX(TSFXType type, float param1, float param2, float param3, return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/sound/base_sound.h b/engines/wintermute/base/sound/base_sound.h index 3412e6c3a3..0a984d240a 100644 --- a/engines/wintermute/base/sound/base_sound.h +++ b/engines/wintermute/base/sound/base_sound.h @@ -82,6 +82,6 @@ private: BaseSoundBuffer *_sound; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp index 9c919abac6..7666a441a3 100644 --- a/engines/wintermute/base/sound/base_sound_buffer.cpp +++ b/engines/wintermute/base/sound/base_sound_buffer.cpp @@ -292,4 +292,4 @@ bool BaseSoundBuffer::applyFX(TSFXType type, float param1, float param2, float p return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/sound/base_sound_buffer.h b/engines/wintermute/base/sound/base_sound_buffer.h index e78d062cd4..53b86f64c6 100644 --- a/engines/wintermute/base/sound/base_sound_buffer.h +++ b/engines/wintermute/base/sound/base_sound_buffer.h @@ -95,6 +95,6 @@ private: int32 _volume; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp index f3e7bfb408..68e62f25b0 100644 --- a/engines/wintermute/base/sound/base_sound_manager.cpp +++ b/engines/wintermute/base/sound/base_sound_manager.cpp @@ -287,4 +287,4 @@ float BaseSoundMgr::posToPan(int x, int y) { return minPan + relPos * (maxPan - minPan); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/base/sound/base_sound_manager.h b/engines/wintermute/base/sound/base_sound_manager.h index 602571765f..5993a05001 100644 --- a/engines/wintermute/base/sound/base_sound_manager.h +++ b/engines/wintermute/base/sound/base_sound_manager.h @@ -64,6 +64,6 @@ private: bool setMasterVolume(byte percent); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/base/timer.cpp b/engines/wintermute/base/timer.cpp index 5dfc117f48..96097c10d5 100644 --- a/engines/wintermute/base/timer.cpp +++ b/engines/wintermute/base/timer.cpp @@ -8,12 +8,12 @@ * 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. diff --git a/engines/wintermute/base/timer.h b/engines/wintermute/base/timer.h index ec5477ba2e..4099c6c825 100644 --- a/engines/wintermute/base/timer.h +++ b/engines/wintermute/base/timer.h @@ -8,12 +8,12 @@ * 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. @@ -51,7 +51,7 @@ public: void persist(BasePersistenceManager *persistMgr); }; - + } // End of namespace Wintermute #endif diff --git a/engines/wintermute/coll_templ.h b/engines/wintermute/coll_templ.h index 4a8e92c121..a3df92d6c8 100644 --- a/engines/wintermute/coll_templ.h +++ b/engines/wintermute/coll_templ.h @@ -138,6 +138,6 @@ public: } }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/dctypes.h b/engines/wintermute/dctypes.h index bd4966eb6b..b40322147f 100644 --- a/engines/wintermute/dctypes.h +++ b/engines/wintermute/dctypes.h @@ -220,6 +220,6 @@ enum TShadowType { SHADOW_STENCIL = 3 }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp index 92b8e6251f..8c8b8255ab 100644 --- a/engines/wintermute/debugger.cpp +++ b/engines/wintermute/debugger.cpp @@ -8,12 +8,12 @@ * 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. @@ -81,4 +81,4 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) { return true; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/debugger.h b/engines/wintermute/debugger.h index 588b81af97..6fbbb084f0 100644 --- a/engines/wintermute/debugger.h +++ b/engines/wintermute/debugger.h @@ -8,12 +8,12 @@ * 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. @@ -32,7 +32,7 @@ class Console : public GUI::Debugger { public: Console(WintermuteEngine *vm); virtual ~Console(); - + bool Cmd_ShowFps(int argc, const char **argv); bool Cmd_DumpFile(int argc, const char **argv); private: diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index 1bf2c76a50..ac21d78ef5 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -181,7 +181,7 @@ public: } }; -} // end of namespace Wintermute +} // End of namespace Wintermute #if PLUGIN_ENABLED_DYNAMIC(WINTERMUTE) REGISTER_PLUGIN_DYNAMIC(WINTERMUTE, PLUGIN_TYPE_ENGINE, Wintermute::WintermuteMetaEngine); diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h index 00ec51a715..702c0b28ba 100644 --- a/engines/wintermute/detection_tables.h +++ b/engines/wintermute/detection_tables.h @@ -27,6 +27,7 @@ namespace Wintermute { static const PlainGameDescriptor wintermuteGames[] = { {"5ld", "Five Lethal Demons"}, {"5ma", "Five Magical Amulets"}, + {"bthreshold", "Beyond the Threshold"}, {"actualdest", "Actual Destination"}, {"carolreed4", "Carol Reed 4 - East Side Story"}, {"carolreed5", "Carol Reed 5 - The Colour of Murder"}, @@ -36,17 +37,22 @@ static const PlainGameDescriptor wintermuteGames[] = { {"carolreed9", "Carol Reed 9 - Cold Case Summer"}, {"chivalry", "Chivalry is Not Dead"}, {"deadcity", "Dead City"}, + {"dreaming", "Des Reves Elastiques Avec Mille Insectes Nommes Georges"}, {"dirtysplit", "Dirty Split"}, {"dreamscape", "Dreamscape"}, {"ghostsheet", "Ghost in the Sheet"}, {"hamlet", "Hamlet or the last game without MMORPS features, shaders and product placement"}, + {"jamesperis", "James Peris: No License Nor Control"}, {"julia", "J.U.L.I.A."}, {"mirage", "Mirage"}, {"pigeons", "Pigeons in the Park"}, {"reversion1", "Reversion: The Escape"}, - {"reversion2", "Reversion: The Meeting"}, + {"reversion2", "Reversion: The Meeting"}, {"rosemary", "Rosemary"}, + {"shinestar", "The Shine of a Star"}, {"thebox", "The Box"}, + {"tib", "Fairy Tales About Toshechka and Boshechka"}, + {"tradestory", "The Trader of Stories"}, {"twc", "the white chamber"}, {"wintermute", "Wintermute engine game"}, {0, 0} @@ -83,6 +89,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Beyond the Threshold + { + "bthreshold", + "", + AD_ENTRY1s("data.dcp", "d49bf9ccb2e74507447c82d6ad3e2bc4", 12773712), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // Carol Reed 4 - East Side Story (Demo) { "carolreed4", @@ -125,6 +141,17 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Carol Reed 7 - Blue Madonna (Demo) + { + "carolreed7", + "Demo", + AD_ENTRY1s("data.dcp", "0372ad0c775266f6355e9e8ae397a2f1", 103719442), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE | + ADGF_DEMO, + GUIO0() + }, // Carol Reed 7 - Blue Madonna { "carolreed7", @@ -237,6 +264,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Des Reves Elastiques Avec Mille Insectes Nommes Georges + { + "dreaming", + "", + AD_ENTRY1s("data.dcp", "4af26d97ea063fc1277ce30ae431de90", 8804073), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // Dreamscape { "dreamscape", @@ -268,6 +305,48 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // James Peris: No License Nor Control (English) + { + "jamesperis", + "", + AD_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, + // James Peris: No License Nor Control (Spanish) + { + "jamesperis", + "", + AD_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, + // James Peris: No License Nor Control (Demo) (English) + { + "jamesperis", + "Demo", + AD_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE | + ADGF_DEMO, + GUIO0() + }, + // James Peris: No License Nor Control (Demo) (Spanish) + { + "jamesperis", + "Demo", + AD_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_UNSTABLE | + ADGF_DEMO, + GUIO0() + }, // J.U.L.I.A. (English) { "julia", @@ -289,6 +368,17 @@ static const ADGameDescription gameDescriptions[] = { ADGF_DEMO, GUIO0() }, + // J.U.L.I.A. (English) (Greenlight Demo) + { + "julia", + "Greenlight Demo", + AD_ENTRY1s("data.dcp", "4befd448d36b0dae9c3ab1aa7cb8b78d", 7271886), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE | + ADGF_DEMO, + GUIO0() + }, // Mirage { "mirage", @@ -535,6 +625,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // The Shine of a Star + { + "shinestar", + "", + AD_ENTRY1s("data.dcp", "f05abe9e2427a5e4f73648fa09c4ba8e", 94113060), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // The Box { "thebox", @@ -545,6 +645,27 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Fairy Tales About Toshechka and Boshechka + { + "tib", + "", + AD_ENTRY1s("data.dcp", "87d296ef3f46570ed18f000d3885db77", 340264526), + Common::RU_RUS, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, + // The Trader of Stories + { + "tradestory", + "Demo", + AD_ENTRY1s("data.dcp", "0a0b51191636cc8ead89b905281c3218", 40401902), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE | + ADGF_DEMO, + GUIO0() + }, // the white chamber (multi-language) { "twc", diff --git a/engines/wintermute/graphics/transform_struct.cpp b/engines/wintermute/graphics/transform_struct.cpp new file mode 100644 index 0000000000..8edbf765b5 --- /dev/null +++ b/engines/wintermute/graphics/transform_struct.cpp @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "engines/wintermute/graphics/transform_struct.h" +#include "engines/wintermute/graphics/transparent_surface.h" + +namespace Wintermute { +void TransformStruct::init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, Point32 offset) { + _zoom = zoom; + _angle = angle; + _hotspot = hotspot; + _blendMode = blendMode; + _rgbaMod = rgbaMod; + _alphaDisable = alphaDisable; + _flip = 0; + _flip += TransparentSurface::FLIP_H * mirrorX; + _flip += TransparentSurface::FLIP_V * mirrorY; + _offset = offset; +} + + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { + init(Point32(zoomX, zoomY), + angle, + Point32(hotspotX, hotspotY), + false, + blendMode, + rgbaMod, + mirrorX, mirrorY, + Point32(offsetX, offsetY)); +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY) { + init(Point32(zoomX, zoomY), + kDefaultAngle, + Point32(kDefaultHotspotX, kDefaultHotspotY), + false, + blendMode, + rgbaMod, + mirrorX, + mirrorY, + Point32(kDefaultOffsetX, kDefaultOffsetY)); +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY) { + init(Point32(zoomX, zoomY), + angle, + Point32(hotspotX, hotspotY), + true, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Point32(kDefaultOffsetX, kDefaultOffsetY)); +} + +TransformStruct::TransformStruct() { + init(Point32(kDefaultZoomX, kDefaultZoomY), + kDefaultAngle, + Point32(kDefaultHotspotX, kDefaultHotspotY), + true, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Point32(kDefaultOffsetX, kDefaultOffsetY)); +} + +bool TransformStruct::getMirrorX() const { + return (bool)(_flip & TransparentSurface::FLIP_H); +} + +bool TransformStruct::getMirrorY() const { + return (bool)(_flip & TransparentSurface::FLIP_V); +} +} // End of namespace Wintermute diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h new file mode 100644 index 0000000000..a54c4cc5d0 --- /dev/null +++ b/engines/wintermute/graphics/transform_struct.h @@ -0,0 +1,83 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef WINTERMUTE_TRANSFORM_STRUCT_H +#define WINTERMUTE_TRANSFORM_STRUCT_H + +#include "engines/wintermute/math/rect32.h" +#include "engines/wintermute/dctypes.h" + +namespace Wintermute { +/** + * Contains all the required information that define a transform. + * Same source sprite + same TransformStruct = Same resulting sprite. + * Has a number of overloaded constructors to accomodate various argument lists. + */ + +const uint32 kDefaultZoomX = 100; +const uint32 kDefaultZoomY = 100; +const uint32 kDefaultRgbaMod = 0xFFFFFFFF; +const int32 kDefaultHotspotX = 0; +const int32 kDefaultHotspotY = 0; +const int32 kDefaultOffsetX = 0; +const int32 kDefaultOffsetY = 0; +const int32 kDefaultAngle = 0; + +struct TransformStruct { +private: + void init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Point32 offset); + +public: + TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); + TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false); + TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0); + TransformStruct(); + + Point32 _zoom; ///< Zoom; 100 = no zoom + Point32 _hotspot; ///< Position of the hotspot + uint32 _angle; ///< Rotation angle, in degrees + byte _flip; ///< Bitflag: see TransparentSurface::FLIP_XXX + bool _alphaDisable; + TSpriteBlendMode _blendMode; + uint32 _rgbaMod; ///< RGBa + Point32 _offset; + + bool getMirrorX() const; + bool getMirrorY() const; + + bool operator==(const TransformStruct &compare) const { + return (compare._angle == _angle && + compare._flip == _flip && + compare._zoom == _zoom && + compare._offset == _offset && + compare._alphaDisable == _alphaDisable && + compare._rgbaMod == _rgbaMod && + compare._blendMode == _blendMode + ); + } + + bool operator!=(const TransformStruct &compare) const { + return !(compare == *this); + } +}; +} // End of namespace Wintermute +#endif diff --git a/engines/wintermute/graphics/transform_tools.cpp b/engines/wintermute/graphics/transform_tools.cpp new file mode 100644 index 0000000000..ebf9092aaa --- /dev/null +++ b/engines/wintermute/graphics/transform_tools.cpp @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "engines/wintermute/graphics/transform_tools.h" +#include <math.h> + +namespace Wintermute { + +FloatPoint TransformTools::transformPoint(const FloatPoint &point, const float rotate, const Point32 &zoom, const bool mirrorX, const bool mirrorY) { + float rotateRad = rotate * M_PI / 180.0f; + FloatPoint newPoint; + newPoint.x = (point.x * cos(rotateRad) - point.y * sin(rotateRad)) * zoom.x / kDefaultZoomX; + newPoint.y = (point.x * sin(rotateRad) + point.y * cos(rotateRad)) * zoom.y / kDefaultZoomY; + if (mirrorX) { + newPoint.x *= -1; + } + if (mirrorY) { + newPoint.y *= -1; + } + return newPoint; +} + +Rect32 TransformTools::newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot) { + Point32 nw(oldRect.left, oldRect.top); + Point32 ne(oldRect.right, oldRect.top); + Point32 sw(oldRect.left, oldRect.bottom); + Point32 se(oldRect.right, oldRect.bottom); + + FloatPoint nw1, ne1, sw1, se1; + + nw1 = transformPoint(nw - transform._hotspot, transform._angle, transform._zoom); + ne1 = transformPoint(ne - transform._hotspot, transform._angle, transform._zoom); + sw1 = transformPoint(sw - transform._hotspot, transform._angle, transform._zoom); + se1 = transformPoint(se - transform._hotspot, transform._angle, transform._zoom); + + float top = MIN(nw1.y, MIN(ne1.y, MIN(sw1.y, se1.y))); + float bottom = MAX(nw1.y, MAX(ne1.y, MAX(sw1.y, se1.y))); + float left = MIN(nw1.x, MIN(ne1.x, MIN(sw1.x, se1.x))); + float right = MAX(nw1.x, MAX(ne1.x, MAX(sw1.x, se1.x))); + + Rect32 res; + newHotspot->y = (uint32)(-floor(top)); + newHotspot->x = (uint32)(-floor(left)); + + res.top = (int32)(floor(top)) + transform._hotspot.y; + res.bottom = (int32)(ceil(bottom)) + transform._hotspot.y; + res.left = (int32)(floor(left)) + transform._hotspot.x; + res.right = (int32)(ceil(right)) + transform._hotspot.x; + + return res; +} + +} // End of namespace Wintermute diff --git a/engines/wintermute/graphics/transform_tools.h b/engines/wintermute/graphics/transform_tools.h new file mode 100644 index 0000000000..c92b81fd11 --- /dev/null +++ b/engines/wintermute/graphics/transform_tools.h @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef WINTERMUTE_TRANSFORM_TOOLS_H +#define WINTERMUTE_TRANSFORM_TOOLS_H + +#include "engines/wintermute/math/rect32.h" +#include "engines/wintermute/math/floatpoint.h" +#include "engines/wintermute/graphics/transform_struct.h" + +namespace Wintermute { + +class TransformTools { +public: + /** + * Basic transform (scale + rotate) for a single point + */ + static FloatPoint transformPoint(const FloatPoint &point, const float rotate, const Point32 &zoom, const bool mirrorX = false, const bool mirrorY = false); + + /** + * @param &point the point on which the transform is to be applied + * @param rotate the angle in degrees + * @param &zoom zoom x,y in percent + * @param mirrorX flip along the vertical axis? + * @param mirrorY flip along the horizontal axis? + * @return the smallest rect that can contain the transformed sprite + * and, as a side-effect, "newHotspot" will tell you where the hotspot will + * have ended up in the new rect, for centering. + */ + static Rect32 newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot); +}; + +} // End of namespace Wintermute +#endif diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp index dcdcbf247e..e375322ae9 100644 --- a/engines/wintermute/graphics/transparent_surface.cpp +++ b/engines/wintermute/graphics/transparent_surface.cpp @@ -23,12 +23,123 @@ #include "common/endian.h" #include "common/util.h" #include "common/rect.h" +#include "common/math.h" #include "common/textconsole.h" #include "graphics/primitives.h" #include "engines/wintermute/graphics/transparent_surface.h" +#include "engines/wintermute/graphics/transform_tools.h" namespace Wintermute { + +#if ENABLE_BILINEAR +void TransparentSurface::copyPixelBilinear(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst) { + int srcW = srcRect.width(); + int srcH = srcRect.height(); + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + assert(dstX >= 0 && dstX < dstW); + assert(dstY >= 0 && dstY < dstH); + + float x1 = floor(projX); + float x2 = ceil(projX); + float y1 = floor(projY); + float y2 = ceil(projY); + + uint32 Q11, Q12, Q21, Q22; + + if (x1 >= srcW || x1 < 0 || y1 >= srcH || y1 < 0) { + Q11 = 0; + } else { + Q11 = READ_UINT32((const byte *)src->getBasePtr((int)(x1 + srcRect.left), (int)(y1 + srcRect.top))); + } + + if (x1 >= srcW || x1 < 0 || y2 >= srcH || y2 < 0) { + Q12 = 0; + } else { + Q12 = READ_UINT32((const byte *)src->getBasePtr((int)(x1 + srcRect.left), (int)(y2 + srcRect.top))); + } + + if (x2 >= srcW || x2 < 0 || y1 >= srcH || y1 < 0) { + Q21 = 0; + } else { + Q21 = READ_UINT32((const byte *)src->getBasePtr((int)(x2 + srcRect.left), (int)(y1 + srcRect.top))); + } + + if (x2 >= srcW || x2 < 0 || y2 >= srcH || y2 < 0) { + Q22 = 0; + } else { + Q22 = READ_UINT32((const byte *)src->getBasePtr((int)(x2 + srcRect.left), (int)(y2 + srcRect.top))); + } + + byte *Q11s = (byte *)&Q11; + byte *Q12s = (byte *)&Q12; + byte *Q21s = (byte *)&Q21; + byte *Q22s = (byte *)&Q22; + + uint32 color; + byte *dest = (byte *)&color; + + float q11x = (x2 - projX); + float q11y = (y2 - projY); + float q21x = (projX - x1); + float q21y = (y2 - projY); + float q12x = (x2 - projX); + float q12y = (projY - y1); + + if (x1 == x2 && y1 == y2) { + for (int c = 0; c < 4; c++) { + dest[c] = ((float)Q11s[c]); + } + } else { + + if (x1 == x2) { + q11x = 0.5; + q12x = 0.5; + q21x = 0.5; + } else if (y1 == y2) { + q11y = 0.5; + q12y = 0.5; + q21y = 0.5; + } + + for (int c = 0; c < 4; c++) { + dest[c] = (byte)( + ((float)Q11s[c]) * q11x * q11y + + ((float)Q21s[c]) * q21x * q21y + + ((float)Q12s[c]) * q12x * q12y + + ((float)Q22s[c]) * (1.0 - + q11x * q11y - + q21x * q21y - + q12x * q12y) + ); + } + } + WRITE_UINT32((byte *)dst->getBasePtr(dstX + dstRect.left, dstY + dstRect.top), color); +} +#else +void TransparentSurface::copyPixelNearestNeighbor(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst) { + int srcW = srcRect.width(); + int srcH = srcRect.height(); + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + assert(dstX >= 0 && dstX < dstW); + assert(dstY >= 0 && dstY < dstH); + + uint32 color; + + if (projX >= srcW || projX < 0 || projY >= srcH || projY < 0) { + color = 0; + } else { + color = READ_UINT32((const byte *)src->getBasePtr((int)projX, (int)projY)); + } + + WRITE_UINT32((byte *)dst->getBasePtr(dstX, dstY), color); +} +#endif + byte *TransparentSurface::_lookup = nullptr; void TransparentSurface::destroyLookup() { @@ -46,11 +157,14 @@ TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Sur h = surf.h; pitch = surf.pitch; format = surf.format; - pixels = surf.pixels; + // We need to cast the const qualifier away here because 'pixels' + // always needs to be writable. 'surf' however is a constant Surface, + // thus getPixels will always return const pixel data. + pixels = const_cast<void *>(surf.getPixels()); } } -void doBlitOpaque(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { +void doBlitOpaque(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { byte *in, *out; #ifdef SCUMM_LITTLE_ENDIAN @@ -81,7 +195,7 @@ void TransparentSurface::generateLookup() { } } -void TransparentSurface::doBlitAlpha(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { +void TransparentSurface::doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { byte *in, *out; if (!_lookup) { @@ -195,16 +309,28 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p } if (pPartRect) { - srcImage.pixels = &((char *)pixels)[pPartRect->top * srcImage.pitch + pPartRect->left * 4]; + + int xOffset = pPartRect->left; + int yOffset = pPartRect->top; + + if (flipping & FLIP_V) { + yOffset = srcImage.h - pPartRect->bottom; + } + + if (flipping & FLIP_H) { + xOffset = srcImage.w - pPartRect->right; + } + + srcImage.pixels = getBasePtr(xOffset, yOffset); srcImage.w = pPartRect->width(); srcImage.h = pPartRect->height(); debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, - pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); + pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); } else { debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, - srcImage.w, srcImage.h, color, width, height); + srcImage.w, srcImage.h, color, width, height); } if (width == -1) @@ -224,7 +350,7 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p if ((width != srcImage.w) || (height != srcImage.h)) { // Scale the image img = imgScaled = srcImage.scale(width, height); - savedPixels = (byte *)img->pixels; + savedPixels = (byte *)img->getPixels(); } else { img = &srcImage; } @@ -232,13 +358,13 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p // Handle off-screen clipping if (posY < 0) { img->h = MAX(0, (int)img->h - -posY); - img->pixels = (byte *)img->pixels + img->pitch * -posY; + img->setPixels((byte *)img->getBasePtr(0, -posY)); posY = 0; } if (posX < 0) { img->w = MAX(0, (int)img->w - -posX); - img->pixels = (byte *)img->pixels + (-posX * 4); + img->setPixels((byte *)img->getBasePtr(-posX, 0)); posX = 0; } @@ -250,12 +376,12 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p int inStep = 4; int inoStep = img->pitch; - if (flipping & TransparentSurface::FLIP_V) { + if (flipping & TransparentSurface::FLIP_H) { inStep = -inStep; xp = img->w - 1; } - if (flipping & TransparentSurface::FLIP_H) { + if (flipping & TransparentSurface::FLIP_V) { inoStep = -inoStep; yp = img->h - 1; } @@ -375,7 +501,7 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p retSize.setHeight(img->h); if (imgScaled) { - imgScaled->pixels = savedPixels; + imgScaled->setPixels(savedPixels); imgScaled->free(); delete imgScaled; } @@ -383,16 +509,54 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p return retSize; } +TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { + + assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway. + + Point32 newHotspot; + Common::Rect srcRect(0, 0, (int16)w, (int16)h); + Rect32 rect = TransformTools::newRect(Rect32(srcRect), transform, &newHotspot); + Common::Rect dstRect(0, 0, (int16)(rect.right - rect.left), (int16)(rect.bottom - rect.top)); + + TransparentSurface *target = new TransparentSurface(); + assert(format.bytesPerPixel == 4); + + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + target->create((uint16)dstW, (uint16)dstH, this->format); + + uint32 invAngle = 360 - (transform._angle % 360); + float invCos = cos(invAngle * M_PI / 180.0); + float invSin = sin(invAngle * M_PI / 180.0); + float targX; + float targY; + + for (int y = 0; y < dstH; y++) { + for (int x = 0; x < dstW; x++) { + int x1 = x - newHotspot.x; + int y1 = y - newHotspot.y; + + targX = ((x1 * invCos - y1 * invSin)) * kDefaultZoomX / transform._zoom.x + srcRect.left; + targY = ((x1 * invSin + y1 * invCos)) * kDefaultZoomY / transform._zoom.y + srcRect.top; + + targX += transform._hotspot.x; + targY += transform._hotspot.y; + +#if ENABLE_BILINEAR + copyPixelBilinear(targX, targY, x, y, srcRect, dstRect, this, target); +#else + copyPixelNearestNeighbor(targX, targY, x, y, srcRect, dstRect, this, target); +#endif + } + } + return target; +} + TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { Common::Rect srcRect(0, 0, (int16)w, (int16)h); Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight); - return scale(srcRect, dstRect); -} -// Copied from clone2727's https://github.com/clone2727/scummvm/blob/pegasus/engines/pegasus/surface.cpp#L247 -TransparentSurface *TransparentSurface::scale(const Common::Rect &srcRect, const Common::Rect &dstRect) const { - // I'm doing simple linear scaling here - // dstRect(x, y) = srcRect(x * srcW / dstW, y * srcH / dstH); TransparentSurface *target = new TransparentSurface(); assert(format.bytesPerPixel == 4); @@ -404,11 +568,18 @@ TransparentSurface *TransparentSurface::scale(const Common::Rect &srcRect, const target->create((uint16)dstW, (uint16)dstH, this->format); + + float projX; + float projY; for (int y = 0; y < dstH; y++) { for (int x = 0; x < dstW; x++) { - uint32 color = READ_UINT32((const byte *)getBasePtr(x * srcW / dstW + srcRect.left, - y * srcH / dstH + srcRect.top)); - WRITE_UINT32((byte *)target->getBasePtr(x + dstRect.left, y + dstRect.top), color); + projX = x / (float)dstW * srcW; + projY = y / (float)dstH * srcH; +#if ENABLE_BILINEAR + copyPixelBilinear(projX, projY, x, y, srcRect, dstRect, this, target); +#else + copyPixelNearestNeighbor(projX, projY, x, y, srcRect, dstRect, this, target); +#endif } } return target; @@ -440,4 +611,4 @@ void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool } } -} // End of namespace Graphics +} // End of namespace Wintermute diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h index dc079a1fbc..9d06f3e006 100644 --- a/engines/wintermute/graphics/transparent_surface.h +++ b/engines/wintermute/graphics/transparent_surface.h @@ -23,6 +23,10 @@ #define GRAPHICS_TRANSPARENTSURFACE_H #include "graphics/surface.h" +#include "engines/wintermute/graphics/transform_struct.h" + +#define ENABLE_BILINEAR 0 + /* * This code is based on Broken Sword 2.5 engine @@ -49,21 +53,26 @@ struct TransparentSurface : public Graphics::Surface { void setColorKey(char r, char g, char b); void disableColorKey(); +#if ENABLE_BILINEAR + static void copyPixelBilinear(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst); +#else + static void copyPixelNearestNeighbor(float projX, float projY, int dstX, int dstY, const Common::Rect &srcRect, const Common::Rect &dstRect, const TransparentSurface *src, TransparentSurface *dst); +#endif // Enums /** @brief The possible flipping parameters for the blit methode. */ enum FLIP_FLAGS { - /// The image will not be flipped. - FLIP_NONE = 0, - /// The image will be flipped at the horizontal axis. - FLIP_H = 1, - /// The image will be flipped at the vertical axis. - FLIP_V = 2, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_HV = FLIP_H | FLIP_V, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_VH = FLIP_H | FLIP_V + /// The image will not be flipped. + FLIP_NONE = 0, + /// The image will be flipped at the horizontal axis. + FLIP_H = 1, + /// The image will be flipped at the vertical axis. + FLIP_V = 2, + /// The image will be flipped at the horizontal and vertical axis. + FLIP_HV = FLIP_H | FLIP_V, + /// The image will be flipped at the horizontal and vertical axis. + FLIP_VH = FLIP_H | FLIP_V }; bool _enableAlphaBlit; @@ -102,13 +111,13 @@ struct TransparentSurface : public Graphics::Surface { uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1); void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); - // The following scale-code supports arbitrary scaling (i.e. no repeats of column 0 at the end of lines) + TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; - TransparentSurface *scale(const Common::Rect &srcRect, const Common::Rect &dstRect) const; + TransparentSurface *rotoscale(const TransformStruct &transform) const; static byte *_lookup; static void destroyLookup(); private: - static void doBlitAlpha(byte *ino, byte* outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); + static void doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); static void generateLookup(); }; @@ -125,7 +134,7 @@ private: };*/ -} // End of namespace Graphics +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/math/floatpoint.h b/engines/wintermute/math/floatpoint.h new file mode 100644 index 0000000000..0c47ef09d7 --- /dev/null +++ b/engines/wintermute/math/floatpoint.h @@ -0,0 +1,52 @@ +/* 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. + * + */ + +#ifndef WINTERMUTE_FLOATPOINT_H +#define WINTERMUTE_FLOATPOINT_H + +namespace Wintermute { + +struct FloatPoint { + float x; + float y; + FloatPoint() : x(0), y(0) {} + FloatPoint(float x1, float y1) : x(x1), y(y1) {} + bool operator==(const FloatPoint &p) const { return x == p.x && y == p.y; } + bool operator!=(const FloatPoint &p) const { return x != p.x || y != p.y; } + FloatPoint operator+(const FloatPoint &delta) const { return FloatPoint (x + delta.x, y + delta.y); } + FloatPoint operator-(const FloatPoint &delta) const { return FloatPoint (x - delta.x, y - delta.y); } + + FloatPoint& operator+=(const FloatPoint &delta) { + x += delta.x; + y += delta.y; + return *this; + } + FloatPoint& operator-=(const FloatPoint &delta) { + x -= delta.x; + y -= delta.y; + return *this; + } +}; + +} // End of namespace Wintermute + +#endif diff --git a/engines/wintermute/math/math_util.cpp b/engines/wintermute/math/math_util.cpp index 31af77538a..903cea6d39 100644 --- a/engines/wintermute/math/math_util.cpp +++ b/engines/wintermute/math/math_util.cpp @@ -27,7 +27,7 @@ */ #include "engines/wintermute/math/math_util.h" -#include <math.h> +#include "common/scummsys.h" namespace Wintermute { @@ -49,4 +49,4 @@ float MathUtil::roundUp(float val) { return result; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/math/math_util.h b/engines/wintermute/math/math_util.h index 38b6d9abf9..41a7a43e2e 100644 --- a/engines/wintermute/math/math_util.h +++ b/engines/wintermute/math/math_util.h @@ -37,6 +37,6 @@ public: static float roundUp(float val); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/math/matrix4.cpp b/engines/wintermute/math/matrix4.cpp index ca1eae8813..011766f510 100644 --- a/engines/wintermute/math/matrix4.cpp +++ b/engines/wintermute/math/matrix4.cpp @@ -28,7 +28,7 @@ #include "engines/wintermute/math/matrix4.h" #include "engines/wintermute/math/vector2.h" -#include <math.h> +#include "common/scummsys.h" namespace Wintermute { @@ -83,4 +83,4 @@ void Matrix4::transformVector2(Vector2 &vec) { vec.y = y; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/math/matrix4.h b/engines/wintermute/math/matrix4.h index 273633f723..4198b50484 100644 --- a/engines/wintermute/math/matrix4.h +++ b/engines/wintermute/math/matrix4.h @@ -45,6 +45,6 @@ public: float m[4][4]; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/math/rect32.h b/engines/wintermute/math/rect32.h index 190c1135cf..f522ab3a35 100644 --- a/engines/wintermute/math/rect32.h +++ b/engines/wintermute/math/rect32.h @@ -24,12 +24,38 @@ #define WINTERMUTE_RECT32_H #include "common/system.h" +#include "engines/wintermute/math/floatpoint.h" +#include "common/rect.h" namespace Wintermute { struct Point32 { int32 x; int32 y; + Point32() : x(0), y(0) {} + Point32(int32 x1, int32 y1) : x(x1), y(y1) {} + bool operator==(const Point32 &p) const { return x == p.x && y == p.y; } + bool operator!=(const Point32 &p) const { return x != p.x || y != p.y; } + Point32 operator+(const Point32 &delta) const { return Point32(x + delta.x, y + delta.y); } + Point32 operator-(const Point32 &delta) const { return Point32(x - delta.x, y - delta.y); } + + Point32 &operator+=(const Point32 &delta) { + x += delta.x; + y += delta.y; + return *this; + } + + Point32 &operator-=(const Point32 &delta) { + x -= delta.x; + y -= delta.y; + return *this; + } + + operator FloatPoint() { + return FloatPoint(x,y); + } + + }; struct Rect32 { @@ -38,6 +64,7 @@ struct Rect32 { Rect32() : top(0), left(0), bottom(0), right(0) {} Rect32(int32 w, int32 h) : top(0), left(0), bottom(h), right(w) {} + Rect32(const Common::Rect &rect) : top(rect.top), left(rect.left), bottom(rect.bottom), right(rect.right) {} Rect32(int32 x1, int32 y1, int32 x2, int32 y2) : top(y1), left(x1), bottom(y2), right(x2) { assert(isValidRect()); } @@ -89,6 +116,6 @@ struct Rect32 { } }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/math/vector2.cpp b/engines/wintermute/math/vector2.cpp index 74c5586d62..618ee9bda9 100644 --- a/engines/wintermute/math/vector2.cpp +++ b/engines/wintermute/math/vector2.cpp @@ -27,7 +27,7 @@ */ #include "engines/wintermute/math/vector2.h" -#include <math.h> +#include "common/scummsys.h" namespace Wintermute { @@ -52,4 +52,4 @@ float Vector2::length() const { return (float)sqrt(x * x + y * y); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/math/vector2.h b/engines/wintermute/math/vector2.h index 31f31daaa0..e4ba97c517 100644 --- a/engines/wintermute/math/vector2.h +++ b/engines/wintermute/math/vector2.h @@ -70,6 +70,6 @@ public: float y; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk index 32931bf05f..95f9ba2ffb 100644 --- a/engines/wintermute/module.mk +++ b/engines/wintermute/module.mk @@ -89,6 +89,8 @@ MODULE_OBJS := \ base/save_thumb_helper.o \ base/timer.o \ detection.o \ + graphics/transform_struct.o \ + graphics/transform_tools.o \ graphics/transparent_surface.o \ math/math_util.o \ math/matrix4.o \ diff --git a/engines/wintermute/persistent.h b/engines/wintermute/persistent.h index 1464ae0fd6..ddc0791054 100644 --- a/engines/wintermute/persistent.h +++ b/engines/wintermute/persistent.h @@ -37,7 +37,7 @@ class BasePersistenceManager; typedef void *(*PERSISTBUILD)(void); typedef bool(*PERSISTLOAD)(void *, BasePersistenceManager *); typedef void(*SYS_INSTANCE_CALLBACK)(void *instance, void *data); -} // end of namespace Wintermute +} // End of namespace Wintermute #include "engines/wintermute/system/sys_class_registry.h" namespace Wintermute { @@ -85,6 +85,6 @@ namespace Wintermute { #define TMEMBER_PTR(memberName) #memberName, &memberName #define TMEMBER_INT(memberName) #memberName, (int32*)&memberName -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/platform_osystem.cpp b/engines/wintermute/platform_osystem.cpp index 362c0da624..87a127d001 100644 --- a/engines/wintermute/platform_osystem.cpp +++ b/engines/wintermute/platform_osystem.cpp @@ -125,9 +125,12 @@ void BasePlatform::handleEvent(Common::Event *event) { // _gameRef->AutoSaveOnExit(); // _gameRef->_quitting = true; // } - if (_gameRef) { - _gameRef->onWindowClose(); - } + +// The engine CAN query for closing, but we disable it for now, as the EVENT_QUIT-event +// can't be stopped. +// if (_gameRef) { +// _gameRef->onWindowClose(); +// } break; default: // TODO: Do we care about any other events? @@ -272,4 +275,4 @@ char *BasePlatform::strlwr(char *string) { return string; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/platform_osystem.h b/engines/wintermute/platform_osystem.h index 8c39b29ea9..46c86df909 100644 --- a/engines/wintermute/platform_osystem.h +++ b/engines/wintermute/platform_osystem.h @@ -70,6 +70,6 @@ private: static WintermuteEngine *_engineRef; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/system/sys_class.cpp b/engines/wintermute/system/sys_class.cpp index cda58bbb48..0577f29e2c 100644 --- a/engines/wintermute/system/sys_class.cpp +++ b/engines/wintermute/system/sys_class.cpp @@ -217,4 +217,4 @@ void SystemClass::instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpDat } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/system/sys_class.h b/engines/wintermute/system/sys_class.h index 3f91723ed8..9fb3f70696 100644 --- a/engines/wintermute/system/sys_class.h +++ b/engines/wintermute/system/sys_class.h @@ -125,6 +125,6 @@ private: InstanceMap _instanceMap; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/system/sys_class_registry.cpp b/engines/wintermute/system/sys_class_registry.cpp index 8a6aae754f..20e4661efb 100644 --- a/engines/wintermute/system/sys_class_registry.cpp +++ b/engines/wintermute/system/sys_class_registry.cpp @@ -333,4 +333,4 @@ void SystemClassRegistry::dumpClasses(Common::WriteStream *stream) { } } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/system/sys_class_registry.h b/engines/wintermute/system/sys_class_registry.h index ef7218c7c1..48a6738ffb 100644 --- a/engines/wintermute/system/sys_class_registry.h +++ b/engines/wintermute/system/sys_class_registry.h @@ -101,6 +101,6 @@ public: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/system/sys_instance.cpp b/engines/wintermute/system/sys_instance.cpp index d106119dba..b8e5c9b50a 100644 --- a/engines/wintermute/system/sys_instance.cpp +++ b/engines/wintermute/system/sys_instance.cpp @@ -46,4 +46,4 @@ SystemInstance::SystemInstance(void *instance, int id, SystemClass *sysClass) { SystemInstance::~SystemInstance() { } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/system/sys_instance.h b/engines/wintermute/system/sys_instance.h index 215a6d1437..115de28094 100644 --- a/engines/wintermute/system/sys_instance.h +++ b/engines/wintermute/system/sys_instance.h @@ -63,6 +63,6 @@ private: SystemClass *_class; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp index 9db1f4f4b4..b2e6c3953b 100644 --- a/engines/wintermute/ui/ui_button.cpp +++ b/engines/wintermute/ui/ui_button.cpp @@ -1206,4 +1206,4 @@ bool UIButton::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_button.h b/engines/wintermute/ui/ui_button.h index 5db9356ef9..b5002f3166 100644 --- a/engines/wintermute/ui/ui_button.h +++ b/engines/wintermute/ui/ui_button.h @@ -75,6 +75,6 @@ public: virtual const char *scToString() override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_edit.cpp b/engines/wintermute/ui/ui_edit.cpp index 91ca7326cb..caed157e0b 100644 --- a/engines/wintermute/ui/ui_edit.cpp +++ b/engines/wintermute/ui/ui_edit.cpp @@ -949,4 +949,4 @@ bool UIEdit::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_edit.h b/engines/wintermute/ui/ui_edit.h index ac626f0f06..a057be9ead 100644 --- a/engines/wintermute/ui/ui_edit.h +++ b/engines/wintermute/ui/ui_edit.h @@ -67,6 +67,6 @@ public: virtual const char *scToString() override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_entity.cpp b/engines/wintermute/ui/ui_entity.cpp index 1872400cdd..6d4cfdb7eb 100644 --- a/engines/wintermute/ui/ui_entity.cpp +++ b/engines/wintermute/ui/ui_entity.cpp @@ -363,4 +363,4 @@ bool UIEntity::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_entity.h b/engines/wintermute/ui/ui_entity.h index 3bd3ec9888..1b6e8a10d6 100644 --- a/engines/wintermute/ui/ui_entity.h +++ b/engines/wintermute/ui/ui_entity.h @@ -54,6 +54,6 @@ public: virtual const char *scToString(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_object.cpp b/engines/wintermute/ui/ui_object.cpp index 07efc5e4cb..c32ae75c20 100644 --- a/engines/wintermute/ui/ui_object.cpp +++ b/engines/wintermute/ui/ui_object.cpp @@ -648,4 +648,4 @@ bool UIObject::saveAsText(BaseDynamicBuffer *buffer, int indent) { return STATUS_FAILED; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_object.h b/engines/wintermute/ui/ui_object.h index 935c27613c..5d9508c2cf 100644 --- a/engines/wintermute/ui/ui_object.h +++ b/engines/wintermute/ui/ui_object.h @@ -80,6 +80,6 @@ public: virtual const char *scToString() override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_text.cpp b/engines/wintermute/ui/ui_text.cpp index 98d70b770e..5dc25f5852 100644 --- a/engines/wintermute/ui/ui_text.cpp +++ b/engines/wintermute/ui/ui_text.cpp @@ -519,4 +519,4 @@ bool UIText::sizeToFit() { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_text.h b/engines/wintermute/ui/ui_text.h index be074755ba..29ed62a5ef 100644 --- a/engines/wintermute/ui/ui_text.h +++ b/engines/wintermute/ui/ui_text.h @@ -55,6 +55,6 @@ public: virtual const char *scToString() override; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp index abccdd6c39..de4b86a6dd 100644 --- a/engines/wintermute/ui/ui_tiled_image.cpp +++ b/engines/wintermute/ui/ui_tiled_image.cpp @@ -388,4 +388,4 @@ bool UITiledImage::persist(BasePersistenceManager *persistMgr) { return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_tiled_image.h b/engines/wintermute/ui/ui_tiled_image.h index a6cd22d53d..39bc6495a9 100644 --- a/engines/wintermute/ui/ui_tiled_image.h +++ b/engines/wintermute/ui/ui_tiled_image.h @@ -59,6 +59,6 @@ private: Rect32 _downRight; }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/ui/ui_window.cpp b/engines/wintermute/ui/ui_window.cpp index 2ce9f68605..9066ee9f5b 100644 --- a/engines/wintermute/ui/ui_window.cpp +++ b/engines/wintermute/ui/ui_window.cpp @@ -1442,4 +1442,4 @@ bool UIWindow::getWindowObjects(BaseArray<UIObject *> &objects, bool interactive return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/ui/ui_window.h b/engines/wintermute/ui/ui_window.h index 70799cea25..8a726fdff8 100644 --- a/engines/wintermute/ui/ui_window.h +++ b/engines/wintermute/ui/ui_window.h @@ -89,6 +89,6 @@ public: virtual const char *scToString(); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/utils/crc.cpp b/engines/wintermute/utils/crc.cpp index e7ec45511b..a9781500fa 100644 --- a/engines/wintermute/utils/crc.cpp +++ b/engines/wintermute/utils/crc.cpp @@ -234,4 +234,4 @@ crc crc_finalize(crc remainder) { return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/utils/path_util.cpp b/engines/wintermute/utils/path_util.cpp index 298f0c268f..ee8b298562 100644 --- a/engines/wintermute/utils/path_util.cpp +++ b/engines/wintermute/utils/path_util.cpp @@ -98,4 +98,4 @@ AnsiString PathUtil::getExtension(const AnsiString &path) { return Common::lastPathComponent(path, '.'); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/utils/path_util.h b/engines/wintermute/utils/path_util.h index 7358c2aba0..2c7dfa99d1 100644 --- a/engines/wintermute/utils/path_util.h +++ b/engines/wintermute/utils/path_util.h @@ -44,6 +44,6 @@ public: static AnsiString getExtension(const AnsiString &path); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp index 9fffad85cd..23abb5d579 100644 --- a/engines/wintermute/utils/string_util.cpp +++ b/engines/wintermute/utils/string_util.cpp @@ -231,4 +231,4 @@ AnsiString StringUtil::toString(int val) { } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/utils/string_util.h b/engines/wintermute/utils/string_util.h index e419e2bca8..3ae5e47493 100644 --- a/engines/wintermute/utils/string_util.h +++ b/engines/wintermute/utils/string_util.h @@ -51,6 +51,6 @@ public: static AnsiString toString(int val); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp index 6e0d69edbe..8fa6313ba6 100644 --- a/engines/wintermute/utils/utils.cpp +++ b/engines/wintermute/utils/utils.cpp @@ -258,4 +258,4 @@ float BaseUtils::Hue2RGB(float v1, float v2, float vH) { return (v1); } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/utils/utils.h b/engines/wintermute/utils/utils.h index d6a603ec72..6c804ff01e 100644 --- a/engines/wintermute/utils/utils.h +++ b/engines/wintermute/utils/utils.h @@ -59,6 +59,6 @@ private: static float Hue2RGB(float v1, float v2, float vH); }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/video/video_player.cpp b/engines/wintermute/video/video_player.cpp index 42857b5c1b..f18311c3e1 100644 --- a/engines/wintermute/video/video_player.cpp +++ b/engines/wintermute/video/video_player.cpp @@ -106,4 +106,4 @@ bool VideoPlayer::loadSubtitles(const char *filename, const char *subtitleFile) return STATUS_OK; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/video/video_player.h b/engines/wintermute/video/video_player.h index 033ab50dfa..51c6bf41d3 100644 --- a/engines/wintermute/video/video_player.h +++ b/engines/wintermute/video/video_player.h @@ -85,6 +85,6 @@ public: BaseArray<CVidSubtitle *, CVidSubtitle *> _subtitles;*/ }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp index 8f9db8392f..f3317684b5 100644 --- a/engines/wintermute/video/video_theora_player.cpp +++ b/engines/wintermute/video/video_theora_player.cpp @@ -163,14 +163,14 @@ bool VideoTheoraPlayer::resetStream() { if (!_file) { return STATUS_FAILED; } - + #if defined (USE_THEORADEC) _theoraDecoder = new Video::TheoraDecoder(); #else return STATUS_FAILED; #endif _theoraDecoder->loadStream(_file); - + if (!_theoraDecoder->isVideoLoaded()) { return STATUS_FAILED; } @@ -369,14 +369,14 @@ void VideoTheoraPlayer::writeAlpha() { if (_alphaImage && _surface.w == _alphaImage->getSurface()->w && _surface.h == _alphaImage->getSurface()->h) { assert(_alphaImage->getSurface()->format.bytesPerPixel == 4); assert(_surface.format.bytesPerPixel == 4); - const byte *alphaData = (const byte *)_alphaImage->getSurface()->getBasePtr(0, 0); + const byte *alphaData = (const byte *)_alphaImage->getSurface()->getPixels(); #ifdef SCUMM_LITTLE_ENDIAN int alphaPlace = (_alphaImage->getSurface()->format.aShift / 8); #else int alphaPlace = 3 - (_alphaImage->getSurface()->format.aShift / 8); #endif alphaData += alphaPlace; - byte *imgData = (byte *)_surface.getBasePtr(0, 0); + byte *imgData = (byte *)_surface.getPixels(); #ifdef SCUMM_LITTLE_ENDIAN imgData += (_surface.format.aShift / 8); #else @@ -417,7 +417,7 @@ bool VideoTheoraPlayer::display(uint32 alpha) { bool VideoTheoraPlayer::setAlphaImage(const Common::String &filename) { delete _alphaImage; _alphaImage = new BaseImage(); - if (!_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) { + if (filename == "" || !_alphaImage || DID_FAIL(_alphaImage->loadFile(filename))) { delete _alphaImage; _alphaImage = nullptr; _alphaFilename = ""; @@ -498,7 +498,7 @@ bool VideoTheoraPlayer::persist(BasePersistenceManager *persistMgr) { persistMgr->transfer(TMEMBER(_alphaFilename)); persistMgr->transfer(TMEMBER(_posX)); persistMgr->transfer(TMEMBER(_posY)); - persistMgr->transfer(TMEMBER(_playZoom)); + persistMgr->transferFloat(TMEMBER(_playZoom)); persistMgr->transfer(TMEMBER_INT(_playbackType)); persistMgr->transfer(TMEMBER(_looping)); persistMgr->transfer(TMEMBER(_volume)); @@ -529,4 +529,4 @@ BaseSurface *VideoTheoraPlayer::getTexture() const { return _texture; } -} // end of namespace Wintermute +} // End of namespace Wintermute diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h index 364509a080..ddeba48bbc 100644 --- a/engines/wintermute/video/video_theora_player.h +++ b/engines/wintermute/video/video_theora_player.h @@ -101,7 +101,7 @@ public: // video properties int32 _posX; int32 _posY; - + bool _dontDropFrames; private: int32 _state; @@ -142,6 +142,6 @@ private: }; -} // end of namespace Wintermute +} // End of namespace Wintermute #endif diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp index 92381742de..a878944661 100644 --- a/engines/wintermute/wintermute.cpp +++ b/engines/wintermute/wintermute.cpp @@ -26,7 +26,6 @@ #include "common/debug.h" #include "common/debug-channels.h" #include "common/error.h" -#include "common/EventRecorder.h" #include "common/file.h" #include "common/fs.h" #include "common/tokenizer.h" @@ -134,7 +133,7 @@ Common::Error WintermuteEngine::run() { } int WintermuteEngine::init() { - BaseEngine::createInstance(_targetName, _gameDescription->language); + BaseEngine::createInstance(_targetName, _gameDescription->gameid, _gameDescription->language); _game = new AdGame(_targetName); if (!_game) { return 1; @@ -148,7 +147,7 @@ int WintermuteEngine::init() { _game->initialize1(); // set gameId, for savegame-naming: - _game->setGameId(_targetName); + _game->setGameTargetName(_targetName); if (DID_FAIL(_game->loadSettings("startup.settings"))) { _game->LOG(0, "Error loading game settings."); @@ -251,6 +250,9 @@ int WintermuteEngine::messageLoop() { } prevTime = time; } + if (shouldQuit()) { + break; + } if (_game && _game->_quitting) { break; } @@ -292,6 +294,7 @@ bool WintermuteEngine::getGameInfo(const Common::FSList &fslist, Common::String Common::SeekableReadStream *stream = nullptr; // Quick-fix, instead of possibly breaking the persistence-system, let's just roll with it BaseFileManager *fileMan = new BaseFileManager(Common::UNK_LANG, true); + fileMan->registerPackages(fslist); stream = fileMan->openFile("startup.settings", false, false); // The process is as follows: Check the "GAME=" tag in startup.settings, to decide where the diff --git a/engines/wintermute/wintypes.h b/engines/wintermute/wintypes.h index c7723808ea..1288ac1a65 100644 --- a/engines/wintermute/wintypes.h +++ b/engines/wintermute/wintypes.h @@ -48,6 +48,6 @@ namespace Wintermute { #define MAX_PATH_LENGTH 512 -} // end of namespace Wintermute +} // End of namespace Wintermute #endif |