diff options
Diffstat (limited to 'engines')
115 files changed, 2221 insertions, 1596 deletions
diff --git a/engines/avalanche/avalot.cpp b/engines/avalanche/avalot.cpp index c8f5599687..0ffe7d3f9d 100644 --- a/engines/avalanche/avalot.cpp +++ b/engines/avalanche/avalot.cpp @@ -217,7 +217,7 @@ void AvalancheEngine::setup() { delete mainmenu; if (_letMeOut) return; - + newGame(); thinkAbout(kObjectMoney, kThing); diff --git a/engines/avalanche/dialogs.cpp b/engines/avalanche/dialogs.cpp index e843d17c5b..f95440900b 100644 --- a/engines/avalanche/dialogs.cpp +++ b/engines/avalanche/dialogs.cpp @@ -105,7 +105,7 @@ void Dialogs::setReadyLight(byte state) { color = kColorGreen; break; // Hit a key } - + _vm->_graphics->drawReadyLight(color); CursorMan.showMouse(true); _vm->_ledStatus = state; diff --git a/engines/avalanche/ghostroom.h b/engines/avalanche/ghostroom.h index 4c659128ce..ca1e8ac806 100644 --- a/engines/avalanche/ghostroom.h +++ b/engines/avalanche/ghostroom.h @@ -56,7 +56,7 @@ private: static const byte kWaveOrder[5]; static const byte kGlerkFade[26]; static const byte kGreldetFade[18]; - + Common::Point dummyCoord; byte ****_ghost;// [5][2][66][26] Graphics::Surface _eyes[2]; diff --git a/engines/avalanche/graphics.cpp b/engines/avalanche/graphics.cpp index 67a7061c75..60c23594d3 100644 --- a/engines/avalanche/graphics.cpp +++ b/engines/avalanche/graphics.cpp @@ -533,7 +533,7 @@ void GraphicManager::ghostDrawMonster(byte ***picture, uint16 destX, int16 destY // Only for the Ghost: const byte kPlaneToUse[4] = { 0, 0, 0, 1 }; int yStart = 0; - + // Constants from the original code: switch (type) { case kMonsterTypeGhost: @@ -820,7 +820,7 @@ void GraphicManager::menuLoadPictures() { int height = 33; int width = 9 * 8; - + for (int plane = 0; plane < 4; plane++) { // The icons themselves: int n = 0; @@ -853,7 +853,7 @@ void GraphicManager::menuLoadPictures() { _menu.fillRect(Common::Rect(114, 70 + i * 33, 584, 73 + i * 33), kColorWhite); _menu.fillRect(Common::Rect(114, 100 + i * 33, 584, 103 + i * 33), kColorDarkgray); } - + file.close(); // The title on the top of the screen: diff --git a/engines/avalanche/help.cpp b/engines/avalanche/help.cpp index 9b077eb4fb..4d08e3d58b 100644 --- a/engines/avalanche/help.cpp +++ b/engines/avalanche/help.cpp @@ -196,9 +196,9 @@ bool Help::handleMouse(const Common::Event &event) { } // Erase the previous highlight only if it's needed: - if (_highlightWas != highlightIs) + if (_highlightWas != highlightIs) _vm->_graphics->helpDrawHighlight(_highlightWas, kColorBlue); - + // Highlight the current one with the proper color: if ((highlightIs != 177) && (_buttons[highlightIs]._trigger != Common::KEYCODE_INVALID)) { _highlightWas = highlightIs; diff --git a/engines/avalanche/module.mk b/engines/avalanche/module.mk index 29bc039b42..919ff0334f 100644 --- a/engines/avalanche/module.mk +++ b/engines/avalanche/module.mk @@ -22,7 +22,7 @@ MODULE_OBJS = \ shootemup.o \ mainmenu.o \ highscore.o - + # This module can be built as a plugin ifeq ($(ENABLE_AVALANCHE), DYNAMIC_PLUGIN) PLUGIN := 1 diff --git a/engines/avalanche/nim.cpp b/engines/avalanche/nim.cpp index 9457a5065b..79be16d3c3 100644 --- a/engines/avalanche/nim.cpp +++ b/engines/avalanche/nim.cpp @@ -77,7 +77,7 @@ void Nim::playNim() { _vm->_dialogs->displayScrollChain('Q', 3); _playedNim++; - + _vm->_graphics->saveScreen(); _vm->fadeOut(); @@ -87,7 +87,7 @@ void Nim::playNim() { //CursorMan.showMouse(true); do { - + startMove(); if (_dogfoodsTurn) dogFood(); @@ -122,7 +122,7 @@ void Nim::playNim() { _vm->refreshObjectList(); _vm->_wonNim = true; _vm->_background->draw(-1, -1, 0); // Show the settle with no lute on it. - + // 7 points for winning! _vm->incScore(7); } @@ -135,7 +135,7 @@ void Nim::playNim() { void Nim::chalk(int x, int y, Common::String text) { const Color greys[] = { kColorBlack, kColorDarkgray, kColorLightgray, kColorWhite }; - + for (int i = 0; i < 4; i++) { _vm->_graphics->drawNormalText(text, _vm->_font, 8, x - i, y, greys[i]); _vm->_graphics->refreshScreen(); @@ -159,7 +159,7 @@ void Nim::setup() { // Bottom right rectangle. _vm->_graphics->drawRectangle(Common::Rect(394, 50, 635, 198), kColorRed); _vm->_graphics->drawFilledRectangle(Common::Rect(395, 51, 634, 197), kColorBrown); - + _vm->_graphics->nimDrawLogo(); _vm->_graphics->nimDrawInitials(); @@ -167,7 +167,7 @@ void Nim::setup() { _vm->_graphics->drawNormalText("Turn:", _vm->_font, 8, 420, 55, kColorYellow); _vm->_graphics->drawNormalText("Player:", _vm->_font, 8, 490, 55, kColorYellow); _vm->_graphics->drawNormalText("Move:", _vm->_font, 8, 570, 55, kColorYellow); - + chalk(27, 7, "Take pieces away with:"); chalk(77, 17, "1) the mouse (click leftmost)"); chalk(53, 27, "or 2) the keyboard:"); @@ -364,7 +364,7 @@ bool Nim::checkInput() { void Nim::takeSome() { _number = 1; - + do { byte sr; do { @@ -377,7 +377,7 @@ void Nim::takeSome() { _number = 1; } } while (sr == 0); - + if (_number > sr) _number = sr; @@ -391,7 +391,7 @@ void Nim::takeSome() { bool confirm = false; do { confirm = checkInput(); - + if (!confirm) { _vm->_graphics->drawRectangle(Common::Rect(x1, y1, x2, y2), kColorBlack); // Erase the previous selection. x1 = 63 + (_stones[_row] - _number) * 64; @@ -402,7 +402,7 @@ void Nim::takeSome() { _vm->_graphics->refreshScreen(); } } while (!confirm); - + return; } while (true); diff --git a/engines/avalanche/parser.cpp b/engines/avalanche/parser.cpp index b152747ab0..220186ca5e 100644 --- a/engines/avalanche/parser.cpp +++ b/engines/avalanche/parser.cpp @@ -2495,7 +2495,7 @@ void Parser::synchronize(Common::Serializer &sz) { sz.syncAsByte(_sworeNum); sz.syncAsByte(_alcoholLevel); if (sz.isLoading() && sz.getVersion() < 2) { - int dummy; + int dummy; sz.syncAsByte(dummy); } sz.syncAsByte(_boughtOnion); diff --git a/engines/avalanche/shootemup.cpp b/engines/avalanche/shootemup.cpp index cabd19d6f9..e5e44ed934 100644 --- a/engines/avalanche/shootemup.cpp +++ b/engines/avalanche/shootemup.cpp @@ -116,7 +116,7 @@ uint16 ShootEmUp::run() { } setup(); - + while ((_time != 0) && (!_vm->shouldQuit())) { uint32 beginLoop = _vm->_system->getMillis(); @@ -142,7 +142,7 @@ uint16 ShootEmUp::run() { if (delay <= 55) _vm->_system->delayMillis(55 - delay); // Replaces slowdown(); 55 comes from 18.2 Hz (B Flight). }; - + _vm->fadeOut(); _vm->_graphics->restoreScreen(); _vm->_graphics->removeBackup(); diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp index d7dccd2c65..babcb7e667 100644 --- a/engines/cge/vga13h.cpp +++ b/engines/cge/vga13h.cpp @@ -482,39 +482,39 @@ void Sprite::sync(Common::Serializer &s) { uint16 flags = 0; if (s.isLoading()) { s.syncAsUint16LE(flags); - _flags._hide = flags & 0x0001 ? true : false; - _flags._near = flags & 0x0002 ? true : false; - _flags._drag = flags & 0x0004 ? true : false; - _flags._hold = flags & 0x0008 ? true : false; - _flags._dummy = flags & 0x0010 ? true : false; - _flags._slav = flags & 0x0020 ? true : false; - _flags._syst = flags & 0x0040 ? true : false; - _flags._kill = flags & 0x0080 ? true : false; - _flags._xlat = flags & 0x0100 ? true : false; - _flags._port = flags & 0x0200 ? true : false; - _flags._kept = flags & 0x0400 ? true : false; - _flags._east = flags & 0x0800 ? true : false; - _flags._shad = flags & 0x1000 ? true : false; - _flags._back = flags & 0x2000 ? true : false; - _flags._bDel = flags & 0x4000 ? true : false; - _flags._tran = flags & 0x8000 ? true : false; + _flags._hide = flags & 0x0001; + _flags._near = flags & 0x0002; + _flags._drag = flags & 0x0004; + _flags._hold = flags & 0x0008; + _flags._dummy = flags & 0x0010; + _flags._slav = flags & 0x0020; + _flags._syst = flags & 0x0040; + _flags._kill = flags & 0x0080; + _flags._xlat = flags & 0x0100; + _flags._port = flags & 0x0200; + _flags._kept = flags & 0x0400; + _flags._east = flags & 0x0800; + _flags._shad = flags & 0x1000; + _flags._back = flags & 0x2000; + _flags._bDel = flags & 0x4000; + _flags._tran = flags & 0x8000; } else { - flags = (flags << 1) | _flags._tran; - flags = (flags << 1) | _flags._bDel; - flags = (flags << 1) | _flags._back; - flags = (flags << 1) | _flags._shad; - flags = (flags << 1) | _flags._east; - flags = (flags << 1) | _flags._kept; - flags = (flags << 1) | _flags._port; - flags = (flags << 1) | _flags._xlat; - flags = (flags << 1) | _flags._kill; - flags = (flags << 1) | _flags._syst; - flags = (flags << 1) | _flags._slav; - flags = (flags << 1) | _flags._dummy; - flags = (flags << 1) | _flags._hold; - flags = (flags << 1) | _flags._drag; - flags = (flags << 1) | _flags._near; - flags = (flags << 1) | _flags._hide; + flags = (flags << 1) | (_flags._tran ? 1 : 0); + flags = (flags << 1) | (_flags._bDel ? 1 : 0); + flags = (flags << 1) | (_flags._back ? 1 : 0); + flags = (flags << 1) | (_flags._shad ? 1 : 0); + flags = (flags << 1) | (_flags._east ? 1 : 0); + flags = (flags << 1) | (_flags._kept ? 1 : 0); + flags = (flags << 1) | (_flags._port ? 1 : 0); + flags = (flags << 1) | (_flags._xlat ? 1 : 0); + flags = (flags << 1) | (_flags._kill ? 1 : 0); + flags = (flags << 1) | (_flags._syst ? 1 : 0); + flags = (flags << 1) | (_flags._slav ? 1 : 0); + flags = (flags << 1) | (_flags._dummy ? 1 : 0); + flags = (flags << 1) | (_flags._hold ? 1 : 0); + flags = (flags << 1) | (_flags._drag ? 1 : 0); + flags = (flags << 1) | (_flags._near ? 1 : 0); + flags = (flags << 1) | (_flags._hide ? 1 : 0); s.syncAsUint16LE(flags); } diff --git a/engines/cge/vga13h.h b/engines/cge/vga13h.h index 9511559df0..cc56eebdac 100644 --- a/engines/cge/vga13h.h +++ b/engines/cge/vga13h.h @@ -88,22 +88,22 @@ public: int _ref; signed char _scene; struct Flags { - uint16 _hide : 1; // general visibility switch - uint16 _near : 1; // Near action lock - uint16 _drag : 1; // sprite is moveable - uint16 _hold : 1; // sprite is held with mouse - uint16 _dummy : 1; // intrrupt driven animation - uint16 _slav : 1; // slave object - uint16 _syst : 1; // system object - uint16 _kill : 1; // dispose memory after remove - uint16 _xlat : 1; // 2nd way display: xlat table - uint16 _port : 1; // portable - uint16 _kept : 1; // kept in pocket - uint16 _east : 1; // talk to east (in opposite to west) - uint16 _shad : 1; // shadow - uint16 _back : 1; // 'send to background' request - uint16 _bDel : 1; // delete bitmaps in ~SPRITE - uint16 _tran : 1; // transparent (untouchable) + bool _hide : true; // general visibility switch + bool _near : true; // Near action lock + bool _drag : true; // sprite is moveable + bool _hold : true; // sprite is held with mouse + bool _dummy : true; // intrrupt driven animation + bool _slav : true; // slave object + bool _syst : true; // system object + bool _kill : true; // dispose memory after remove + bool _xlat : true; // 2nd way display: xlat table + bool _port : true; // portable + bool _kept : true; // kept in pocket + bool _east : true; // talk to east (in opposite to west) + bool _shad : true; // shadow + bool _back : true; // 'send to background' request + bool _bDel : true; // delete bitmaps in ~SPRITE + bool _tran : true; // transparent (untouchable) } _flags; int _x; int _y; diff --git a/engines/cruise/background.cpp b/engines/cruise/background.cpp index 921c621eba..4cf52f62e1 100644 --- a/engines/cruise/background.cpp +++ b/engines/cruise/background.cpp @@ -178,7 +178,7 @@ int loadBackground(const char *name, int idx) { break; default: - ASSERT(0); + assert(0); } gfxModuleData_setPal256(palScreen[idx]); diff --git a/engines/cruise/backgroundIncrust.cpp b/engines/cruise/backgroundIncrust.cpp index 3286cd6ebf..77e15ccf4c 100644 --- a/engines/cruise/backgroundIncrust.cpp +++ b/engines/cruise/backgroundIncrust.cpp @@ -59,6 +59,8 @@ void backupBackground(backgroundIncrustStruct *pIncrust, int X, int Y, int width } void restoreBackground(backgroundIncrustStruct *pIncrust) { + if (!pIncrust) + return; if (pIncrust->type != 1) return; if (pIncrust->ptr == NULL) @@ -87,39 +89,32 @@ void restoreBackground(backgroundIncrustStruct *pIncrust) { } backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, backgroundIncrustStruct *pHead, int16 scriptNumber, int16 scriptOverlay, int16 backgroundIdx, int16 saveBuffer) { - uint8 *backgroundPtr; - uint8 *ptr; objectParamsQuery params; - backgroundIncrustStruct *newElement; - backgroundIncrustStruct *currentHead; - backgroundIncrustStruct *currentHead2; - getMultipleObjectParam(overlayIdx, objectIdx, ¶ms); - ptr = filesDatabase[params.fileIdx].subData.ptr; + uint8 *ptr = filesDatabase[params.fileIdx].subData.ptr; // Don't process any further if not a sprite or polygon - if (!ptr) return NULL; - if ((filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_SPRITE) && - (filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_POLY)) { + if (!ptr) return NULL; - } - backgroundPtr = backgroundScreens[backgroundIdx]; - - backgroundChanged[backgroundIdx] = true; + if ((filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_SPRITE) && + (filesDatabase[params.fileIdx].subData.resourceType != OBJ_TYPE_POLY)) + return NULL; + uint8 *backgroundPtr = backgroundScreens[backgroundIdx]; assert(backgroundPtr != NULL); - currentHead = pHead; - currentHead2 = currentHead->next; + backgroundChanged[backgroundIdx] = true; + backgroundIncrustStruct *currentHead = pHead; + backgroundIncrustStruct *currentHead2 = currentHead->next; while (currentHead2) { currentHead = currentHead2; currentHead2 = currentHead->next; } - newElement = (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct)); + backgroundIncrustStruct *newElement = (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct)); if (!newElement) return NULL; @@ -127,13 +122,11 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, newElement->next = currentHead->next; currentHead->next = newElement; - if (!currentHead2) { + if (!currentHead2) currentHead2 = pHead; - } newElement->prev = currentHead2->prev; currentHead2->prev = newElement; - newElement->objectIdx = objectIdx; newElement->type = saveBuffer; newElement->backgroundIdx = backgroundIdx; @@ -152,9 +145,8 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, // sprite int width = filesDatabase[params.fileIdx].width; int height = filesDatabase[params.fileIdx].height; - if (saveBuffer == 1) { + if (saveBuffer == 1) backupBackground(newElement, newElement->X, newElement->Y, width, height, backgroundPtr); - } drawSprite(width, height, NULL, filesDatabase[params.fileIdx].subData.ptr, newElement->Y, newElement->X, backgroundPtr, filesDatabase[params.fileIdx].subData.ptrMask); @@ -168,7 +160,7 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, int sizeTable[4]; // 0 = left, 1 = right, 2 = bottom, 3 = top - // this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1) + // this function checks if the dataPtr is not 0, else it retrieves the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1) flipPoly(params.fileIdx, (int16 *)filesDatabase[params.fileIdx].subData.ptr, params.scale, &newFrame, newElement->X, newElement->Y, &newX, &newY, &newScale); // this function fills the sizeTable for the poly (OLD: mainDrawSub1Sub2) @@ -187,16 +179,15 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx, int16 objectIdx, } void regenerateBackgroundIncrust(backgroundIncrustStruct *pHead) { - lastAni[0] = 0; - - backgroundIncrustStruct* pl = pHead->next; + backgroundIncrustStruct *pl = pHead->next; while (pl) { backgroundIncrustStruct* pl2 = pl->next; int frame = pl->frame; - //int screen = pl->backgroundIdx; + if (frame < 0) + error("regenerateBackgroundIncrust() : Unexpected use of negative frame index"); if ((filesDatabase[frame].subData.ptr == NULL) || (strcmp(pl->name, filesDatabase[frame].subData.name))) { frame = NUM_FILE_ENTRIES - 1; @@ -235,7 +226,6 @@ void freeBackgroundIncrustList(backgroundIncrustStruct *pHead) { MemFree(pCurrent->ptr); MemFree(pCurrent); - pCurrent = pNext; } @@ -244,52 +234,41 @@ void freeBackgroundIncrustList(backgroundIncrustStruct *pHead) { void removeBackgroundIncrust(int overlay, int idx, backgroundIncrustStruct * pHead) { objectParamsQuery params; - int var_4; - int var_6; - - backgroundIncrustStruct *pCurrent; - backgroundIncrustStruct *pCurrentHead; getMultipleObjectParam(overlay, idx, ¶ms); - var_4 = params.X; - var_6 = params.Y; - - pCurrent = pHead->next; + int x = params.X; + int y = params.Y; + backgroundIncrustStruct *pCurrent = pHead->next; while (pCurrent) { - if ((pCurrent->overlayIdx == overlay || overlay == -1) && (pCurrent->objectIdx == idx || idx == -1) && (pCurrent->X == var_4) && (pCurrent->Y == var_6)) { - pCurrent->type = - 1; - } + if ((pCurrent->overlayIdx == overlay || overlay == -1) && (pCurrent->objectIdx == idx || idx == -1) && (pCurrent->X == x) && (pCurrent->Y == y)) + pCurrent->type = -1; pCurrent = pCurrent->next; } - pCurrentHead = pHead; + backgroundIncrustStruct *pCurrentHead = pHead; pCurrent = pHead->next; while (pCurrent) { - if (pCurrent->type == - 1) { + if (pCurrent->type == -1) { backgroundIncrustStruct *pNext = pCurrent->next; backgroundIncrustStruct *bx = pCurrentHead; - backgroundIncrustStruct *cx; bx->next = pNext; - cx = pNext; + backgroundIncrustStruct *cx = pNext; - if (!pNext) { + if (!pNext) cx = pHead; - } bx = cx; bx->prev = pCurrent->next; - if (pCurrent->ptr) { + if (pCurrent->ptr) MemFree(pCurrent->ptr); - } MemFree(pCurrent); - pCurrent = pNext; } else { pCurrentHead = pCurrent; @@ -299,25 +278,24 @@ void removeBackgroundIncrust(int overlay, int idx, backgroundIncrustStruct * pHe } void unmergeBackgroundIncrust(backgroundIncrustStruct * pHead, int ovl, int idx) { - backgroundIncrustStruct *pl; - backgroundIncrustStruct *pl2; - objectParamsQuery params; getMultipleObjectParam(ovl, idx, ¶ms); int x = params.X; int y = params.Y; - pl = pHead; - pl2 = pl; + backgroundIncrustStruct *pl = pHead; + backgroundIncrustStruct *pl2 = pl; pl = pl2->next; while (pl) { pl2 = pl; - if ((pl->overlayIdx == ovl) || (ovl == -1)) - if ((pl->objectIdx == idx) || (idx == -1)) + if ((pl->overlayIdx == ovl) || (ovl == -1)) { + if ((pl->objectIdx == idx) || (idx == -1)) { if ((pl->X == x) && (pl->Y == y)) restoreBackground(pl); + } + } pl = pl2->next; } diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp index 6dcb0b1432..eebd8fdc15 100644 --- a/engines/cruise/cruise.cpp +++ b/engines/cruise/cruise.cpp @@ -50,6 +50,15 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc _debugger = new Debugger(); _sound = new PCSound(_mixer, this); + PCFadeFlag = false; + _preLoad = false; + _savedCursor = CURSOR_NOMOUSE; + _lastTick = 0; + _gameSpeed = GAME_FRAME_DELAY_1; + _speedFlag = false; + _polyStructs = nullptr; + _polyStruct = nullptr; + // Setup mixer syncSoundSettings(); } @@ -87,9 +96,6 @@ Common::Error CruiseEngine::run() { Cruise::changeCursor(Cruise::CURSOR_NORMAL); CursorMan.showMouse(true); - lastTick = 0; - lastTickDebug = 0; - mainLoop(); deinitialize(); @@ -98,24 +104,12 @@ Common::Error CruiseEngine::run() { } void CruiseEngine::initialize() { - PCFadeFlag = 0; - _gameSpeed = GAME_FRAME_DELAY_1; - _speedFlag = false; - - /*volVar1 = 0; - * fileData1 = 0; */ - - /*PAL_fileHandle = -1; */ - // video init stuff - initSystem(); gfxModuleData_Init(); // another bit of video init - readVolCnf(); - _vm->_polyStruct = NULL; } void CruiseEngine::deinitialize() { diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h index c81e5dd5ec..8624ba693e 100644 --- a/engines/cruise/cruise.h +++ b/engines/cruise/cruise.h @@ -60,7 +60,7 @@ private: PCSound *_sound; Common::StringArray _langStrings; CursorType _savedCursor; - uint32 lastTick, lastTickDebug; + uint32 _lastTick; int _gameSpeed; bool _speedFlag; diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index c00f8a55ae..0ad1416df2 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -35,10 +35,10 @@ namespace Cruise { enum RelationType {RT_REL = 30, RT_MSG = 50}; -static int playerDontAskQuit; +static bool _playerDontAskQuit; unsigned int timer = 0; -gfxEntryStruct* linkedMsgList = NULL; +gfxEntryStruct *linkedMsgList = nullptr; typedef CruiseEngine::MemInfo MemInfo; @@ -427,7 +427,7 @@ void resetFileEntry(int32 entryNumber) { } uint8 *mainProc14(uint16 overlay, uint16 idx) { - ASSERT(0); + assert(0); return NULL; } @@ -909,14 +909,14 @@ bool createDialog(int objOvl, int objIdx, int x, int y) { if (obj2Ovl > 0) ovl4 = overlayTable[obj2Ovl].ovlData; - if ((ovl3) && (ptrHead->obj1Number >= 0)) { + if (ovl3 && (ptrHead->obj1Number >= 0)) { testState1 = ptrHead->obj1OldState; } - if ((ovl4) && (ptrHead->obj2Number >= 0)) { + if (ovl4 && (ptrHead->obj2Number >= 0)) { testState2 = ptrHead->obj2OldState; } - if ((ovl4) && (ptrHead->verbNumber >= 0) && + if (ovl4 && ovl2 && (ptrHead->verbNumber >= 0) && ((testState1 == -1) || (testState1 == objectState2)) && ((testState2 == -1) || (testState2 == objectState))) { if (ovl2->nameVerbGlob) { @@ -934,8 +934,11 @@ bool createDialog(int objOvl, int objIdx, int x, int y) { else color = -1; - ptr = getObjectName(ptrHead->obj1Number, ovl3->arrayNameObj); - addSelectableMenuEntry(j, i, menuTable[0], 1, color, ptr); + if (ovl3) { + ptr = getObjectName(ptrHead->obj1Number, ovl3->arrayNameObj); + addSelectableMenuEntry(j, i, menuTable[0], 1, color, ptr); + } else + error("Unexpected null pointer in createDialog()"); } } } @@ -1157,7 +1160,7 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) { createTextObject(&cellHead, ovlIdx, pHeader->id, x, y, 200, findHighColor(), masterScreen, 0, 0); } - userWait = 1; + userWait = true; autoOvl = ovlIdx; autoMsg = pHeader->id; @@ -1186,7 +1189,7 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) { pTrack->flag = 1; autoTrack = true; - userWait = 0; + userWait = false; userEnabled = 0; freezeCell(&cellHead, ovlIdx, pHeader->id, 5, -1, 0, 9998); } @@ -1303,7 +1306,7 @@ void callRelation(menuElementSubStruct *pMenuElement, int nObj2) { createTextObject(&cellHead, ovlIdx, pHeader->id, x, y, 200, findHighColor(), masterScreen, 0, 0); } - userWait = 1; + userWait = true; autoOvl = ovlIdx; autoMsg = pHeader->id; @@ -1334,7 +1337,7 @@ void callRelation(menuElementSubStruct *pMenuElement, int nObj2) { pTrack->flag = 1; autoTrack = true; - userWait = 0; + userWait = false; userEnabled = 0; freezeCell(&cellHead, ovlIdx, pHeader->id, 5, -1, 0, 9998); } @@ -1359,7 +1362,7 @@ void closeAllMenu() { menuTable[1] = NULL; } if (linkedMsgList) { - ASSERT(0); + assert(0); // freeMsgList(linkedMsgList); } @@ -1455,7 +1458,7 @@ int CruiseEngine::processInput() { if (userWait) { // Check for left mouse button click or Space to end user waiting if ((keyboardCode == Common::KEYCODE_SPACE) || (button == CRS_MB_LEFT)) - userWait = 0; + userWait = false; keyboardCode = Common::KEYCODE_INVALID; return 0; @@ -1514,7 +1517,7 @@ int CruiseEngine::processInput() { menuTable[0] = NULL; if (linkedMsgList) { - ASSERT(0); + assert(0); // freeMsgList(linkedMsgList); } @@ -1706,7 +1709,7 @@ bool manageEvents() { break; case Common::EVENT_QUIT: case Common::EVENT_RTL: - playerDontAskQuit = 1; + _playerDontAskQuit = true; break; case Common::EVENT_KEYUP: switch (event.kbd.keycode) { @@ -1772,16 +1775,12 @@ void CruiseEngine::mainLoop() { currentActiveMenu = -1; autoMsg = -1; linkedRelation = 0; - main21 = 0; - main22 = 0; - userWait = 0; + userWait = false; autoTrack = false; initAllData(); - playerDontAskQuit = 0; - int quitValue2 = 1; - int quitValue = 0; + _playerDontAskQuit = false; if (ConfMan.hasKey("save_slot")) loadGameState(ConfMan.getInt("save_slot")); @@ -1831,23 +1830,20 @@ void CruiseEngine::mainLoop() { if (!skipEvents || bFastMode) skipEvents = manageEvents(); - if (bFastMode) { - if (currentTick >= (lastTickDebug + 10)) - lastTickDebug = currentTick; - } else { + if (!bFastMode) { g_system->delayMillis(10); currentTick = g_system->getMillis(); } - if (playerDontAskQuit) + if (_playerDontAskQuit) break; _vm->getDebugger()->onFrame(); - } while (currentTick < lastTick + _gameSpeed && !bFastMode); - if (playerDontAskQuit) + } while (currentTick < _lastTick + _gameSpeed && !bFastMode); + if (_playerDontAskQuit) break; - lastTick = g_system->getMillis(); + _lastTick = g_system->getMillis(); // Handle switchover in game speed after intro if (!_speedFlag && canLoadGameStateCurrently()) { @@ -1862,7 +1858,7 @@ void CruiseEngine::mainLoop() { // readKeyboard(); - bool isUserWait = userWait != 0; + bool isUserWait = userWait; // WORKAROUND: This prevents hotspots responding during // delays i.e. Menu opening if you click fast on another // hotspot after trying to open a locked door, which @@ -1871,8 +1867,8 @@ void CruiseEngine::mainLoop() { currentMouseButton = 0; } - playerDontAskQuit = processInput(); - if (playerDontAskQuit) + _playerDontAskQuit = processInput(); + if (_playerDontAskQuit) break; if (enableUser) { @@ -1918,7 +1914,7 @@ void CruiseEngine::mainLoop() { processAnimation(); if (remdo) { - // ASSERT(0); + // assert(0); /* main3 = 0; * var24 = 0; * var23 = 0; @@ -1927,7 +1923,7 @@ void CruiseEngine::mainLoop() { } if (cmdLine[0]) { - ASSERT(0); + assert(0); /* redrawStrings(0,&cmdLine,8); waitForPlayerInput(); @@ -1937,13 +1933,13 @@ void CruiseEngine::mainLoop() { if (displayOn) { if (doFade) - PCFadeFlag = 0; + PCFadeFlag = false; /*if (!PCFadeFlag)*/ mainDraw(userWait); flipScreen(); - if (userWait == 1) { + if (userWait) { // Waiting for press - original wait loop has been integrated into the // main event loop continue; @@ -1958,7 +1954,7 @@ void CruiseEngine::mainLoop() { char* pText = getText(autoMsg, autoOvl); if (strlen(pText)) - userWait = 1; + userWait = true; } changeScriptParamInList(-1, -1, &relHead, 9998, 0); @@ -1976,7 +1972,7 @@ void CruiseEngine::mainLoop() { g_system->updateScreen(); } - } while (!playerDontAskQuit && quitValue2 && quitValue != 7); + } while (!_playerDontAskQuit); // Free data removeAllScripts(&relHead); diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h index caaaad2068..f9d0e2fc78 100644 --- a/engines/cruise/cruise_main.h +++ b/engines/cruise/cruise_main.h @@ -62,9 +62,6 @@ enum MouseButton { /*#define DUMP_SCRIPT #define DUMP_OBJECT*/ -#define ASSERT_PTR assert -#define ASSERT assert - enum ResType { OBJ_TYPE_LINE = 0, OBJ_TYPE_MASK = 1, diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp index 074132d9a2..9515b552e1 100644 --- a/engines/cruise/ctp.cpp +++ b/engines/cruise/ctp.cpp @@ -244,7 +244,7 @@ int initCt(const char *ctpName) { } // get the path-finding coordinates - ASSERT((segementSizeTable[0] % 4) == 0); + assert((segementSizeTable[0] % 4) == 0); for (int i = 0; i < segementSizeTable[0] / 4; i++) { ctp_routeCoords[i][0] = (int16)READ_BE_UINT16(dataPointer); dataPointer += 2; @@ -253,7 +253,7 @@ int initCt(const char *ctpName) { } // get the path-finding line informations (indexing the routeCoords array) - ASSERT((segementSizeTable[1] % 20) == 0); + assert((segementSizeTable[1] % 20) == 0); for (int i = 0; i < segementSizeTable[1] / 20; i++) { for (int j = 0; j < 10; j++) { ctp_routes[i][j] = (int16)READ_BE_UINT16(dataPointer); @@ -262,7 +262,7 @@ int initCt(const char *ctpName) { } // read polygons - ASSERT((segementSizeTable[2] % 80) == 0); + assert((segementSizeTable[2] % 80) == 0); for (int i = 0; i < segementSizeTable[2] / 80; i++) { for (int j = 0; j < 40; j++) { ctp_walkboxTable[i][j] = (int16)READ_BE_UINT16(dataPointer); @@ -277,14 +277,14 @@ int initCt(const char *ctpName) { } else { // get the walkbox type // Type: 0x00 - non walkable, 0x01 - walkable, 0x02 - exit zone - ASSERT((segementSizeTable[3] % 2) == 0); + assert((segementSizeTable[3] % 2) == 0); for (int i = 0; i < segementSizeTable[3] / 2; i++) { walkboxColor[i] = (int16)READ_BE_UINT16(dataPointer); dataPointer += 2; } // change indicator, walkbox type can change, i.e. blocked by object (values are either 0x00 or 0x01) - ASSERT((segementSizeTable[4] % 2) == 0); + assert((segementSizeTable[4] % 2) == 0); for (int i = 0; i < segementSizeTable[4] / 2; i++) { walkboxState[i] = (int16)READ_BE_UINT16(dataPointer); dataPointer += 2; @@ -292,14 +292,14 @@ int initCt(const char *ctpName) { } // - ASSERT((segementSizeTable[5] % 2) == 0); + assert((segementSizeTable[5] % 2) == 0); for (int i = 0; i < segementSizeTable[5] / 2; i++) { walkboxColorIndex[i] = (int16)READ_BE_UINT16(dataPointer); dataPointer += 2; } // - ASSERT((segementSizeTable[6] % 2) == 0); + assert((segementSizeTable[6] % 2) == 0); for (int i = 0; i < segementSizeTable[6] / 2; i++) { walkboxZoom[i] = (int16)READ_BE_UINT16(dataPointer); dataPointer += 2; diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp index d2426331b1..7a1258dbde 100644 --- a/engines/cruise/dataLoader.cpp +++ b/engines/cruise/dataLoader.cpp @@ -225,7 +225,7 @@ fileTypeEnum getFileType(const char *name) { newFileType = type_FNT; } - ASSERT(newFileType != type_UNK); + assert(newFileType != type_UNK); return newFileType; } @@ -352,39 +352,32 @@ int loadFullBundle(const char *name, int startIdx) { } int loadFNTSub(uint8 *ptr, int destIdx) { - uint8 *ptr2 = ptr; - uint8 *destPtr; - int fileIndex; - //uint32 fontSize; - - ptr2 += 4; + uint8 *ptr2 = ptr + 4; loadFileVar1 = READ_BE_UINT32(ptr2); - if (destIdx == -1) { + int fileIndex; + if (destIdx == -1) fileIndex = createResFileEntry(loadFileVar1, 1, loadFileVar1, 1); - } else { + else fileIndex = updateResFileEntry(loadFileVar1, 1, loadFileVar1, destIdx, 1); - } - destPtr = filesDatabase[fileIndex].subData.ptr; + if (fileIndex < 0) + error("Unable to load FNT resource"); - if (destPtr != NULL) { - int32 i; - uint8 *currentPtr; + uint8 *destPtr = filesDatabase[fileIndex].subData.ptr; + if (destPtr != NULL) { memcpy(destPtr, ptr2, loadFileVar1); - //fontSize = READ_BE_UINT32(ptr2); - destPtr = filesDatabase[fileIndex].subData.ptr; bigEndianLongToNative((int32 *) destPtr); bigEndianLongToNative((int32 *)(destPtr + 4)); flipGen(destPtr + 8, 6); - currentPtr = destPtr + 14; + uint8 *currentPtr = destPtr + 14; - for (i = 0; i < (int16)READ_UINT16(destPtr + 8); i++) { + for (int i = 0; i < (int16)READ_UINT16(destPtr + 8); i++) { bigEndianLongToNative((int32 *) currentPtr); currentPtr += 4; @@ -397,16 +390,17 @@ int loadFNTSub(uint8 *ptr, int destIdx) { } int loadSPLSub(uint8 *ptr, int destIdx) { - uint8 *destPtr; int fileIndex; - if (destIdx == -1) { + if (destIdx == -1) fileIndex = createResFileEntry(loadFileVar1, 1, loadFileVar1, 1); - } else { + else fileIndex = updateResFileEntry(loadFileVar1, 1, loadFileVar1, destIdx, 1); - } - destPtr = filesDatabase[fileIndex].subData.ptr; + if (fileIndex < 0) + error("Unable to load SPL resource"); + + uint8* destPtr = filesDatabase[fileIndex].subData.ptr; memcpy(destPtr, ptr, loadFileVar1); return 1; @@ -419,131 +413,119 @@ int loadSetEntry(const char *name, uint8 *ptr, int currentEntryIdx, int currentD int sec = 0; uint16 numIdx; - if (!strcmp((char *)ptr, "SEC")) { + if (!strcmp((char *)ptr, "SEC")) sec = 1; - } numIdx = READ_BE_UINT16(ptr + 4); - ptr3 = ptr + 6; - offset = currentEntryIdx * 16; - { - int resourceSize; - int fileIndex; - setHeaderEntry localBuffer; + int resourceSize; + int fileIndex; + setHeaderEntry localBuffer; - Common::MemoryReadStream s4(ptr + offset + 6, 16); + Common::MemoryReadStream s4(ptr + offset + 6, 16); - localBuffer.offset = s4.readUint32BE(); - localBuffer.width = s4.readUint16BE(); - localBuffer.height = s4.readUint16BE(); - localBuffer.type = s4.readUint16BE(); - localBuffer.transparency = s4.readUint16BE() & 0x1F; - localBuffer.hotspotY = s4.readUint16BE(); - localBuffer.hotspotX = s4.readUint16BE(); + localBuffer.offset = s4.readUint32BE(); + localBuffer.width = s4.readUint16BE(); + localBuffer.height = s4.readUint16BE(); + localBuffer.type = s4.readUint16BE(); + localBuffer.transparency = s4.readUint16BE() & 0x1F; + localBuffer.hotspotY = s4.readUint16BE(); + localBuffer.hotspotX = s4.readUint16BE(); - if (sec == 1) - // Type 1: Width - (1*2) , Type 5: Width - (5*2) - localBuffer.width -= localBuffer.type * 2; + if (sec == 1) + // Type 1: Width - (1*2) , Type 5: Width - (5*2) + localBuffer.width -= localBuffer.type * 2; - resourceSize = localBuffer.width * localBuffer.height; + resourceSize = localBuffer.width * localBuffer.height; - if (!sec && (localBuffer.type == 5)) - // Type 5: Width - (2*5) - localBuffer.width -= 10; + if (!sec && (localBuffer.type == 5)) + // Type 5: Width - (2*5) + localBuffer.width -= 10; - if (currentDestEntry == -1) { - fileIndex = createResFileEntry(localBuffer.width, localBuffer.height, resourceSize, localBuffer.type); - } else { - fileIndex = updateResFileEntry(localBuffer.height, localBuffer.width, resourceSize, currentDestEntry, localBuffer.type); - } + if (currentDestEntry == -1) + fileIndex = createResFileEntry(localBuffer.width, localBuffer.height, resourceSize, localBuffer.type); + else + fileIndex = updateResFileEntry(localBuffer.height, localBuffer.width, resourceSize, currentDestEntry, localBuffer.type); - if (fileIndex < 0) { - return -1; // TODO: buffer is not freed - } + if (fileIndex < 0) + return -1; // TODO: buffer is not freed - if (!sec && (localBuffer.type == 5)) { - // There are sometimes sprites with a reduced width than what their pixels provide. - // The original handled this here by copy parts of each line - for ScummVM, we're - // simply setting the width in bytes and letting the decoder do the rest - filesDatabase[fileIndex].width += 2; - } + if (!sec && (localBuffer.type == 5)) { + // There are sometimes sprites with a reduced width than what their pixels provide. + // The original handled this here by copy parts of each line - for ScummVM, we're + // simply setting the width in bytes and letting the decoder do the rest + filesDatabase[fileIndex].width += 2; + } - uint8 *ptr5 = ptr3 + localBuffer.offset + numIdx * 16; - memcpy(filesDatabase[fileIndex].subData.ptr, ptr5, resourceSize); + uint8 *ptr5 = ptr3 + localBuffer.offset + numIdx * 16; + memcpy(filesDatabase[fileIndex].subData.ptr, ptr5, resourceSize); - switch (localBuffer.type) { - case 0: { // polygon + switch (localBuffer.type) { + case 0: // polygon filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_POLY; filesDatabase[fileIndex].subData.index = currentEntryIdx; break; - } - case 1: { + + case 1: filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn * 8; filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_BGMASK; decodeGfxUnified(&filesDatabase[fileIndex], localBuffer.type); filesDatabase[fileIndex].subData.index = currentEntryIdx; filesDatabase[fileIndex].subData.transparency = 0; break; - } - case 4: { + + case 4: filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn * 2; filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_SPRITE; decodeGfxUnified(&filesDatabase[fileIndex], localBuffer.type); filesDatabase[fileIndex].subData.index = currentEntryIdx; filesDatabase[fileIndex].subData.transparency = localBuffer.transparency % 0x10; break; - } - case 5: { + + case 5: filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_SPRITE; decodeGfxUnified(&filesDatabase[fileIndex], localBuffer.type); filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn; filesDatabase[fileIndex].subData.index = currentEntryIdx; filesDatabase[fileIndex].subData.transparency = localBuffer.transparency; break; - } - case 8: { + + case 8: filesDatabase[fileIndex].subData.resourceType = OBJ_TYPE_SPRITE; filesDatabase[fileIndex].width = filesDatabase[fileIndex].widthInColumn; filesDatabase[fileIndex].subData.index = currentEntryIdx; filesDatabase[fileIndex].subData.transparency = localBuffer.transparency; break; - } - default: { + + default: warning("Unsupported gfx loading type: %d", localBuffer.type); break; - } - } + } - if (name != filesDatabase[fileIndex].subData.name) - Common::strlcpy(filesDatabase[fileIndex].subData.name, name, sizeof(filesDatabase[fileIndex].subData.name)); + if (name != filesDatabase[fileIndex].subData.name) + Common::strlcpy(filesDatabase[fileIndex].subData.name, name, sizeof(filesDatabase[fileIndex].subData.name)); - // create the mask - switch (localBuffer.type) { + // create the mask + switch (localBuffer.type) { case 1: case 4: case 5: - case 8: { - int maskX; - int maskY; - + case 8: memset(filesDatabase[fileIndex].subData.ptrMask, 0, filesDatabase[fileIndex].width / 8 * filesDatabase[fileIndex].height); - for (maskY = 0; maskY < filesDatabase[fileIndex].height; maskY++) { - for (maskX = 0; maskX < filesDatabase[fileIndex].width; maskX++) { + for (int maskY = 0; maskY < filesDatabase[fileIndex].height; maskY++) { + for (int maskX = 0; maskX < filesDatabase[fileIndex].width; maskX++) { if (*(filesDatabase[fileIndex].subData.ptr + filesDatabase[fileIndex].width * maskY + maskX) != filesDatabase[fileIndex].subData.transparency) { *(filesDatabase[fileIndex].subData.ptrMask + filesDatabase[fileIndex].width / 8 * maskY + maskX / 8) |= 0x80 >> (maskX & 7); } } } + break; + default: break; - } - default: { - } - } } // TODO: free diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index dc4303c286..3f794c4e70 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -196,13 +196,22 @@ int16 Op_Random() { int16 Op_PlayFX() { int volume = popVar(); + +#if 0 int speed = popVar(); - /*int channelNum = */popVar(); + int channelNum = popVar(); +#else + popVar(); + popVar(); +#endif + int sampleNum = popVar(); if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) { +#if 0 if (speed == -1) speed = filesDatabase[sampleNum].subData.transparency; +#endif _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr, filesDatabase[sampleNum].width, volume); @@ -213,13 +222,23 @@ int16 Op_PlayFX() { int16 Op_LoopFX() { int volume = popVar(); + +#if 0 int speed = popVar(); - /*int channelNum = */popVar(); + int channelNum = popVar(); +#else + popVar(); + popVar(); +#endif + int sampleNum = popVar(); if ((sampleNum >= 0) && (sampleNum < NUM_FILE_ENTRIES) && (filesDatabase[sampleNum].subData.ptr)) { + +#if 0 if (speed == -1) speed = filesDatabase[sampleNum].subData.transparency; +#endif _vm->sound().playSound(filesDatabase[sampleNum].subData.ptr, filesDatabase[sampleNum].width, volume); @@ -552,15 +571,13 @@ int16 Op_LoadFrame() { } int16 Op_LoadAbs() { - int slot; - char name[36] = ""; - char *ptr; int result = 0; - ptr = (char *) popPtr(); - slot = popVar(); + char *ptr = (char *) popPtr(); + int slot = popVar(); if ((slot >= 0) && (slot < NUM_FILE_ENTRIES)) { + char name[36] = ""; Common::strlcpy(name, ptr, sizeof(name)); strToUpper(name); @@ -627,7 +644,7 @@ int16 Op_FadeOut() { flip(); fadeFlag = 1; - PCFadeFlag = 1; + PCFadeFlag = true; return 0; } @@ -1082,11 +1099,6 @@ actorStruct *addAnimation(actorStruct * pHead, int overlay, int objIdx, int para pCurrent = pPrevious->next; } - if (pCurrent && (pCurrent->overlayNumber == overlay) - && (pCurrent->idx == objIdx) && (pCurrent->type == param2)) { - return NULL; - } - actorStruct *pNewElement = (actorStruct *) MemAlloc(sizeof(actorStruct)); if (!pNewElement) return NULL; @@ -1365,12 +1377,11 @@ int16 Op_RestoreSong() { } int16 Op_SongSize() { - int size, oldSize; - + int oldSize; if (_vm->sound().songLoaded()) { oldSize = _vm->sound().numOrders(); - size = popVar(); + int size = popVar(); if ((size >= 1) && (size < 128)) _vm->sound().setNumOrders(size); } else @@ -1500,8 +1511,9 @@ int16 Op_Itoa() { int nbp = popVar(); int param[160]; char txt[40]; - char format[30]; - char nbf[20]; + + for (int i = 0; i < 160; ++i) + param[i] = 0; for (int i = nbp - 1; i >= 0; i--) param[i] = popVar(); @@ -1512,6 +1524,8 @@ int16 Op_Itoa() { if (!nbp) sprintf(txt, "%d", val); else { + char format[30]; + char nbf[20]; strcpy(format, "%"); sprintf(nbf, "%d", param[0]); strcat(format, nbf); @@ -1597,7 +1611,7 @@ int16 Op_GetNodeX() { int result = getNode(nodeInfo, node); - ASSERT(result == 0); + assert(result == 0); return nodeInfo[0]; } @@ -1609,7 +1623,7 @@ int16 Op_GetNodeY() { int result = getNode(nodeInfo, node); - ASSERT(result == 0); + assert(result == 0); return nodeInfo[1]; } @@ -1818,7 +1832,7 @@ int16 Op_ThemeReset() { } int16 Op_UserWait() { - userWait = 1; + userWait = true; if (currentScriptPtr->type == scriptType_PROC) { changeScriptParamInList(currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber, &procHead, -1, 9999); } else if (currentScriptPtr->type == scriptType_REL) { diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp index e3e7a2d510..9fd94d7ea6 100644 --- a/engines/cruise/gfxModule.cpp +++ b/engines/cruise/gfxModule.cpp @@ -121,12 +121,10 @@ void gfxModuleData_setPalColor(int idx, int r, int g, int b) { } void gfxModuleData_setPalEntries(const byte *ptr, int start, int num) { - int R, G, B, i; - - for (i = start; i < start + num; i++) { - R = *(ptr++); - G = *(ptr++); - B = *(ptr++); + for (int i = start; i < start + num; i++) { + int R = *(ptr++); + int G = *(ptr++); + int B = *(ptr++); lpalette[i].R = R; lpalette[i].G = G; @@ -339,7 +337,6 @@ void resetBitmap(uint8 *dataPtr, int32 dataSize) { */ void switchBackground(const byte *newBg) { const byte *bg = gfxModuleData.pPage00; - int sliceXStart, sliceXEnd; // If both the upper corners are different, presume it's a full screen change if ((*newBg != *bg) && (*(newBg + 319) != *(bg + 319))) { @@ -352,7 +349,8 @@ void switchBackground(const byte *newBg) { */ for (int yp = 0; yp < 200; ++yp) { - sliceXStart = -1; sliceXEnd = -1; + int sliceXStart = -1; + int sliceXEnd = -1; for (int xp = 0; xp < 320; ++xp, ++bg, ++newBg) { if (*bg != *newBg) { if (sliceXStart == -1) { diff --git a/engines/cruise/linker.cpp b/engines/cruise/linker.cpp index 7768e05585..9786de775f 100644 --- a/engines/cruise/linker.cpp +++ b/engines/cruise/linker.cpp @@ -129,8 +129,6 @@ int updateScriptImport(int ovlIdx) { // do it for the 2 first string types do { - int i = 0; - if (param == 0) { var_32 = numData3; } else { @@ -138,16 +136,16 @@ int updateScriptImport(int ovlIdx) { } if (var_32) { + int i = 0; do { importScriptStruct *ptrImportData; const char *ptrImportName; uint8 *ptrData; - if (param == 0) { + if (param == 0) pScript = getOvlData3Entry(ovlIdx, i); - } else { + else pScript = scriptFunc1Sub2(ovlIdx, i); - } ptrImportData = (importScriptStruct *)(pScript->dataPtr + pScript->offsetToImportData); // import data ptrImportName = (const char*)(pScript->dataPtr + pScript->offsetToImportName); // import name diff --git a/engines/cruise/mainDraw.cpp b/engines/cruise/mainDraw.cpp index 0e39740822..5777b846b4 100644 --- a/engines/cruise/mainDraw.cpp +++ b/engines/cruise/mainDraw.cpp @@ -120,7 +120,7 @@ void fadeIn() { gfxModuleData_setPal256(workpal); fadeFlag = 0; - PCFadeFlag = 0; + PCFadeFlag = false; } void flipScreen() { @@ -479,10 +479,7 @@ void buildSegment() { // swap again ? SWAP(X1, X2); - int patchAdd = 2; - int dy = Y2 - Y1; - if (dy == 0) { // hline int16* ptr = (Y1 - ydep) * 2 + XMIN_XMAX + 1; @@ -503,6 +500,8 @@ void buildSegment() { ptr[1] = SI; } } else { + int patchAdd = 2; + if (dy < 0) { dy = -dy; patchAdd = -2; @@ -721,7 +720,6 @@ void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char * int startX = 0; // first X in model int startY = 0; // first Y in model int x = 0; // current X - int y = 0; // current Y int offsetXinModel = 0; // offset of the X value in the model int offsetYinModel = 0; // offset of the Y value in the model unsigned char *dataPointer = (unsigned char *)dataPtr; @@ -761,9 +759,8 @@ void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char * startY >>= 1; } - if (m_flipLeftRight) { + if (m_flipLeftRight) startX = -startX; - } /* * NOTE: @@ -796,7 +793,7 @@ void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char * ptrPoly_1_Buf++; offsetXinModel = x; - y = *(dataPointer) - m_first_Y; + int y = *(dataPointer) - m_first_Y; dataPointer++; if (m_useSmallScale) { y >>= 1; @@ -881,7 +878,6 @@ bool findPoly(char* dataPtr, int positionX, int positionY, int scale, int mouseX int startX = 0; // first X in model int startY = 0; // first Y in model int x = 0; // current X - int y = 0; // current Y int offsetXinModel = 0; // offset of the X value in the model int offsetYinModel = 0; // offset of the Y value in the model unsigned char *dataPointer = (unsigned char *)dataPtr; @@ -955,11 +951,11 @@ bool findPoly(char* dataPtr, int positionX, int positionY, int scale, int mouseX ptrPoly_1_Buf++; offsetXinModel = x; - y = *(dataPointer) - m_first_Y; + int y = *(dataPointer) - m_first_Y; dataPointer++; - if (m_useSmallScale) { + if (m_useSmallScale) y >>= 1; - } + ptrPoly_1_Buf[0] = -(offsetYinModel - y); ptrPoly_1_Buf++; offsetYinModel = y; @@ -1150,10 +1146,6 @@ void drawMessage(const gfxEntryStruct *pGfxPtr, int globalX, int globalY, int wi // this is used for font only if (pGfxPtr) { - uint8 *initialOuput; - uint8 *output; - int xp, yp; - int x, y; const uint8 *ptr = pGfxPtr->imagePtr; int height = pGfxPtr->height; @@ -1172,14 +1164,14 @@ void drawMessage(const gfxEntryStruct *pGfxPtr, int globalX, int globalY, int wi gfxModuleData_addDirtyRect(Common::Rect(globalX, globalY, globalX + width, globalY + height)); - initialOuput = ouputPtr + (globalY * 320) + globalX; + uint8 *initialOuput = ouputPtr + (globalY * 320) + globalX; - for (yp = 0; yp < height; yp++) { - output = initialOuput + 320 * yp; - y = globalY + yp; + for (int yp = 0; yp < height; yp++) { + uint8 *output = initialOuput + 320 * yp; + int y = globalY + yp; - for (xp = 0; xp < pGfxPtr->width; xp++) { - x = globalX + xp; + for (int xp = 0; xp < pGfxPtr->width; xp++) { + int x = globalX + xp; uint8 color = *(ptr++); if (color) { @@ -1385,7 +1377,7 @@ int getValueFromObjectQuerry(objectParamsQuery *params, int idx) { return 0; } -void mainDraw(int16 param) { +void mainDraw(bool waitFl) { uint8 *bgPtr; cellStruct *currentObjPtr; int16 currentObjIdx; @@ -1469,7 +1461,7 @@ void mainDraw(int16 param) { } // automatic animation process - if (currentObjPtr->animStep && !param) { + if (currentObjPtr->animStep && !waitFl) { if (currentObjPtr->animCounter <= 0) { bool change = true; diff --git a/engines/cruise/mainDraw.h b/engines/cruise/mainDraw.h index bb71b9759b..1af403fca5 100644 --- a/engines/cruise/mainDraw.h +++ b/engines/cruise/mainDraw.h @@ -33,7 +33,7 @@ extern int m_color; int upscaleValue(int value, int scale); void pixel(int x, int y, char color); -void mainDraw(int16 param); +void mainDraw(bool waitFl); void flipScreen(); void buildPolyModel(int X, int Y, int scale, char *ptr2, char *destBuffer, char *dataPtr); void drawSprite(int width, int height, cellStruct *currentObjPtr, const uint8 *dataIn, int ys, int xs, uint8 *output, const uint8 *dataBuf); diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp index 8f162ee1ad..cf0b872646 100644 --- a/engines/cruise/menu.cpp +++ b/engines/cruise/menu.cpp @@ -39,7 +39,7 @@ menuStruct *createMenu(int X, int Y, const char *menuName) { menuStruct *entry; entry = (menuStruct *) MemAlloc(sizeof(menuStruct)); - ASSERT(entry); + assert(entry); entry->x = X - 160 / 2; entry->y = Y; @@ -69,7 +69,7 @@ void addSelectableMenuEntry(int ovlIdx, int headerIdx, menuStruct *pMenu, int pa if (!strcmp(var_6->string, menuText)) { pNewElement = var_6; pSubStruct = (menuElementSubStruct *)allocAndZero(sizeof(menuElementSubStruct)); - ASSERT(pSubStruct); + assert(pSubStruct); pSubStruct->pNext = NULL; pSubStruct->ovlIdx = ovlIdx; @@ -99,9 +99,9 @@ void addSelectableMenuEntry(int ovlIdx, int headerIdx, menuStruct *pMenu, int pa } pNewElement = (menuElementStruct *)allocAndZero(sizeof(menuElementStruct)); - ASSERT(pNewElement); + assert(pNewElement); pSubStruct = (menuElementSubStruct *)allocAndZero(sizeof(menuElementSubStruct)); - ASSERT(pSubStruct); + assert(pSubStruct); pNewElement->string = menuText; pNewElement->next = NULL; @@ -160,7 +160,7 @@ int processMenu(menuStruct *pMenu) { int si; currentActiveMenu = 0; - mainDraw(1); + mainDraw(true); flipScreen(); di = 0; @@ -179,7 +179,7 @@ int processMenu(menuStruct *pMenu) { di = 1; } - mainDraw(1); + mainDraw(true); flipScreen(); manageEvents(); @@ -190,7 +190,7 @@ int processMenu(menuStruct *pMenu) { currentActiveMenu = -1; - mainDraw(1); + mainDraw(true); flipScreen(); if (mouseButton & 1) { @@ -233,7 +233,6 @@ static void handleSaveLoad(bool saveFlag) { } int playerMenu(int menuX, int menuY) { - int retourMenu; //int restartGame = 0; if (playerMenuEnabled && displayOn) { @@ -267,7 +266,7 @@ int playerMenu(int menuX, int menuY) { freeDisk(); menuTable[0] = createMenu(menuX, menuY, _vm->langString(ID_PLAYER_MENU)); - ASSERT(menuTable[0]); + assert(menuTable[0]); //addSelectableMenuEntry(0, 3, menuTable[0], 1, -1, "Save game disk"); if (userEnabled) { @@ -277,7 +276,7 @@ int playerMenu(int menuX, int menuY) { addSelectableMenuEntry(0, 6, menuTable[0], 1, -1, _vm->langString(ID_RESTART)); addSelectableMenuEntry(0, 7, menuTable[0], 1, -1, _vm->langString(ID_QUIT)); - retourMenu = processMenu(menuTable[0]); + int retourMenu = processMenu(menuTable[0]); freeMenu(menuTable[0]); menuTable[0] = NULL; diff --git a/engines/cruise/object.cpp b/engines/cruise/object.cpp index 3e61ff4d7d..845fc34d1f 100644 --- a/engines/cruise/object.cpp +++ b/engines/cruise/object.cpp @@ -116,14 +116,10 @@ int16 getMultipleObjectParam(int16 overlayIdx, int16 objectIdx, objectParamsQuer } void setObjectPosition(int16 ovlIdx, int16 objIdx, int16 param3, int16 param4) { - objDataStruct *ptr; - objectParams *ptr2; - - ptr = getObjectDataFromOverlay(ovlIdx, objIdx); - - if (!ptr) { + objDataStruct *ptr = getObjectDataFromOverlay(ovlIdx, objIdx); + if (!ptr) return; - } + //overlayTable[param1].ovlData switch (ptr->_class) { @@ -138,7 +134,7 @@ void setObjectPosition(int16 ovlIdx, int16 objIdx, int16 param3, int16 param4) { case UNIQUE: return; case VARIABLE: { - ptr2 = &overlayTable[ovlIdx].ovlData->arrayObjVar[ptr->_varTableIdx]; + objectParams *ptr2 = &overlayTable[ovlIdx].ovlData->arrayObjVar[ptr->_varTableIdx]; switch (param3) { case 0: { // x @@ -167,14 +163,14 @@ void setObjectPosition(int16 ovlIdx, int16 objIdx, int16 param3, int16 param4) { break; } default: { - ASSERT(0); + assert(0); } } break; } default: { - ASSERT(0); + assert(0); } } } diff --git a/engines/cruise/overlay.cpp b/engines/cruise/overlay.cpp index 386a11f7ef..f7df741892 100644 --- a/engines/cruise/overlay.cpp +++ b/engines/cruise/overlay.cpp @@ -295,7 +295,7 @@ int loadOverlay(const char *scriptName) { } if (ovlData->numMsgRelHeader) { // link data - ASSERT(sizeof(linkDataStruct) == 0x22); + assert(sizeof(linkDataStruct) == 0x22); ovlData->arrayMsgRelHeader = (linkDataStruct *) mallocAndZero(ovlData->numMsgRelHeader * sizeof(linkDataStruct)); @@ -626,7 +626,7 @@ int loadOverlay(const char *scriptName) { sprintf(nameBundle, "%s-objs.txt", scriptName); fHandle = fopen(nameBundle, "w+"); - ASSERT(fHandle); + assert(fHandle); for (int i = 0; i < ovlData->numMsgRelHeader; i++) { linkDataStruct *var_34; diff --git a/engines/cruise/perso.cpp b/engines/cruise/perso.cpp index 3a599bca22..ff33eca14b 100644 --- a/engines/cruise/perso.cpp +++ b/engines/cruise/perso.cpp @@ -172,23 +172,20 @@ void processActorWalk(MovementEntry &resx_y, int16 *inc_droite, int16 *inc_droit int16 *inc_chemin, point* cor_joueur, int16 solution0[NUM_NODES + 3][2], int16 *inc_jo1, int16 *inc_jo2, int16 *dir_perso, int16 *inc_jo0, int16 num) { - int x1, x2, y1, y2; - int i, u; - - u = 0; + int u = 0; inc_jo = *inc_jo0; - i = *inc_chemin; + int i = *inc_chemin; if (!*inc_droite) { - x1 = solution0[i][0]; - y1 = solution0[i][1]; + int x1 = solution0[i][0]; + int y1 = solution0[i][1]; i++; if (solution0[i][0] != -1) { do { if (solution0[i][0] != -2) { - x2 = solution0[i][0]; - y2 = solution0[i][1]; + int x2 = solution0[i][0]; + int y2 = solution0[i][1]; if ((x1 == x2) && (y1 == y2)) { resx_y.x = -1; resx_y.y = -1; @@ -240,7 +237,7 @@ void processActorWalk(MovementEntry &resx_y, int16 *inc_droite, int16 *inc_droit void affiche_chemin(int16 persoIdx, MovementEntry &data) { persoStruct *pPerso = persoTable[persoIdx]; - ASSERT(pPerso); + assert(pPerso); processActorWalk(data, &pPerso->inc_droite, &pPerso->inc_droite0, &pPerso->inc_chemin, pPerso->coordinates, pPerso->solution, diff --git a/engines/cruise/polys.cpp b/engines/cruise/polys.cpp index 415f0520a6..f6d0691c69 100644 --- a/engines/cruise/polys.cpp +++ b/engines/cruise/polys.cpp @@ -211,20 +211,15 @@ void fillpoly(int16 *point_data, int lineCount, ColorP color) { } // Reinit array counters - - int x1, y1, x2, y2; - int y, i; - - for (i = 0; i < SCREENHEIGHT; i++) { + for (int i = 0; i < SCREENHEIGHT; i++) { num_intersect[i] = 0; } // Find the top/bottom of the polygon. - int top = point_data[1]; int bottom = point_data[1]; - for (i = 1; i < lineCount; i++) { + for (int i = 1; i < lineCount; i++) { if (point_data[2 * i + 1] < top) top = point_data[2 * i + 1]; else if (point_data[2 * i + 1] > bottom) @@ -237,14 +232,13 @@ void fillpoly(int16 *point_data, int lineCount, ColorP color) { bottom = SCREENHEIGHT - 1; // Calculate intersections for each scan line + for (int y = top; y <= bottom; y++) { + int x2 = point_data[2 * lineCount - 2]; + int y2 = point_data[2 * lineCount - 1]; - for (y = top; y <= bottom; y++) { - x2 = point_data[2 * lineCount - 2]; - y2 = point_data[2 * lineCount - 1]; - - for (i = 0; i < lineCount; i++) { - x1 = x2; - y1 = y2; + for (int i = 0; i < lineCount; i++) { + int x1 = x2; + int y1 = y2; x2 = point_data[2 * i]; y2 = point_data[2 * i + 1]; @@ -264,9 +258,8 @@ void fillpoly(int16 *point_data, int lineCount, ColorP color) { } // Drawing. - - for (y = top; y <= bottom; y++) { - for (i = 0; i < num_intersect[y]; i += 2) { + for (int y = top; y <= bottom; y++) { + for (int i = 0; i < num_intersect[y]; i += 2) { hline(intersect[y][i], intersect[y][i + 1], y, color); } } diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index 0f496465e9..a62648df08 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -284,7 +284,7 @@ static void syncOverlays2(Common::Serializer &s) { if (ovlRestoreData[i]._sBssSize) { ovlRestoreData[i]._pBss = (uint8 *) mallocAndZero(ovlRestoreData[i]._sBssSize); - ASSERT(ovlRestoreData[i]._pBss); + assert(ovlRestoreData[i]._pBss); s.syncBytes(ovlRestoreData[i]._pBss, ovlRestoreData[i]._sBssSize); } @@ -293,7 +293,7 @@ static void syncOverlays2(Common::Serializer &s) { if (ovlRestoreData[i]._sNumObj) { ovlRestoreData[i]._pObj = (objectParams *) mallocAndZero(ovlRestoreData[i]._sNumObj * sizeof(objectParams)); - ASSERT(ovlRestoreData[i]._pObj); + assert(ovlRestoreData[i]._pObj); for (int j = 0; j < ovlRestoreData[i]._sNumObj; j++) { s.syncAsSint16LE(ovlRestoreData[i]._pObj[j].X); @@ -735,7 +735,7 @@ void initVars() { resetBackgroundIncrustList(&backgroundIncrustHead); vblLimit = 0; - remdo = 0; + remdo = false; songLoaded = 0; songPlayed = 0; songLoop = 1; @@ -777,7 +777,7 @@ void initVars() { buttonDown = 0; var41 = 0; playerMenuEnabled = 0; - PCFadeFlag = 0; + PCFadeFlag = false; } Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName) { @@ -915,17 +915,14 @@ Common::Error loadSavegameData(int saveGameIdx) { while (currentcellHead) { if (currentcellHead->type == 5) { + assert(0); +#if 0 uint8 *ptr = mainProc14(currentcellHead->overlay, currentcellHead->idx); - - ASSERT(0); - - if (ptr) { - ASSERT(0); - //*(int16 *)(currentcellHead->datas+0x2E) = getSprite(ptr,*(int16 *)(currentcellHead->datas+0xE)); - } else { - ASSERT(0); - //*(int16 *)(currentcellHead->datas+0x2E) = 0; - } + if (ptr) + *(int16 *)(currentcellHead->datas+0x2E) = getSprite(ptr,*(int16 *)(currentcellHead->datas+0xE)); + else + *(int16 *)(currentcellHead->datas+0x2E) = 0; +#endif } currentcellHead = currentcellHead->next; @@ -950,7 +947,7 @@ Common::Error loadSavegameData(int saveGameIdx) { // to finish changeCursor(CURSOR_NORMAL); - mainDraw(1); + mainDraw(true); flipScreen(); return Common::kNoError; diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp index 5403c5da59..1f308714f7 100644 --- a/engines/cruise/script.cpp +++ b/engines/cruise/script.cpp @@ -51,12 +51,13 @@ int32 opcodeType0() { int index = 0; switch (currentScriptOpcodeType) { - case 0: { + case 0: pushVar(getShortFromScript()); return (0); - } + case 5: index = saveOpcodeVar; + // No break on purpose case 1: { uint8 *address = 0; int type = getByteFromScript(); @@ -131,12 +132,12 @@ int32 opcodeType1() { int offset = 0; switch (currentScriptOpcodeType) { - case 0: { + case 0: return (0); // strange, but happens also in original interpreter - } - case 5: { + + case 5: offset = saveOpcodeVar; - } + //no break on purpose case 1: { int var_A = 0; @@ -169,7 +170,7 @@ int32 opcodeType1() { if (var_6 == 5) { ptr = overlayTable[byte2].ovlData->data4Ptr + var_C; } else { - ASSERT(0); + assert(0); } } else { ptr = scriptDataPtrTable[var_6] + var_C; @@ -226,6 +227,7 @@ int32 opcodeType2() { switch (currentScriptOpcodeType) { case 5: index = saveOpcodeVar; + // No break on purpose case 1: { uint8* adresse = NULL; int type = getByteFromScript(); @@ -247,7 +249,7 @@ int32 opcodeType2() { if (!overlayTable[overlay].ovlData) { return (-4); } - ASSERT(0); + assert(0); } adresse += offset; @@ -261,6 +263,7 @@ int32 opcodeType2() { } } + break; } return 0; @@ -281,39 +284,37 @@ int32 opcodeType4() { // test int var2 = popVar(); switch (currentScriptOpcodeType) { - case 0: { + case 0: if (var2 != var1) boolVar = 1; break; - } - case 1: { + + case 1: if (var2 == var1) boolVar = 1; break; - } - case 2: { + + case 2: if (var2 < var1) boolVar = 1; break; - } - case 3: { + + case 3: if (var2 <= var1) boolVar = 1; break; - } - case 4: { + + case 4: if (var2 > var1) boolVar = 1; break; - } - case 5: { + + case 5: if (var2 >= var1) boolVar = 1; break; } - } - pushVar(boolVar); return (0); @@ -327,13 +328,11 @@ int32 opcodeType6() { if (!pop) si = 1; - if (pop < 0) { + if (pop < 0) si |= 4; - } - if (pop > 0) { + if (pop > 0) si |= 2; - } currentScriptPtr->ccr = si; @@ -357,50 +356,49 @@ int32 opcodeType5() { int bitMask = currentScriptPtr->ccr; switch (currentScriptOpcodeType) { - case 0: { - if (!(bitMask & 1)) { + case 0: + if (!(bitMask & 1)) currentScriptPtr->scriptOffset = newSi; - } + break; - } - case 1: { - if (bitMask & 1) { + + case 1: + if (bitMask & 1) currentScriptPtr->scriptOffset = newSi; - } + break; - } - case 2: { - if (bitMask & 2) { + + case 2: + if (bitMask & 2) currentScriptPtr->scriptOffset = newSi; - } + break; - } - case 3: { - if (bitMask & 3) { + + case 3: + if (bitMask & 3) currentScriptPtr->scriptOffset = newSi; - } + break; - } - case 4: { - if (bitMask & 4) { + + case 4: + if (bitMask & 4) currentScriptPtr->scriptOffset = newSi; - } + break; - } - case 5: { - if (bitMask & 5) { + + case 5: + if (bitMask & 5) currentScriptPtr->scriptOffset = newSi; - } + break; - } - case 6: { + + case 6: break; // never - } - case 7: { + + case 7: currentScriptPtr->scriptOffset = newSi; //always break; } - } return (0); } @@ -410,39 +408,39 @@ int32 opcodeType3() { // math int pop2 = popVar(); switch (currentScriptOpcodeType) { - case 0: { + case 0: pushVar(pop1 + pop2); return (0); - } - case 1: { + + case 1: if (pop2 == 0) error("opcodeType3 - Invalid value for pop2"); pushVar(pop1 / pop2); return (0); - } - case 2: { + + case 2: pushVar(pop1 - pop2); return (0); - } - case 3: { + + case 3: pushVar(pop1 * pop2); return (0); - } - case 4: { + + case 4: if (pop2 == 0) error("opcodeType3 - Invalid value for pop2"); pushVar(pop1 % pop2); return (0); - } + case 7: - case 5: { + case 5: pushVar(pop2 | pop1); return (0); - } - case 6: { + + case 6: pushVar(pop2 & pop1); return (0); - } + } return 0; @@ -455,9 +453,8 @@ int32 opcodeType9() { // stop script } void setupFuncArray() { - for (int i = 0; i < 64; i++) { + for (int i = 0; i < 64; i++) opcodeTypeTable[i] = NULL; - } opcodeTypeTable[1] = opcodeType0; opcodeTypeTable[2] = opcodeType1; @@ -474,19 +471,13 @@ void setupFuncArray() { } int removeScript(int overlay, int idx, scriptInstanceStruct *headPtr) { - scriptInstanceStruct *scriptPtr; - - scriptPtr = headPtr->nextScriptPtr; + scriptInstanceStruct *scriptPtr = headPtr->nextScriptPtr; - if (scriptPtr) { - do { - if (scriptPtr->overlayNumber == overlay - && (scriptPtr->scriptNumber == idx || idx == -1)) { - scriptPtr->scriptNumber = -1; - } + while (scriptPtr) { + if (scriptPtr->overlayNumber == overlay && (scriptPtr->scriptNumber == idx || idx == -1)) + scriptPtr->scriptNumber = -1; - scriptPtr = scriptPtr->nextScriptPtr; - } while (scriptPtr); + scriptPtr = scriptPtr->nextScriptPtr; } return (0); @@ -495,77 +486,61 @@ int removeScript(int overlay, int idx, scriptInstanceStruct *headPtr) { uint8 *attacheNewScriptToTail(scriptInstanceStruct *scriptHandlePtr, int16 overlayNumber, int16 param, int16 arg0, int16 arg1, int16 arg2, scriptTypeEnum scriptType) { int useArg3Neg = 0; ovlData3Struct *data3Ptr; - scriptInstanceStruct *tempPtr; int var_C; scriptInstanceStruct *oldTail; - //debug("Starting script %d of overlay %s", param,overlayTable[overlayNumber].overlayName); - if (scriptType < 0) { useArg3Neg = 1; - scriptType = (scriptTypeEnum) - scriptType; + scriptType = (scriptTypeEnum) -scriptType; } - if (scriptType == 20) { + if (scriptType == 20) data3Ptr = getOvlData3Entry(overlayNumber, param); - } else { - if (scriptType == 30) { - data3Ptr = scriptFunc1Sub2(overlayNumber, param); - } else { - return (NULL); - } - } + else if (scriptType == 30) + data3Ptr = scriptFunc1Sub2(overlayNumber, param); + else + return (NULL); - if (!data3Ptr) { + if (!data3Ptr) return (NULL); - } - if (!data3Ptr->dataPtr) { + if (!data3Ptr->dataPtr) return (NULL); - } var_C = data3Ptr->sysKey; - oldTail = scriptHandlePtr; - while (oldTail->nextScriptPtr) { // go to the end of the list + while (oldTail->nextScriptPtr) // go to the end of the list oldTail = oldTail->nextScriptPtr; - } - tempPtr = - (scriptInstanceStruct *) - mallocAndZero(sizeof(scriptInstanceStruct)); + scriptInstanceStruct *tempPtr = (scriptInstanceStruct *)mallocAndZero(sizeof(scriptInstanceStruct)); if (!tempPtr) return (NULL); tempPtr->data = NULL; - if (var_C) { + if (var_C) tempPtr->data = (uint8 *) mallocAndZero(var_C); - } tempPtr->dataSize = var_C; tempPtr->nextScriptPtr = NULL; tempPtr->scriptOffset = 0; - tempPtr->scriptNumber = param; tempPtr->overlayNumber = overlayNumber; - if (scriptType == 20) { // Obj or not ? + if (scriptType == 20) // Obj or not ? tempPtr->sysKey = useArg3Neg; - } else { + else tempPtr->sysKey = 1; - } tempPtr->freeze = 0; tempPtr->type = scriptType; tempPtr->var18 = arg2; tempPtr->var16 = arg1; tempPtr->var1A = arg0; - tempPtr->nextScriptPtr = oldTail->nextScriptPtr; // should always be NULL as it's the tail - - oldTail->nextScriptPtr = tempPtr; // attache the new node to the list + tempPtr->nextScriptPtr = oldTail->nextScriptPtr; // should always be NULL as it's the tail + oldTail->nextScriptPtr = tempPtr; // attach the new node to the list return (tempPtr->data); } @@ -578,27 +553,18 @@ int executeScripts(scriptInstanceStruct *ptr) { numScript2 = ptr->scriptNumber; - if (ptr->type == 20) { + if (ptr->type == 20) ptr2 = getOvlData3Entry(ptr->overlayNumber, numScript2); + else if (ptr->type == 30) + ptr2 = scriptFunc1Sub2(ptr->overlayNumber, numScript2); + else + return (-6); - if (!ptr2) { - return (-4); - } - } else { - if (ptr->type == 30) { - ptr2 = scriptFunc1Sub2(ptr->overlayNumber, numScript2); - - if (!ptr2) { - return (-4); - } - } else { - return (-6); - } - } + if (!ptr2) + return (-4); - if (!overlayTable[ptr->overlayNumber].alreadyLoaded) { + if (!overlayTable[ptr->overlayNumber].alreadyLoaded) return (-7); - } ovlData = overlayTable[ptr->overlayNumber].ovlData; @@ -606,14 +572,11 @@ int executeScripts(scriptInstanceStruct *ptr) { return (-4); currentData3DataPtr = ptr2->dataPtr; - scriptDataPtrTable[1] = (uint8 *) ptr->data; scriptDataPtrTable[2] = getDataFromData3(ptr2, 1); scriptDataPtrTable[5] = ovlData->data4Ptr; // free strings scriptDataPtrTable[6] = ovlData->ptr8; - currentScriptPtr = ptr; - positionInStack = 0; do { @@ -647,21 +610,15 @@ int executeScripts(scriptInstanceStruct *ptr) { void manageScripts(scriptInstanceStruct *scriptHandle) { scriptInstanceStruct *ptr = scriptHandle; - if (ptr) { - do { - if (!overlayTable[ptr->overlayNumber].executeScripts) { - if ((ptr->scriptNumber != -1) && (ptr->freeze == 0) && (ptr->sysKey != 0)) { - executeScripts(ptr); - } - - if (ptr->sysKey == 0) { - ptr->sysKey = 1; - } - } - - ptr = ptr->nextScriptPtr; + while (ptr) { + if (!overlayTable[ptr->overlayNumber].executeScripts) { + if ((ptr->scriptNumber != -1) && (ptr->freeze == 0) && (ptr->sysKey != 0)) + executeScripts(ptr); - } while (ptr); + if (ptr->sysKey == 0) + ptr->sysKey = 1; + } + ptr = ptr->nextScriptPtr; } } diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp index cef67385f9..0b0fab8c4a 100644 --- a/engines/cruise/sound.cpp +++ b/engines/cruise/sound.cpp @@ -342,9 +342,7 @@ void AdLibSoundDriver::adjustVolume(int channel, int volume) { volume = 0; } volume += volume / 4; - if (volume > 127) { - volume = 127; - } + // The higher possible value for volume is 100 int volAdjust = (channel == 4) ? _sfxVolume : _musicVolume; volume = (volume * volAdjust) / 128; @@ -609,6 +607,13 @@ PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver) _sfxData = NULL; _fadeOutCounter = 0; _driver->setUpdateCallback(updateCallback, this); + + _currentPos = 0; + _currentOrder = 0; + _numOrders = 0; + _eventsDelay = 0; + _looping = false; + _updateTicksCounter = 0; } PCSoundFxPlayer::~PCSoundFxPlayer() { @@ -794,6 +799,7 @@ PCSound::PCSound(Audio::Mixer *mixer, CruiseEngine *vm) { _mixer = mixer; _soundDriver = new AdLibSoundDriverADL(_mixer); _player = new PCSoundFxPlayer(_soundDriver); + _genVolume = 0; } PCSound::~PCSound() { diff --git a/engines/cruise/stack.cpp b/engines/cruise/stack.cpp index e4ecf72133..52a7a84814 100644 --- a/engines/cruise/stack.cpp +++ b/engines/cruise/stack.cpp @@ -44,7 +44,7 @@ int16 popVar() { positionInStack--; - ASSERT(scriptStack[positionInStack].type == STACK_SHORT); + assert(scriptStack[positionInStack].type == STACK_SHORT); return (scriptStack[positionInStack].data.shortVar); } @@ -66,7 +66,7 @@ void *popPtr() { positionInStack--; - ASSERT(scriptStack[positionInStack].type == STACK_PTR); + assert(scriptStack[positionInStack].type == STACK_PTR); return (scriptStack[positionInStack].data.ptrVar); } diff --git a/engines/cruise/various.cpp b/engines/cruise/various.cpp index a7d701f9a1..df09ac92c8 100644 --- a/engines/cruise/various.cpp +++ b/engines/cruise/various.cpp @@ -24,8 +24,8 @@ namespace Cruise { -uint16 remdo = 0; -uint16 PCFadeFlag; +bool remdo = false; +bool PCFadeFlag; char *getText(int textIndex, int overlayIndex) { if (!overlayTable[overlayIndex].ovlData) { diff --git a/engines/cruise/various.h b/engines/cruise/various.h index c2ff1e22bb..94fc29173a 100644 --- a/engines/cruise/various.h +++ b/engines/cruise/various.h @@ -27,8 +27,8 @@ namespace Cruise { -extern uint16 remdo; -extern uint16 PCFadeFlag; +extern bool remdo; +extern bool PCFadeFlag; int16 objInit(int ovlIdx, int param1, int param2); char *getText(int textIndex, int overlayIndex); diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp index 9a59c8a714..e9b68968ef 100644 --- a/engines/cruise/vars.cpp +++ b/engines/cruise/vars.cpp @@ -53,9 +53,7 @@ char nextOverlay[38]; int16 currentActiveMenu; int16 autoMsg; menuElementSubStruct* linkedRelation; -int16 main21; -int16 main22; -int16 userWait; +bool userWait; int16 autoTrack; int16 currentDiskNumber = 1; diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h index fe3f7d6303..e7c687d5fb 100644 --- a/engines/cruise/vars.h +++ b/engines/cruise/vars.h @@ -156,9 +156,7 @@ extern char nextOverlay[38]; extern int16 currentActiveMenu; extern int16 autoMsg; extern menuElementSubStruct* linkedRelation; -extern int16 main21; -extern int16 main22; -extern int16 userWait; +extern bool userWait; extern int16 autoTrack; extern int16 currentDiskNumber; diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp index 3f7a133d9e..99d86e48bb 100644 --- a/engines/cruise/volume.cpp +++ b/engines/cruise/volume.cpp @@ -202,24 +202,25 @@ int16 findFileInList(char *fileName) { void askDisk(int16 discNumber) { char fileName[256]; char string[256]; - char messageDrawn = 0; if (discNumber != -1) { currentDiskNumber = discNumber; } - // skip drive selection stuff sprintf(fileName, "VOL.%d", currentDiskNumber); - sprintf(string, "INSERER LE DISQUE %d EN ", currentDiskNumber); - //while (Common::File::exists((const char*)fileName)) - { +#if 0 // skip drive selection stuff + bool messageDrawn = false; + while (Common::File::exists((const char*)fileName)) { if (!messageDrawn) { drawMsgString(string); - messageDrawn = 1; + messageDrawn = true; } } +#else + drawMsgString(string); +#endif changeCursor(currentCursor); } diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 35461f1d71..797b6d94b0 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -194,6 +194,9 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam _console = 0; + const Common::FSNode gameDataDir(ConfMan.get("path")); + SearchMan.addSubDirectoryMatching(gameDataDir, "audio"); + int cd_num = ConfMan.getInt("cdrom"); if (cd_num >= 0) _system->getAudioCDManager()->openCD(cd_num); diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index 85a5167841..f79564eb27 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -34,6 +34,7 @@ #include "fullpipe/modal.h" #include "fullpipe/input.h" #include "fullpipe/motion.h" +#include "fullpipe/statics.h" #include "fullpipe/scenes.h" #include "fullpipe/floaters.h" #include "fullpipe/console.h" @@ -413,21 +414,32 @@ void FullpipeEngine::updateEvents() { } } - -#if 0 - warning("STUB: FullpipeEngine::updateEvents() <mainWindowProc>"); - if (Msg == MSG_SC11_SHOWSWING && _modalObject) { - _modalObject->method14(); - } -#endif + // pollEvent() is implemented only for video player. So skip it. + //if (event.kbd.keycode == MSG_SC11_SHOWSWING && _modalObject) { + // _modalObject->pollEvent(); + //} } void FullpipeEngine::freeGameLoader() { - warning("STUB: FullpipeEngine::freeGameLoader()"); + setCursor(0); + delete _movTable; + _floaters->stopAll(); + delete _gameLoader; + _currentScene = 0; + _scene2 = 0; + _loaderScene = 0; } void FullpipeEngine::cleanup() { - warning("STUB: FullpipeEngine::cleanup()"); + //cleanRecorder(); + clearMessageHandlers(); + clearMessages(); + _globalMessageQueueList->compact(); + + for (uint i = 0; i < _globalMessageQueueList->size(); i++) + delete (*_globalMessageQueueList)[i]; + + stopAllSoundStreams(); } void FullpipeEngine::updateScreen() { @@ -514,7 +526,7 @@ void FullpipeEngine::disableSaves(ExCommand *ex) { _isSaveAllowed = false; if (_globalMessageQueueList->size() && (*_globalMessageQueueList)[0] != 0) { - for (int i = 0; i < _globalMessageQueueList->size(); i++) { + for (uint i = 0; i < _globalMessageQueueList->size(); i++) { if ((*_globalMessageQueueList)[i]->_flags & 1) if ((*_globalMessageQueueList)[i]->_id != ex->_parId && !(*_globalMessageQueueList)[i]->_isFinished) return; diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp index c8b01939dd..fbf96b3060 100644 --- a/engines/fullpipe/gameloader.cpp +++ b/engines/fullpipe/gameloader.cpp @@ -84,7 +84,29 @@ GameLoader::~GameLoader() { delete _interactionController; delete _inputController; - warning("STUB: GameLoader::~GameLoader()"); + g_fp->_gameLoader = 0; + + for (uint i = 0; i < _sc2array.size(); i++) { + if (_sc2array[i]._defPicAniInfos) + delete _sc2array[i]._defPicAniInfos; + + if (_sc2array[i]._picAniInfos) + delete _sc2array[i]._picAniInfos; + + if (_sc2array[i]._motionController) + delete _sc2array[i]._motionController; + + if (_sc2array[i]._data1) + free(_sc2array[i]._data1); + + if (_sc2array[i]._entranceData) + free(_sc2array[i]._entranceData); + } + + delete _gameVar; + _gameVar = 0; + + _sc2array.clear(); } bool GameLoader::load(MfcArchive &file) { @@ -635,7 +657,16 @@ bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header) } void GameLoader::restoreDefPicAniInfos() { - warning("STUB: restoreDefPicAniInfos()"); + for (uint i = 0; i < _sc2array.size(); i++) { + if (_sc2array[i]._picAniInfos) { + free(_sc2array[i]._picAniInfos); + _sc2array[i]._picAniInfos = 0; + _sc2array[i]._picAniInfosCount = 0; + } + + if (_sc2array[i]._scene) + applyPicAniInfos(_sc2array[i]._scene, _sc2array[i]._defPicAniInfos, _sc2array[i]._defPicAniInfosCount); + } } GameVar *FullpipeEngine::getGameLoaderGameVar() { diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index b643ff9b8f..a7337b98ed 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -397,7 +397,7 @@ void MessageQueue::update() { void MessageQueue::messageQueueCallback1(int par) { if (g_fp->_isSaveAllowed && par == 16) { if (g_fp->_globalMessageQueueList->size() && (*g_fp->_globalMessageQueueList)[0] != 0) { - for (int i = 0; i < g_fp->_globalMessageQueueList->size(); i++) { + for (uint i = 0; i < g_fp->_globalMessageQueueList->size(); i++) { if ((*g_fp->_globalMessageQueueList)[i]->_flags & 1) if ((*g_fp->_globalMessageQueueList)[i] != this && !(*g_fp->_globalMessageQueueList)[i]->_isFinished) return; diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index 8981cdb8e6..6f99200529 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -1456,6 +1456,9 @@ ModalSaveGame::ModalSaveGame() { _cancelL = 0; _emptyD = 0; _emptyL = 0; + _fullD = 0; + _fullL = 0; + _menuScene = 0; _queryRes = -1; _rect = g_fp->_sceneRect; _queryDlg = 0; @@ -1593,7 +1596,7 @@ void ModalSaveGame::setup(Scene *sc, int mode) { fileinfo = new FileInfo; memset(fileinfo, 0, sizeof(FileInfo)); - strncpy(fileinfo->filename, getSavegameFile(i), 160); + Common::strlcpy(fileinfo->filename, getSavegameFile(i), 160); if (!getFileInfo(i, fileinfo)) { fileinfo->empty = true; diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index 4492168ddb..66d587f134 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -345,13 +345,11 @@ void MctlLadder::addObject(StaticANIObject *obj) { } int MctlLadder::findObjectPos(StaticANIObject *obj) { - int res = -1; - - for (Common::List<MctlLadderMovement *>::iterator it = _ladmovements.begin(); it != _ladmovements.end(); ++it, ++res) - if ((*it)->objId == obj->_id) - break; + for (uint i = 0; i < _ladmovements.size(); i++) + if (_ladmovements[i]->objId == obj->_id) + return i; - return res; + return -1; } bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement) { @@ -401,9 +399,9 @@ bool MctlLadder::initMovement(StaticANIObject *ani, MctlLadderMovement *movement void MctlLadder::freeItems() { _mgm.clear(); - for (Common::List<MctlLadderMovement *>::iterator it = _ladmovements.begin(); it != _ladmovements.end(); ++it) { - delete (*it)->movVars; - delete [] (*it)->staticIds; + for (uint i = 0; i < _ladmovements.size(); i++) { + delete _ladmovements[i]->movVars; + delete[] _ladmovements[i]->staticIds; } _ladmovements.clear(); @@ -421,7 +419,6 @@ MessageQueue *MctlLadder::method34(StaticANIObject *subj, int xpos, int ypos, in } MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { -#if 0 int pos = findObjectPos(ani); if (pos < 0) @@ -445,21 +442,20 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int MGMInfo mgminfo; PicAniInfo picinfo; MessageQueue *mq; + ExCommand *ex; Common::Point point; if (ani->_movement) { ani->getPicAniInfo(&picinfo); - v20 = ani->_ox; - v73 = ani->_oy; - StaticANIObject_getSomeDynamicPhaseIndex(ani); - v21 = ani->_movement->calcSomeXY(&point, 1, _someDynamicPhaseIndex); - v22 = point.x + v20; - v23 = point.y + v73; - v24 = ani->go.CObject.vmt; + int ox = ani->_ox; + int oy = ani->_oy; + + ani->_movement->calcSomeXY(point, 1, ani->_someDynamicPhaseIndex); ani->_statics = ani->_movement->_staticsObj2; ani->_movement = 0; - ani->setOXY(v22, v23); + ani->setOXY(point.x + ox, point.y + oy); + mq = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId); ani->setPicAniInfo(&picinfo); @@ -467,181 +463,154 @@ MessageQueue *MctlLadder::doWalkTo(StaticANIObject *ani, int xpos, int ypos, int return mq; } - v27 = _ladmovements.m_pData; - LOWORD(v19) = ani->_statics->_staticsId; - movidx = pos; - point.x = v19; - v29 = &v27[pos]; - stids = v27[pos].staticIds; - if ((unsigned __int16)v19 == *stids) { - memset(&mgminfo, 0, sizeof(mgminfo)); + if (ani->_statics->_staticsId == _ladmovements[pos]->staticIds[0]) { mgminfo.ani = ani; - if ((_WORD)staticsId) - mgminfo.staticsId2 = (unsigned __int16)staticsId; + + if (staticsId) + mgminfo.staticsId2 = staticsId; else - mgminfo.staticsId2 = v29->staticIds[direction]; + mgminfo.staticsId2 = _ladmovements[pos]->staticIds[direction]; + mgminfo.x1 = normx; - v31 = _ladder_field_14; mgminfo.y1 = normy; - mgminfo.field_1C = v31; + mgminfo.field_1C = _ladder_field_14; mgminfo.flags = 14; - mgminfo.movementId = *(&v29->movVars->varUpGo + direction); - return MGM_genMovement(&_mgm, &mgminfo); + mgminfo.movementId = direction ? _ladmovements[pos]->movVars->varDownGo : _ladmovements[pos]->movVars->varUpGo; + + return _mgm.genMovement(&mgminfo); } - if ((unsigned __int16)point.x == stids[2]) { + + if (ani->_statics->_staticsId == _ladmovements[pos]->staticIds[2]) { if (!direction) { - memset(&mgminfo, 0, sizeof(mgminfo)); mgminfo.ani = ani; - if ( (_WORD)staticsId ) - mgminfo.staticsId2 = (unsigned __int16)staticsId; + + if (staticsId) + mgminfo.staticsId2 = staticsId; else - mgminfo.staticsId2 = *v29->staticIds; + mgminfo.staticsId2 = _ladmovements[pos]->staticIds[0]; + mgminfo.x1 = normx; - v32 = _ladder_field_14; mgminfo.y1 = normy; - mgminfo.field_1C = v32; + mgminfo.field_1C = _ladder_field_14; mgminfo.flags = 14; - mgminfo.movementId = v29->movVars->varUpGo; - return MGM_genMovement(&_mgm, &mgminfo); - } - v33 = ani->_ox; - v73 = ani->_oy; - v34 = StaticANIObject_getMovementById(ani, LOWORD(v29->movVars->varUpStop)); - v35 = Movement_calcSomeXY(v34, &point, 0, -1); - v36 = v35->y; - v72 = v35->x + v33; - v73 += v36; - memset(&mgminfo, 0, sizeof(mgminfo)); + mgminfo.movementId = _ladmovements[pos]->movVars->varUpGo; + + return _mgm.genMovement(&mgminfo); + } + + int ox = ani->_ox; + int oy = ani->_oy; + + ani->getMovementById(_ladmovements[pos]->movVars->varUpStop)->calcSomeXY(point, 0, -1); + mgminfo.ani = ani; - if ( (_WORD)staticsId ) - mgminfo.staticsId2 = (unsigned __int16)staticsId; + + if (staticsId) + mgminfo.staticsId2 = staticsId; else - mgminfo.staticsId2 = _ladmovements.m_pData[movidx].staticIds[1]; - v37 = _ladder_field_14; - mgminfo.y1 = normy; - mgminfo.field_1C = v37; - v38 = _ladmovements.m_pData; + mgminfo.staticsId2 = _ladmovements[pos]->staticIds[1]; + + mgminfo.field_1C = _ladder_field_14; mgminfo.x1 = normx; - mgminfo.y2 = v73; - v39 = &v38[movidx]; - mgminfo.x2 = v72; - v40 = *v38[movidx].staticIds; + mgminfo.y1 = normy; + mgminfo.y2 = point.y + oy; + mgminfo.x2 = point.x + ox; mgminfo.flags = 63; - mgminfo.staticsId1 = v40; - mgminfo.movementId = v39->movVars->varDownGo; - v41 = _mgm->genMovement(&mgminfo); - v42 = (MessageQueue *)v41; - v72 = v41; - v43 = (ExCommand *)operator new(0x48u); - point.x = (LONG)v43; - v76 = 0; - if (v43) { - v44 = ExCommand_ctor(v43, ani->_id, 1, _ladmovements.m_pData[movidx].movVars->varUpStop, 0, 0, 0, 1, 0, 0, 0); - v42 = (MessageQueue *)v72; - LABEL_29: - v45 = v44->_excFlags | 2; - v44->msg._keyCode = ani->_okeyCode; - v76 = -1; - v44->_excFlags = v45; - MessageQueue_insertExCommandAt(v42, 0, v44); - return v42; - } - LABEL_28: - v44 = 0; - goto LABEL_29; - } - if ((unsigned __int16)point.x != stids[3]) { - LOWORD(stids) = *(_WORD *)v29->staticIds; - v72 = (int)MGM_genMQ(&_mgm, ani, (int)stids, 0, 0, 0); - if (v72) { - v58 = ani->_statics; - v59 = ani->_ox; - point.y = ani->_oy; - v60 = _ladmovements.m_pData; - LOWORD(v58) = v58->_staticsId; - point.x = v59; - v61 = MGM_getPoint(&_mgm, &point1, ani->_id, (__int16)v58, *(_WORD *)v60[movidx].staticIds); - v62 = v61->y; - point.x += v61->x; - point.y += v62; - GameObject_getPicAniInfo(ani, &picinfo); - v63 = StaticANIObject_getStaticsById(ani, (Objects)*(_WORD *)_ladmovements.m_pData[movidx].staticIds); - v64 = point.x; - v65 = ani->go.CObject.vmt; - ani->_statics = v63; - v66 = point.y; - ani->_movement = 0; - ani->sotOXY(v64, v66); - v67 = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId); - v68 = v72; - v69 = v67; - MessageQueue_transferExCommands((MessageQueue *)v72, v67); - if ( v69 ) - (*(void (__thiscall **)(MessageQueue *, signed int))(v69->CObject.vmt + 4))(v69, 1); - GameObject_setPicAniInfo(ani, &picinfo); - return (MessageQueue *)v68; - } - return 0; + mgminfo.staticsId1 = _ladmovements[pos]->staticIds[0]; + mgminfo.movementId = _ladmovements[pos]->movVars->varDownGo; + + mq = _mgm.genMovement(&mgminfo); + + ex = new ExCommand(ani->_id, 1, _ladmovements[pos]->movVars->varUpStop, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_excFlags |= 2; + + mq->insertExCommandAt(0, ex); + + return mq; + } + + if (ani->_statics->_staticsId != _ladmovements[pos]->staticIds[3]) { + mq = _mgm.genMQ(ani, _ladmovements[pos]->staticIds[0], 0, 0, 0); + + if (!mq) + return 0; + + int nx = ani->_ox; + int ny = ani->_oy; + + _mgm.getPoint(&point, ani->_id, ani->_statics->_staticsId, _ladmovements[pos]->staticIds[0]); + + nx += point.x; + ny += point.y; + + ani->getPicAniInfo(&picinfo); + + ani->_statics = ani->getStaticsById(_ladmovements[pos]->staticIds[0]); + ani->_movement = 0; + ani->setOXY(nx, ny); + + MessageQueue *newmq = doWalkTo(ani, normx, normy, fuzzyMatch, staticsId); + + mq->transferExCommands(newmq); + + delete newmq; + + ani->setPicAniInfo(&picinfo); + + return mq; } if (!direction) { - v46 = v29->movVars; - v47 = ani->_ox; - v73 = ani->_oy; - v48 = StaticANIObject_getMovementById(ani, LOWORD(v46->varDownStop)); - v49 = Movement_calcSomeXY(v48, &point, 0, -1); - v50 = v49->y; - v72 = v49->x + v47; - v73 += v50; - memset(&mgminfo, 0, sizeof(mgminfo)); + int nx = ani->_ox; + int ny = ani->_oy; + + ani->getMovementById(_ladmovements[pos]->movVars->varDownStop)->calcSomeXY(point, 0, -1); + + nx += point.x; + ny += point.y; + mgminfo.ani = ani; - if ((_WORD)staticsId) - mgminfo.staticsId2 = (unsigned __int16)staticsId; + if (staticsId) + mgminfo.staticsId2 = staticsId; else - mgminfo.staticsId2 = *_ladmovements.m_pData[movidx].staticIds; - v51 = _ladder_field_14; - mgminfo.y1 = normy; - mgminfo.field_1C = v51; - v52 = _ladmovements.m_pData; + mgminfo.staticsId2 = _ladmovements[pos]->staticIds[0]; + + mgminfo.field_1C = _ladder_field_14; mgminfo.x1 = normx; - mgminfo.y2 = v73; - v53 = &v52[movidx]; - mgminfo.x2 = v72; - v54 = v52[movidx].staticIds[1]; + mgminfo.y1 = normy; + mgminfo.y2 = ny; + mgminfo.x2 = nx; mgminfo.flags = 63; - mgminfo.staticsId1 = v54; - mgminfo.movementId = v53->movVars->varUpGo; - v55 = MGM_genMovement(&_mgm, &mgminfo); - v42 = v55; - v72 = (int)v55; - v56 = (ExCommand *)operator new(0x48u); - point.x = (LONG)v56; - v76 = 1; - if (v56) { - v44 = ExCommand_ctor(v56, ani->_id, 1, _ladmovements.m_pData[movidx].movVars->varDownStop, 0, 0, 0, 1, 0, 0, 0); - v42 = (MessageQueue *)v72; - goto LABEL_29; - } - goto LABEL_28; - } - memset(&mgminfo, 0, sizeof(mgminfo)); + mgminfo.staticsId1 = _ladmovements[pos]->staticIds[1]; + mgminfo.movementId = _ladmovements[pos]->movVars->varUpGo; + + mq = _mgm.genMovement(&mgminfo); + + ex = new ExCommand(ani->_id, 1, _ladmovements[pos]->movVars->varDownStop, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_excFlags |= 2; + + mq->insertExCommandAt(0, ex); + + return mq; + } + + mgminfo.ani = ani; - if ((_WORD)staticsId) - mgminfo.staticsId2 = (unsigned __int16)staticsId; + + if (staticsId) + mgminfo.staticsId2 = staticsId; else - mgminfo.staticsId2 = v29->staticIds[1]; + mgminfo.staticsId2 = _ladmovements[pos]->staticIds[1]; + mgminfo.x1 = normx; - v57 = _ladder_field_14; mgminfo.y1 = normy; - mgminfo.field_1C = v57; + mgminfo.field_1C = _ladder_field_14; mgminfo.flags = 14; - mgminfo.movementId = v29->movVars->varDownGo; + mgminfo.movementId = _ladmovements[pos]->movVars->varDownGo; - return _mgm->genMovement(&mgminfo); -#endif - warning("STUB: MctlLadder::doWalkTo()"); - - return 0; + return _mgm.genMovement(&mgminfo); } MessageQueue *MctlLadder::controllerWalkTo(StaticANIObject *ani, int off) { @@ -660,7 +629,7 @@ MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, in MctlConnectionPoint *minConnectionPoint = 0; for (uint i = 0; i < _motionControllers[sourceIdx]->_connectionPoints.size(); i++) { - for (int j = 0; j < _motionControllers.size(); j++) { + for (uint j = 0; j < _motionControllers.size(); j++) { if (_motionControllers[j]->_movGraphReactObj) { MctlConnectionPoint *pt = _motionControllers[sourceIdx]->_connectionPoints[i]; @@ -847,13 +816,14 @@ void MovGraph::freeItems() { _items.clear(); } + Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { *rescount = 0; if (_items.size() <= 0) return 0; - int idx = 0; + uint idx = 0; while (_items[idx]->ani != ani) { idx++; @@ -889,7 +859,7 @@ Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y, Common::Array<MovItem *> *movitems = calcMovItems(&_items[idx]->movarr, (*movarr)[i], &sz); if (sz > 0) { - for (uint j = 0; j < sz; j++) + for (int j = 0; j < sz; j++) _items[idx]->movitems->push_back(movitems[j]); delete movitems; @@ -1166,6 +1136,8 @@ MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x _items[idx]->movarr._link = 0; res = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, stid2); + + break; } } @@ -1547,6 +1519,8 @@ Common::Array<MovItem *> *MovGraph::calcMovItems(MovArr *movarr1, MovArr *movarr genMovItem(r, tempObList2[i], movarr1, movarr2); + res->push_back(r); + delete tempObList2[i]; } @@ -1656,8 +1630,22 @@ int MovGraph2::getItemSubIndexByMovementId(int idx, int movId) { return -1; } -int MovGraph2::getItemSubIndexByMGM(int idx, StaticANIObject *ani) { - warning("STUB: MovGraph2::getItemSubIndexByMGM()"); +int MovGraph2::getItemSubIndexByMGM(int index, StaticANIObject *ani) { + if (findNode(ani->_ox, ani->_oy, 0) || findLink1(ani->_ox, ani->_oy, -1, 0) || findLink2(ani->_ox, ani->_oy)) { + int minidx = -1; + int min = 0; + + for (int i = 0; i < 4; i++) { + int tmp = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, _items2[index]->_subItems[i]._staticsId1); + + if (tmp >= 0 && (minidx == -1 || tmp < min)) { + minidx = i; + min = tmp; + } + } + + return minidx; + } return -1; } @@ -2442,7 +2430,7 @@ MessageQueue *MovGraph2::genMovement(MovInfo1 *info) { int y = info->pt2.y - info->pt1.y - my2 - my1; int x = info->pt2.x - info->pt1.x - mx2 - mx1; - int a2; + int a2 = 0; int mgmLen; _mgm.calcLength(&point, _items2[info->index]->_subItems[info->subIndex]._walk[1]._mov, x, y, &mgmLen, &a2, info->flags & 1); @@ -3002,7 +2990,7 @@ MessageQueue *MGM::genMovement(MGMInfo *mgminfo) { int n2x = point1.x; int n2y = point1.y; int mult; - int len; + int len = -1; if (mgminfo->flags & 0x40) { mult = mgminfo->field_10; diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index b7e96f61be..2cbf999f86 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -210,7 +210,7 @@ public: int _height; int _ladder_field_20; int _ladder_field_24; - Common::List<MctlLadderMovement *> _ladmovements; + Common::Array<MctlLadderMovement *> _ladmovements; MGM _mgm; public: diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index b346bf3a17..13c653ad09 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -1455,6 +1455,9 @@ void BallChain::init(Ball **ball) { Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { if (!pTail) { + if (!cPlexLen) + error("BallChain::sub04: cPlexLen is 0"); + cPlex = (byte *)calloc(cPlexLen, sizeof(Ball)); Ball *runPtr = (Ball *)&cPlex[(cPlexLen - 1) * sizeof(Ball)]; @@ -1463,7 +1466,7 @@ Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { runPtr->p0 = pTail; pTail = runPtr; - runPtr -= sizeof(Ball); + runPtr--; } } diff --git a/engines/fullpipe/scenes/scene04.cpp b/engines/fullpipe/scenes/scene04.cpp index 0a69335bea..fd1ececdf2 100644 --- a/engines/fullpipe/scenes/scene04.cpp +++ b/engines/fullpipe/scenes/scene04.cpp @@ -633,6 +633,7 @@ MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) { mq1->addExCommandToEnd(mq2->getExCommandByIndex(0)->createClone()); delete mq2; + mq2 = 0; ExCommand *ex = new ExCommand(ANI_KOZAWKA, 1, MV_KZW_STANDUP, 0, 0, 0, 1, 0, 0, 0); ex->_excFlags |= 2; @@ -662,6 +663,9 @@ MessageQueue *sceneHandler04_kozFly5(StaticANIObject *ani, double phase) { mq1->addExCommandToEnd(ex); } + if (mq2) + delete mq2; + return mq1; } diff --git a/engines/fullpipe/scenes/scene16.cpp b/engines/fullpipe/scenes/scene16.cpp index 9ed355fdd9..ed3c51a6c2 100644 --- a/engines/fullpipe/scenes/scene16.cpp +++ b/engines/fullpipe/scenes/scene16.cpp @@ -182,7 +182,7 @@ void sceneHandler16_fillMug() { mq = new MessageQueue(g_fp->_currentScene->getMessageQueueById(QU_SC16_BOYOUT), 0, 1); mq->replaceKeyCode(-1, g_vars->scene16_walkingBoy->_okeyCode); - if (mq->chain(g_vars->scene16_walkingBoy) || !mq) + if (!mq || mq->chain(g_vars->scene16_walkingBoy)) return; } else { if (!g_vars->scene16_walkingGirl) diff --git a/engines/fullpipe/scenes/scene29.cpp b/engines/fullpipe/scenes/scene29.cpp index 2d5127137d..8f82e99ad1 100644 --- a/engines/fullpipe/scenes/scene29.cpp +++ b/engines/fullpipe/scenes/scene29.cpp @@ -972,7 +972,7 @@ int sceneHandler29(ExCommand *cmd) { break; case MSG_SC29_SHOWLASTRED: - if (g_vars->scene29_balls.numBalls) { + if (g_vars->scene29_redBalls.numBalls) { // original uses scene29_balls which looks like a copy/paste error g_vars->scene29_redBalls.field_8->ani->show1(-1, -1, -1, 0); g_vars->scene29_redBalls.field_8->ani->startAnim(MV_SHR_HITASS, 0, -1); } diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp index 65c9bf84ca..a4ca06f489 100644 --- a/engines/fullpipe/sound.cpp +++ b/engines/fullpipe/sound.cpp @@ -268,7 +268,7 @@ void FullpipeEngine::setSceneMusicParameters(GameVar *gvar) { while (sub) { if (_musicAllowed & sub->_value.intValue) { - strcpy(_sceneTracks[_numSceneTracks], sub->_varName); + Common::strlcpy(_sceneTracks[_numSceneTracks], sub->_varName, 260); _numSceneTracks++; } @@ -286,7 +286,7 @@ void FullpipeEngine::setSceneMusicParameters(GameVar *gvar) { if (seq) { _sceneTrackHasSequence = true; - strcpy(_trackName, seq->_value.stringValue); + Common::strlcpy(_trackName, seq->_value.stringValue, 2600); } if (_musicLocal) @@ -432,7 +432,7 @@ void FullpipeEngine::playTrack(GameVar *sceneVar, const char *name, bool delayed while (sub) { if (_musicAllowed & sub->_value.intValue) { - strcpy(_sceneTracks[_numSceneTracks], sub->_varName); + Common::strlcpy(_sceneTracks[_numSceneTracks], sub->_varName, 260); _numSceneTracks++; } @@ -450,7 +450,7 @@ void FullpipeEngine::playTrack(GameVar *sceneVar, const char *name, bool delayed if (seq) { _sceneTrackHasSequence = true; - strcpy(_trackName, seq->_value.stringValue); + Common::strlcpy(_trackName, seq->_value.stringValue, 2600); } if (delayed) { diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp index 41641457d3..141196c7d7 100644 --- a/engines/fullpipe/stateloader.cpp +++ b/engines/fullpipe/stateloader.cpp @@ -162,7 +162,43 @@ GameVar::GameVar() { } GameVar::~GameVar() { - warning("STUB: GameVar::~GameVar()"); + if (_varType == 2) + free(_value.stringValue); + + if (_parentVarObj && !_prevVarObj ) { + if (_parentVarObj->_subVars == this) { + _parentVarObj->_subVars = _nextVarObj; + } else if (_parentVarObj->_field_14 == this) { + _parentVarObj->_field_14 = _nextVarObj; + } else { + _parentVarObj = 0; + } + } + + if (_prevVarObj) + _prevVarObj->_nextVarObj = _nextVarObj; + + if (_nextVarObj) + _nextVarObj->_prevVarObj = _prevVarObj; + + _prevVarObj = 0; + _nextVarObj = 0; + + GameVar *s = _subVars; + + while (s) { + delete s; + s = _subVars; + } + + s = _field_14; + + while (s) { + delete s; + s = _field_14; + } + + free(_varName); } bool GameVar::load(MfcArchive &file) { diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 5d7de050f0..292ef08914 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -979,11 +979,12 @@ void StaticANIObject::stopAnim_maybe() { _ox += point.x; _oy += point.y; } + } else { + _statics = _movement->_staticsObj2; } - } - - if (_movement->_currDynamicPhaseIndex || !(_flags & 0x40)) + } else { _statics = _movement->_staticsObj2; + } _statics->getSomeXY(point); @@ -1765,8 +1766,8 @@ Common::Point *Movement::calcSomeXY(Common::Point &p, int idx, int dynidx) { setOXY(x, y); - while (_currDynamicPhaseIndex != dynidx) - gotoNextFrame(0, 0); + while (_currDynamicPhaseIndex != dynidx && gotoNextFrame(0, 0)) + ; p.x = _ox; p.y = _oy; diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp index 65f3e108b8..442f0bfada 100644 --- a/engines/groovie/cursor.cpp +++ b/engines/groovie/cursor.cpp @@ -107,8 +107,8 @@ Cursor_t7g::Cursor_t7g(uint8 *img, uint8 *pal) : _img = img + 5; - debugC(1, kGroovieDebugCursor | kGroovieDebugAll, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames); - debugC(1, kGroovieDebugCursor | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::Cursor: elinor: 0x%02X (%d), 0x%02X (%d)", elinor1, elinor1, elinor2, elinor2); + debugC(1, kDebugCursor, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames); + debugC(1, kDebugCursor | kDebugUnknown, "Groovie::Cursor: elinor: 0x%02X (%d), 0x%02X (%d)", elinor1, elinor1, elinor2, elinor2); } void Cursor_t7g::enable() { @@ -262,26 +262,26 @@ Cursor_v2::Cursor_v2(Common::File &file) { _img = new byte[_width * _height * _numFrames * 4]; - debugC(1, kGroovieDebugCursor | kGroovieDebugAll, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames); + debugC(1, kDebugCursor, "Groovie::Cursor: width: %d, height: %d, frames:%d", _width, _height, _numFrames); uint16 tmp16 = file.readUint16LE(); - debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "hotspot x?: %d\n", tmp16); + debugC(5, kDebugCursor, "hotspot x?: %d\n", tmp16); tmp16 = file.readUint16LE(); - debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "hotspot y?: %d\n", tmp16); + debugC(5, kDebugCursor, "hotspot y?: %d\n", tmp16); int loop2count = file.readUint16LE(); - debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2count?: %d\n", loop2count); + debugC(5, kDebugCursor, "loop2count?: %d\n", loop2count); for (int l = 0; l < loop2count; l++) { tmp16 = file.readUint16LE(); - debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2a: %d\n", tmp16); // Index frame can merge to/from? + debugC(5, kDebugCursor, "loop2a: %d\n", tmp16); // Index frame can merge to/from? tmp16 = file.readUint16LE(); - debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop2b: %d\n", tmp16); // Number of frames? + debugC(5, kDebugCursor, "loop2b: %d\n", tmp16); // Number of frames? } file.read(pal, 0x20 * 3); for (int f = 0; f < _numFrames; f++) { uint32 tmp32 = file.readUint32LE(); - debugC(5, kGroovieDebugCursor | kGroovieDebugAll, "loop3: %d\n", tmp32); + debugC(5, kDebugCursor, "loop3: %d\n", tmp32); byte *data = new byte[tmp32]; file.read(data, tmp32); diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 427b1c866a..b42cf09245 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -68,17 +68,16 @@ GroovieEngine::GroovieEngine(OSystem *syst, const GroovieGameDescription *gd) : _modeSpeed = kGroovieSpeedFast; // Initialize the custom debug levels - DebugMan.addDebugChannel(kGroovieDebugAll, "All", "Debug everything"); - DebugMan.addDebugChannel(kGroovieDebugVideo, "Video", "Debug video and audio playback"); - DebugMan.addDebugChannel(kGroovieDebugResource, "Resource", "Debug resouce management"); - DebugMan.addDebugChannel(kGroovieDebugScript, "Script", "Debug the scripts"); - DebugMan.addDebugChannel(kGroovieDebugUnknown, "Unknown", "Report values of unknown data in files"); - DebugMan.addDebugChannel(kGroovieDebugHotspots, "Hotspots", "Show the hotspots"); - DebugMan.addDebugChannel(kGroovieDebugCursor, "Cursor", "Debug cursor decompression / switching"); - DebugMan.addDebugChannel(kGroovieDebugMIDI, "MIDI", "Debug MIDI / XMIDI files"); - DebugMan.addDebugChannel(kGroovieDebugScriptvars, "Scriptvars", "Print out any change to script variables"); - DebugMan.addDebugChannel(kGroovieDebugCell, "Cell", "Debug the cell game (in the microscope)"); - DebugMan.addDebugChannel(kGroovieDebugFast, "Fast", "Play videos quickly, with no sound (unstable)"); + DebugMan.addDebugChannel(kDebugVideo, "Video", "Debug video and audio playback"); + DebugMan.addDebugChannel(kDebugResource, "Resource", "Debug resouce management"); + DebugMan.addDebugChannel(kDebugScript, "Script", "Debug the scripts"); + DebugMan.addDebugChannel(kDebugUnknown, "Unknown", "Report values of unknown data in files"); + DebugMan.addDebugChannel(kDebugHotspots, "Hotspots", "Show the hotspots"); + DebugMan.addDebugChannel(kDebugCursor, "Cursor", "Debug cursor decompression / switching"); + DebugMan.addDebugChannel(kDebugMIDI, "MIDI", "Debug MIDI / XMIDI files"); + DebugMan.addDebugChannel(kDebugScriptvars, "Scriptvars", "Print out any change to script variables"); + DebugMan.addDebugChannel(kDebugCell, "Cell", "Debug the cell game (in the microscope)"); + DebugMan.addDebugChannel(kDebugFast, "Fast", "Play videos quickly, with no sound (unstable)"); } GroovieEngine::~GroovieEngine() { diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index 9fe6b0c2f5..d442d39cb2 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -58,18 +58,18 @@ class Script; class VideoPlayer; enum DebugLevels { - kGroovieDebugAll = 1 << 0, - kGroovieDebugVideo = 1 << 1, - kGroovieDebugResource = 1 << 2, - kGroovieDebugScript = 1 << 3, - kGroovieDebugUnknown = 1 << 4, - kGroovieDebugHotspots = 1 << 5, - kGroovieDebugCursor = 1 << 6, - kGroovieDebugMIDI = 1 << 7, - kGroovieDebugScriptvars = 1 << 8, - kGroovieDebugCell = 1 << 9, - kGroovieDebugFast = 1 << 10 - // the current limitation is 32 debug levels (1 << 31 is the last one) + kDebugVideo = 1 << 0, + kDebugResource = 1 << 1, + kDebugScript = 1 << 2, + kDebugUnknown = 1 << 3, + kDebugHotspots = 1 << 4, + kDebugCursor = 1 << 5, + kDebugMIDI = 1 << 6, + kDebugScriptvars = 1 << 7, + kDebugCell = 1 << 8, + kDebugFast = 1 << 9 + // the current limitation is 32 debug levels (1 << 31 is the last one) + // but some are used by system, so avoid high values. }; /** diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 390f47f084..2c164e020c 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -64,7 +64,7 @@ void MusicPlayer::playSong(uint32 fileref) { void MusicPlayer::setBackgroundSong(uint32 fileref) { Common::StackLock lock(_mutex); - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Changing the background song: %04X", fileref); + debugC(1, kDebugMIDI, "Groovie::Music: Changing the background song: %04X", fileref); _backgroundFileRef = fileref; } @@ -86,7 +86,7 @@ void MusicPlayer::playCD(uint8 track) { // Stop the MIDI playback unload(); - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Playing CD track %d", track); + debugC(1, kDebugMIDI, "Groovie::Music: Playing CD track %d", track); if (track == 3) { // This is the credits song, start at 23:20 @@ -136,9 +136,9 @@ void MusicPlayer::playCD(uint8 track) { } void MusicPlayer::startBackground() { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: startBackground()"); + debugC(3, kDebugMIDI, "Groovie::Music: startBackground()"); if (!_isPlaying && _backgroundFileRef) { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef); + debugC(3, kDebugMIDI, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef); play(_backgroundFileRef, true); } } @@ -158,7 +158,7 @@ void MusicPlayer::setUserVolume(uint16 volume) { void MusicPlayer::setGameVolume(uint16 volume, uint16 time) { Common::StackLock lock(_mutex); - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Setting game volume from %d to %d in %dms", _gameVolume, volume, time); + debugC(1, kDebugMIDI, "Groovie::Music: Setting game volume from %d to %d in %dms", _gameVolume, volume, time); // Save the start parameters of the fade _fadingStartTime = _vm->_system->getMillis(); @@ -183,12 +183,12 @@ bool MusicPlayer::play(uint32 fileref, bool loop) { } void MusicPlayer::applyFading() { - debugC(6, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: applyFading() _fadingStartTime = %d, _fadingDuration = %d, _fadingStartVolume = %d, _fadingEndVolume = %d", _fadingStartTime, _fadingDuration, _fadingStartVolume, _fadingEndVolume); + debugC(6, kDebugMIDI, "Groovie::Music: applyFading() _fadingStartTime = %d, _fadingDuration = %d, _fadingStartVolume = %d, _fadingEndVolume = %d", _fadingStartTime, _fadingDuration, _fadingStartVolume, _fadingEndVolume); Common::StackLock lock(_mutex); // Calculate the passed time uint32 time = _vm->_system->getMillis() - _fadingStartTime; - debugC(6, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: time = %d, _gameVolume = %d", time, _gameVolume); + debugC(6, kDebugMIDI, "Groovie::Music: time = %d, _gameVolume = %d", time, _gameVolume); if (time >= _fadingDuration) { // Set the end volume _gameVolume = _fadingEndVolume; @@ -200,7 +200,7 @@ void MusicPlayer::applyFading() { if (_gameVolume == _fadingEndVolume) { // If we were fading to 0, stop the playback and restore the volume if (_fadingEndVolume == 0) { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Faded to zero: end of song. _fadingEndVolume set to 100"); + debugC(1, kDebugMIDI, "Groovie::Music: Faded to zero: end of song. _fadingEndVolume set to 100"); unload(); } } @@ -210,7 +210,7 @@ void MusicPlayer::applyFading() { } void MusicPlayer::onTimer(void *refCon) { - debugC(9, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: onTimer()"); + debugC(9, kDebugMIDI, "Groovie::Music: onTimer()"); MusicPlayer *music = (MusicPlayer *)refCon; Common::StackLock lock(music->_mutex); @@ -225,7 +225,7 @@ void MusicPlayer::onTimer(void *refCon) { } void MusicPlayer::unload() { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Stopping the playback"); + debugC(1, kDebugMIDI, "Groovie::Music: Stopping the playback"); // Set the new state _isPlaying = false; @@ -319,7 +319,7 @@ void MusicPlayerMidi::updateChanVolume(byte channel) { } void MusicPlayerMidi::endTrack() { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: endTrack()"); + debugC(3, kDebugMIDI, "Groovie::Music: endTrack()"); unload(); } @@ -439,7 +439,7 @@ void MusicPlayerXMI::send(uint32 b) { byte chan = b & 0xF; byte bank = (b >> 16) & 0xFF; - debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Selecting bank %X for channel %X", bank, chan); + debugC(5, kDebugMIDI, "Groovie::Music: Selecting bank %X for channel %X", bank, chan); _chanBanks[chan] = bank; return; } else if ((b & 0xF0) == 0xC0) { // Program change @@ -450,7 +450,7 @@ void MusicPlayerXMI::send(uint32 b) { byte chan = b & 0xF; byte patch = (b >> 8) & 0xFF; - debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Setting custom patch %X from bank %X to channel %X", patch, _chanBanks[chan], chan); + debugC(5, kDebugMIDI, "Groovie::Music: Setting custom patch %X from bank %X to channel %X", patch, _chanBanks[chan], chan); // Try to find the requested patch from the previously // specified bank @@ -475,7 +475,7 @@ void MusicPlayerXMI::send(uint32 b) { } bool MusicPlayerXMI::load(uint32 fileref, bool loop) { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); + debugC(1, kDebugMIDI, "Groovie::Music: Starting the playback of song: %04X", fileref); // Open the song resource Common::SeekableReadStream *file = _vm->_resMan->open(fileref); @@ -489,7 +489,7 @@ bool MusicPlayerXMI::load(uint32 fileref, bool loop) { void MusicPlayerXMI::loadTimbres(const Common::String &filename) { // Load the Global Timbre Library format as documented in AIL2 - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Loading the GTL file %s", filename.c_str()); + debugC(1, kDebugMIDI, "Groovie::Music: Loading the GTL file %s", filename.c_str()); // Does it exist? if (!Common::File::exists(filename)) { @@ -537,7 +537,7 @@ void MusicPlayerXMI::loadTimbres(const Common::String &filename) { // Read the timbre data gtl->read(_timbres[i].data, _timbres[i].size); - debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Loaded patch %x in bank %x with size %d", + debugC(5, kDebugMIDI, "Groovie::Music: Loaded patch %x in bank %x with size %d", _timbres[i].patch, _timbres[i].bank, _timbres[i].size); } @@ -636,7 +636,7 @@ void setRolandInstrument(MidiDriver *drv, byte channel, byte *instrument) { // Show the timbre name as extra debug information Common::String name((char *)instrument, 10); - debugC(5, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Setting MT32 timbre '%s' to channel %d", name.c_str(), channel); + debugC(5, kDebugMIDI, "Groovie::Music: Setting MT32 timbre '%s' to channel %d", name.c_str(), channel); sysex.roland_id = 0x41; sysex.device_id = channel; // Unit# @@ -702,7 +702,7 @@ MusicPlayerMac_t7g::MusicPlayerMac_t7g(GroovieEngine *vm) : MusicPlayerMidi(vm) } bool MusicPlayerMac_t7g::load(uint32 fileref, bool loop) { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); + debugC(1, kDebugMIDI, "Groovie::Music: Starting the playback of song: %04X", fileref); // First try for compressed MIDI Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKTAG('c','m','i','d'), fileref & 0x3FF); @@ -789,7 +789,7 @@ MusicPlayerMac_v2::MusicPlayerMac_v2(GroovieEngine *vm) : MusicPlayerMidi(vm) { } bool MusicPlayerMac_v2::load(uint32 fileref, bool loop) { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); + debugC(1, kDebugMIDI, "Groovie::Music: Starting the playback of song: %04X", fileref); // Find correct filename ResInfo info; diff --git a/engines/groovie/player.cpp b/engines/groovie/player.cpp index 16cb3c47ff..c1b90fbd2c 100644 --- a/engines/groovie/player.cpp +++ b/engines/groovie/player.cpp @@ -94,13 +94,13 @@ void VideoPlayer::waitFrame() { } else { uint32 millisDiff = currTime - _lastFrameTime; if (millisDiff < _millisBetweenFrames) { - debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%d)", + debugC(7, kDebugVideo, "Groovie::Player: Delaying %d (currTime=%d, _lastFrameTime=%d, millisDiff=%d, _millisBetweenFrame=%d)", _millisBetweenFrames - millisDiff, currTime, _lastFrameTime, millisDiff, _millisBetweenFrames); _syst->delayMillis(_millisBetweenFrames - millisDiff); currTime = _syst->getMillis(); - debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Finished delay at %d", currTime); + debugC(7, kDebugVideo, "Groovie::Player: Finished delay at %d", currTime); } - debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::Player: Frame displayed at %d (%f FPS)", currTime, 1000.0 / (currTime - _lastFrameTime)); + debugC(6, kDebugVideo, "Groovie::Player: Frame displayed at %d (%f FPS)", currTime, 1000.0 / (currTime - _lastFrameTime)); _lastFrameTime = currTime; } } diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp index 8229d02d91..75eba95240 100644 --- a/engines/groovie/resource.cpp +++ b/engines/groovie/resource.cpp @@ -47,7 +47,7 @@ Common::SeekableReadStream *ResMan::open(uint32 fileRef) { return NULL; } - debugC(1, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size); + debugC(1, kDebugResource, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size); // Does it exist? if (!Common::File::exists(_gjds[resInfo.gjd])) { @@ -120,7 +120,7 @@ uint32 ResMan_t7g::getRef(Common::String name, Common::String scriptname) { // Test whether it's the resource we're searching Common::String resname(readname, 12); if (resname.hasPrefix(name.c_str())) { - debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %12s matches %s", readname, name.c_str()); + debugC(2, kDebugResource, "Groovie::Resource: Resource %12s matches %s", readname, name.c_str()); found = true; } @@ -173,7 +173,7 @@ bool ResMan_t7g::getResInfo(uint32 fileRef, ResInfo &resInfo) { char resname[13]; rlFile->read(resname, 12); resname[12] = 0; - debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %12s", resname); + debugC(2, kDebugResource, "Groovie::Resource: Resource name: %12s", resname); resInfo.filename = resname; // Read the resource information @@ -240,7 +240,7 @@ uint32 ResMan_v2::getRef(Common::String name, Common::String scriptname) { // Test whether it's the resource we're searching Common::String resname(readname, 18); if (resname.hasPrefix(name.c_str())) { - debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource %18s matches %s", readname, name.c_str()); + debugC(2, kDebugResource, "Groovie::Resource: Resource %18s matches %s", readname, name.c_str()); found = true; break; } @@ -284,7 +284,7 @@ bool ResMan_v2::getResInfo(uint32 fileRef, ResInfo &resInfo) { char resname[19]; resname[18] = 0; rlFile.read(resname, 18); - debugC(2, kGroovieDebugResource | kGroovieDebugAll, "Groovie::Resource: Resource name: %18s", resname); + debugC(2, kDebugResource, "Groovie::Resource: Resource name: %18s", resname); resInfo.filename = resname; // 6 padding bytes? (it looks like they're always 0) diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp index 3b82543695..379fcabc07 100644 --- a/engines/groovie/roq.cpp +++ b/engines/groovie/roq.cpp @@ -64,7 +64,7 @@ ROQPlayer::~ROQPlayer() { uint16 ROQPlayer::loadInternal() { // Begin reading the file - debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Loading video"); + debugC(1, kDebugVideo, "Groovie::ROQ: Loading video"); // Read the file header ROQBlockHeader blockHeader; @@ -131,7 +131,7 @@ void ROQPlayer::buildShowBuf() { } bool ROQPlayer::playFrameInternal() { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Playing frame"); + debugC(5, kDebugVideo, "Groovie::ROQ: Playing frame"); // Process the needed blocks until the next video frame bool endframe = false; @@ -168,9 +168,9 @@ bool ROQPlayer::readBlockHeader(ROQBlockHeader &blockHeader) { blockHeader.size = _file->readUint32LE(); blockHeader.param = _file->readUint16LE(); - debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block type = 0x%02X", blockHeader.type); - debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block size = 0x%08X", blockHeader.size); - debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Block param = 0x%04X", blockHeader.param); + debugC(10, kDebugVideo, "Groovie::ROQ: Block type = 0x%02X", blockHeader.type); + debugC(10, kDebugVideo, "Groovie::ROQ: Block size = 0x%08X", blockHeader.size); + debugC(10, kDebugVideo, "Groovie::ROQ: Block param = 0x%04X", blockHeader.param); return true; } @@ -238,7 +238,7 @@ bool ROQPlayer::processBlock() { } bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing info block"); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing info block"); // Verify the block header if (blockHeader.type != 0x1001 || blockHeader.size != 8 || (blockHeader.param != 0 && blockHeader.param != 1)) { @@ -285,7 +285,7 @@ bool ROQPlayer::processBlockInfo(ROQBlockHeader &blockHeader) { } bool ROQPlayer::processBlockQuadCodebook(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad codebook block"); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing quad codebook block"); // Get the number of 2x2 pixel blocks to read int newNum2blocks = blockHeader.param >> 8; @@ -333,7 +333,7 @@ bool ROQPlayer::processBlockQuadCodebook(ROQBlockHeader &blockHeader) { } bool ROQPlayer::processBlockQuadVector(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector block"); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing quad vector block"); // Get the mean motion vectors int8 Mx = blockHeader.param >> 8; @@ -396,7 +396,7 @@ void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8 } void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, int8 My) { - debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing quad vector sub block"); + debugC(6, kDebugVideo, "Groovie::ROQ: Processing quad vector sub block"); uint16 codingType = getCodingType(); switch (codingType) { @@ -422,7 +422,7 @@ void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, in } bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing still (JPEG) block"); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing still (JPEG) block"); Image::JPEGDecoder jpg; @@ -440,7 +440,7 @@ bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) { } bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing mono sound block"); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing mono sound block"); // Verify the block header if (blockHeader.type != 0x1020) { @@ -483,7 +483,7 @@ bool ROQPlayer::processBlockSoundMono(ROQBlockHeader &blockHeader) { } bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing stereo sound block"); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing stereo sound block"); // Verify the block header if (blockHeader.type != 0x1021) { @@ -539,7 +539,7 @@ bool ROQPlayer::processBlockSoundStereo(ROQBlockHeader &blockHeader) { } bool ROQPlayer::processBlockAudioContainer(ROQBlockHeader &blockHeader) { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::ROQ: Processing audio container block: 0x%04X", blockHeader.param); + debugC(5, kDebugVideo, "Groovie::ROQ: Processing audio container block: 0x%04X", blockHeader.param); return true; } diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index 25c421f699..7625151082 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -47,26 +47,6 @@ namespace Groovie { -static void debugScript(int level, bool nl, const char *s, ...) GCC_PRINTF(3, 4); - -static void debugScript(int level, bool nl, const char *s, ...) { - char buf[STRINGBUFLEN]; - va_list va; - - if (!DebugMan.isDebugChannelEnabled(kGroovieDebugScript) && - !DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) - return; - - va_start(va, s); - vsnprintf(buf, STRINGBUFLEN, s, va); - va_end(va); - - if (nl) - debug(level, "%s", buf); - else - debugN(level, "%s", buf); -} - Script::Script(GroovieEngine *vm, EngineVersion version) : _code(NULL), _savedCode(NULL), _stacktop(0), _debugger(NULL), _vm(vm), _videoFile(NULL), _videoRef(0), _staufsMove(NULL), _lastCursor(0xff), @@ -120,7 +100,7 @@ Script::~Script() { void Script::setVariable(uint16 variablenum, byte value) { _variables[variablenum] = value; - debugC(1, kGroovieDebugScriptvars | kGroovieDebugAll, "script variable[0x%03X] = %d (0x%04X)", variablenum, value, value); + debugC(1, kDebugScriptvars, "script variable[0x%03X] = %d (0x%04X)", variablenum, value, value); } void Script::setDebugger(Debugger *debugger) { @@ -229,7 +209,7 @@ void Script::step() { // Only output if we're not re-doing the previous instruction if (_currentInstruction != _oldInstruction) { - debugScript(1, false, "%s", _debugString.c_str()); + debugCN(1, kDebugScript, "%s", _debugString.c_str()); _oldInstruction = _currentInstruction; } @@ -354,7 +334,7 @@ uint32 Script::getVideoRefString() { // Add a trailing dot str += 0x2E; - debugScript(0, false, "%s", str.c_str()); + debugCN(0, kDebugScript, "%s", str.c_str()); // Extract the script name. Common::String scriptname(_scriptFile.c_str(), _scriptFile.size() - 4); @@ -369,8 +349,7 @@ bool Script::hotspot(Common::Rect rect, uint16 address, uint8 cursor) { bool contained = rect.contains(mousepos); // Show hotspots when debugging - if (DebugMan.isDebugChannelEnabled(kGroovieDebugHotspots) || - DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) { + if (DebugMan.isDebugChannelEnabled(kDebugHotspots)) { rect.translate(0, -80); _vm->_graphicsMan->_foreground.frameRect(rect, 250); _vm->_system->copyRectToScreen(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_foreground.pitch, 0, 80, 640, 320); @@ -416,7 +395,7 @@ void Script::savegame(uint slot) { Common::OutSaveFile *file = SaveLoad::openForSaving(ConfMan.getActiveDomainName(), slot); if (!file) { - debugC(9, kGroovieDebugScript, "Save file pointer is null"); + debugC(9, kDebugScript, "Save file pointer is null"); GUI::MessageDialog dialog(_("Failed to save game"), _("OK")); dialog.runModal(); return; @@ -462,32 +441,32 @@ void Script::o_invalid() { } void Script::o_nop() { - debugScript(1, true, "NOP"); + debugC(1, kDebugScript, "NOP"); } void Script::o_nop8() { uint8 tmp = readScript8bits(); - debugScript(1, true, "NOP8: 0x%02X", tmp); + debugC(1, kDebugScript, "NOP8: 0x%02X", tmp); } void Script::o_nop16() { uint16 tmp = readScript16bits(); - debugScript(1, true, "NOP16: 0x%04X", tmp); + debugC(1, kDebugScript, "NOP16: 0x%04X", tmp); } void Script::o_nop32() { uint32 tmp = readScript32bits(); - debugScript(1, true, "NOP32: 0x%08X", tmp); + debugC(1, kDebugScript, "NOP32: 0x%08X", tmp); } void Script::o_nop8or16() { uint16 tmp = readScript8or16bits(); - debugScript(1, true, "NOP8OR16: 0x%04X", tmp); + debugC(1, kDebugScript, "NOP8OR16: 0x%04X", tmp); } void Script::o_playsong() { // 0x02 uint16 fileref = readScript16bits(); - debugScript(1, true, "PlaySong(0x%04X): Play xmidi file", fileref); + debugC(1, kDebugScript, "PlaySong(0x%04X): Play xmidi file", fileref); if (fileref == 0x4C17) { warning("this song is special somehow"); // don't save the reference? @@ -496,33 +475,33 @@ void Script::o_playsong() { // 0x02 } void Script::o_bf9on() { // 0x03 - debugScript(1, true, "BF9ON: bitflag 9 turned on"); + debugC(1, kDebugScript, "BF9ON: bitflag 9 turned on"); _bitflags |= 1 << 9; } void Script::o_palfadeout() { - debugScript(1, true, "PALFADEOUT"); + debugC(1, kDebugScript, "PALFADEOUT"); _vm->_graphicsMan->fadeOut(); } void Script::o_bf8on() { // 0x05 - debugScript(1, true, "BF8ON: bitflag 8 turned on"); + debugC(1, kDebugScript, "BF8ON: bitflag 8 turned on"); _bitflags |= 1 << 8; } void Script::o_bf6on() { // 0x06 - debugScript(1, true, "BF6ON: bitflag 6 turned on"); + debugC(1, kDebugScript, "BF6ON: bitflag 6 turned on"); _bitflags |= 1 << 6; } void Script::o_bf7on() { // 0x07 - debugScript(1, true, "BF7ON: bitflag 7 turned on"); + debugC(1, kDebugScript, "BF7ON: bitflag 7 turned on"); _bitflags |= 1 << 7; } void Script::o_setbackgroundsong() { // 0x08 uint16 fileref = readScript16bits(); - debugScript(1, true, "SetBackgroundSong(0x%04X)", fileref); + debugC(1, kDebugScript, "SetBackgroundSong(0x%04X)", fileref); _vm->_musicPlayer->setBackgroundSong(fileref); } @@ -531,15 +510,15 @@ void Script::o_videofromref() { // 0x09 // Show the debug information just when starting the playback if (fileref != _videoRef) { - debugScript(1, false, "VIDEOFROMREF(0x%04X) (Not fully imp): Play video file from ref", fileref); - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%04X via 0x09", fileref); + debugC(1, kDebugScript, "VIDEOFROMREF(0x%04X) (Not fully imp): Play video file from ref", fileref); + debugC(5, kDebugVideo, "Playing video 0x%04X via 0x09", fileref); } switch (fileref) { case 0x1C03: // Trilobyte logo case 0x1C04: // Virgin logo case 0x1C05: // Credits if (fileref != _videoRef) { - debugScript(1, true, "Use external file if available"); + debugC(1, kDebugScript, "Use external file if available"); } break; @@ -551,12 +530,12 @@ void Script::o_videofromref() { // 0x09 case 0x206D: // Cards on table puzzle (bedroom) case 0x2001: // Coins on table puzzle (bedroom) if (fileref != _videoRef) { - debugScript(1, false, " (This video is special somehow!)"); + debugCN(1, kDebugScript, " (This video is special somehow!)"); warning("(This video (0x%04X) is special somehow!)", fileref); } } if (fileref != _videoRef) { - debugScript(1, false, "\n"); + debugCN(1, kDebugScript, "\n"); } // Play the video if (!playvideofromref(fileref)) { @@ -570,14 +549,14 @@ bool Script::playvideofromref(uint32 fileref) { if (fileref != _videoRef) { // Debug bitflags - debugScript(1, false, "Play video 0x%04X (bitflags:", fileref); + debugCN(1, kDebugScript, "Play video 0x%04X (bitflags:", fileref); for (int i = 15; i >= 0; i--) { - debugScript(1, false, "%d", _bitflags & (1 << i)? 1 : 0); + debugCN(1, kDebugScript, "%d", _bitflags & (1 << i)? 1 : 0); if (i % 4 == 0) { - debugScript(1, false, " "); + debugCN(1, kDebugScript, " "); } } - debugScript(1, true, " <- 0)"); + debugC(1, kDebugScript, " <- 0)"); // Close the previous video file if (_videoFile) { @@ -634,7 +613,7 @@ bool Script::playvideofromref(uint32 fileref) { _eventKbdChar = 0; // Newline - debugScript(1, false, "\n"); + debugCN(1, kDebugScript, "\n"); } // Let the caller know if the video has ended @@ -646,12 +625,12 @@ bool Script::playvideofromref(uint32 fileref) { } void Script::o_bf5on() { // 0x0A - debugScript(1, true, "BF5ON: bitflag 5 turned on"); + debugC(1, kDebugScript, "BF5ON: bitflag 5 turned on"); _bitflags |= 1 << 5; } void Script::o_inputloopstart() { //0x0B - debugScript(5, true, "Input loop start"); + debugC(5, kDebugScript, "Input loop start"); // Reset the input action and the mouse cursor _inputAction = -1; @@ -675,7 +654,7 @@ void Script::o_keyboardaction() { uint8 val = readScript8bits(); uint16 address = readScript16bits(); - debugScript(5, true, "Test key == 0x%02X @0x%04X", val, address); + debugC(5, kDebugScript, "Test key == 0x%02X @0x%04X", val, address); // If there's an already planned action, do nothing if (_inputAction != -1) { @@ -700,7 +679,7 @@ void Script::o_hotspot_rect() { uint16 address = readScript16bits(); uint8 cursor = readScript8bits(); - debugScript(5, true, "HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor); + debugC(5, kDebugScript, "HOTSPOT-RECT(%d,%d,%d,%d) @0x%04X cursor=%d", left, top, right, bottom, address, cursor); // Mark the specified rectangle Common::Rect rect(left, top, right, bottom); @@ -710,7 +689,7 @@ void Script::o_hotspot_rect() { void Script::o_hotspot_left() { uint16 address = readScript16bits(); - debugScript(5, true, "HOTSPOT-LEFT @0x%04X", address); + debugC(5, kDebugScript, "HOTSPOT-LEFT @0x%04X", address); // Mark the leftmost 100 pixels of the game area Common::Rect rect(0, 80, 100, 400); @@ -720,7 +699,7 @@ void Script::o_hotspot_left() { void Script::o_hotspot_right() { uint16 address = readScript16bits(); - debugScript(5, true, "HOTSPOT-RIGHT @0x%04X", address); + debugC(5, kDebugScript, "HOTSPOT-RIGHT @0x%04X", address); // Mark the rightmost 100 pixels of the game area Common::Rect rect(540, 80, 640, 400); @@ -730,7 +709,7 @@ void Script::o_hotspot_right() { void Script::o_hotspot_center() { uint16 address = readScript16bits(); - debugScript(5, true, "HOTSPOT-CENTER @0x%04X", address); + debugC(5, kDebugScript, "HOTSPOT-CENTER @0x%04X", address); // Mark the centermost 240 pixels of the game area Common::Rect rect(200, 80, 440, 400); @@ -740,7 +719,7 @@ void Script::o_hotspot_center() { void Script::o_hotspot_current() { uint16 address = readScript16bits(); - debugScript(5, true, "HOTSPOT-CURRENT @0x%04X", address); + debugC(5, kDebugScript, "HOTSPOT-CURRENT @0x%04X", address); // The original interpreter doesn't check the position, so accept the // whole screen @@ -749,7 +728,7 @@ void Script::o_hotspot_current() { } void Script::o_inputloopend() { - debugScript(5, true, "Input loop end"); + debugC(5, kDebugScript, "Input loop end"); // Handle the predefined hotspots if (_hotspotTopAction) { @@ -802,7 +781,7 @@ void Script::o_random() { uint16 varnum = readScript8or16bits(); uint8 maxnum = readScript8bits(); - debugScript(1, true, "RANDOM: var[0x%04X] = rand(%d)", varnum, maxnum); + debugC(1, kDebugScript, "RANDOM: var[0x%04X] = rand(%d)", varnum, maxnum); setVariable(varnum, _random.getRandomNumber(maxnum)); } @@ -810,7 +789,7 @@ void Script::o_random() { void Script::o_jmp() { uint16 address = readScript16bits(); - debugScript(1, true, "JMP @0x%04X", address); + debugC(1, kDebugScript, "JMP @0x%04X", address); // Set the current address _currentInstruction = address; @@ -819,18 +798,18 @@ void Script::o_jmp() { void Script::o_loadstring() { uint16 varnum = readScript8or16bits(); - debugScript(1, false, "LOADSTRING var[0x%04X..] =", varnum); + debugCN(1, kDebugScript, "LOADSTRING var[0x%04X..] =", varnum); do { setVariable(varnum++, readScriptChar(true, true, true)); - debugScript(1, false, " 0x%02X", _variables[varnum - 1]); + debugCN(1, kDebugScript, " 0x%02X", _variables[varnum - 1]); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); - debugScript(1, false, "\n"); + debugCN(1, kDebugScript, "\n"); } void Script::o_ret() { uint8 val = readScript8bits(); - debugScript(1, true, "RET %d", val); + debugC(1, kDebugScript, "RET %d", val); // Set the return value setVariable(0x102, val); @@ -847,7 +826,7 @@ void Script::o_ret() { void Script::o_call() { uint16 address = readScript16bits(); - debugScript(1, true, "CALL @0x%04X", address); + debugC(1, kDebugScript, "CALL @0x%04X", address); // Save return address in the call stack _stack[_stacktop] = _currentInstruction; @@ -860,7 +839,7 @@ void Script::o_call() { void Script::o_sleep() { uint16 time = readScript16bits(); - debugScript(1, true, "SLEEP 0x%04X", time); + debugC(1, kDebugScript, "SLEEP 0x%04X", time); _vm->_system->delayMillis(time * 3); } @@ -869,7 +848,7 @@ void Script::o_strcmpnejmp() { // 0x1A uint16 varnum = readScript8or16bits(); uint8 result = 1; - debugScript(1, false, "STRCMP-NEJMP: var[0x%04X..],", varnum); + debugCN(1, kDebugScript, "STRCMP-NEJMP: var[0x%04X..],", varnum); do { uint8 val = readScriptChar(true, true, true); @@ -878,33 +857,33 @@ void Script::o_strcmpnejmp() { // 0x1A result = 0; } varnum++; - debugScript(1, false, " 0x%02X", val); + debugCN(1, kDebugScript, " 0x%02X", val); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); uint16 address = readScript16bits(); if (!result) { - debugScript(1, true, " jumping to @0x%04X", address); + debugC(1, kDebugScript, " jumping to @0x%04X", address); _currentInstruction = address; } else { - debugScript(1, true, " not jumping"); + debugC(1, kDebugScript, " not jumping"); } } void Script::o_xor_obfuscate() { uint16 varnum = readScript8or16bits(); - debugScript(1, false, "XOR OBFUSCATE: var[0x%04X..] = ", varnum); + debugCN(1, kDebugScript, "XOR OBFUSCATE: var[0x%04X..] = ", varnum); do { uint8 val = readScript8bits(); _firstbit = ((val & 0x80) != 0); val &= 0x4F; setVariable(varnum, _variables[varnum] ^ val); - debugScript(1, false, "%c", _variables[varnum]); + debugCN(1, kDebugScript, "%c", _variables[varnum]); varnum++; } while (!_firstbit); - debugScript(1, false, "\n"); + debugCN(1, kDebugScript, "\n"); } void Script::o_vdxtransition() { // 0x1C @@ -912,8 +891,8 @@ void Script::o_vdxtransition() { // 0x1C // Show the debug information just when starting the playback if (fileref != _videoRef) { - debugScript(1, true, "VDX transition fileref = 0x%04X", fileref); - debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%04X with transition", fileref); + debugC(1, kDebugScript, "VDX transition fileref = 0x%04X", fileref); + debugC(1, kDebugVideo, "Playing video 0x%04X with transition", fileref); } // Set bit 1 @@ -938,7 +917,7 @@ void Script::o_swap() { uint16 varnum1 = readScript8or16bits(); uint16 varnum2 = readScript16bits(); - debugScript(1, true, "SWAP var[0x%04X] <-> var[0x%04X]", varnum1, varnum2); + debugC(1, kDebugScript, "SWAP var[0x%04X] <-> var[0x%04X]", varnum1, varnum2); uint8 tmp = _variables[varnum1]; setVariable(varnum1, _variables[varnum2]); @@ -948,7 +927,7 @@ void Script::o_swap() { void Script::o_inc() { uint16 varnum = readScript8or16bits(); - debugScript(1, true, "INC var[0x%04X]", varnum); + debugC(1, kDebugScript, "INC var[0x%04X]", varnum); setVariable(varnum, _variables[varnum] + 1); } @@ -956,7 +935,7 @@ void Script::o_inc() { void Script::o_dec() { uint16 varnum = readScript8or16bits(); - debugScript(1, true, "DEC var[0x%04X]", varnum); + debugC(1, kDebugScript, "DEC var[0x%04X]", varnum); setVariable(varnum, _variables[varnum] - 1); } @@ -982,7 +961,7 @@ void Script::o_strcmpnejmp_var() { // 0x21 } void Script::o_copybgtofg() { // 0x22 - debugScript(1, true, "COPY_BG_TO_FG"); + debugC(1, kDebugScript, "COPY_BG_TO_FG"); memcpy(_vm->_graphicsMan->_foreground.getPixels(), _vm->_graphicsMan->_background.getPixels(), 640 * 320); } @@ -990,7 +969,7 @@ void Script::o_strcmpeqjmp() { // 0x23 uint16 varnum = readScript8or16bits(); uint8 result = 1; - debugScript(1, false, "STRCMP-EQJMP: var[0x%04X..],", varnum); + debugCN(1, kDebugScript, "STRCMP-EQJMP: var[0x%04X..],", varnum); do { uint8 val = readScriptChar(true, true, true); @@ -998,15 +977,15 @@ void Script::o_strcmpeqjmp() { // 0x23 result = 0; } varnum++; - debugScript(1, false, " 0x%02X", val); + debugCN(1, kDebugScript, " 0x%02X", val); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); uint16 address = readScript16bits(); if (result) { - debugScript(1, true, " jumping to @0x%04X", address); + debugC(1, kDebugScript, " jumping to @0x%04X", address); _currentInstruction = address; } else { - debugScript(1, true, " not jumping"); + debugC(1, kDebugScript, " not jumping"); } } @@ -1014,7 +993,7 @@ void Script::o_mov() { uint16 varnum1 = readScript8or16bits(); uint16 varnum2 = readScript16bits(); - debugScript(1, true, "MOV var[0x%04X] = var[0x%04X]", varnum1, varnum2); + debugC(1, kDebugScript, "MOV var[0x%04X] = var[0x%04X]", varnum1, varnum2); setVariable(varnum1, _variables[varnum2]); } @@ -1023,7 +1002,7 @@ void Script::o_add() { uint16 varnum1 = readScript8or16bits(); uint16 varnum2 = readScript16bits(); - debugScript(1, true, "ADD var[0x%04X] += var[0x%04X]", varnum1, varnum2); + debugC(1, kDebugScript, "ADD var[0x%04X] += var[0x%04X]", varnum1, varnum2); setVariable(varnum1, _variables[varnum1] + _variables[varnum2]); } @@ -1034,7 +1013,7 @@ void Script::o_videofromstring1() { // Show the debug information just when starting the playback if (fileref != _videoRef) { - debugScript(0, true, "VIDEOFROMSTRING1 0x%04X", fileref); + debugC(0, kDebugScript, "VIDEOFROMSTRING1 0x%04X", fileref); } // Play the video @@ -1050,7 +1029,7 @@ void Script::o_videofromstring2() { // Show the debug information just when starting the playback if (fileref != _videoRef) { - debugScript(0, true, "VIDEOFROMSTRING2 0x%04X", fileref); + debugC(0, kDebugScript, "VIDEOFROMSTRING2 0x%04X", fileref); } // Set bit 1 @@ -1069,11 +1048,11 @@ void Script::o_videofromstring2() { } void Script::o_stopmidi() { - debugScript(1, true, "STOPMIDI (TODO)"); + debugC(1, kDebugScript, "STOPMIDI (TODO)"); } void Script::o_endscript() { - debugScript(1, true, "END OF SCRIPT"); + debugC(1, kDebugScript, "END OF SCRIPT"); _vm->quitGame(); } @@ -1081,7 +1060,7 @@ void Script::o_sethotspottop() { uint16 address = readScript16bits(); uint8 cursor = readScript8bits(); - debugScript(5, true, "SETHOTSPOTTOP @0x%04X cursor=%d", address, cursor); + debugC(5, kDebugScript, "SETHOTSPOTTOP @0x%04X cursor=%d", address, cursor); _hotspotTopAction = address; _hotspotTopCursor = cursor; @@ -1091,7 +1070,7 @@ void Script::o_sethotspotbottom() { uint16 address = readScript16bits(); uint8 cursor = readScript8bits(); - debugScript(5, true, "SETHOTSPOTBOTTOM @0x%04X cursor=%d", address, cursor); + debugC(5, kDebugScript, "SETHOTSPOTBOTTOM @0x%04X cursor=%d", address, cursor); _hotspotBottomAction = address; _hotspotBottomCursor = cursor; @@ -1101,7 +1080,7 @@ void Script::o_loadgame() { uint16 varnum = readScript8or16bits(); uint8 slot = _variables[varnum]; - debugScript(1, true, "LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot); + debugC(1, kDebugScript, "LOADGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot); loadgame(slot); _vm->_system->fillScreen(0); @@ -1111,7 +1090,7 @@ void Script::o_savegame() { uint16 varnum = readScript8or16bits(); uint8 slot = _variables[varnum]; - debugScript(1, true, "SAVEGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot); + debugC(1, kDebugScript, "SAVEGAME var[0x%04X] -> slot=%d (TODO)", varnum, slot); savegame(slot); } @@ -1119,7 +1098,7 @@ void Script::o_savegame() { void Script::o_hotspotbottom_4() { //0x30 uint16 address = readScript16bits(); - debugScript(5, true, "HOTSPOT-BOTTOM @0x%04X", address); + debugC(5, kDebugScript, "HOTSPOT-BOTTOM @0x%04X", address); // Mark the 80 pixels under the game area Common::Rect rect(0, 400, 640, 480); @@ -1130,7 +1109,7 @@ void Script::o_midivolume() { uint16 arg1 = readScript16bits(); uint16 arg2 = readScript16bits(); - debugScript(1, true, "MIDI volume: %d %d", arg1, arg2); + debugC(1, kDebugScript, "MIDI volume: %d %d", arg1, arg2); _vm->_musicPlayer->setGameVolume(arg1, arg2); } @@ -1139,13 +1118,13 @@ void Script::o_jne() { uint16 varnum2 = readScript16bits(); uint16 address = readScript16bits(); - debugScript(1, false, "JNE: var[var[0x%04X] - 0x31] != var[0x%04X] @0x%04X", varnum1, varnum2, address); + debugCN(1, kDebugScript, "JNE: var[var[0x%04X] - 0x31] != var[0x%04X] @0x%04X", varnum1, varnum2, address); if (_variables[_variables[varnum1] - 0x31] != _variables[varnum2]) { _currentInstruction = address; - debugScript(1, true, " jumping to @0x%04X", address); + debugC(1, kDebugScript, " jumping to @0x%04X", address); } else { - debugScript(1, true, " not jumping"); + debugC(1, kDebugScript, " not jumping"); } } @@ -1153,19 +1132,19 @@ void Script::o_loadstringvar() { uint16 varnum = readScript8or16bits(); varnum = _variables[varnum] - 0x31; - debugScript(1, false, "LOADSTRINGVAR var[0x%04X..] =", varnum); + debugCN(1, kDebugScript, "LOADSTRINGVAR var[0x%04X..] =", varnum); do { setVariable(varnum++, readScriptChar(true, true, true)); - debugScript(1, false, " 0x%02X", _variables[varnum - 1]); + debugCN(1, kDebugScript, " 0x%02X", _variables[varnum - 1]); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); - debugScript(1, false, "\n"); + debugCN(1, kDebugScript, "\n"); } void Script::o_chargreatjmp() { uint16 varnum = readScript8or16bits(); uint8 result = 0; - debugScript(1, false, "CHARGREAT-JMP: var[0x%04X..],", varnum); + debugCN(1, kDebugScript, "CHARGREAT-JMP: var[0x%04X..],", varnum); do { uint8 val = readScriptChar(true, true, true); @@ -1173,20 +1152,20 @@ void Script::o_chargreatjmp() { result = 1; } varnum++; - debugScript(1, false, " 0x%02X", val); + debugCN(1, kDebugScript, " 0x%02X", val); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); uint16 address = readScript16bits(); if (result) { - debugScript(1, true, " jumping to @0x%04X", address); + debugC(1, kDebugScript, " jumping to @0x%04X", address); _currentInstruction = address; } else { - debugScript(1, true, " not jumping"); + debugC(1, kDebugScript, " not jumping"); } } void Script::o_bf7off() { - debugScript(1, true, "BF7OFF: bitflag 7 turned off"); + debugC(1, kDebugScript, "BF7OFF: bitflag 7 turned off"); _bitflags &= ~(1 << 7); } @@ -1194,7 +1173,7 @@ void Script::o_charlessjmp() { uint16 varnum = readScript8or16bits(); uint8 result = 0; - debugScript(1, false, "CHARLESS-JMP: var[0x%04X..],", varnum); + debugCN(1, kDebugScript, "CHARLESS-JMP: var[0x%04X..],", varnum); do { uint8 val = readScriptChar(true, true, true); @@ -1202,15 +1181,15 @@ void Script::o_charlessjmp() { result = 1; } varnum++; - debugScript(1, false, " 0x%02X", val); + debugCN(1, kDebugScript, " 0x%02X", val); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); uint16 address = readScript16bits(); if (result) { - debugScript(1, true, " jumping to @0x%04X", address); + debugC(1, kDebugScript, " jumping to @0x%04X", address); _currentInstruction = address; } else { - debugScript(1, true, " not jumping"); + debugC(1, kDebugScript, " not jumping"); } } @@ -1219,11 +1198,50 @@ void Script::o_copyrecttobg() { // 0x37 uint16 top = readScript16bits(); uint16 right = readScript16bits(); uint16 bottom = readScript16bits(); + + // Sanity checks to prevent bad pointer access crashes + if (left > right) { + warning("COPYRECT left:%d > right:%d", left, right); + // swap over left and right parameters + uint16 j; + j = right; + right = left; + left = j; + } + if (top > bottom) { + warning("COPYRECT top:%d > bottom:%d", top, bottom); + // swap over top and bottom parameters + uint16 j; + j = bottom; + bottom = top; + top = j; + } + if (top < 80) { + warning("COPYRECT top < 80... clamping"); + top = 80; + } + if (top >= 480) { + warning("COPYRECT top >= 480... clamping"); + top = 480 - 1; + } + if (bottom >= 480) { + warning("COPYRECT bottom >= 480... clamping"); + bottom = 480 - 1; + } + if (left >= 640) { + warning("COPYRECT left >= 640... clamping"); + left = 640 - 1; + } + if (right >= 640) { + warning("COPYRECT right >= 640... clamping"); + right = 640 - 1; + } + uint16 i, width = right - left, height = bottom - top; uint32 offset = 0; byte *fg, *bg; - debugScript(1, true, "COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom); + debugC(1, kDebugScript, "COPYRECT((%d,%d)->(%d,%d))", left, top, right, bottom); fg = (byte *)_vm->_graphicsMan->_foreground.getBasePtr(left, top - 80); bg = (byte *)_vm->_graphicsMan->_background.getBasePtr(left, top - 80); @@ -1236,13 +1254,13 @@ void Script::o_copyrecttobg() { // 0x37 } void Script::o_restorestkpnt() { - debugScript(1, true, "Restore stack pointer from saved (TODO)"); + debugC(1, kDebugScript, "Restore stack pointer from saved (TODO)"); } void Script::o_obscureswap() { uint16 var1, var2, tmp; - debugScript(1, true, "OBSCSWAP"); + debugC(1, kDebugScript, "OBSCSWAP"); // Read the first variable var1 = readScriptChar(false, true, true) * 10; @@ -1262,7 +1280,7 @@ void Script::o_printstring() { char stringstorage[15]; uint8 counter = 0; - debugScript(1, true, "PRINTSTRING"); + debugC(1, kDebugScript, "PRINTSTRING"); memset(stringstorage, 0, 15); do { @@ -1300,7 +1318,7 @@ void Script::o_hotspot_slot() { uint16 address = readScript16bits(); uint16 cursor = readScript8bits(); - debugScript(1, true, "HOTSPOT-SLOT %d (%d,%d,%d,%d) @0x%04X cursor=%d (TODO)", slot, left, top, right, bottom, address, cursor); + debugC(1, kDebugScript, "HOTSPOT-SLOT %d (%d,%d,%d,%d) @0x%04X cursor=%d (TODO)", slot, left, top, right, bottom, address, cursor); Common::Rect rect(left, top, right, bottom); if (hotspot(rect, address, cursor)) { @@ -1338,7 +1356,7 @@ void Script::o_hotspot_slot() { } void Script::o_checkvalidsaves() { - debugScript(1, true, "CHECKVALIDSAVES"); + debugC(1, kDebugScript, "CHECKVALIDSAVES"); // Reset the array of valid saves and the savegame names cache for (int i = 0; i < 10; i++) { @@ -1355,7 +1373,7 @@ void Script::o_checkvalidsaves() { while (it != list.end()) { int8 slot = it->getSaveSlot(); if (SaveLoad::isSlotValid(slot)) { - debugScript(2, true, " Found valid savegame: %s", it->getDescription().c_str()); + debugC(2, kDebugScript, " Found valid savegame: %s", it->getDescription().c_str()); // Mark this slot as used setVariable(slot, 1); @@ -1369,11 +1387,11 @@ void Script::o_checkvalidsaves() { // Save the number of valid saves setVariable(0x104, count); - debugScript(1, true, " Found %d valid savegames", count); + debugC(1, kDebugScript, " Found %d valid savegames", count); } void Script::o_resetvars() { - debugScript(1, true, "RESETVARS"); + debugC(1, kDebugScript, "RESETVARS"); for (int i = 0; i < 0x100; i++) { setVariable(i, 0); } @@ -1383,7 +1401,7 @@ void Script::o_mod() { uint16 varnum = readScript8or16bits(); uint8 val = readScript8bits(); - debugScript(1, true, "MOD var[0x%04X] %%= %d", varnum, val); + debugC(1, kDebugScript, "MOD var[0x%04X] %%= %d", varnum, val); setVariable(varnum, _variables[varnum] % val); } @@ -1395,7 +1413,7 @@ void Script::o_loadscript() { while ((c = readScript8bits())) { filename += c; } - debugScript(1, true, "LOADSCRIPT %s", filename.c_str()); + debugC(1, kDebugScript, "LOADSCRIPT %s", filename.c_str()); // Just 1 level of sub-scripts are allowed if (_savedCode) { @@ -1430,7 +1448,7 @@ void Script::o_setvideoorigin() { // Set bitflag 7 _bitflags |= 1 << 7; - debugScript(1, true, "SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY); + debugC(1, kDebugScript, "SetVideoOrigin(0x%04X,0x%04X) (%d, %d)", origX, origY, origX, origY); _vm->_videoPlayer->setOrigin(origX, origY); } @@ -1438,7 +1456,7 @@ void Script::o_sub() { uint16 varnum1 = readScript8or16bits(); uint16 varnum2 = readScript16bits(); - debugScript(1, true, "SUB var[0x%04X] -= var[0x%04X]", varnum1, varnum2); + debugC(1, kDebugScript, "SUB var[0x%04X] -= var[0x%04X]", varnum1, varnum2); setVariable(varnum1, _variables[varnum1] - _variables[varnum2]); } @@ -1448,7 +1466,7 @@ void Script::o_cellmove() { byte *scriptBoard = &_variables[0x19]; byte startX, startY, endX, endY; - debugScript(1, true, "CELL MOVE var[0x%02X]", depth); + debugC(1, kDebugScript, "CELL MOVE var[0x%02X]", depth); if (!_staufsMove) _staufsMove = new CellGame; @@ -1471,7 +1489,7 @@ void Script::o_cellmove() { void Script::o_returnscript() { uint8 val = readScript8bits(); - debugScript(1, true, "RETURNSCRIPT @0x%02X", val); + debugC(1, kDebugScript, "RETURNSCRIPT @0x%02X", val); // Are we returning from a sub-script? if (!_savedCode) { @@ -1504,7 +1522,7 @@ void Script::o_returnscript() { void Script::o_sethotspotright() { uint16 address = readScript16bits(); - debugScript(1, true, "SETHOTSPOTRIGHT @0x%04X", address); + debugC(1, kDebugScript, "SETHOTSPOTRIGHT @0x%04X", address); _hotspotRightAction = address; } @@ -1512,13 +1530,13 @@ void Script::o_sethotspotright() { void Script::o_sethotspotleft() { uint16 address = readScript16bits(); - debugScript(1, true, "SETHOTSPOTLEFT @0x%04X", address); + debugC(1, kDebugScript, "SETHOTSPOTLEFT @0x%04X", address); _hotspotLeftAction = address; } void Script::o_getcd() { - debugScript(1, true, "GETCD"); + debugC(1, kDebugScript, "GETCD"); // By default set it to no CD available int8 cd = -1; @@ -1545,7 +1563,7 @@ void Script::o_getcd() { void Script::o_playcd() { uint8 val = readScript8bits(); - debugScript(1, true, "PLAYCD %d", val); + debugC(1, kDebugScript, "PLAYCD %d", val); if (val == 2) { // TODO: Play the alternative logo @@ -1557,7 +1575,7 @@ void Script::o_playcd() { void Script::o_musicdelay() { uint16 delay = readScript16bits(); - debugScript(1, true, "MUSICDELAY %d", delay); + debugC(1, kDebugScript, "MUSICDELAY %d", delay); _vm->_musicPlayer->setBackgroundDelay(delay); } @@ -1569,7 +1587,7 @@ void Script::o_hotspot_outrect() { uint16 bottom = readScript16bits(); uint16 address = readScript16bits(); - debugScript(1, true, "HOTSPOT-OUTRECT(%d,%d,%d,%d) @0x%04X (TODO)", left, top, right, bottom, address); + debugC(1, kDebugScript, "HOTSPOT-OUTRECT(%d,%d,%d,%d) @0x%04X (TODO)", left, top, right, bottom, address); // Test if the current mouse position is outside the specified rectangle Common::Rect rect(left, top, right, bottom); @@ -1587,25 +1605,25 @@ void Script::o_stub56() { uint8 val2 = readScript8bits(); uint8 val3 = readScript8bits(); - debugScript(1, true, "STUB56: 0x%08X 0x%02X 0x%02X", val1, val2, val3); + debugC(1, kDebugScript, "STUB56: 0x%08X 0x%02X 0x%02X", val1, val2, val3); } void Script::o_stub59() { uint16 val1 = readScript8or16bits(); uint8 val2 = readScript8bits(); - debugScript(1, true, "STUB59: 0x%04X 0x%02X", val1, val2); + debugC(1, kDebugScript, "STUB59: 0x%04X 0x%02X", val1, val2); } void Script::o2_playsong() { uint32 fileref = readScript32bits(); - debugScript(1, true, "PlaySong(0x%08X): Play xmidi file", fileref); + debugC(1, kDebugScript, "PlaySong(0x%08X): Play xmidi file", fileref); _vm->_musicPlayer->playSong(fileref); } void Script::o2_setbackgroundsong() { uint32 fileref = readScript32bits(); - debugScript(1, true, "SetBackgroundSong(0x%08X)", fileref); + debugC(1, kDebugScript, "SetBackgroundSong(0x%08X)", fileref); _vm->_musicPlayer->setBackgroundSong(fileref); } @@ -1614,8 +1632,8 @@ void Script::o2_videofromref() { // Show the debug information just when starting the playback if (fileref != _videoRef) { - debugScript(1, true, "VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref); - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%08X via 0x09", fileref); + debugC(1, kDebugScript, "VIDEOFROMREF(0x%08X) (Not fully imp): Play video file from ref", fileref); + debugC(5, kDebugVideo, "Playing video 0x%08X via 0x09", fileref); } // Play the video @@ -1630,8 +1648,8 @@ void Script::o2_vdxtransition() { // Show the debug information just when starting the playback if (fileref != _videoRef) { - debugScript(1, true, "VDX transition fileref = 0x%08X", fileref); - debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Playing video 0x%08X with transition", fileref); + debugC(1, kDebugScript, "VDX transition fileref = 0x%08X", fileref); + debugC(1, kDebugVideo, "Playing video 0x%08X with transition", fileref); } // Set bit 1 @@ -1652,30 +1670,30 @@ void Script::o2_vdxtransition() { void Script::o2_copyscreentobg() { uint16 val = readScript16bits(); - debugScript(1, true, "CopyScreenToBG3: 0x%04X", val); + debugC(1, kDebugScript, "CopyScreenToBG3: 0x%04X", val); error("Unimplemented Opcode 0x4F"); } void Script::o2_copybgtoscreen() { uint16 val = readScript16bits(); - debugScript(1, true, "CopyBG3ToScreen: 0x%04X", val); + debugC(1, kDebugScript, "CopyBG3ToScreen: 0x%04X", val); error("Unimplemented Opcode 0x50"); } void Script::o2_setvideoskip() { _videoSkipAddress = readScript16bits(); - debugScript(1, true, "SetVideoSkip (0x%04X)", _videoSkipAddress); + debugC(1, kDebugScript, "SetVideoSkip (0x%04X)", _videoSkipAddress); } void Script::o2_stub52() { uint8 arg = readScript8bits(); - debugScript(1, true, "STUB52 (0x%02X)", arg); + debugC(1, kDebugScript, "STUB52 (0x%02X)", arg); } void Script::o2_setscriptend() { uint16 arg = readScript16bits(); - debugScript(1, true, "SetScriptEnd (0x%04X)", arg); + debugC(1, kDebugScript, "SetScriptEnd (0x%04X)", arg); } Script::OpcodeFunc Script::_opcodesT7G[NUM_OPCODES] = { diff --git a/engines/groovie/vdx.cpp b/engines/groovie/vdx.cpp index 4626a6f81b..09c2e0d3ea 100644 --- a/engines/groovie/vdx.cpp +++ b/engines/groovie/vdx.cpp @@ -56,8 +56,7 @@ void VDXPlayer::setOrigin(int16 x, int16 y) { } uint16 VDXPlayer::loadInternal() { - if (DebugMan.isDebugChannelEnabled(kGroovieDebugVideo) || - DebugMan.isDebugChannelEnabled(kGroovieDebugAll)) { + if (DebugMan.isDebugChannelEnabled(kDebugVideo)) { int8 i; debugN(1, "Groovie::VDX: New VDX: bitflags are "); for (i = 15; i >= 0; i--) { @@ -106,24 +105,24 @@ uint16 VDXPlayer::loadInternal() { //_flagUpdateStill = _flagNine || _flagSix; // Begin reading the file - debugC(1, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Playing video"); + debugC(1, kDebugVideo, "Groovie::VDX: Playing video"); if (_file->readUint16LE() != VDX_IDENT) { error("Groovie::VDX: This does not appear to be a 7th guest VDX file"); return 0; } else { - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: VDX file identified correctly"); + debugC(5, kDebugVideo, "Groovie::VDX: VDX file identified correctly"); } uint16 tmp; // Skip unknown data: 6 bytes, ref Martine tmp = _file->readUint16LE(); - debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine1 = 0x%04X", tmp); + debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine1 = 0x%04X", tmp); tmp = _file->readUint16LE(); - debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine2 = 0x%04X", tmp); + debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine2 = 0x%04X", tmp); tmp = _file->readUint16LE(); - debugC(2, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Martine3 (FPS?) = %d", tmp); + debugC(2, kDebugVideo | kDebugUnknown, "Groovie::VDX: Martine3 (FPS?) = %d", tmp); return tmp; } @@ -144,7 +143,7 @@ bool VDXPlayer::playFrameInternal() { if (_file->eos()) break; - debugC(5, kGroovieDebugVideo | kGroovieDebugUnknown | kGroovieDebugAll, "Groovie::VDX: Edward = 0x%04X", tmp); + debugC(5, kDebugVideo | kDebugUnknown, "Groovie::VDX: Edward = 0x%04X", tmp); // Read the chunk data and decompress if needed if (compSize) @@ -159,18 +158,18 @@ bool VDXPlayer::playFrameInternal() { // Use the current chunk switch (currRes) { case 0x00: - debugC(6, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Replay frame"); + debugC(6, kDebugVideo, "Groovie::VDX: Replay frame"); break; case 0x20: - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Still frame"); + debugC(5, kDebugVideo, "Groovie::VDX: Still frame"); getStill(vdxData); break; case 0x25: - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Animation frame"); + debugC(5, kDebugVideo, "Groovie::VDX: Animation frame"); getDelta(vdxData); break; case 0x80: - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Sound resource"); + debugC(5, kDebugVideo, "Groovie::VDX: Sound resource"); chunkSound(vdxData); break; default: @@ -182,7 +181,7 @@ bool VDXPlayer::playFrameInternal() { // Wait until the current frame can be shown - if (!DebugMan.isDebugChannelEnabled(kGroovieDebugFast)) { + if (!DebugMan.isDebugChannelEnabled(kDebugFast)) { waitFrame(); } // TODO: Move it to a better place @@ -344,13 +343,13 @@ void VDXPlayer::getDelta(Common::ReadStream *in) { void VDXPlayer::getStill(Common::ReadStream *in) { uint16 numXTiles = in->readUint16LE(); - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numXTiles=%d", numXTiles); + debugC(5, kDebugVideo, "Groovie::VDX: numXTiles=%d", numXTiles); uint16 numYTiles = in->readUint16LE(); - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: numYTiles=%d", numYTiles); + debugC(5, kDebugVideo, "Groovie::VDX: numYTiles=%d", numYTiles); // It's skipped in the original: uint16 colorDepth = in->readUint16LE(); - debugC(5, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: colorDepth=%d", colorDepth); + debugC(5, kDebugVideo, "Groovie::VDX: colorDepth=%d", colorDepth); uint16 imageWidth = TILE_SIZE * numXTiles; @@ -423,7 +422,7 @@ void VDXPlayer::getStill(Common::ReadStream *in) { */ } else { // Skip the remaining data - debugC(10, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Skipping still frame"); + debugC(10, kDebugVideo, "Groovie::VDX: Skipping still frame"); while (!in->eos()) { in->readByte(); } @@ -538,7 +537,7 @@ void VDXPlayer::chunkSound(Common::ReadStream *in) { byte *data = (byte *)malloc(60000); int chunksize = in->read(data, 60000); - if (!DebugMan.isDebugChannelEnabled(kGroovieDebugFast)) { + if (!DebugMan.isDebugChannelEnabled(kDebugFast)) { _audioStream->queueBuffer(data, chunksize, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED); } } @@ -563,7 +562,7 @@ void VDXPlayer::setPalette(uint8 *palette) { if (_flagSkipPalette) return; - debugC(7, kGroovieDebugVideo | kGroovieDebugAll, "Groovie::VDX: Setting palette"); + debugC(7, kDebugVideo, "Groovie::VDX: Setting palette"); _syst->getPaletteManager()->setPalette(palette, 0, 256); } diff --git a/engines/mads/action.cpp b/engines/mads/action.cpp index 207fcd9a11..199ae39000 100644 --- a/engines/mads/action.cpp +++ b/engines/mads/action.cpp @@ -57,12 +57,12 @@ MADSAction::MADSAction(MADSEngine *vm) : _vm(vm) { _inProgress = false; _pickedWord = -1; - _savedFields._commandSource = 0; - _savedFields._mainObjectSource = 0; + _savedFields._commandSource = CAT_NONE; + _savedFields._mainObjectSource = CAT_NONE; _savedFields._command = -1; _savedFields._mainObject = 0; _savedFields._secondObject = 0; - _savedFields._secondObjectSource = 0; + _savedFields._secondObjectSource = CAT_NONE; _savedFields._articleNumber = PREP_NONE; _savedFields._lookFlag = false; diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp index 6af8a9ae5f..512a3979f9 100644 --- a/engines/mads/animation.cpp +++ b/engines/mads/animation.cpp @@ -310,8 +310,10 @@ void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface for (int idx = 0; idx < _header._spriteSetsCount; ++idx) usageList.push_back(_spriteSets[idx]->_usageIndex); - if (usageList.size() > 0) - _vm->_palette->_paletteUsage.updateUsage(usageList, _header._messagesCount); + if (usageList.size() > 0) { + int spritesUsageIndex = _spriteSets[0]->_usageIndex; + _vm->_palette->_paletteUsage.updateUsage(usageList, spritesUsageIndex); + } // Remaps the sprite list indexes for frames to the loaded sprite list indexes for (uint i = 0; i < _frameEntries.size(); ++i) { diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp index dc8c846beb..7e6909d113 100644 --- a/engines/mads/dialogs.cpp +++ b/engines/mads/dialogs.cpp @@ -64,7 +64,7 @@ void Dialog::restore() { Common::copy(&_dialogPalette[0], &_dialogPalette[8 * 3], &_vm->_palette->_mainPalette[248 * 3]); - _vm->_palette->setPalette(_vm->_palette->_mainPalette, 248, 8); + _vm->_palette->setPalette(&_vm->_palette->_mainPalette[248 * 3], 248, 8); } } diff --git a/engines/mads/dragonsphere/game_dragonsphere.cpp b/engines/mads/dragonsphere/game_dragonsphere.cpp index c6097125b1..3836adb6d2 100644 --- a/engines/mads/dragonsphere/game_dragonsphere.cpp +++ b/engines/mads/dragonsphere/game_dragonsphere.cpp @@ -41,22 +41,12 @@ GameDragonsphere::GameDragonsphere(MADSEngine *vm) _storyMode = STORYMODE_NAUGHTY; } -ProtectionResult GameDragonsphere::checkCopyProtection() { - /* - // DEBUG: Flag copy protection failure - _globals[5] = -1; - - if (!ConfMan.getBool("copy_protection")) - return true; - - * DEBUG: Disabled for now - CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); - dlg->show(); - delete dlg; - */ - - // DEBUG: Return that copy protection failed - return PROTECTION_SUCCEED; +void GameDragonsphere::startGame() { + _scene._priorSceneId = 0; + _scene._currentSceneId = -1; + _scene._nextSceneId = 101; + + initializeGlobals(); } void GameDragonsphere::initializeGlobals() { diff --git a/engines/mads/dragonsphere/game_dragonsphere.h b/engines/mads/dragonsphere/game_dragonsphere.h index 5147f75178..7869dc87b4 100644 --- a/engines/mads/dragonsphere/game_dragonsphere.h +++ b/engines/mads/dragonsphere/game_dragonsphere.h @@ -102,7 +102,7 @@ class GameDragonsphere : public Game { protected: GameDragonsphere(MADSEngine *vm); - virtual ProtectionResult checkCopyProtection(); + virtual void startGame(); virtual void initializeGlobals(); diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index ea87a1f4d1..8639f59418 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -59,7 +59,8 @@ Game *Game::init(MADSEngine *vm) { Game::Game(MADSEngine *vm) : _vm(vm), _surface(nullptr), _objects(vm), _scene(vm), _screenObjects(vm), _player(vm) { - _sectionNumber = _priorSectionNumber = 0; + _sectionNumber = 1; + _priorSectionNumber = 0; _loadGameSlot = -1; _lastSave = -1; _saveFile = nullptr; @@ -108,49 +109,15 @@ void Game::run() { } _statusFlag = true; - int protectionResult = -1; if (_loadGameSlot == -1) { - protectionResult = checkCopyProtection(); - switch (protectionResult) { - case PROTECTION_FAIL: - // Copy protection failed - _scene._nextSceneId = 804; - break; - case PROTECTION_ESCAPE: - // User escaped out of copy protection dialog - _vm->quitGame(); - break; - default: - // Copy protection check succeeded - _scene._nextSceneId = 101; - _scene._priorSceneId = -1; - break; - } + startGame(); } // Get the initial starting time for the first scene _scene._frameStartTime = _vm->_events->getFrameCounter(); - if (_saveFile == nullptr && protectionResult != -1 && protectionResult != -2) { - initSection(_sectionNumber); - _statusFlag = true; - - _vm->_dialogs->_pendingDialog = DIALOG_DIFFICULTY; - _vm->_dialogs->showDialog(); - _vm->_dialogs->_pendingDialog = DIALOG_NONE; - - _priorSectionNumber = 0; - _priorSectionNumber = -1; - _scene._priorSceneId = 0; - _scene._currentSceneId = -1; - } - - if (protectionResult != 1 && protectionResult != 2) { - initializeGlobals(); - } - - if (_statusFlag) + if (!_vm->shouldQuit()) gameLoop(); } @@ -192,8 +159,6 @@ void Game::gameLoop() { _vm->_events->freeCursors(); _vm->_sound->closeDriver(); } - - _vm->_palette->close(); } void Game::sectionLoop() { diff --git a/engines/mads/game.h b/engines/mads/game.h index 8b16590503..08cd7e7843 100644 --- a/engines/mads/game.h +++ b/engines/mads/game.h @@ -44,10 +44,6 @@ enum KernelMode { KERNEL_ROOM_PRELOAD = 3, KERNEL_ROOM_INIT = 4, KERNEL_ACTIVE_CODE = 5 }; -enum ProtectionResult { - PROTECTION_SUCCEED = 0, PROTECTION_FAIL = 1, PROTECTION_ESCAPE = 2 -}; - #define MADS_SAVEGAME_VERSION 1 struct MADSSavegameHeader { @@ -101,9 +97,9 @@ protected: /** @name Virtual Method list */ /** - * Perform any copy protection check + * Perform any game-specifcic startup */ - virtual ProtectionResult checkCopyProtection() = 0; + virtual void startGame() = 0; /** * Initializes global variables for a new game diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 31e9b0dbe2..59eec40bcc 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -67,6 +67,7 @@ MADSEngine::~MADSEngine() { delete _palette; delete _resources; delete _sound; + delete _audio; } void MADSEngine::initialize() { diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 83369f5b94..36858a4940 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -28,6 +28,7 @@ #include "mads/msurface.h" #include "mads/staticres.h" #include "mads/nebular/dialogs_nebular.h" +#include "mads/nebular/game_nebular.h" namespace MADS { @@ -268,6 +269,14 @@ void DialogsNebular::showDialog() { case DIALOG_GAME_MENU: //GameMenuDialog::show(); break; + case DIALOG_DIFFICULTY: { +/* + DifficultyDialog *dlg = new DifficultyDialog(_vm); + dlg->show(); + delete dlg; +*/ + break; + } default: break; } @@ -461,14 +470,17 @@ void PictureDialog::restore() { /*------------------------------------------------------------------------*/ ScreenDialog::DialogLine::DialogLine() { - _state = 0; + _active = true; + _state = DLGSTATE_UNSELECTED; _textDisplayIndex = -1; _font = nullptr; _widthAdjust = 0; + _msg = ""; } ScreenDialog::DialogLine::DialogLine(const Common::String &s) { - _state = 0; + _active = true; + _state = DLGSTATE_UNSELECTED; _textDisplayIndex = -1; _font = nullptr; _widthAdjust = -1; @@ -477,17 +489,19 @@ ScreenDialog::DialogLine::DialogLine(const Common::String &s) { /*------------------------------------------------------------------------*/ -ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm), - _savedSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT) { +ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm) { Game &game = *_vm->_game; Scene &scene = game._scene; _v1 = 0; + _v2 = 0; + _v3 = false; _selectedLine = 0; _dirFlag = false; _textLineCount = 0; _screenId = 920; + chooseBackground(); game.loadQuoteSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 0); @@ -512,7 +526,7 @@ ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm), scene._priorSceneId = priorSceneId; scene._currentSceneId = currentSceneId; scene._nextSceneId = nextSceneId; - _vm->_screen._offset.y = 22; + scene._posAdjust.y = 22; _vm->_sound->pauseNewCommands(); _vm->_events->initVars(); game._kernelMode = KERNEL_ROOM_INIT; @@ -529,17 +543,10 @@ ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm), _vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16); } - _vm->_screen.copyTo(&_savedSurface); - /* + _vm->_screen.empty(); _vm->_screen.hLine(0, 0, MADS_SCREEN_WIDTH, 2); - _vm->_screen.copyRectToScreen(Common::Rect(0, _vm->_screen._offset.y, - MADS_SCREEN_WIDTH, _vm->_screen._offset.y + 1)); - _vm->_screen.copyRectToScreen(Common::Rect(0, _vm->_screen._offset.y + 157, - MADS_SCREEN_WIDTH, _vm->_screen._offset.y + 157)); - */ - - game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? - kCenterVertTransition : kTransitionFadeIn; + + game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? kTransitionFadeIn : kCenterVertTransition; game._trigger = 0; _vm->_events->setCursor(CURSOR_ARROW); @@ -555,10 +562,32 @@ ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm), void ScreenDialog::clearLines() { Scene &scene = _vm->_game->_scene; + _v2 = 0; _lines.clear(); scene._spriteSlots.fullRefresh(true); } +void ScreenDialog::setClickableLines() { + ScreenObjects &screenObjects = _vm->_game->_screenObjects; + + for (uint idx = 0; idx < _lines.size(); ++idx) { + if (_lines[idx]._active) { + const Common::Point &pt = _lines[idx]._pos; + int strWidth = _lines[idx]._font->getWidth(_lines[idx]._msg); + int maxHeight = _lines[idx]._font->getHeight(); + + screenObjects.add(Common::Rect(pt.x, pt.y, pt.x + strWidth, pt.y + maxHeight - 1), + LAYER_GUI, CAT_COMMAND, idx); + } + } + + if (_vm->_dialogs->_pendingDialog == DIALOG_SAVE || + _vm->_dialogs->_pendingDialog == DIALOG_RESTORE) { + screenObjects.add(Common::Rect(293, 26, 312, 75), LAYER_GUI, CAT_INV_LIST, 50); + screenObjects.add(Common::Rect(293, 78, 312, 127), LAYER_GUI, CAT_INV_LIST, 51); + } +} + void ScreenDialog::addQuote(int id1, int id2, DialogTextAlign align, const Common::Point &pt, Font *font) { Common::String msg = _vm->_game->getQuote(id1); @@ -576,6 +605,9 @@ void ScreenDialog::addLine(const Common::String &msg, DialogTextAlign align, Scene &scene = _vm->_game->_scene; DialogLine *line; + if (font == nullptr) + font = _vm->_font->getFont(FONT_CONVERSATION); + if (_lineIndex < (int)_lines.size()) { if (_lines.size() >= 20) { ++_lineIndex; @@ -604,7 +636,7 @@ void ScreenDialog::addLine(const Common::String &msg, DialogTextAlign align, } line->_font = font; - line->_state = 0; + line->_state = DLGSTATE_UNSELECTED; line->_pos = pt; line->_widthAdjust = -1; line->_textDisplayIndex = -1; @@ -677,13 +709,174 @@ void ScreenDialog::setFrame(int frameNumber, int depth) { spriteSlot._seqIndex = 1; spriteSlot._spritesIndex = _menuSpritesIndex; spriteSlot._frameNumber = frameNumber; +} + +void ScreenDialog::show() { + Scene &scene = _vm->_game->_scene; + while (_selectedLine < 1 && !_vm->shouldQuit()) { + handleEvents(); + if (_v3) { + if (!_v1) + _v1 = -1; + + refreshText(); + scene.drawElements(_vm->_game->_fx, _vm->_game->_fx); + _v3 = false; + } + + _vm->_events->waitForNextFrame(); + _vm->_game->_fx = kTransitionNone; + } +} + +void ScreenDialog::handleEvents() { + ScreenObjects &screenObjects = _vm->_game->_screenObjects; + EventsManager &events = *_vm->_events; + Nebular::DialogsNebular &dialogs = *(Nebular::DialogsNebular *)_vm->_dialogs; + int v1 = _v1; + + // Mark all the lines as initially unselected + for (uint i = 0; i < _lines.size(); ++i) + _lines[i]._state = DLGSTATE_UNSELECTED; + + // Process pending events + _vm->_events->pollEvents(); + + // Scan for objects in the dialog + int objIndex = screenObjects.scan(events.currentPos() - _vm->_screen._offset, LAYER_GUI); + + if (_v2) { + int yp = events.currentPos().y - _vm->_screen._offset.y; + if (yp < screenObjects[1]._bounds.top) { + if (!events._mouseReleased) + _lines[1]._state = DLGSTATE_SELECTED; + objIndex = 19; + } + + if (yp < screenObjects[7]._bounds.bottom) { + if (!events._mouseReleased) + _lines[1]._state = DLGSTATE_SELECTED; + objIndex = 20; + } + } + + int line = -1; + if (objIndex > 0 || events._mouseButtons) { + line = screenObjects[objIndex]._descId; + if (dialogs._pendingDialog == DIALOG_SAVE || dialogs._pendingDialog == DIALOG_RESTORE) { + if (line > 7 && line <= 14) { + _lines[line]._state = DLGSTATE_UNSELECTED; + line -= 7; + } + + int v2 = (line > 0 && line < 8) ? 1 : 0; + if (events._mouseMoved) + _v2 = v2; + } + + if (screenObjects[objIndex]._category == CAT_COMMAND) { + _lines[line]._state = DLGSTATE_SELECTED; + } + } + if (!line) + line = -1; + + if (dialogs._pendingDialog == DIALOG_ERROR && line == 1) + line = -1; + + if (events._mouseReleased) { + if (!_v2 || line <= 18) + _selectedLine = line; + _v3 = true; + } + + _v1 = line; + if (v1 == line || _selectedLine >= 0) + _v3 = true; +} + +void ScreenDialog::refreshText() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < _lines.size(); ++i) { + if (_lines[i]._active) { + int fontColor; + switch (_lines[i]._state) { + case DLGSTATE_UNSELECTED: + fontColor = 0xB0A; + break; + case DLGSTATE_SELECTED: + fontColor = 0xD0C; + break; + default: + fontColor = 0xF0E; + break; + } + + bool skipFlag = false; + if (_lines[i]._textDisplayIndex >= 0) { + TextDisplay &textDisplay = scene._textDisplay[_lines[i]._textDisplayIndex]; + int currCol = textDisplay._color1; + if (currCol != fontColor) { + scene._textDisplay.expire(_lines[i]._textDisplayIndex); + _lines[i]._textDisplayIndex = -1; + } else { + skipFlag = true; + } + } + + if (!skipFlag) { + _lines[i]._textDisplayIndex = scene._textDisplay.add(_lines[i]._pos.x, _lines[i]._pos.y, + fontColor, _lines[i]._widthAdjust, _lines[i]._msg, _lines[i]._font); + } + } + } +} + +/*------------------------------------------------------------------------*/ + +DifficultyDialog::DifficultyDialog(MADSEngine *vm) : ScreenDialog(vm) { + setFrame(8, 2); + setLines(); + setClickableLines(); +} + +void DifficultyDialog::setLines() { + Font *font = _vm->_font->getFont(FONT_CONVERSATION); + int yp = 78 - ((font->getHeight() + 1) * 4 + 6) / 2; + + addQuote(41, 0, ALIGN_CENTER, Common::Point(0, yp), font); + yp += 6; + + for (int id = 42; id <= 44; ++id) { + yp += font->getHeight(); + addQuote(id, 0, ALIGN_CENTER, Common::Point(0, yp)); + } +} + +void DifficultyDialog::show() { + ScreenDialog::show(); + Nebular::GameNebular &game = *(Nebular::GameNebular *)_vm->_game; + + switch (_selectedLine) { + case 1: + game._difficulty = Nebular::DIFFICULTY_HARD; + break; + case 2: + game._difficulty = Nebular::DIFFICULTY_MEDIUM; + break; + case 3: + game._difficulty = Nebular::DIFFICULTY_EASY; + break; + default: + _vm->quitGame(); + } } /*------------------------------------------------------------------------*/ GameMenuDialog::GameMenuDialog(MADSEngine *vm) : ScreenDialog(vm) { - clearLines(); setFrame(1, 2); } diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h index 0554becea4..a144ee9d83 100644 --- a/engines/mads/nebular/dialogs_nebular.h +++ b/engines/mads/nebular/dialogs_nebular.h @@ -39,7 +39,7 @@ private: int _dialogWidth; CapitalizationMode _capitalizationMode; - DialogsNebular(MADSEngine *vm): Dialogs(vm), _capitalizationMode(kUppercase) {} + DialogsNebular(MADSEngine *vm): Dialogs(vm), _capitalizationMode(kUppercase), _dialogWidth(0) {} virtual Common::String getVocab(int vocabId); @@ -101,9 +101,12 @@ public: enum DialogTextAlign { ALIGN_CENTER = -1, ALIGN_AT_CENTER = -2, ALIGN_RIGHT = -3 }; +enum DialogState { DLGSTATE_UNSELECTED = 0, DLGSTATE_SELECTED = 1, DLGSTATE_FOCUSED = 2 }; + class ScreenDialog { struct DialogLine { - int _state; + bool _active; + DialogState _state; Common::Point _pos; int _textDisplayIndex; Common::String _msg; @@ -115,9 +118,10 @@ class ScreenDialog { }; protected: MADSEngine *_vm; - MSurface _savedSurface; Common::Array<DialogLine> _lines; int _v1; + int _v2; + bool _v3; int _selectedLine; bool _dirFlag; int _screenId; @@ -131,14 +135,19 @@ protected: void clearLines(); /** + * Setup lines to be clickable + */ + void setClickableLines(); + + /** * Add a quote to the lines list */ - void addQuote(int id1, int id2, DialogTextAlign align, const Common::Point &pt, Font *font); + void addQuote(int id1, int id2, DialogTextAlign align, const Common::Point &pt, Font *font = nullptr); /** * Adds a line to the lines list */ - void addLine(const Common::String &msg, DialogTextAlign align, const Common::Point &pt, Font *font); + void addLine(const Common::String &msg, DialogTextAlign align, const Common::Point &pt, Font *font = nullptr); /** * Initializes variables @@ -154,11 +163,46 @@ protected: * Choose the background to display for the dialog */ void chooseBackground(); + + /** + * Handle events whilst the dialog is active + */ + void handleEvents(); + + /** + * Refresh the display of the dialog's text + */ + void refreshText(); public: /** * Constructor */ ScreenDialog(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~ScreenDialog() {} + + /** + * Show the dialog + */ + virtual void show(); +}; + +class DifficultyDialog : public ScreenDialog { +private: + /** + * Set the lines for the dialog + */ + void setLines(); +public: + DifficultyDialog(MADSEngine *vm); + + /** + * Show the dialog + */ + virtual void show(); }; class GameMenuDialog : public ScreenDialog { diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index f2889feb31..d6d7a07e52 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -48,18 +48,54 @@ ProtectionResult GameNebular::checkCopyProtection() { _globals[kCopyProtectFailed] = -1; if (!ConfMan.getBool("copy_protection")) - return true; + return true; * DEBUG: Disabled for now CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); dlg->show(); delete dlg; */ - - // DEBUG: Return that copy protection failed return PROTECTION_SUCCEED; } +void GameNebular::startGame() { + // Show the main menu + // TODO: Show the main menu here + + // Check copy protection + ProtectionResult protectionResult = checkCopyProtection(); + switch (protectionResult) { + case PROTECTION_FAIL: + // Copy protection failed + _scene._nextSceneId = 804; + initializeGlobals(); + _globals[kCopyProtectFailed] = true; + return; + case PROTECTION_ESCAPE: + // User escaped out of copy protection dialog + _vm->quitGame(); + return; + default: + // Copy protection check succeeded + break; + } + + initSection(_sectionNumber); + _statusFlag = true; + + _vm->_dialogs->_pendingDialog = DIALOG_DIFFICULTY; + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + + _priorSectionNumber = 0; + _priorSectionNumber = -1; + _scene._priorSceneId = 0; + _scene._currentSceneId = -1; + _scene._nextSceneId = 101; + + initializeGlobals(); +} + void GameNebular::initializeGlobals() { int count, count2; int bad; @@ -351,10 +387,10 @@ void GameNebular::doObjectAction() { } else if (action.isAction(VERB_LICK, NOUN_POISON_DARTS)) { dialogs.show(450); } else if (action.isAction(VERB_EAT, NOUN_TWINKIFRUIT)) { - _objects.setRoom(OBJ_TWINKIFRUIT, PLAYER_INVENTORY); + _objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE); dialogs.show(451); } else if (action.isAction(VERB_GORGE_ON, NOUN_TWINKIFRUIT)) { - _objects.setRoom(OBJ_TWINKIFRUIT, PLAYER_INVENTORY); + _objects.setRoom(OBJ_TWINKIFRUIT, NOWHERE); dialogs.show(452); } else if (action.isAction(VERB_GNAW_ON)) { dialogs.show(453); @@ -419,7 +455,7 @@ void GameNebular::doObjectAction() { dialogs.show(479); } else if ((action.isAction(VERB_READ) || action.isAction(VERB_LOOK_AT) || action.isAction(VERB_LOOK)) && action.isObject(NOUN_NOTE) && _objects.isInInventory(OBJ_NOTE)) { - _objects.setRoom(OBJ_NOTE, PLAYER_INVENTORY); + _objects.setRoom(OBJ_NOTE, NOWHERE); _objects.addToInventory(OBJ_COMBINATION); dialogs.showItem(OBJ_COMBINATION, 851); } else if ((action.isAction(VERB_LOOK) || action.isAction(VERB_READ)) && @@ -488,8 +524,8 @@ void GameNebular::doObjectAction() { } else if ((action.isAction(VERB_ATTACH, NOUN_DETONATORS, NOUN_CHARGE_CASES) || action.isAction(VERB_PUT, NOUN_DETONATORS, NOUN_CHARGE_CASES)) && _objects.isInInventory(OBJ_DETONATORS) && _objects.isInInventory(OBJ_CHARGE_CASES)) { if (_objects[OBJ_CHARGE_CASES].getQuality(3)) { - _objects.setRoom(OBJ_CHARGE_CASES, 1); - _objects.setRoom(OBJ_DETONATORS, 1); + _objects.setRoom(OBJ_CHARGE_CASES, NOWHERE); + _objects.setRoom(OBJ_DETONATORS, NOWHERE); _objects.addToInventory(OBJ_BOMBS); dialogs.showItem(OBJ_BOMBS, 403); } else { @@ -501,13 +537,13 @@ void GameNebular::doObjectAction() { || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMB)) && _objects.isInInventory(OBJ_TIMER_MODULE) && ( _objects.isInInventory(OBJ_BOMBS) || _objects.isInInventory(OBJ_BOMB))) { if (_objects.isInInventory(OBJ_BOMBS)) { - _objects.setRoom(OBJ_BOMBS, PLAYER_INVENTORY); + _objects.setRoom(OBJ_BOMBS, NOWHERE); _objects.addToInventory(OBJ_BOMB); } else { - _objects.setRoom(OBJ_BOMB, PLAYER_INVENTORY); + _objects.setRoom(OBJ_BOMB, NOWHERE); } - _objects.setRoom(OBJ_TIMER_MODULE, PLAYER_INVENTORY); + _objects.setRoom(OBJ_TIMER_MODULE, NOWHERE); _objects.addToInventory(OBJ_TIMEBOMB); dialogs.showItem(OBJ_TIMEBOMB, 404); } else if (action.isAction(VERB_FONDLE, NOUN_PLANT_STALK)) { @@ -576,7 +612,7 @@ void GameNebular::doObjectAction() { } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PENLIGHT)) { if (_globals[kPenlightCellStatus] == 0) { _globals[kPenlightCellStatus] = 3; - _objects.setRoom(OBJ_PHONE_CELLS, PLAYER_INVENTORY); + _objects.setRoom(OBJ_PHONE_CELLS, NOWHERE); dialogs.show(419); } else { dialogs.show(420); @@ -584,7 +620,7 @@ void GameNebular::doObjectAction() { } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PHONE_HANDSET)) { if (_globals[kHandsetCellStatus] == 0) { _globals[kHandsetCellStatus] = 3; - _objects.setRoom(OBJ_PHONE_CELLS, PLAYER_INVENTORY); + _objects.setRoom(OBJ_PHONE_CELLS, NOWHERE); dialogs.show(421); } else { dialogs.show(422); @@ -608,12 +644,12 @@ void GameNebular::doObjectAction() { } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) { dialogs.show(427); } else if (action.isAction(VERB_PUT, NOUN_BOMB, NOUN_CHICKEN) || action.isAction(VERB_PUT, NOUN_BOMBS, NOUN_CHICKEN)) { - _objects.setRoom(OBJ_CHICKEN, PLAYER_INVENTORY); + _objects.setRoom(OBJ_CHICKEN, NOWHERE); if (_objects.isInInventory(OBJ_BOMBS)) { - _objects.setRoom(OBJ_BOMBS, PLAYER_INVENTORY); + _objects.setRoom(OBJ_BOMBS, NOWHERE); _objects.addToInventory(OBJ_BOMB); } else { - _objects.setRoom(OBJ_BOMB, PLAYER_INVENTORY); + _objects.setRoom(OBJ_BOMB, NOWHERE); } _objects.addToInventory(OBJ_CHICKEN_BOMB); diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h index 6620deaea6..da607d47ee 100644 --- a/engines/mads/nebular/game_nebular.h +++ b/engines/mads/nebular/game_nebular.h @@ -38,6 +38,11 @@ enum Difficulty { DIFFICULTY_HARD = 1, DIFFICULTY_MEDIUM = 2, DIFFICULTY_EASY = 3 }; + +enum ProtectionResult { + PROTECTION_SUCCEED = 0, PROTECTION_FAIL = 1, PROTECTION_ESCAPE = 2 +}; + enum InventoryObject { OBJ_NONE = -1, OBJ_BINOCULARS = 0, @@ -98,10 +103,12 @@ enum InventoryObject { class GameNebular : public Game { friend class Game; +private: + ProtectionResult checkCopyProtection(); protected: GameNebular(MADSEngine *vm); - virtual ProtectionResult checkCopyProtection(); + virtual void startGame(); virtual void initializeGlobals(); diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 8cf4107ad4..a81f11b8a5 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -188,10 +188,6 @@ void Scene101::enter() { _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); _panelOpened = false; - // HACK: set the prior scene to 102 for now when the game starts, to avoid Rex's getting up animation - if (_scene->_priorSceneId == -1) - _scene->_priorSceneId = 102; - if (_scene->_priorSceneId != -1) _globals[kNeedToStandUp] = false; @@ -721,7 +717,7 @@ void Scene102::enter() { if (_scene->_priorSceneId == 101) { _game._player._playerPos = Common::Point(229, 109); _game._player._stepEnabled = false; - _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 2, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); } else if (_scene->_priorSceneId == 103) _game._player._playerPos = Common::Point(47, 152); diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 725548f889..d33675c578 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -3254,7 +3254,6 @@ void Scene611::handleSubDialog1() { handleTalking(500); displayHermitQuestions(17); _dialog1.write(0x290, false); - _dialog1.write(0x28E, false); if (!_dialog1.read(0x28F)) _dialog1.write(0x291, true); diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp index 584c1c75f8..930bb7c250 100644 --- a/engines/mads/nebular/nebular_scenes7.cpp +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -2603,7 +2603,7 @@ void Scene752::actions() { _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); break; case 1: - _vm->_sound->command(0xF); + _vm->_sound->command(15); _scene->_sequences.remove(_globals._sequenceIndexes[13]); _game._objects.addToInventory(OBJ_ID_CARD); _scene->_dynamicHotspots.remove(_cardId); @@ -2616,7 +2616,8 @@ void Scene752::actions() { default: break; } - } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4) && (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) { + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._savedFields._mainObjectSource == CAT_HOTSPOT) && + (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) { switch (_game._trigger) { case 0: _game._player._stepEnabled = false; @@ -2627,9 +2628,9 @@ void Scene752::actions() { _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); break; case 1: - _vm->_sound->command(0xF); + _vm->_sound->command(15); if (_game._objects.isInInventory(OBJ_BONE)) - _game._objects.setRoom(OBJ_BONE, 1); + _game._objects.setRoom(OBJ_BONE, NOWHERE); _game._objects.addToInventory(OBJ_BONES); _vm->_dialogs->showItem(OBJ_BONES, 75221); break; @@ -2658,12 +2659,12 @@ void Scene752::actions() { _vm->_dialogs->show(75217); else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) _vm->_dialogs->show(75218); - else if ((_action.isAction(VERB_LOOK, NOUN_BONES) || _action.isAction(VERB_LOOK, NOUN_ID_CARD)) && (_action._mainObjectSource == 4)) { + else if ((_action.isAction(VERB_LOOK, NOUN_BONES) || _action.isAction(VERB_LOOK, NOUN_ID_CARD)) && (_action._mainObjectSource == CAT_HOTSPOT)) { if (_game._objects[OBJ_ID_CARD]._roomNumber == 752) _vm->_dialogs->show(75219); else _vm->_dialogs->show(75220); - } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4)) { + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._savedFields._mainObjectSource == CAT_HOTSPOT)) { if (_game._objects.isInInventory(OBJ_BONES)) _vm->_dialogs->show(75222); } else diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp index f8670c71dc..eedbf36ddd 100644 --- a/engines/mads/palette.cpp +++ b/engines/mads/palette.cpp @@ -143,12 +143,12 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { bool changed = false; - int var4 = 0xffff; + int newPalIndex = -1; int v1 = palRange[palIndex]._v2; if (palette[v1]._flags & 8) { changed = true; - var4 = 0xFD; + newPalIndex = 0xFD; } if (hasUsage && palette[v1]._flags & 0x10) { @@ -156,7 +156,7 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { if ((*tempUsage._data)[usageIndex]._palIndex == palIndex) { changed = true; int dataIndex = MIN(usageIndex, _data->size() - 1); - var4 = (*_data)[dataIndex]._palIndex; + newPalIndex = (*_data)[dataIndex]._palIndex; } } } @@ -165,11 +165,11 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { for (uint usageIndex = 0; usageIndex < _data->size() && !changed; ++usageIndex) { if ((*_data)[usageIndex]._palIndex == palIndex) { changed = true; - var4 = 0xF0 + usageIndex; + newPalIndex = 0xF0 + usageIndex; // Copy data into the high end of the main palette RGB6 &pSrc = palette[palIndex]; - byte *pDest = &_vm->_palette->_mainPalette[var4 * 3]; + byte *pDest = &_vm->_palette->_mainPalette[newPalIndex * 3]; pDest[0] = pSrc.r; pDest[1] = pSrc.g; pDest[2] = pSrc.b; @@ -201,7 +201,7 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { if (var2 > var10) { changed = true; - var4 = idx; + newPalIndex = idx; var2 = var10; } } @@ -214,7 +214,7 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { --palCount; ++freeIndex; changed = true; - var4 = idx; + newPalIndex = idx; RGB6 &pSrc = palette[palIndex]; byte *pDest = &_vm->_palette->_mainPalette[idx * 3]; @@ -229,11 +229,12 @@ int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { // In at least scene 318, when the doctor knocks you with the blackjack, // the changed flag can be false //assert(changed); + assert(newPalIndex != -1); int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0; - _vm->_palette->_palFlags[var4] |= var52 | rgbMask; - palette[palIndex]._palIndex = var4; + _vm->_palette->_palFlags[newPalIndex] |= var52 | rgbMask; + palette[palIndex]._palIndex = newPalIndex; } _vm->_palette->_rgbList[rgbIndex] = true; diff --git a/engines/mads/palette.h b/engines/mads/palette.h index ff93b2f2fe..975167a458 100644 --- a/engines/mads/palette.h +++ b/engines/mads/palette.h @@ -309,13 +309,6 @@ public: */ void setLowRange(); - /** - * Set up the palette as the game ends - */ - void close() { - warning("TODO: Palette::close"); - } - void setColorFlags(byte r, byte g, byte b); void setColorValues(byte r, byte g, byte b); diff --git a/engines/mads/phantom/game_phantom.cpp b/engines/mads/phantom/game_phantom.cpp index 15ac241d8c..ba2179fcbf 100644 --- a/engines/mads/phantom/game_phantom.cpp +++ b/engines/mads/phantom/game_phantom.cpp @@ -41,22 +41,12 @@ GamePhantom::GamePhantom(MADSEngine *vm) _storyMode = STORYMODE_NAUGHTY; } -ProtectionResult GamePhantom::checkCopyProtection() { - /* - // DEBUG: Flag copy protection failure - _globals[5] = -1; - - if (!ConfMan.getBool("copy_protection")) - return true; - - * DEBUG: Disabled for now - CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); - dlg->show(); - delete dlg; - */ - - // DEBUG: Return that copy protection failed - return PROTECTION_SUCCEED; +void GamePhantom::startGame() { + _scene._priorSceneId = 0; + _scene._currentSceneId = -1; + _scene._nextSceneId = 101; + + initializeGlobals(); } void GamePhantom::initializeGlobals() { diff --git a/engines/mads/phantom/game_phantom.h b/engines/mads/phantom/game_phantom.h index 7a84ee1c72..99cc2c1230 100644 --- a/engines/mads/phantom/game_phantom.h +++ b/engines/mads/phantom/game_phantom.h @@ -78,7 +78,7 @@ class GamePhantom : public Game { protected: GamePhantom(MADSEngine *vm); - virtual ProtectionResult checkCopyProtection(); + virtual void startGame(); virtual void initializeGlobals(); diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp index ca953a0ec9..ffeed6cda8 100644 --- a/engines/mads/scene.cpp +++ b/engines/mads/scene.cpp @@ -451,8 +451,8 @@ void Scene::doFrame() { if (_vm->_game->_fx) { uint32 priorTime = _vm->_game->_priorFrameTimer; uint32 newTime = _vm->_events->getFrameCounter(); - _sequences.delay(newTime, priorTime); - _kernelMessages.delay(newTime, priorTime); + _sequences.delay(priorTime, newTime); + _kernelMessages.delay(priorTime, newTime); } if (_vm->_debugger->_showMousePos) diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp index 91aa3abdb0..7e8710db56 100644 --- a/engines/mads/screen.cpp +++ b/engines/mads/screen.cpp @@ -364,6 +364,17 @@ void ScreenObjects::check(bool scanFlag) { } } +int ScreenObjects::scan(const Common::Point &pt, int layer) { + for (uint i = 1; i <= size(); ++i) { + ScreenObject &sObj = (*this)[i]; + if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer) + return i; + } + + // Entry not found + return 0; +} + int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) { for (int i = (int)size(); i >= 1; --i) { ScreenObject &sObj = (*this)[i]; diff --git a/engines/mads/screen.h b/engines/mads/screen.h index a3653d6d62..7937e15456 100644 --- a/engines/mads/screen.h +++ b/engines/mads/screen.h @@ -165,10 +165,16 @@ public: void add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId); /** - */ + * Check objects on the screen + */ void check(bool scanFlag); /** + * Scan the registered screen objects + */ + int scan(const Common::Point &pt, int layer); + + /** * Handle an element being highlighted on the screen, and make it active. */ void elementHighlighted(); diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp index 34606bb2bf..07b1451718 100644 --- a/engines/mads/sequence.cpp +++ b/engines/mads/sequence.cpp @@ -473,8 +473,8 @@ int SequenceList::startReverseCycle(int srcSpriteIndex, bool flipped, int numTic int depth = _vm->_game->_scene._depthSurface.getDepth(Common::Point( frame->_offset.x + frame->w / 2, frame->_offset.y + frame->h / 2)); - return add(srcSpriteIndex, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, - numTicks, 0, 0, true, 100, depth - 1, 1, ANIMTYPE_REVERSIBLE, 0, 0); + return add(srcSpriteIndex, flipped, sprites->getCount(), triggerCountdown, timeoutTicks, + extraTicks, numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_REVERSIBLE, 0, 0); } void SequenceList::updateTimeout(int spriteIdx, int seqIndex) { diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index c67c905251..cd358077b5 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -54,14 +54,14 @@ typedef Common::List<DepthEntry> DepthList; /*------------------------------------------------------------------------*/ -MSprite::MSprite() - : MSurface() { +MSprite::MSprite() : MSurface() { + _transparencyIndex = TRANSPARENT_COLOR_INDEX; } MSprite::MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette, const Common::Rect &bounds) : MSurface(bounds.width(), bounds.height()), - _offset(Common::Point(bounds.left, bounds.top)), _transparencyIndex(0xFF) { + _offset(Common::Point(bounds.left, bounds.top)), _transparencyIndex(TRANSPARENT_COLOR_INDEX) { // Load the sprite data loadSprite(source, palette); } @@ -133,7 +133,7 @@ void MSprite::loadSprite(Common::SeekableReadStream *source, } byte MSprite::getTransparencyIndex() const { - return TRANSPARENT_COLOR_INDEX; + return _transparencyIndex; } /*------------------------------------------------------------------------*/ @@ -253,15 +253,14 @@ void SpriteSlots::drawBackground() { if (spriteSlot._scale != -1) { // Adjust the drawing position pt.x -= frame->w / 2; - pt.y -= frame->h / 2; + pt.y -= frame->h - 1; } - if (spriteSlot._depth <= 1) { frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex()); } else if (scene._depthStyle == 0) { scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface, - 100, frame->getTransparencyIndex()); + -1, false, frame->getTransparencyIndex()); } else { error("Unsupported depth style"); } diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 8c1cba7bd9..1f8d5037bc 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -154,7 +154,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) { bool flipped = slot._frameNumber < 0; if (slot._segmentId == IMG_SPINNING_OBJECT) { - MSprite *sprite = asset->getFrame(frameNumber); + MSprite *sprite = asset->getFrame(frameNumber - 1); sprite->copyTo(&userInterface, slot._position, sprite->getTransparencyIndex()); } else { @@ -487,7 +487,7 @@ void UserInterface::drawItemVocabList() { } } -void UserInterface::drawScrolller() { +void UserInterface::drawScroller() { if (_scrollbarActive) writeVocab(CAT_INV_SCROLLER, _scrollbarActive); writeVocab(CAT_INV_SCROLLER, 4); @@ -573,7 +573,7 @@ void UserInterface::scrollbarChanged() { Common::Rect r(73, 4, 73 + 9, 4 + 38); _uiSlots.add(r); _uiSlots.draw(false, false); - drawScrolller(); + drawScroller(); updateRect(r); } @@ -995,8 +995,8 @@ void UserInterface::selectObject(int invIndex) { noInventoryAnim(); } else { loadInventoryAnim(_vm->_game->_objects._inventoryList[invIndex]); - _vm->_palette->setPalette(_vm->_palette->_mainPalette, 7, 1); - _vm->_palette->setPalette(_vm->_palette->_mainPalette, 246, 2); + _vm->_palette->setPalette(&_vm->_palette->_mainPalette[7 * 3], 7, 1); + _vm->_palette->setPalette(&_vm->_palette->_mainPalette[246 * 3], 246, 2); } } diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h index 827fa3041f..f251441e40 100644 --- a/engines/mads/user_interface.h +++ b/engines/mads/user_interface.h @@ -180,7 +180,7 @@ private: /** * Draw the inventory scroller */ - void drawScrolller(); + void drawScroller(); /** * Called when the inventory scrollbar has changed diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 8a9c0f70fa..7632cde294 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -294,7 +294,7 @@ static const MohawkGameDescription gameDescriptions[] = { }, // Riven: The Sequel to Myst - // Version 1.? (5CD) + // Version 1.? (5CD) - Spanish // From jvprat { { @@ -312,6 +312,24 @@ static const MohawkGameDescription gameDescriptions[] = { }, // Riven: The Sequel to Myst + // Version 1.0 (5CD) - Italian + // From dodomorandi on bug #6629 + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "0e21e89df7788f32056b6521abf2e81a"), + Common::IT_ITA, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst // Version 1.? (DVD, From "Myst 10th Anniversary Edition") // From Clone2727 { diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp index 2a112435fc..a510c02558 100644 --- a/engines/neverhood/modules/module2700.cpp +++ b/engines/neverhood/modules/module2700.cpp @@ -461,6 +461,7 @@ void Module2700::updateScene() { _vm->_soundMan->deleteMusic(_musicFileHash); _vm->_soundMan->startMusic(0x04020210, 0, 2); _vm->_soundMan->deleteSoundGroup(0x42212411); + _radioMusicInitialized = false; createScene(20, 3); break; case 22: diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp index 3f16acc2f6..e1b7e25cd5 100644 --- a/engines/pegasus/input.cpp +++ b/engines/pegasus/input.cpp @@ -57,8 +57,10 @@ InputDeviceManager::InputDeviceManager() { _keyMap[Common::KEYCODE_p] = false; _keyMap[Common::KEYCODE_TILDE] = false; _keyMap[Common::KEYCODE_BACKQUOTE] = false; + _keyMap[Common::KEYCODE_KP7] = false; _keyMap[Common::KEYCODE_BACKSPACE] = false; _keyMap[Common::KEYCODE_KP_MULTIPLY] = false; + _keyMap[Common::KEYCODE_KP9] = false; _keyMap[Common::KEYCODE_LALT] = false; _keyMap[Common::KEYCODE_RALT] = false; _keyMap[Common::KEYCODE_e] = false; @@ -117,10 +119,14 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) { // events don't come as expected. In many cases, the key down event is sent many times // causing the drawer to open and close constantly until pressed again. It only causes // more grief than anything else. - if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE]) + + // The original doesn't use KP7 for inventory, but we're using it as an alternative for + // num lock. KP9 is used for the biochip drawer to balance things out. + + if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_KP7]) currentBits |= (kRawButtonDown << kLeftFireButtonShift); - if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY]) + if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY] || _keyMap[Common::KEYCODE_KP9]) currentBits |= (kRawButtonDown << kRightFireButtonShift); // Update mouse button state diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 65acdbcdf5..61fb717567 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -896,12 +896,25 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { gamestate_restore(s, in); delete in; - if (g_sci->getGameId() == GID_MOTHERGOOSE256) { + switch (g_sci->getGameId()) { + case GID_MOTHERGOOSE: + // WORKAROUND: Mother Goose SCI0 + // Script 200 / rm200::newRoom will set global C5h directly right after creating a child to the + // current number of children plus 1. + // We can't trust that global, that's why we set the actual savedgame id right here directly after + // restoring a saved game. + // If we didn't, the game would always save to a new slot + s->variables[VAR_GLOBAL][0xC5].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); + break; + case GID_MOTHERGOOSE256: // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for // saving a previously restored game. // We set the current savedgame-id directly and remove the script // code concerning this via script patch. s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); + break; + default: + break; } } else { s->r_acc = TRUE_REG; diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index f94c65c76b..7d106b5b02 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -43,8 +43,12 @@ GfxPaint32::~GfxPaint32() { void GfxPaint32::fillRect(Common::Rect rect, byte color) { int16 y, x; - for (y = rect.top; y < rect.bottom; y++) { - for (x = rect.left; x < rect.right; x++) { + Common::Rect clipRect = rect; + + clipRect.clip(_screen->getWidth(), _screen->getHeight()); + + for (y = clipRect.top; y < clipRect.bottom; y++) { + for (x = clipRect.left; x < clipRect.right; x++) { _screen->putPixel(x, y, GFX_SCREEN_MASK_VISUAL, color, 0, 0); } } diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 806881cc2a..c5c94d7991 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -778,6 +778,10 @@ void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x, Sci32ViewNativ } switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_480x300: + x = (x << 1) / 3; + y = (y << 1) / 3; + break; case GFX_SCREEN_UPSCALED_640x400: x /= 2; y /= 2; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index cf5192e1e6..fc723f18cf 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -511,6 +511,7 @@ void SciEngine::patchGameSaveRestore() { case GID_HOYLE1: // gets confused, although the game doesnt support saving/restoring at all case GID_HOYLE2: // gets confused, see hoyle1 case GID_JONES: // gets confused, when we patch us in, the game is only able to save to 1 slot, so hooking is not required + case GID_MOTHERGOOSE: // mother goose EGA saves/restores directly and has no save/restore dialogs case GID_MOTHERGOOSE256: // mother goose saves/restores directly and has no save/restore dialogs case GID_PHANTASMAGORIA: // has custom save/load code case GID_SHIVERS: // has custom save/load code diff --git a/engines/scumm/music.h b/engines/scumm/music.h index c5762ed24a..e170647560 100644 --- a/engines/scumm/music.h +++ b/engines/scumm/music.h @@ -24,10 +24,11 @@ #define SCUMM_MUSIC_H #include "common/scummsys.h" -#include "engines/scumm/saveload.h" namespace Scumm { +class Serializer; + /** * Pure virtual base class for the various music/sound engines used in Scumm * games. In particular, the iMuse code provides a subclass of this. There are diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp index 7b525116cf..5ed50ab65c 100644 --- a/engines/scumm/players/player_ad.cpp +++ b/engines/scumm/players/player_ad.cpp @@ -24,6 +24,7 @@ #include "scumm/imuse/imuse.h" #include "scumm/scumm.h" #include "scumm/resource.h" +#include "scumm/saveload.h" #include "audio/fmopl.h" @@ -62,9 +63,21 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer) _sfxTimer = 4; _rndSeed = 1; - memset(_channels, 0, sizeof(_channels)); - memset(_sfxResource, 0, sizeof(_sfxResource)); - memset(_sfxPriority, 0, sizeof(_sfxPriority)); + memset(_sfx, 0, sizeof(_sfx)); + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + _sfx[i].resource = -1; + for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) { + _sfx[i].channels[j].hardwareChannel = -1; + } + } + + memset(_hwChannels, 0, sizeof(_hwChannels)); + _numHWChannels = ARRAYSIZE(_hwChannels); + + memset(_voiceChannels, 0, sizeof(_voiceChannels)); + + _musicVolume = _sfxVolume = 255; + _isSeeking = false; } Player_AD::~Player_AD() { @@ -86,79 +99,57 @@ void Player_AD::setMusicVolume(int vol) { void Player_AD::startSound(int sound) { Common::StackLock lock(_mutex); + // Setup the sound volume + setupVolume(); + // Query the sound resource const byte *res = _vm->getResourceAddress(rtSound, sound); if (res[2] == 0x80) { // Stop the current sounds - stopAllSounds(); + stopMusic(); // Lock the new music resource _soundPlaying = sound; _vm->_res->lock(rtSound, _soundPlaying); // Start the new music resource - _resource = res; + _musicData = res; startMusic(); } else { - // Only try to start a sfx when no music is playing. - if (_soundPlaying == -1) { - const byte priority = res[0]; - const byte channel = res[1]; - - // Check for out of bounds access - if (channel >= 3) { - warning("AdLib sfx resource %d uses channel %d", sound, channel); - return; - } - - // Check whether the channel is free or the priority of the new - // sfx resource is above the old one. - if (_channels[channel * 3 + 0].state - || _channels[channel * 3 + 1].state - || _channels[channel * 3 + 2].state) { - if (_sfxPriority[channel] > priority) { - return; - } - } + const byte priority = res[0]; + // The original specified the channel to use in the sound + // resource. However, since we play as much as possible we sill + // ignore it and simply use the priority value to determine + // whether the sfx can be played or not. + //const byte channel = res[1]; + + // Try to allocate a sfx slot for playback. + SfxSlot *sfx = allocateSfxSlot(priority); + if (!sfx) { + ::debugC(3, DEBUG_SOUND, "AdLib: No free sfx slot for sound %d", sound); + return; + } + // Try to start sfx playback + sfx->resource = sound; + sfx->priority = priority; + if (startSfx(sfx, res)) { // Lock the new resource - _sfxResource[channel] = sound; - _sfxPriority[channel] = priority; _vm->_res->lock(rtSound, sound); - - // Start the actual sfx resource - _resource = res; - startSfx(); } } - - // Setup the sound volume - setupVolume(); } void Player_AD::stopSound(int sound) { Common::StackLock lock(_mutex); if (sound == _soundPlaying) { - stopAllSounds(); + stopMusic(); } else { - for (int i = 0; i < 3; ++i) { - if (_sfxResource[i] == sound) { - if (_channels[i * 3 + 0].state - || _channels[i * 3 + 1].state - || _channels[i * 3 + 2].state) { - // Unlock the sound resource - _vm->_res->unlock(rtSound, sound); - - // Stop the actual sfx playback - _channels[i * 3 + 0].state = 0; - _channels[i * 3 + 1].state = 0; - _channels[i * 3 + 2].state = 0; - clearChannel(i * 3 + 0); - clearChannel(i * 3 + 1); - clearChannel(i * 3 + 2); - } + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + if (_sfx[i].resource == sound) { + stopSfx(&_sfx[i]); } } } @@ -167,29 +158,13 @@ void Player_AD::stopSound(int sound) { void Player_AD::stopAllSounds() { Common::StackLock lock(_mutex); - // Unlock the music resource if present - if (_soundPlaying != -1) { - _vm->_res->unlock(rtSound, _soundPlaying); - _soundPlaying = -1; - } - - // Stop the music playback - _curOffset = 0; + // Stop the music + stopMusic(); - // Unloack all used sfx resources - for (int i = 0; i < 3; ++i) { - if (_channels[i * 3 + 0].state || _channels[i * 3 + 1].state || _channels[i * 3 + 2].state) { - _vm->_res->unlock(rtSound, _sfxResource[i]); - } - } - - // Reset all the sfx channels - for (int i = 0; i < 9; ++i) { - _channels[i].state = 0; - clearChannel(i); + // Stop all the sfx playback + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + stopSfx(&_sfx[i]); } - - writeReg(0xBD, 0x00); } int Player_AD::getMusicTimer() { @@ -210,8 +185,51 @@ void Player_AD::saveLoadWithSerializer(Serializer *ser) { return; } - // TODO: Be nicer than the original and save the data to continue the - // currently played sound resources on load? + if (ser->getVersion() >= VER(96)) { + int32 res[4] = { + _soundPlaying, _sfx[0].resource, _sfx[1].resource, _sfx[2].resource + }; + + // The first thing we save is a list of sound resources being played + // at the moment. + ser->saveLoadArrayOf(res, 4, sizeof(res[0]), sleInt32); + + // If we are loading start the music again at this point. + if (ser->isLoading()) { + if (res[0] != -1) { + startSound(res[0]); + } + } + + uint32 musicOffset = _curOffset; + + static const SaveLoadEntry musicData[] = { + MKLINE(Player_AD, _engineMusicTimer, sleInt32, VER(96)), + MKLINE(Player_AD, _musicTimer, sleUint32, VER(96)), + MKLINE(Player_AD, _internalMusicTimer, sleUint32, VER(96)), + MKLINE(Player_AD, _curOffset, sleUint32, VER(96)), + MKLINE(Player_AD, _nextEventTimer, sleUint32, VER(96)), + MKEND() + }; + + ser->saveLoadEntries(this, musicData); + + // We seek back to the old music position. + if (ser->isLoading()) { + SWAP(musicOffset, _curOffset); + musicSeekTo(musicOffset); + } + + // Finally start up the SFX. This makes sure that they are not + // accidently stopped while seeking to the old music position. + if (ser->isLoading()) { + for (int i = 1; i < ARRAYSIZE(res); ++i) { + if (res[i] != -1) { + startSound(res[i]); + } + } + } + } } int Player_AD::readBuffer(int16 *buffer, const int numSamples) { @@ -221,14 +239,12 @@ int Player_AD::readBuffer(int16 *buffer, const int numSamples) { while (len > 0) { if (!_samplesTillCallback) { - // Run the update callback for music or sfx depending on which is - // active. if (_curOffset) { updateMusic(); - } else { - updateSfx(); } + updateSfx(); + _samplesTillCallback = _samplesPerCallback; _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; if (_samplesTillCallbackRemainder >= AD_CALLBACK_FREQUENCY) { @@ -250,29 +266,134 @@ int Player_AD::readBuffer(int16 *buffer, const int numSamples) { void Player_AD::setupVolume() { // Setup the correct volume - int soundVolumeMusic = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume); - int soundVolumeSfx = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume); + _musicVolume = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume); + _sfxVolume = CLIP<int>(ConfMan.getInt("sfx_volume"), 0, Audio::Mixer::kMaxChannelVolume); + if (ConfMan.hasKey("mute")) { if (ConfMan.getBool("mute")) { - soundVolumeMusic = 0; - soundVolumeSfx = 0; + _musicVolume = 0; + _sfxVolume = 0; } } - // In case a music is being played set the music volume. Set the sfx - // volume otherwise. This is safe because in the latter case either - // sfx are playing or there is no sound being played at all. - if (_soundPlaying != -1) { - _mixer->setChannelVolume(_soundHandle, soundVolumeMusic); - } else { - _mixer->setChannelVolume(_soundHandle, soundVolumeSfx); + // Update current output levels + for (int i = 0; i < ARRAYSIZE(_operatorOffsetTable); ++i) { + const uint reg = 0x40 + _operatorOffsetTable[i]; + writeReg(reg, readReg(reg)); + } + + // Reset note on status + for (int i = 0; i < ARRAYSIZE(_hwChannels); ++i) { + const uint reg = 0xB0 + i; + writeReg(reg, readReg(reg)); } } +int Player_AD::allocateHWChannel(int priority, SfxSlot *owner) { + // First pass: Check whether there's any unallocated channel + for (int i = 0; i < _numHWChannels; ++i) { + if (!_hwChannels[i].allocated) { + _hwChannels[i].allocated = true; + _hwChannels[i].priority = priority; + _hwChannels[i].sfxOwner = owner; + return i; + } + } + + // Second pass: Reassign channels based on priority + for (int i = 0; i < _numHWChannels; ++i) { + if (_hwChannels[i].priority <= priority) { + // In case the HW channel belongs to a SFX we will completely + // stop playback of that SFX. + // TODO: Maybe be more fine grained in the future and allow + // detachment of individual channels of a SFX? + if (_hwChannels[i].sfxOwner) { + stopSfx(_hwChannels[i].sfxOwner); + } + _hwChannels[i].allocated = true; + _hwChannels[i].priority = priority; + _hwChannels[i].sfxOwner = owner; + return i; + } + } + + return -1; +} + +void Player_AD::freeHWChannel(int channel) { + assert(_hwChannels[channel].allocated); + _hwChannels[channel].allocated = false; + _hwChannels[channel].sfxOwner = nullptr; +} + +void Player_AD::limitHWChannels(int newCount) { + for (int i = newCount; i < ARRAYSIZE(_hwChannels); ++i) { + if (_hwChannels[i].allocated) { + freeHWChannel(i); + } + } + _numHWChannels = newCount; +} + +const int Player_AD::_operatorOffsetToChannel[22] = { + 0, 1, 2, 0, 1, 2, -1, -1, + 3, 4, 5, 3, 4, 5, -1, -1, + 6, 7, 8, 6, 7, 8 +}; + void Player_AD::writeReg(int r, int v) { if (r >= 0 && r < ARRAYSIZE(_registerBackUpTable)) { _registerBackUpTable[r] = v; } + + // Handle volume scaling depending on the sound type. + if (r >= 0x40 && r <= 0x55) { + const int operatorOffset = r - 0x40; + const int channel = _operatorOffsetToChannel[operatorOffset]; + if (channel != -1) { + const bool twoOPOutput = (readReg(0xC0 + channel) & 0x01) != 0; + + int scale = Audio::Mixer::kMaxChannelVolume; + // We only scale the volume of operator 2 unless both operators + // are set to directly produce sound. + if (twoOPOutput || operatorOffset == _operatorOffsetTable[channel * 2 + 1]) { + if (_hwChannels[channel].sfxOwner) { + scale = _sfxVolume; + } else { + scale = _musicVolume; + } + } + + int vol = 0x3F - (v & 0x3F); + vol = vol * scale / Audio::Mixer::kMaxChannelVolume; + v &= 0xC0; + v |= (0x3F - vol); + } + } + + // Since AdLib's lowest volume level does not imply that the sound is + // completely silent we ignore key on in such a case. + // We also ignore key on for music whenever we do seeking. + if (r >= 0xB0 && r <= 0xB8) { + const int channel = r - 0xB0; + bool mute = false; + if (_hwChannels[channel].sfxOwner) { + if (!_sfxVolume) { + mute = true; + } + } else { + if (!_musicVolume) { + mute = true; + } else { + mute = _isSeeking; + } + } + + if (mute) { + v &= ~0x20; + } + } + _opl2->writeReg(r, v); } @@ -311,26 +432,23 @@ const int Player_AD::_operatorOffsetTable[18] = { void Player_AD::startMusic() { memset(_instrumentOffset, 0, sizeof(_instrumentOffset)); - memset(_channelLastEvent, 0, sizeof(_channelLastEvent)); - memset(_channelFrequency, 0, sizeof(_channelFrequency)); - memset(_channelB0Reg, 0, sizeof(_channelB0Reg)); - _voiceChannels = 0; - uint instruments = _resource[10]; + bool hasRhythmData = false; + uint instruments = _musicData[10]; for (uint i = 0; i < instruments; ++i) { - const int instrIndex = _resource[11 + i] - 1; + const int instrIndex = _musicData[11 + i] - 1; if (0 <= instrIndex && instrIndex < 16) { _instrumentOffset[instrIndex] = i * 16 + 16 + 3; - _voiceChannels |= _resource[_instrumentOffset[instrIndex] + 13]; + hasRhythmData |= (_musicData[_instrumentOffset[instrIndex] + 13] != 0); } } - if (_voiceChannels) { + if (hasRhythmData) { _mdvdrState = 0x20; - _voiceChannels = 6; + limitHWChannels(6); } else { _mdvdrState = 0; - _voiceChannels = 9; + limitHWChannels(9); } _curOffset = 0x93; @@ -344,9 +462,33 @@ void Player_AD::startMusic() { const bool isLoom = (_vm->_game.id == GID_LOOM); _timerLimit = isLoom ? 473 : 256; - _musicTicks = _resource[3] * (isLoom ? 2 : 1); - _loopFlag = (_resource[4] == 0); - _musicLoopStart = READ_LE_UINT16(_resource + 5); + _musicTicks = _musicData[3] * (isLoom ? 2 : 1); + _loopFlag = (_musicData[4] == 0); + _musicLoopStart = _curOffset + READ_LE_UINT16(_musicData + 5); +} + +void Player_AD::stopMusic() { + if (_soundPlaying == -1) { + return; + } + + // Unlock the music resource if present + _vm->_res->unlock(rtSound, _soundPlaying); + _soundPlaying = -1; + + // Stop the music playback + _curOffset = 0; + + // Stop all music voice channels + for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) { + if (_voiceChannels[i].lastEvent) { + noteOff(i); + } + } + + // Reset rhythm state + writeReg(0xBD, 0x00); + limitHWChannels(9); } void Player_AD::updateMusic() { @@ -368,129 +510,142 @@ void Player_AD::updateMusic() { } while (true) { - uint command = _resource[_curOffset++]; - if (command == 0xFF) { - // META EVENT - // Get the command number. - command = _resource[_curOffset++]; - if (command == 47) { - // End of track - if (_loopFlag) { - // In case the track is looping jump to the start. - _curOffset = _musicLoopStart; - _nextEventTimer = 0; - } else { - // Otherwise completely stop playback. - stopAllSounds(); - } + if (parseCommand()) { + // We received an EOT command. In case there's no music playing + // we know there was no looping enabled. Thus, we stop further + // handling. Otherwise we will just continue parsing. It is + // important to note that we need to parse a command directly + // at the new position, i.e. there is no time value we need to + // parse. + if (_soundPlaying == -1) { return; - } else if (command == 88) { - // This is proposedly a debug information insertion. The CMS - // player code handles this differently, but is still using - // the same resources... - _curOffset += 5; - } else if (command == 81) { - // Change tempo. This is used exclusively in Loom. - const uint timing = _resource[_curOffset + 2] | (_resource[_curOffset + 1] << 8); - _musicTicks = 0x73000 / timing; - command = _resource[_curOffset++]; - _curOffset += command; } else { - // In case an unknown meta event occurs just skip over the - // data by using the length supplied. - command = _resource[_curOffset++]; - _curOffset += command; + continue; } - } else { - if (command >= 0x90) { - // NOTE ON - // Extract the channel number and save it in command. - command -= 0x90; - - const uint instrOffset = _instrumentOffset[command]; - if (instrOffset) { - if (_resource[instrOffset + 13] != 0) { - setupRhythm(_resource[instrOffset + 13], instrOffset); - } else { - int channel = findFreeChannel(); - if (channel != -1) { - noteOff(channel); - setupChannel(channel, instrOffset); - _channelLastEvent[channel] = command + 0x90; - _channelFrequency[channel] = _resource[_curOffset]; - setupFrequency(channel, _resource[_curOffset]); - } - } - } - } else { - // NOTE OFF - const uint note = _resource[_curOffset]; - command += 0x10; - - // Find the output channel which plays the note. - uint channel = 0xFF; - for (uint i = 0; i < _voiceChannels; ++i) { - if (_channelFrequency[i] == note && _channelLastEvent[i] == command) { - channel = i; - break; - } - } - - if (channel != 0xFF) { - // In case a output channel playing the note was found, - // stop it. - noteOff(channel); - } else { - // In case there is no such note this will disable the - // rhythm instrument played on the channel. - command -= 0x90; - const uint instrOffset = _instrumentOffset[command]; - if (instrOffset && _resource[instrOffset + 13] != 0) { - const uint rhythmInstr = _resource[instrOffset + 13]; - if (rhythmInstr < 6) { - _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF; - writeReg(0xBD, _mdvdrState); - } - } - } - } - - _curOffset += 2; } // In case there is a delay till the next event stop handling. - if (_resource[_curOffset] != 0) { + if (_musicData[_curOffset] != 0) { break; } ++_curOffset; } - _nextEventTimer = _resource[_curOffset++]; - if (_nextEventTimer & 0x80) { - _nextEventTimer -= 0x80; - _nextEventTimer <<= 7; - _nextEventTimer |= _resource[_curOffset++]; - } - + _nextEventTimer = parseVLQ(); _nextEventTimer >>= (_vm->_game.id == GID_LOOM) ? 2 : 1; if (!_nextEventTimer) { _nextEventTimer = 1; } } -void Player_AD::noteOff(uint channel) { - _channelLastEvent[channel] = 0; - writeReg(0xB0 + channel, _channelB0Reg[channel] & 0xDF); -} +bool Player_AD::parseCommand() { + uint command = _musicData[_curOffset++]; + if (command == 0xFF) { + // META EVENT + // Get the command number. + command = _musicData[_curOffset++]; + if (command == 47) { + // End of track + if (_loopFlag) { + // In case the track is looping jump to the start. + _curOffset = _musicLoopStart; + _nextEventTimer = 0; + } else { + // Otherwise completely stop playback. + stopMusic(); + } + return true; + } else if (command == 88) { + // This is proposedly a debug information insertion. The CMS + // player code handles this differently, but is still using + // the same resources... + _curOffset += 5; + } else if (command == 81) { + // Change tempo. This is used exclusively in Loom. + const uint timing = _musicData[_curOffset + 2] | (_musicData[_curOffset + 1] << 8); + _musicTicks = 0x73000 / timing; + command = _musicData[_curOffset++]; + _curOffset += command; + } else { + // In case an unknown meta event occurs just skip over the + // data by using the length supplied. + command = _musicData[_curOffset++]; + _curOffset += command; + } + } else { + if (command >= 0x90) { + // NOTE ON + // Extract the channel number and save it in command. + command -= 0x90; + + const uint instrOffset = _instrumentOffset[command]; + if (instrOffset) { + if (_musicData[instrOffset + 13] != 0) { + setupRhythm(_musicData[instrOffset + 13], instrOffset); + } else { + // Priority 256 makes sure we always prefer music + // channels over SFX channels. + int channel = allocateHWChannel(256); + if (channel != -1) { + setupChannel(channel, _musicData + instrOffset); + _voiceChannels[channel].lastEvent = command + 0x90; + _voiceChannels[channel].frequency = _musicData[_curOffset]; + setupFrequency(channel, _musicData[_curOffset]); + } + } + } + } else { + // NOTE OFF + const uint note = _musicData[_curOffset]; + command += 0x10; + + // Find the output channel which plays the note. + uint channel = 0xFF; + for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) { + if (_voiceChannels[i].frequency == note && _voiceChannels[i].lastEvent == command) { + channel = i; + break; + } + } -int Player_AD::findFreeChannel() { - for (uint i = 0; i < _voiceChannels; ++i) { - if (!_channelLastEvent[i]) { - return i; + if (channel != 0xFF) { + // In case a output channel playing the note was found, + // stop it. + noteOff(channel); + } else { + // In case there is no such note this will disable the + // rhythm instrument played on the channel. + command -= 0x90; + const uint instrOffset = _instrumentOffset[command]; + if (instrOffset && _musicData[instrOffset + 13] != 0) { + const uint rhythmInstr = _musicData[instrOffset + 13]; + if (rhythmInstr < 6) { + _mdvdrState &= _mdvdrTable[rhythmInstr] ^ 0xFF; + writeReg(0xBD, _mdvdrState); + } + } + } } + + _curOffset += 2; } - return -1; + return false; +} + +uint Player_AD::parseVLQ() { + uint vlq = _musicData[_curOffset++]; + if (vlq & 0x80) { + vlq -= 0x80; + vlq <<= 7; + vlq |= _musicData[_curOffset++]; + } + return vlq; +} + +void Player_AD::noteOff(uint channel) { + writeReg(0xB0 + channel, _voiceChannels[channel].b0Reg & 0xDF); + freeVoiceChannel(channel); } void Player_AD::setupFrequency(uint channel, int8 frequency) { @@ -510,28 +665,67 @@ void Player_AD::setupFrequency(uint channel, int8 frequency) { octave |= noteFrequency >> 8; octave |= 0x20; writeReg(0xA0 + channel, noteFrequency & 0xFF); - _channelB0Reg[channel] = octave; + _voiceChannels[channel].b0Reg = octave; writeReg(0xB0 + channel, octave); } void Player_AD::setupRhythm(uint rhythmInstr, uint instrOffset) { if (rhythmInstr == 1) { - setupChannel(6, instrOffset); - writeReg(0xA6, _resource[instrOffset++]); - writeReg(0xB6, _resource[instrOffset] & 0xDF); + setupChannel(6, _musicData + instrOffset); + writeReg(0xA6, _musicData[instrOffset++]); + writeReg(0xB6, _musicData[instrOffset] & 0xDF); _mdvdrState |= 0x10; writeReg(0xBD, _mdvdrState); } else if (rhythmInstr < 6) { - const byte *secondOperatorOffset = _resource + instrOffset + 8; + const byte *secondOperatorOffset = _musicData + instrOffset + 8; setupOperator(_rhythmOperatorTable[rhythmInstr], secondOperatorOffset); - writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++]); - writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset++] & 0xDF); - writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _resource[instrOffset]); + writeReg(0xA0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset++]); + writeReg(0xB0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset++] & 0xDF); + writeReg(0xC0 + _rhythmChannelTable[rhythmInstr], _musicData[instrOffset]); _mdvdrState |= _mdvdrTable[rhythmInstr]; writeReg(0xBD, _mdvdrState); } } +void Player_AD::freeVoiceChannel(uint channel) { + VoiceChannel &vChannel = _voiceChannels[channel]; + assert(vChannel.lastEvent); + + freeHWChannel(channel); + vChannel.lastEvent = 0; + vChannel.b0Reg = 0; + vChannel.frequency = 0; +} + +void Player_AD::musicSeekTo(const uint position) { + // This method is actually dangerous to use and should only be used for + // loading save games because it does not set up anything like the engine + // music timer or similar. + _isSeeking = true; + + // Seek until the given position. + while (_curOffset != position) { + if (parseCommand()) { + // We encountered an EOT command. This should not happen unless + // we try to seek to an illegal position. In this case just abort + // seeking. + ::debugC(3, DEBUG_SOUND, "AD illegal seek to %u", position); + break; + } + parseVLQ(); + } + + _isSeeking = false; + + // Turn on all notes. + for (int i = 0; i < ARRAYSIZE(_voiceChannels); ++i) { + if (_voiceChannels[i].lastEvent != 0) { + const int reg = 0xB0 + i; + writeReg(reg, readReg(reg)); + } + } +} + const uint Player_AD::_noteFrequencies[12] = { 0x200, 0x21E, 0x23F, 0x261, 0x285, 0x2AB, 0x2D4, 0x300, @@ -552,29 +746,47 @@ const uint Player_AD::_rhythmChannelTable[6] = { // SFX -void Player_AD::startSfx() { - writeReg(0xBD, 0x00); +Player_AD::SfxSlot *Player_AD::allocateSfxSlot(int priority) { + // First pass: Check whether there's a unused slot + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + if (_sfx[i].resource == -1) { + return &_sfx[i]; + } + } + + // Second pass: Look for a slot with lower priority + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + if (_sfx[i].priority <= priority) { + // Stop the old sfx + stopSfx(&_sfx[i]); + return &_sfx[i]; + } + } - // The second byte of the resource defines the logical channel where - // the sound effect should be played. - const int startChannel = _resource[1] * 3; + return nullptr; +} - // Clear the channel. - _channels[startChannel + 0].state = 0; - _channels[startChannel + 1].state = 0; - _channels[startChannel + 2].state = 0; +bool Player_AD::startSfx(SfxSlot *sfx, const byte *resource) { + writeReg(0xBD, 0x00); - clearChannel(startChannel + 0); - clearChannel(startChannel + 1); - clearChannel(startChannel + 2); + // Clear the channels. + sfx->channels[0].state = kChannelStateOff; + sfx->channels[1].state = kChannelStateOff; + sfx->channels[2].state = kChannelStateOff; // Set up the first channel to pick up playback. - _channels[startChannel].currentOffset = _channels[startChannel].startOffset = _resource + 2; - _channels[startChannel].state = 1; + // Try to allocate a hardware channel. + sfx->channels[0].hardwareChannel = allocateHWChannel(sfx->priority, sfx); + if (sfx->channels[0].hardwareChannel == -1) { + ::debugC(3, DEBUG_SOUND, "AD No hardware channel available"); + return false; + } + sfx->channels[0].currentOffset = sfx->channels[0].startOffset = resource + 2; + sfx->channels[0].state = kChannelStateParse; // Scan for the start of the other channels and set them up if required. - int curChannel = startChannel + 1; - const byte *bufferPosition = _resource + 2; + int curChannel = 1; + const byte *bufferPosition = resource + 2; uint8 command = 0; while ((command = *bufferPosition) != 0xFF) { switch (command) { @@ -596,13 +808,46 @@ void Player_AD::startSfx() { default: // START OF CHANNEL bufferPosition += 1; - _channels[curChannel].currentOffset = bufferPosition; - _channels[curChannel].startOffset = bufferPosition; - _channels[curChannel].state = 1; + if (curChannel >= 3) { + error("AD SFX resource %d uses more than 3 channels", sfx->resource); + } + sfx->channels[curChannel].hardwareChannel = allocateHWChannel(sfx->priority, sfx); + if (sfx->channels[curChannel].hardwareChannel == -1) { + ::debugC(3, DEBUG_SOUND, "AD No hardware channel available"); + return false; + } + sfx->channels[curChannel].currentOffset = bufferPosition; + sfx->channels[curChannel].startOffset = bufferPosition; + sfx->channels[curChannel].state = kChannelStateParse; ++curChannel; break; } } + + return true; +} + +void Player_AD::stopSfx(SfxSlot *sfx) { + if (sfx->resource == -1) { + return; + } + + // 1. step: Clear all the channels. + for (int i = 0; i < ARRAYSIZE(sfx->channels); ++i) { + if (sfx->channels[i].state) { + clearChannel(sfx->channels[i]); + sfx->channels[i].state = kChannelStateOff; + } + + if (sfx->channels[i].hardwareChannel != -1) { + freeHWChannel(sfx->channels[i].hardwareChannel); + sfx->channels[i].hardwareChannel = -1; + } + } + + // 2. step: Unlock the resource. + _vm->_res->unlock(rtSound, sfx->resource); + sfx->resource = -1; } void Player_AD::updateSfx() { @@ -611,64 +856,75 @@ void Player_AD::updateSfx() { } _sfxTimer = 4; - for (int i = 0; i <= 9; ++i) { - if (!_channels[i].state) { + for (int i = 0; i < ARRAYSIZE(_sfx); ++i) { + if (_sfx[i].resource == -1) { continue; } - updateChannel(i); + bool hasActiveChannel = false; + for (int j = 0; j < ARRAYSIZE(_sfx[i].channels); ++j) { + if (_sfx[i].channels[j].state) { + hasActiveChannel = true; + updateChannel(&_sfx[i].channels[j]); + } + } + + // In case no channel is active we will stop the sfx. + if (!hasActiveChannel) { + stopSfx(&_sfx[i]); + } } } -void Player_AD::clearChannel(int channel) { - writeReg(0xA0 + channel, 0x00); - writeReg(0xB0 + channel, 0x00); +void Player_AD::clearChannel(const Channel &channel) { + writeReg(0xA0 + channel.hardwareChannel, 0x00); + writeReg(0xB0 + channel.hardwareChannel, 0x00); } -void Player_AD::updateChannel(int channel) { - if (_channels[channel].state == 1) { +void Player_AD::updateChannel(Channel *channel) { + if (channel->state == kChannelStateParse) { parseSlot(channel); } else { updateSlot(channel); } } -void Player_AD::parseSlot(int channel) { +void Player_AD::parseSlot(Channel *channel) { while (true) { - const byte *curOffset = _channels[channel].currentOffset; + const byte *curOffset = channel->currentOffset; switch (*curOffset) { case 1: // INSTRUMENT DEFINITION ++curOffset; - _channels[channel].instrumentData[0] = *(curOffset + 0); - _channels[channel].instrumentData[1] = *(curOffset + 2); - _channels[channel].instrumentData[2] = *(curOffset + 9); - _channels[channel].instrumentData[3] = *(curOffset + 8); - _channels[channel].instrumentData[4] = *(curOffset + 4); - _channels[channel].instrumentData[5] = *(curOffset + 3); - _channels[channel].instrumentData[6] = 0; + channel->instrumentData[0] = *(curOffset + 0); + channel->instrumentData[1] = *(curOffset + 2); + channel->instrumentData[2] = *(curOffset + 9); + channel->instrumentData[3] = *(curOffset + 8); + channel->instrumentData[4] = *(curOffset + 4); + channel->instrumentData[5] = *(curOffset + 3); + channel->instrumentData[6] = 0; - setupChannel(channel, curOffset); + setupChannel(channel->hardwareChannel, curOffset); - writeReg(0xA0 + channel, *(curOffset + 0)); - writeReg(0xB0 + channel, *(curOffset + 1) & 0xDF); + writeReg(0xA0 + channel->hardwareChannel, *(curOffset + 0)); + writeReg(0xB0 + channel->hardwareChannel, *(curOffset + 1) & 0xDF); - _channels[channel].currentOffset += 15; + channel->currentOffset += 15; break; case 2: // NOTE DEFINITION ++curOffset; - _channels[channel].state = 2; - noteOffOn(channel); - parseNote(channel, 0, curOffset); - parseNote(channel, 1, curOffset); + channel->state = kChannelStatePlay; + noteOffOn(channel->hardwareChannel); + parseNote(&channel->notes[0], *channel, curOffset + 0); + parseNote(&channel->notes[1], *channel, curOffset + 5); return; case 0x80: // LOOP - _channels[channel].currentOffset = _channels[channel].startOffset; + channel->currentOffset = channel->startOffset; break; default: @@ -676,120 +932,106 @@ void Player_AD::parseSlot(int channel) { // When we encounter a start of another channel while playback // it means that the current channel is finished. Thus, we will // stop it. - clearChannel(channel); - _channels[channel].state = 0; - - // If no channel of the sound effect is playing anymore, unlock - // the resource. - channel /= 3; - if (!_channels[channel + 0].state - && !_channels[channel + 1].state - && !_channels[channel + 2].state) { - _vm->_res->unlock(rtSound, _sfxResource[channel]); - } + clearChannel(*channel); + channel->state = kChannelStateOff; return; } } } -void Player_AD::updateSlot(int channel) { - const byte *curOffset = _channels[channel].currentOffset + 1; +void Player_AD::updateSlot(Channel *channel) { + const byte *curOffset = channel->currentOffset + 1; for (int num = 0; num <= 1; ++num, curOffset += 5) { if (!(*curOffset & 0x80)) { continue; } - const int note = channel * 2 + num; + Note *const note = &channel->notes[num]; bool updateNote = false; - if (_notes[note].state == 2) { - if (!--_notes[note].sustainTimer) { + if (note->state == kNoteStateSustain) { + if (!--note->sustainTimer) { updateNote = true; } } else { - updateNote = processNoteEnvelope(note, _notes[note].instrumentValue); + updateNote = processNoteEnvelope(note); - if (_notes[note].bias) { - writeRegisterSpecial(note, _notes[note].bias - _notes[note].instrumentValue, *curOffset & 0x07); + if (note->bias) { + writeRegisterSpecial(channel->hardwareChannel, note->bias - note->instrumentValue, *curOffset & 0x07); } else { - writeRegisterSpecial(note, _notes[note].instrumentValue, *curOffset & 0x07); + writeRegisterSpecial(channel->hardwareChannel, note->instrumentValue, *curOffset & 0x07); } } if (updateNote) { - if (processNote(note, curOffset)) { + if (processNote(note, *channel, curOffset)) { if (!(*curOffset & 0x08)) { - _channels[channel].currentOffset += 11; - _channels[channel].state = 1; + channel->currentOffset += 11; + channel->state = kChannelStateParse; continue; } else if (*curOffset & 0x10) { - noteOffOn(channel); + noteOffOn(channel->hardwareChannel); } - _notes[note].state = -1; - processNote(note, curOffset); + note->state = kNoteStatePreInit; + processNote(note, *channel, curOffset); } } - if ((*curOffset & 0x20) && !--_notes[note].playTime) { - _channels[channel].currentOffset += 11; - _channels[channel].state = 1; + if ((*curOffset & 0x20) && !--note->playTime) { + channel->currentOffset += 11; + channel->state = kChannelStateParse; } } } -void Player_AD::parseNote(int channel, int num, const byte *offset) { - if (num) { - offset += 5; - } - +void Player_AD::parseNote(Note *note, const Channel &channel, const byte *offset) { if (*offset & 0x80) { - const int note = channel * 2 + num; - _notes[note].state = -1; - processNote(note, offset); - _notes[note].playTime = 0; + note->state = kNoteStatePreInit; + processNote(note, channel, offset); + note->playTime = 0; if (*offset & 0x20) { - _notes[note].playTime = (*(offset + 4) >> 4) * 118; - _notes[note].playTime += (*(offset + 4) & 0x0F) * 8; + note->playTime = (*(offset + 4) >> 4) * 118; + note->playTime += (*(offset + 4) & 0x0F) * 8; } } } -bool Player_AD::processNote(int note, const byte *offset) { - if (++_notes[note].state == 4) { +bool Player_AD::processNote(Note *note, const Channel &channel, const byte *offset) { + if (++note->state == kNoteStateOff) { return true; } const int instrumentDataOffset = *offset & 0x07; - _notes[note].bias = _noteBiasTable[instrumentDataOffset]; + note->bias = _noteBiasTable[instrumentDataOffset]; uint8 instrumentDataValue = 0; - if (_notes[note].state == 0) { - instrumentDataValue = _channels[note / 2].instrumentData[instrumentDataOffset]; + if (note->state == kNoteStateAttack) { + instrumentDataValue = channel.instrumentData[instrumentDataOffset]; } - uint8 noteInstrumentValue = readRegisterSpecial(note, instrumentDataValue, instrumentDataOffset); - if (_notes[note].bias) { - noteInstrumentValue = _notes[note].bias - noteInstrumentValue; + uint8 noteInstrumentValue = readRegisterSpecial(channel.hardwareChannel, instrumentDataValue, instrumentDataOffset); + if (note->bias) { + noteInstrumentValue = note->bias - noteInstrumentValue; } - _notes[note].instrumentValue = noteInstrumentValue; + note->instrumentValue = noteInstrumentValue; - if (_notes[note].state == 2) { - _notes[note].sustainTimer = _numStepsTable[*(offset + 3) >> 4]; + if (note->state == kNoteStateSustain) { + note->sustainTimer = _numStepsTable[*(offset + 3) >> 4]; if (*offset & 0x40) { - _notes[note].sustainTimer = (((getRnd() << 8) * _notes[note].sustainTimer) >> 16) + 1; + note->sustainTimer = (((getRnd() << 8) * note->sustainTimer) >> 16) + 1; } } else { int timer1, timer2; - if (_notes[note].state == 3) { + if (note->state == kNoteStateRelease) { timer1 = *(offset + 3) & 0x0F; timer2 = 0; } else { - timer1 = *(offset + _notes[note].state + 1) >> 4; - timer2 = *(offset + _notes[note].state + 1) & 0x0F; + timer1 = *(offset + note->state + 1) >> 4; + timer2 = *(offset + note->state + 1) & 0x0F; } int adjustValue = ((_noteAdjustTable[timer2] * _noteAdjustScaleTable[instrumentDataOffset]) >> 16) - noteInstrumentValue; @@ -805,19 +1047,16 @@ void Player_AD::noteOffOn(int channel) { writeReg(0xB0 | channel, regValue | 0x20); } -void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) { +void Player_AD::writeRegisterSpecial(int channel, uint8 value, int offset) { if (offset == 6) { return; } - // Division by 2 extracts the channel number out of the note. - note /= 2; - uint8 regNum; if (_useOperatorTable[offset]) { - regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2]; + regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + channel * 2]; } else { - regNum = _channelOffsetTable[note]; + regNum = _channelOffsetTable[channel]; } regNum += _baseRegisterTable[offset]; @@ -828,19 +1067,16 @@ void Player_AD::writeRegisterSpecial(int note, uint8 value, int offset) { writeReg(regNum, regValue); } -uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) { +uint8 Player_AD::readRegisterSpecial(int channel, uint8 defaultValue, int offset) { if (offset == 6) { return 0; } - // Division by 2 extracts the channel number out of the note. - note /= 2; - uint8 regNum; if (_useOperatorTable[offset]) { - regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + note * 2]; + regNum = _operatorOffsetTable[_channelOperatorOffsetTable[offset] + channel * 2]; } else { - regNum = _channelOffsetTable[note]; + regNum = _channelOffsetTable[channel]; } regNum += _baseRegisterTable[offset]; @@ -858,39 +1094,39 @@ uint8 Player_AD::readRegisterSpecial(int note, uint8 defaultValue, int offset) { return regValue; } -void Player_AD::setupNoteEnvelopeState(int note, int steps, int adjust) { - _notes[note].preIncrease = 0; +void Player_AD::setupNoteEnvelopeState(Note *note, int steps, int adjust) { + note->preIncrease = 0; if (ABS(adjust) > steps) { - _notes[note].preIncrease = 1; - _notes[note].adjust = adjust / steps; - _notes[note].envelope.stepIncrease = ABS(adjust % steps); + note->preIncrease = 1; + note->adjust = adjust / steps; + note->envelope.stepIncrease = ABS(adjust % steps); } else { - _notes[note].adjust = adjust; - _notes[note].envelope.stepIncrease = ABS(adjust); + note->adjust = adjust; + note->envelope.stepIncrease = ABS(adjust); } - _notes[note].envelope.step = steps; - _notes[note].envelope.stepCounter = 0; - _notes[note].envelope.timer = steps; + note->envelope.step = steps; + note->envelope.stepCounter = 0; + note->envelope.timer = steps; } -bool Player_AD::processNoteEnvelope(int note, int &instrumentValue) { - if (_notes[note].preIncrease) { - instrumentValue += _notes[note].adjust; +bool Player_AD::processNoteEnvelope(Note *note) { + if (note->preIncrease) { + note->instrumentValue += note->adjust; } - _notes[note].envelope.stepCounter += _notes[note].envelope.stepIncrease; - if (_notes[note].envelope.stepCounter >= _notes[note].envelope.step) { - _notes[note].envelope.stepCounter -= _notes[note].envelope.step; + note->envelope.stepCounter += note->envelope.stepIncrease; + if (note->envelope.stepCounter >= note->envelope.step) { + note->envelope.stepCounter -= note->envelope.step; - if (_notes[note].adjust < 0) { - --instrumentValue; + if (note->adjust < 0) { + --note->instrumentValue; } else { - ++instrumentValue; + ++note->instrumentValue; } } - if (--_notes[note].envelope.timer) { + if (--note->envelope.timer) { return false; } else { return true; diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h index fbb65fbe24..63a8503f47 100644 --- a/engines/scumm/players/player_ad.h +++ b/engines/scumm/players/player_ad.h @@ -68,7 +68,10 @@ private: Audio::Mixer *const _mixer; const int _rate; Audio::SoundHandle _soundHandle; + void setupVolume(); + int _musicVolume; + int _sfxVolume; OPL::OPL *_opl2; @@ -78,7 +81,21 @@ private: int _samplesTillCallbackRemainder; int _soundPlaying; - int _engineMusicTimer; + int32 _engineMusicTimer; + + struct SfxSlot; + + struct HardwareChannel { + bool allocated; + int priority; + SfxSlot *sfxOwner; + } _hwChannels[9]; + int _numHWChannels; + static const int _operatorOffsetToChannel[22]; + + int allocateHWChannel(int priority, SfxSlot *owner = nullptr); + void freeHWChannel(int channel); + void limitHWChannels(int newCount); // AdLib register utilities uint8 _registerBackUpTable[256]; @@ -86,40 +103,43 @@ private: uint8 readReg(int r) const; // Instrument setup - void setupChannel(const uint channel, uint instrOffset) { - setupChannel(channel, _resource + instrOffset); - } void setupChannel(const uint channel, const byte *instrOffset); void setupOperator(const uint opr, const byte *&instrOffset); static const int _operatorOffsetTable[18]; - // Sound data - const byte *_resource; - // Music handling void startMusic(); + void stopMusic(); void updateMusic(); + bool parseCommand(); + uint parseVLQ(); void noteOff(uint channel); - int findFreeChannel(); void setupFrequency(uint channel, int8 frequency); void setupRhythm(uint rhythmInstr, uint instrOffset); + const byte *_musicData; uint _timerLimit; uint _musicTicks; - uint _musicTimer; - uint _internalMusicTimer; + uint32 _musicTimer; + uint32 _internalMusicTimer; bool _loopFlag; uint _musicLoopStart; uint _instrumentOffset[16]; - uint _channelLastEvent[9]; - uint _channelFrequency[9]; - uint _channelB0Reg[9]; + + struct VoiceChannel { + uint lastEvent; + uint frequency; + uint b0Reg; + } _voiceChannels[9]; + void freeVoiceChannel(uint channel); + + void musicSeekTo(const uint position); + bool _isSeeking; uint _mdvdrState; - uint _voiceChannels; - - uint _curOffset; - uint _nextEventTimer; + + uint32 _curOffset; + uint32 _nextEventTimer; static const uint _noteFrequencies[12]; static const uint _mdvdrTable[6]; @@ -127,34 +147,14 @@ private: static const uint _rhythmChannelTable[6]; // SFX handling - void startSfx(); - void updateSfx(); - void clearChannel(int channel); - void updateChannel(int channel); - void parseSlot(int channel); - void updateSlot(int channel); - void parseNote(int channel, int num, const byte *offset); - bool processNote(int note, const byte *offset); - void noteOffOn(int channel); - void writeRegisterSpecial(int note, uint8 value, int offset); - uint8 readRegisterSpecial(int note, uint8 defaultValue, int offset); - void setupNoteEnvelopeState(int note, int steps, int adjust); - bool processNoteEnvelope(int note, int &instrumentValue); - - int _sfxTimer; - - int _sfxResource[3]; - int _sfxPriority[3]; - - struct Channel { - int state; - const byte *currentOffset; - const byte *startOffset; - uint8 instrumentData[7]; - } _channels[11]; - - uint8 _rndSeed; - uint8 getRnd(); + enum { + kNoteStatePreInit = -1, + kNoteStateAttack = 0, + kNoteStateDecay = 1, + kNoteStateSustain = 2, + kNoteStateRelease = 3, + kNoteStateOff = 4 + }; struct Note { int state; @@ -164,14 +164,60 @@ private: int bias; int preIncrease; int adjust; - + struct Envelope { int stepIncrease; int step; int stepCounter; int timer; } envelope; - } _notes[22]; + }; + + enum { + kChannelStateOff = 0, + kChannelStateParse = 1, + kChannelStatePlay = 2 + }; + + struct Channel { + int state; + const byte *currentOffset; + const byte *startOffset; + uint8 instrumentData[7]; + + Note notes[2]; + + int hardwareChannel; + }; + + struct SfxSlot { + int resource; + int priority; + + Channel channels[3]; + } _sfx[3]; + + SfxSlot *allocateSfxSlot(int priority); + bool startSfx(SfxSlot *sfx, const byte *resource); + void stopSfx(SfxSlot *sfx); + + void updateSfx(); + void clearChannel(const Channel &channel); + void updateChannel(Channel *channel); + void parseSlot(Channel *channel); + void updateSlot(Channel *channel); + void parseNote(Note *note, const Channel &channel, const byte *offset); + bool processNote(Note *note, const Channel &channel, const byte *offset); + void noteOffOn(int channel); + void writeRegisterSpecial(int channel, uint8 value, int offset); + uint8 readRegisterSpecial(int channel, uint8 defaultValue, int offset); + void setupNoteEnvelopeState(Note *note, int steps, int adjust); + bool processNoteEnvelope(Note *note); + + int _sfxTimer; + + uint8 _rndSeed; + uint8 getRnd(); static const uint _noteBiasTable[7]; static const uint _numStepsTable[16]; diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index bd8ae3ff59..01ed21ece5 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -47,7 +47,7 @@ namespace Scumm { * only saves/loads those which are valid for the version of the savegame * which is being loaded/saved currently. */ -#define CURRENT_VER 95 +#define CURRENT_VER 96 /** * An auxillary macro, used to specify savegame versions. We use this instead diff --git a/engines/teenagent/actor.cpp b/engines/teenagent/actor.cpp index a4df43a5fe..5c796c13ab 100644 --- a/engines/teenagent/actor.cpp +++ b/engines/teenagent/actor.cpp @@ -134,10 +134,6 @@ Common::Rect Actor::render(Graphics::Surface *surface, const Common::Point &posi default: return Common::Rect(); } - if (s == NULL) { - warning("no surface, skipping"); - return Common::Rect(); - } Common::Rect dirty; Common::Rect clip(0, 0, s->w, s->h); diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp index fa5d1a3b6a..ce24c76290 100644 --- a/engines/tsage/graphics.cpp +++ b/engines/tsage/graphics.cpp @@ -1229,6 +1229,8 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) { selectedButton = defaultButton; breakFlag = true; break; + } else if (event.eventType == EVENT_KEYPRESS && handleKeypress(event, selectedButton)) { + breakFlag = true; } } } diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h index cdb4826528..d65d0bcf8b 100644 --- a/engines/tsage/graphics.h +++ b/engines/tsage/graphics.h @@ -343,6 +343,8 @@ public: virtual void draw(); static void setPalette(); + + virtual bool handleKeypress(Event &evt, GfxButton *&btn) { return false; } }; GfxSurface *surfaceGetArea(GfxSurface &src, const Rect &bounds); diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp index dfbb281cfb..99f88a1687 100644 --- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp +++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp @@ -365,7 +365,7 @@ void HelpDialog::show() { HelpDialog *dlg = new HelpDialog(); dlg->draw(); - // Show the character selection dialog + // Show the help dialog GfxButton *btn = dlg->execute(&dlg->_btnResume); // If a function button was selected, take care of it @@ -458,6 +458,36 @@ HelpDialog::HelpDialog() { setCenter(160, 100); } +bool HelpDialog::handleKeypress(Event &event, GfxButton *&btn) { + switch (event.kbd.keycode) { + case Common::KEYCODE_F2: + btn = &_btnList[0]; + break; + case Common::KEYCODE_F3: + btn = &_btnList[1]; + break; + case Common::KEYCODE_F4: + btn = &_btnList[2]; + break; + case Common::KEYCODE_F5: + btn = &_btnList[3]; + break; + case Common::KEYCODE_F7: + btn = &_btnList[4]; + break; + case Common::KEYCODE_F8: + btn = &_btnList[5]; + break; + case Common::KEYCODE_F10: + btn = &_btnList[6]; + break; + default: + return false; + } + + return true; +} + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.h b/engines/tsage/ringworld2/ringworld2_dialogs.h index 8ef35c9024..3d1e1ad48c 100644 --- a/engines/tsage/ringworld2/ringworld2_dialogs.h +++ b/engines/tsage/ringworld2/ringworld2_dialogs.h @@ -83,6 +83,8 @@ public: virtual ~HelpDialog() {} static void show(); + + virtual bool handleKeypress(Event &event, GfxButton *&btn); }; } // End of namespace Ringworld2 diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp index c5c6de980c..99188c1ab6 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.cpp +++ b/engines/tsage/ringworld2/ringworld2_logic.cpp @@ -1215,12 +1215,6 @@ void Ringworld2Game::processEvent(Event &event) { R2_GLOBALS._events.setCursorFromFlag(); break; - case Common::KEYCODE_F5: - // F5 - Save - saveGame(); - R2_GLOBALS._events.setCursorFromFlag(); - break; - case Common::KEYCODE_F7: // F7 - Restore restoreGame(); diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp index 110c3ff510..29646d1612 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp @@ -4931,6 +4931,9 @@ int Scene1337::getPreventionCardId(int cardId) { } bool Scene1337::isAttackPossible(int victimId, int cardId) { + if (victimId < 0 || victimId >= ARRAYSIZE(_gameBoardSide)) + error("Scene1337::isAttackPossible() victimId:%d out of range 0 to %d", victimId, ARRAYSIZE(_gameBoardSide)-1); + for (int i = 0; i <= 7; i++) { if (_gameBoardSide[victimId]._outpostStation[i]._cardId != 0) { if (getPreventionCardId(cardId) == _gameBoardSide[victimId]._outpostStation[i]._cardId) @@ -5978,11 +5981,18 @@ void Scene1337::handlePlayer1() { for (int j = 0; j <= 3; j++) { //CHECKME: tmpVal or rndVal? + // FIXME: This is probably meant to be rndVal, but not clear... + if (tmpVal < 0 || tmpVal >= ARRAYSIZE(_gameBoardSide)) + error("Scene1337::handlePlayer1() tmpVal:%d out of range 0 to %d", tmpVal, ARRAYSIZE(_gameBoardSide)-1); + if (tmpVal != 1) { if ((_gameBoardSide[tmpVal]._delayCard._cardId == 0) && isAttackPossible(tmpVal, _gameBoardSide[1]._handCard[i]._cardId)) count = tmpVal; } + if (count < 0 || count >= ARRAYSIZE(_gameBoardSide)) + error("Scene1337::handlePlayer1() count:%d out of range 0 to %d", count, ARRAYSIZE(_gameBoardSide)-1); + if (count != -1) { playDelayCard(&_gameBoardSide[1]._handCard[i], &_gameBoardSide[count]._delayCard); return; diff --git a/engines/tsage/ringworld2/ringworld2_speakers.cpp b/engines/tsage/ringworld2/ringworld2_speakers.cpp index 6d4ef4ab75..016242edd1 100644 --- a/engines/tsage/ringworld2/ringworld2_speakers.cpp +++ b/engines/tsage/ringworld2/ringworld2_speakers.cpp @@ -1057,7 +1057,7 @@ void SpeakerNej2800::animateSpeaker() { _object1.setup(4023, 3, 1); if (_object2->_visage == 2801) - _object1.setPosition(Common::Point(R2_GLOBALS._player._position.x - 12, R2_GLOBALS._player._position.y)); + _object1.setPosition(Common::Point(_object2->_position.x - 12, _object2->_position.y)); _object1.animate(ANIM_MODE_5, this); } } diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp index 45bfe2b5ea..3ee585d5ef 100644 --- a/engines/tsage/user_interface.cpp +++ b/engines/tsage/user_interface.cpp @@ -289,12 +289,13 @@ void UICollection::draw() { void UICollection::r2rDrawFrame() { Visage visage; visage.setVisage(2, 1); - GfxSurface vertLine = visage.getFrame(1); + GfxSurface vertLineLeft = visage.getFrame(1); + GfxSurface vertLineRight = visage.getFrame(3); GfxSurface horizLine = visage.getFrame(2); GLOBALS._screenSurface.copyFrom(horizLine, 0, 0); - GLOBALS._screenSurface.copyFrom(vertLine, 0, 3); - GLOBALS._screenSurface.copyFrom(vertLine, SCREEN_WIDTH - 4, 3); + GLOBALS._screenSurface.copyFrom(vertLineLeft, 0, 3); + GLOBALS._screenSurface.copyFrom(vertLineRight, SCREEN_WIDTH - 4, 3); // Restrict drawing area to exclude the borders at the edge of the screen R2_GLOBALS._screenSurface._clipRect = Rect(4, 3, SCREEN_WIDTH - 4, diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp index 346fd2419e..300e086f75 100644 --- a/engines/voyeur/files.cpp +++ b/engines/voyeur/files.cpp @@ -1056,13 +1056,18 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): byte *imgData = state._curLibPtr->boltEntry(id)._picResource->_imgData; _freeImgData = DisposeAfterUse::NO; +#if 0 // TODO: Double check code below. Despite different coding in the - // original, both looked like they do the same formula + // original, both looked like they do the same formula. + // Until it's clarified, this check is disabled and replaced by the + // common code. if (_flags & PICFLAG_PIC_OFFSET) { _imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff); } else { _imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff); } +#endif + _imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff); } } else if (_flags & PICFLAG_PIC_OFFSET) { int mode = 0; diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp index 8edacc5883..681f431635 100644 --- a/engines/voyeur/voyeur.cpp +++ b/engines/voyeur/voyeur.cpp @@ -82,6 +82,8 @@ VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc) _glGoStack = -1; _resolvePtr = nullptr; _mainThread = nullptr; + + centerMansionView(); } VoyeurEngine::~VoyeurEngine() { diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h index a35473ba93..e0bb734fa8 100644 --- a/engines/voyeur/voyeur.h +++ b/engines/voyeur/voyeur.h @@ -150,6 +150,11 @@ private: * Synchronizes the game data */ void synchronize(Common::Serializer &s); + + /** + * Resets the mansion view position + */ + void centerMansionView(); protected: // Engine APIs virtual Common::Error run(); diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp index 34ad62a88d..c7df924f7e 100644 --- a/engines/voyeur/voyeur_game.cpp +++ b/engines/voyeur/voyeur_game.cpp @@ -1063,9 +1063,7 @@ void VoyeurEngine::initIFace() { CMapResource *pal = _bVoy->boltEntry(_playStampGroupId + 2)._cMapResource; pal->startFade(); - // Start the mansion off centered - _mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2, - (MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2); + // Reset the mansion view off to it's prior position (if any) doScroll(_mansionViewPos); _voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId)._rectResource; @@ -1138,6 +1136,7 @@ void VoyeurEngine::checkTransition() { } _checkTransitionId = _voy->_transitionId; + centerMansionView(); } } @@ -1420,4 +1419,9 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) { } } +void VoyeurEngine::centerMansionView() { + _mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2, + (MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2); +} + } // End of namespace Voyeur diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp index b1461283e8..ae4955390b 100644 --- a/engines/wintermute/base/file/base_package.cpp +++ b/engines/wintermute/base/file/base_package.cpp @@ -53,8 +53,8 @@ static bool findPackageSignature(Common::SeekableReadStream *f, uint32 *offset) byte buf[32768]; byte signature[8]; - ((uint32 *)signature)[0] = PACKAGE_MAGIC_1; - ((uint32 *)signature)[1] = PACKAGE_MAGIC_2; + WRITE_LE_UINT32(signature + 0, PACKAGE_MAGIC_1); + WRITE_LE_UINT32(signature + 4, PACKAGE_MAGIC_2); uint32 fileSize = (uint32)f->size(); uint32 startPos = 1024 * 1024; diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp index f0b868209d..44fd117e61 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -488,7 +488,8 @@ double ScScript::getFloat() { SWAP(buffer[3], buffer[4]); #endif - double ret = *(double *)(buffer); + double ret; + memcpy(&ret, buffer, sizeof(double)); _iP += 8; // Hardcode the double-size used originally. return ret; } diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp index 36a624367c..15ddd4bcca 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.cpp +++ b/engines/wintermute/base/scriptables/script_ext_file.cpp @@ -443,7 +443,7 @@ bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, return STATUS_OK; } float val; - (*(uint32 *)&val) = _readFile->readUint32LE(); + WRITE_UINT32(&val, _readFile->readUint32LE()); if (!_readFile->err()) { stack->pushFloat(val); } else { diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h index 69d66c3498..6087e60ece 100644 --- a/engines/wintermute/detection_tables.h +++ b/engines/wintermute/detection_tables.h @@ -55,6 +55,7 @@ static const PlainGameDescriptor wintermuteGames[] = { {"looky", "Looky"}, {"julia", "J.U.L.I.A."}, {"mirage", "Mirage"}, + {"oknytt", "Oknytt"}, {"paintaria", "Paintaria"}, {"pigeons", "Pigeons in the Park"}, {"projectdoom", "Project: Doom"}, @@ -73,6 +74,7 @@ static const PlainGameDescriptor wintermuteGames[] = { {"tib", "Fairy Tales About Toshechka and Boshechka"}, {"tradestory", "The Trader of Stories"}, {"twc", "the white chamber"}, + {"vsevolod", "Vsevolod"}, {"wintermute", "Wintermute engine game"}, {"wtetris", "Wilma Tetris"}, {"zilm", "Zilm: A Game of Reflex"}, @@ -697,6 +699,16 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Oknytt + { + "oknytt", + "Version 1.0", + AD_ENTRY1s("data.dcp", "6456cf8f429905c83f07509f9da536dd", 109502959), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO0() + }, // Paintaria { "paintaria", @@ -1278,6 +1290,17 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, GUIO0() }, + // Vsevolod Prologue (Demo) + { + "vsevolod", + "Prologue", + AD_ENTRY1s("data.dcp", "f2dcffd2692dbfcc9371fa1a87970fe7", 388669493), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_UNSTABLE | + ADGF_DEMO, + GUIO0() + }, // Wilma Tetris { "wtetris", |