diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/igor/igor.cpp | 88 | ||||
-rw-r--r-- | engines/igor/igor.h | 25 | ||||
-rw-r--r-- | engines/igor/menu.cpp | 1 | ||||
-rw-r--r-- | engines/igor/module.mk | 1 | ||||
-rw-r--r-- | engines/igor/parts/part_04.cpp | 2 | ||||
-rw-r--r-- | engines/igor/parts/part_05.cpp | 2 | ||||
-rw-r--r-- | engines/igor/parts/part_06.cpp | 2 | ||||
-rw-r--r-- | engines/igor/parts/part_85.cpp | 2 | ||||
-rw-r--r-- | engines/igor/parts/part_main.cpp | 2 | ||||
-rw-r--r-- | engines/igor/saveload.cpp | 197 |
10 files changed, 268 insertions, 54 deletions
diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp index ece5645743..6a75be08b8 100644 --- a/engines/igor/igor.cpp +++ b/engines/igor/igor.cpp @@ -218,6 +218,11 @@ void IgorEngine::waitForTimer(int ticks) { _inputVars[kInputOptions] = 1; } else if (ev.kbd.keycode == Common::KEYCODE_p) { _inputVars[kInputPause] = 1; + } else if (ev.kbd.keycode == Common::KEYCODE_F11) { + sprintf(_saveStateDescriptions[kQuickSaveSlot], "Quicksave part %d", _currentPart); + saveGameState(kQuickSaveSlot); + } else if (ev.kbd.keycode == Common::KEYCODE_F12) { + loadGameState(kQuickSaveSlot); } break; case Common::EVENT_MOUSEMOVE: @@ -241,11 +246,11 @@ void IgorEngine::waitForTimer(int ticks) { break; } } while (!_fastMode); - _nextTimer = _system->getMillis() + 8 * 1000 / kTickDelay; + _nextTimer = _system->getMillis() + kTimerTicksCount * 1000 / kTickDelay; if (ticks != -1) { return; } - _gameTicks += 8; + _gameTicks += kTimerTicksCount; if (_gameTicks == 64) { _gameTicks = 0; setCursor(_currentCursor); @@ -276,7 +281,7 @@ int IgorEngine::getRandomNumber(int m) { } void IgorEngine::playMusic(int num) { - debug(kDebugEngine, "playMusic() %d", num); + debugC(9, kDebugEngine, "playMusic() %d", num); const int *seq = 0; switch (num) { case 2: { @@ -358,6 +363,7 @@ void IgorEngine::updateMusic() { } void IgorEngine::playSound(int num, int fl) { + debugC(9, kDebugEngine, "playSound() %d", num); if (fl && _mixer->isSoundHandleActive(_sfxHandle)) { return; } @@ -417,7 +423,7 @@ void IgorEngine::fixDialogueTextPosition(int num, int count, int *x, int *y) { } void IgorEngine::startCutsceneDialogue(int x, int y, int r, int g, int b) { - debug(kDebugEngine, "startCutsceneDialogue() pos %d,%d color %d,%d,%d", x, y, r, g, b); + debugC(9, kDebugEngine, "startCutsceneDialogue() pos %d,%d color %d,%d,%d", x, y, r, g, b); --_dialogueTextsCount; int talkX = x; int talkY = y; @@ -514,7 +520,7 @@ void IgorEngine::fixIgorDialogueTextPosition(int num, int count, int *x, int *y) } void IgorEngine::startIgorDialogue() { - debug(kDebugEngine, "startIgorDialogue()"); + debugC(9, kDebugEngine, "startIgorDialogue()"); // if (_dialogueCursorOn) { // clearCursor(); // } @@ -635,7 +641,7 @@ ResourceEntry IgorEngine::findData(int id) { uint8 *IgorEngine::loadData(int id, uint8 *dst, int *size) { ResourceEntry re = findData(id); - debug(kDebugResource, "loadData() id %d offset %d size %d", id, re.offs, re.size); + debugC(9, kDebugResource, "loadData() id %d offset %d size %d", id, re.offs, re.size); if (!dst) { dst = (uint8 *)malloc(re.size); if (!dst) { @@ -701,7 +707,7 @@ void IgorEngine::decodeRoomStrings(const uint8 *p, bool skipObjectNames) { decodeRoomString(p, _roomObjectNames[index], len); p += len; _roomObjectNames[index][len] = '\0'; - debug(kDebugResource, "decodeRoomStrings() _roomObjectNames[%d] '%s'", index, _roomObjectNames[index]); + debugC(9, kDebugResource, "decodeRoomStrings() _roomObjectNames[%d] '%s'", index, _roomObjectNames[index]); } code = *p++; } @@ -720,14 +726,14 @@ void IgorEngine::decodeRoomStrings(const uint8 *p, bool skipObjectNames) { decodeRoomString(p, _globalDialogueTexts[index], len); p += len; _globalDialogueTexts[index][len] = '\0'; - debug(kDebugResource, "decodeRoomStrings() _globalDialogueTexts[%d] '%s'", index, _globalDialogueTexts[index]); + debugC(9, kDebugResource, "decodeRoomStrings() _globalDialogueTexts[%d] '%s'", index, _globalDialogueTexts[index]); } code = *p++; } } void IgorEngine::decodeRoomText(const uint8 *p) { - debug(kDebugResource, "decodeRoomText()"); + debugC(9, kDebugResource, "decodeRoomText()"); memcpy(_walkXScaleRoom, p, 320); p += 320; memcpy(_walkYScaleRoom, p, 432); p += 432; decodeRoomStrings(p); @@ -818,7 +824,7 @@ void IgorEngine::loadDialogueData(int dlg) { if (len != 0) { decodeRoomString(src, _dialogueQuestions[i][n], len); _dialogueQuestions[i][n][len] = '\0'; - debug(kDebugResource, "loadDialogueData() _dialogueQuestions[%d][%d] '%s'", i, n, _dialogueQuestions[i][n]); + debugC(9, kDebugResource, "loadDialogueData() _dialogueQuestions[%d][%d] '%s'", i, n, _dialogueQuestions[i][n]); } } } @@ -829,7 +835,7 @@ void IgorEngine::loadDialogueData(int dlg) { if (len != 0) { decodeRoomString(src, _dialogueReplies[i], len); _dialogueReplies[i][len] = '\0'; - debug(kDebugResource, "loadDialogueData() _dialogueReplies[%d] '%s'", i, _dialogueReplies[i]); + debugC(9, kDebugResource, "loadDialogueData() _dialogueReplies[%d] '%s'", i, _dialogueReplies[i]); } } free(p); @@ -854,22 +860,22 @@ void IgorEngine::loadMainTexts() { const uint8 *src = &p[0] + _language * 7; for (int i = 0; i < 3; ++i, src += 7 * 2) { decodeMainString(src, _verbPrepositions[i]); - debug(kDebugResource, "loadMainTexts() _verbPrepositions[%d] '%s'", i, _verbPrepositions[i]); + debugC(9, kDebugResource, "loadMainTexts() _verbPrepositions[%d] '%s'", i, _verbPrepositions[i]); } src = &p[0x2A] + _language * 31; for (int i = 0; i < 35; ++i, src += 31 * 2) { decodeMainString(src, _globalObjectNames[i]); - debug(kDebugResource, "loadMainTexts() _globalObjectNames[%d] '%s'", i, _globalObjectNames[i]); + debugC(9, kDebugResource, "loadMainTexts() _globalObjectNames[%d] '%s'", i, _globalObjectNames[i]); } src = &p[0x8BA] + _language * 51; for (int i = 0; i < 250; ++i, src += 51 * 2) { decodeMainString(src, _globalDialogueTexts[i]); - debug(kDebugResource, "loadMainTexts() _globalDialogueTexts[%d] '%s'", i, _globalDialogueTexts[i]); + debugC(9, kDebugResource, "loadMainTexts() _globalDialogueTexts[%d] '%s'", i, _globalDialogueTexts[i]); } src = &p[0x6CA4] + _language * 12; for (int i = 0; i < 9; ++i, src += 12 * 2) { decodeMainString(src, _verbsName[i]); - debug(kDebugResource, "loadMainTexts() _verbsName[%d] '%s'", i, _verbsName[i]); + debugC(9, kDebugResource, "loadMainTexts() _verbsName[%d] '%s'", i, _verbsName[i]); } free(p); } @@ -907,7 +913,7 @@ void IgorEngine::setPaletteColor(uint8 index, uint8 r, uint8 g, uint8 b) { } void IgorEngine::setPaletteRange(int startColor, int endColor) { - debug(kDebugScreen, "setPaletteRange(%d, %d)", startColor, endColor); + debugC(9, kDebugScreen, "setPaletteRange(%d, %d)", startColor, endColor); assert(endColor - startColor + 1 <= 256); for (int i = startColor; i <= endColor; ++i) { setPaletteColor(i, _currentPalette[3 * i], _currentPalette[3 * i + 1], _currentPalette[3 * i + 2]); @@ -915,7 +921,7 @@ void IgorEngine::setPaletteRange(int startColor, int endColor) { } void IgorEngine::fadeInPalette(int count) { - debug(kDebugScreen, "fadeInPalette(%d)", count); + debugC(9, kDebugScreen, "fadeInPalette(%d)", count); _system->copyRectToScreen(_screenVGA, 320, 0, _screenVGAVOffset, 320, 200 - _screenVGAVOffset); int m = 66; do { @@ -936,7 +942,7 @@ void IgorEngine::fadeInPalette(int count) { } void IgorEngine::fadeOutPalette(int count) { - debug(kDebugScreen, "fadeOutPalette(%d)", count); + debugC(9, kDebugScreen, "fadeOutPalette(%d)", count); _system->copyRectToScreen(_screenVGA, 320, 0, _screenVGAVOffset, 320, 200 - _screenVGAVOffset); memcpy(_paletteBuffer, _currentPalette, 768); int m = 0; @@ -960,7 +966,7 @@ void IgorEngine::fadeOutPalette(int count) { } void IgorEngine::scrollPalette(int startColor, int endColor) { - debug(kDebugScreen, "scrollPalette(%d, %d)", startColor, endColor); + debugC(9, kDebugScreen, "scrollPalette(%d, %d)", startColor, endColor); uint8 c[3]; memcpy(c, &_currentPalette[startColor * 3], 3); memmove(&_currentPalette[startColor * 3], &_currentPalette[(startColor + 1) * 3], (endColor - startColor) * 3); @@ -1110,13 +1116,13 @@ void IgorEngine::setCursor(int num) { } void IgorEngine::showCursor() { - debug(kDebugEngine, "showCursor()"); + debugC(9, kDebugEngine, "showCursor()"); _roomCursorOn = true; CursorMan.showMouse(_roomCursorOn); } void IgorEngine::hideCursor() { - debug(kDebugEngine, "hideCursor()"); + debugC(9, kDebugEngine, "hideCursor()"); _roomCursorOn = false; CursorMan.showMouse(_roomCursorOn); } @@ -1337,7 +1343,7 @@ void IgorEngine::removeObjectFromInventory(int index) { } void IgorEngine::executeAction(int action) { - debug(kDebugEngine, "executeAction %d", action); + debugC(9, kDebugEngine, "executeAction %d", action); assert(action < 200); if (action <= 100) { (this->*_executeMainAction)(action); @@ -1511,7 +1517,7 @@ void IgorEngine::handleRoomInput() { _actionCode = 0; return; } - debug(kDebugEngine, "handleRoomInput() actionCode %d", _actionCode); + debugC(9, kDebugEngine, "handleRoomInput() actionCode %d", _actionCode); if (_actionCode == 0) { clearAction(); return; @@ -1534,7 +1540,7 @@ void IgorEngine::handleRoomInput() { int offset = READ_LE_UINT16(_roomActionsTable + _roomDataOffsets.obj.walkPoints + _currentAction.object1Num * 2); _walkToObjectPosX = offset % 320; _walkToObjectPosY = offset / 320; - debug(kDebugEngine, "handleRoomInput() walkToObject offset %d (0x%X)", offset, _roomDataOffsets.obj.walkPoints); + debugC(9, kDebugEngine, "handleRoomInput() walkToObject offset %d (0x%X)", offset, _roomDataOffsets.obj.walkPoints); } if (_gameState.igorMoving) { // stop igor at the current position @@ -1692,7 +1698,7 @@ int IgorEngine::lookupScale(int xOffset, int yOffset, int h) const { void IgorEngine::moveIgor(int pos, int frame) { assert(_gameState.enableLight == 1 || _gameState.enableLight == 2); - debug(kDebugWalk, "moveIgorHelper _walkDataCurrentIndex %d pos %d frame %d", _walkDataCurrentIndex, pos, frame); + debugC(9, kDebugWalk, "moveIgorHelper _walkDataCurrentIndex %d pos %d frame %d", _walkDataCurrentIndex, pos, frame); WalkData *wd = &_walkData[_walkDataCurrentIndex]; uint8 _walkClipSkipX = wd->clipSkipX; uint8 _walkHeightScale = wd->scaleHeight; @@ -1819,7 +1825,7 @@ void IgorEngine::moveIgor(int pos, int frame) { } void IgorEngine::buildWalkPathSimple(int srcX, int srcY, int dstX, int dstY) { - debug(kDebugWalk, "IgorEngine::buildWalkPathSimple(%d, %d, %d, %d)", srcX, srcY, dstX, dstY); + debugC(9, kDebugWalk, "IgorEngine::buildWalkPathSimple(%d, %d, %d, %d)", srcX, srcY, dstX, dstY); if (srcX != dstX || srcY != dstY) { _walkData[0] = _walkData[_walkDataLastIndex]; _walkDataLastIndex = 1; @@ -1845,7 +1851,7 @@ void IgorEngine::getClosestAreaTrianglePoint(int dstArea, int srcArea, int *dstY minSqrDist = sqrDist; } } - debug(kDebugWalk, "getClosestAreaTrianglePoint() sqrDist %d pos %d,%d", minSqrDist, *dstX, *dstY); + debugC(9, kDebugWalk, "getClosestAreaTrianglePoint() sqrDist %d pos %d,%d", minSqrDist, *dstX, *dstY); } void IgorEngine::getClosestAreaTrianglePoint2(int dstArea, int srcArea, int *dstY, int *dstX, int srcY1, int srcX1, int srcY2, int srcX2) { @@ -1867,7 +1873,7 @@ void IgorEngine::getClosestAreaTrianglePoint2(int dstArea, int srcArea, int *dst minSqrDist = sqrDist; } } - debug(kDebugWalk, "getClosestAreaTrianglePoint2() sqrDist %d pos %d,%d", minSqrDist, *dstX, *dstY); + debugC(9, kDebugWalk, "getClosestAreaTrianglePoint2() sqrDist %d pos %d,%d", minSqrDist, *dstX, *dstY); } void IgorEngine::buildWalkPath(int srcX, int srcY, int dstX, int dstY) { @@ -1876,19 +1882,19 @@ void IgorEngine::buildWalkPath(int srcX, int srcY, int dstX, int dstY) { _walkDataLastIndex = 1; int srcArea = _roomObjectAreasTable[_screenLayer2[srcY * 320 + srcX]].area; int dstArea = _roomObjectAreasTable[_screenLayer2[dstY * 320 + dstX]].area; - debug(kDebugWalk, "srcArea = %d dstArea = %d", srcArea, dstArea); + debugC(9, kDebugWalk, "srcArea = %d dstArea = %d", srcArea, dstArea); int currentArea = srcArea; for (int i = 1; dstArea != currentArea; ++i) { const int boxOffset = srcArea * _roomDataOffsets.area.boxSrcSize + dstArea * _roomDataOffsets.area.boxDstSize; int nextArea = _roomActionsTable[boxOffset + i + _roomDataOffsets.area.box]; - debug(kDebugWalk, "nextArea %d (%d,%d,%d)", nextArea, _roomDataOffsets.area.box, _roomDataOffsets.area.boxSrcSize, _roomDataOffsets.area.boxDstSize); + debugC(9, kDebugWalk, "nextArea %d (%d,%d,%d)", nextArea, _roomDataOffsets.area.box, _roomDataOffsets.area.boxSrcSize, _roomDataOffsets.area.boxDstSize); int nextPosX, nextPosY; if (dstArea != nextArea) { getClosestAreaTrianglePoint(nextArea, currentArea, &nextPosY, &nextPosX, srcY, srcX); } else { getClosestAreaTrianglePoint2(nextArea, currentArea, &nextPosY, &nextPosX, dstY, dstX, srcY, srcX); } - debug(kDebugWalk, "buildWalkPath() transitionArea = %d next %d,%d pos %d,%d offset 0x%X", nextArea, nextPosX, nextPosY, dstX, dstY, _roomDataOffsets.area.box); + debugC(9, kDebugWalk, "buildWalkPath() transitionArea = %d next %d,%d pos %d,%d offset 0x%X", nextArea, nextPosX, nextPosY, dstX, dstY, _roomDataOffsets.area.box); buildWalkPathArea(srcX, srcY, nextPosX, nextPosY); srcX = nextPosX; srcY = nextPosY; @@ -1897,14 +1903,14 @@ void IgorEngine::buildWalkPath(int srcX, int srcY, int dstX, int dstY) { buildWalkPathArea(srcX, srcY, dstX, dstY); --_walkDataLastIndex; } - debug(kDebugWalk, "buildWalkPath() end _walkDataLastIndex %d", _walkDataLastIndex); + debugC(9, kDebugWalk, "buildWalkPath() end _walkDataLastIndex %d", _walkDataLastIndex); } void IgorEngine::buildWalkPathArea(int srcX, int srcY, int dstX, int dstY) { if (srcX != dstX || srcY != dstY) { const int dx = dstX - srcX; const int dy = dstY - srcY; - debug(kDebugWalk, "buildWalkPathArea() dx = %d dy = %d src %d,%d dst %d,%d", dx, dy, srcX, srcY, dstX, dstY); + debugC(9, kDebugWalk, "buildWalkPathArea() dx = %d dy = %d src %d,%d dst %d,%d", dx, dy, srcX, srcY, dstX, dstY); assert(_walkDataLastIndex > 0); if (ABS(dy) * 2 > ABS(dx)) { if (srcY > dstY) { @@ -1931,7 +1937,7 @@ static int16 truncReal(float f) { } int IgorEngine::getVerticalStepsCount(int minX, int minY, int maxX, int maxY) { - debug(kDebugWalk, "getVerticalStepsCount() %d %d %d %d", minX, minY, maxX, maxY); + debugC(9, kDebugWalk, "getVerticalStepsCount() %d %d %d %d", minX, minY, maxX, maxY); int curX = 2; if ((_walkXScaleRoom[minX] != 1 || _walkXScaleRoom[maxX] != 3) && (_walkXScaleRoom[maxX] != 1 || _walkXScaleRoom[minX] != 3)) { curX = _walkXScaleRoom[minX]; @@ -1957,7 +1963,7 @@ int IgorEngine::getHorizontalStepsCount(int minX, int minY, int maxX, int maxY) float r1 = _walkScaleSpeedTable[scale - 1]; scale = _walkYScaleRoom[(_walkXScaleRoom[minX] - 1) * 144 + minY]; float r2 = _walkScaleSpeedTable[scale - 1]; - debug(kDebugWalk, "getHorizontalStepsCount() maxX - minX = %d r1 = %f r2 = %f", maxX - minX, r1, r2); + debugC(9, kDebugWalk, "getHorizontalStepsCount() maxX - minX = %d r1 = %f r2 = %f", maxX - minX, r1, r2); int16 steps = roundReal((maxX - minX) / ((r1 + r2) / 2.)); int count = 0; @@ -2814,7 +2820,7 @@ void IgorEngine::handleDialogue(int x, int y, int r, int g, int b) { _gameState.dialogueData[offset + 2] = 2; } } - debug(kDebugEngine, "handleDialogue() action %d offset %d", _gameState.dialogueData[offset + 2], offset); + debugC(9, kDebugEngine, "handleDialogue() action %d offset %d", _gameState.dialogueData[offset + 2], offset); switch (_gameState.dialogueData[offset + 2]) { case 1: _gameState.dialogueChoiceCount = _gameState.dialogueData[offset + 1]; @@ -2832,7 +2838,7 @@ void IgorEngine::handleDialogue(int x, int y, int r, int g, int b) { _dialogueEnded = true; break; } - debug(kDebugEngine, "handleDialogue() end %d start %d count %d", _dialogueEnded, _gameState.dialogueChoiceStart, _gameState.dialogueChoiceCount); + debugC(9, kDebugEngine, "handleDialogue() end %d start %d count %d", _dialogueEnded, _gameState.dialogueChoiceStart, _gameState.dialogueChoiceCount); } while (!_dialogueEnded); memset(_screenVGA + 46080, 0, 17920); drawVerbsPanel(); @@ -2858,7 +2864,7 @@ void IgorEngine::drawDialogueChoices() { sprintf(questionText, "@%s %s", _dialogueQuestions[num][0], _dialogueQuestions[num][1]); drawString(_screenVGA, questionText, 0, _dialogueInfo[0] * 11 + 135, 240, 0, 0); } - debug(kDebugEngine, "drawDialogueChoices() i %d state %d num %d", i, _gameState.dialogueData[offset], _gameState.dialogueData[offset + 3]); + debugC(9, kDebugEngine, "drawDialogueChoices() i %d state %d num %d", i, _gameState.dialogueData[offset], _gameState.dialogueData[offset + 3]); } setPaletteColor(240, _paletteBuffer[0x2F6 + 1], _paletteBuffer[0x2F6 + 2], _paletteBuffer[0x2F6 + 3]); setPaletteColor(241, _paletteBuffer[0x2F0 + 1], _paletteBuffer[0x2F0 + 2], _paletteBuffer[0x2F0 + 3]); @@ -2903,7 +2909,7 @@ void IgorEngine::dialogueAskQuestion() { if (getPart() == 17) { num = 5; } - debug(kDebugEngine, "dialogueAskQuestion() num %d offset %d", num, offset); + debugC(9, kDebugEngine, "dialogueAskQuestion() num %d offset %d", num, offset); strcpy(_globalDialogueTexts[250], _dialogueQuestions[num][0]); strcpy(_globalDialogueTexts[251], _dialogueQuestions[num][1]); if (_globalDialogueTexts[251][0]) { @@ -2919,7 +2925,7 @@ void IgorEngine::dialogueAskQuestion() { void IgorEngine::dialogueReplyToQuestion(int x, int y, int r, int g, int b) { int offset = (_dialogueInfo[_dialogueChoiceSelected] - 1) * 6 + (_gameState.dialogueChoiceCount - 1) * 30 + (_gameState.dialogueChoiceStart - 1) * _roomDataOffsets.dlg.matSize; int reply = _gameState.dialogueData[offset + 4]; - debug(kDebugEngine, "dialogueReplyToQuestion() dialogue choice %d reply %d", _dialogueChoiceSelected, reply); + debugC(9, kDebugEngine, "dialogueReplyToQuestion() dialogue choice %d reply %d", _dialogueChoiceSelected, reply); if (reply == 0) { return; } @@ -2929,7 +2935,7 @@ void IgorEngine::dialogueReplyToQuestion(int x, int y, int r, int g, int b) { for (int i = 0; i < count; ++i) { int num = _gameState.dialogueData[offset] - 1; int len = _gameState.dialogueData[offset + 1]; - debug(kDebugEngine, "dialogueReplyToQuestion() reply %d %d offset %d", num, len, offset); + debugC(9, kDebugEngine, "dialogueReplyToQuestion() reply %d %d offset %d", num, len, offset); ADD_DIALOGUE_TEXT(dialogueIndex, len); for (int j = 0; j < len; ++j) { strcpy(_globalDialogueTexts[dialogueIndex], _dialogueReplies[num + j]); diff --git a/engines/igor/igor.h b/engines/igor/igor.h index 7074637fa5..6a8b79d1af 100644 --- a/engines/igor/igor.h +++ b/engines/igor/igor.h @@ -62,7 +62,10 @@ enum { kSharewarePart = 950, kTalkColor = 240, kTalkShadowColor = 241, - kTickDelay = 1193180 / 4096 + kTickDelay = 1193180 / 4096, + kTimerTicksCount = 8, + kQuickSaveSlot = 0, + kMaxSaveStates = 10 }; enum { @@ -204,7 +207,7 @@ struct WalkData { scaleHeight = h; } - static void setNextFrame(int pos, int &frame) { + static void setNextFrame(uint8 pos, uint8 &frame) { switch (pos) { case kFacingPositionBack: case kFacingPositionFront: @@ -261,6 +264,8 @@ struct Action { uint8 object2Type; }; +class TypeSerializer; + class IgorEngine: public Engine { public: @@ -387,7 +392,10 @@ protected: void dialogueAskQuestion(); void dialogueReplyToQuestion(int x, int y, int r, int g, int b); -// void serializeGameState(int slot, File *f, bool saving); + void saveOrLoadGameState(TypeSerializer &typeSerializer); + void loadGameState(int slot); + void saveGameState(int slot); + void generateGameStateFileName(int num, char *dst, int len) const; Common::File _ovlFile; Common::File _sndFile; @@ -417,13 +425,13 @@ protected: WalkData _walkData[100]; uint8 _walkCurrentPos; - int _walkDataLastIndex; - int _walkDataCurrentIndex; - int _walkCurrentFrame; + uint8 _walkDataLastIndex; + uint8 _walkDataCurrentIndex; + uint8 _walkCurrentFrame; int _walkDataCurrentPosX, _walkDataCurrentPosY; int _walkToObjectPosX, _walkToObjectPosY; - int _currentPart; + int16 _currentPart; int _talkDelay; int _talkSpeechCounter; int _talkDelayCounter; @@ -461,7 +469,7 @@ protected: Action _currentAction; uint8 _actionCode; uint8 _actionWalkPoint; - int _inputVars[kInputVarCount]; + int16 _inputVars[kInputVarCount]; bool _scrollInventory; int _scrollInventoryStartY, _scrollInventoryEndY, _scrollInventoryDy; bool _roomCursorOn; @@ -474,6 +482,7 @@ protected: int _gameTicks; int _resourceEntriesCount; int _resourceEntriesOffset; + char _saveStateDescriptions[kMaxSaveStates][100]; static const uint8 _dialogueColor[]; static const uint8 _sentenceColorIndex[]; diff --git a/engines/igor/menu.cpp b/engines/igor/menu.cpp index 60d1d287c3..cb977bcdac 100644 --- a/engines/igor/menu.cpp +++ b/engines/igor/menu.cpp @@ -338,6 +338,7 @@ void IgorEngine::handleOptionsMenu() { _currentPart = kSharewarePart; } } + showCursor(); } void IgorEngine::handlePause() { diff --git a/engines/igor/module.mk b/engines/igor/module.mk index 8c42a36a08..a5d4f0e979 100644 --- a/engines/igor/module.mk +++ b/engines/igor/module.mk @@ -4,6 +4,7 @@ MODULE_OBJS := \ detection.o \ igor.o \ menu.o \ + saveload.o \ staticres.o \ parts/part_04.o \ parts/part_05.o \ diff --git a/engines/igor/parts/part_04.cpp b/engines/igor/parts/part_04.cpp index 7090a64513..bb198cee15 100644 --- a/engines/igor/parts/part_04.cpp +++ b/engines/igor/parts/part_04.cpp @@ -28,7 +28,7 @@ namespace Igor { void IgorEngine::PART_04_EXEC_ACTION(int action) { - debug(kDebugGame, "PART_04_EXEC_ACTION %d", action); + debugC(9, kDebugGame, "PART_04_EXEC_ACTION %d", action); switch (action) { case 101: _currentPart = 120; diff --git a/engines/igor/parts/part_05.cpp b/engines/igor/parts/part_05.cpp index 8a938ef587..ae4ff11999 100644 --- a/engines/igor/parts/part_05.cpp +++ b/engines/igor/parts/part_05.cpp @@ -30,7 +30,7 @@ namespace Igor { void IgorEngine::PART_05_EXEC_ACTION(int action) { - debug(kDebugGame, "PART_05_EXEC_ACTION %d", action); + debugC(9, kDebugGame, "PART_05_EXEC_ACTION %d", action); switch (action) { case 101: ADD_DIALOGUE_TEXT(201, 2); diff --git a/engines/igor/parts/part_06.cpp b/engines/igor/parts/part_06.cpp index e39e38b4d0..e6fed6e68d 100644 --- a/engines/igor/parts/part_06.cpp +++ b/engines/igor/parts/part_06.cpp @@ -30,7 +30,7 @@ namespace Igor { void IgorEngine::PART_06_EXEC_ACTION(int action) { - debug(kDebugGame, "PART_06_EXEC_ACTION %d", action); + debugC(9, kDebugGame, "PART_06_EXEC_ACTION %d", action); switch (action) { case 101: ADD_DIALOGUE_TEXT(201, 2); diff --git a/engines/igor/parts/part_85.cpp b/engines/igor/parts/part_85.cpp index 26c6129e5c..dc0aab55fe 100644 --- a/engines/igor/parts/part_85.cpp +++ b/engines/igor/parts/part_85.cpp @@ -181,7 +181,7 @@ void IgorEngine::PART_85() { if (_inputVars[kInputEscape]) goto PART_85_EXIT; PART_85_HELPER_1(0x74CA, 0xA6C4, 1, 6, 32); if (_inputVars[kInputEscape]) goto PART_85_EXIT; - for (int i = 0; i != 200; ++i) { + for (int i = 0; i <= 200 / kTimerTicksCount; ++i) { PART_85_UPDATE_ROOM_BACKGROUND(); if (_inputVars[kInputEscape]) goto PART_85_EXIT; waitForTimer(); diff --git a/engines/igor/parts/part_main.cpp b/engines/igor/parts/part_main.cpp index 98c8f3bffb..09b2454f08 100644 --- a/engines/igor/parts/part_main.cpp +++ b/engines/igor/parts/part_main.cpp @@ -793,7 +793,7 @@ void IgorEngine::PART_MAIN() { drawInventory(1, 0); } do { - debug(kDebugGame, "PART_MAIN _currentPart %d", _currentPart); + debugC(9, kDebugGame, "PART_MAIN _currentPart %d", _currentPart); switch (_currentPart) { case 40: PART_04(); diff --git a/engines/igor/saveload.cpp b/engines/igor/saveload.cpp new file mode 100644 index 0000000000..96bacdf1ac --- /dev/null +++ b/engines/igor/saveload.cpp @@ -0,0 +1,197 @@ + +#include "common/savefile.h" +#include "common/system.h" + +#include "igor/igor.h" + +namespace Igor { + +class TypeSerializer { +public: + + TypeSerializer(Common::ReadStream *s) : _readStr(s), _writeStr(0), _saving(false) {} + TypeSerializer(Common::WriteStream *s) : _readStr(0), _writeStr(s), _saving(true) {} + +#define SAVEORLOAD_BASIC_TYPE(T, N, S) \ + void saveOrLoad ## N (T &t) { \ + if (_saving) { \ + _writeStr->write ## S (t); \ + } else { \ + t = _readStr->read ## S (); \ + } \ + } + + SAVEORLOAD_BASIC_TYPE(int8, Byte, Byte) + SAVEORLOAD_BASIC_TYPE(uint8, Byte, Byte) + SAVEORLOAD_BASIC_TYPE(int16, Int16, Uint16LE) + SAVEORLOAD_BASIC_TYPE(uint16, Int16, Uint16LE) + + void saveOrLoadBool(bool &b) { + if (_saving) { + _writeStr->writeByte(b ? 1 : 0); + } else { + b = _readStr->readByte() != 0; + } + } + + void saveOrLoadPad(int sz) { + if (_saving) { + while (sz--) { + _writeStr->writeByte(0); + } + } else { + while (sz--) { + _readStr->readByte(); + } + } + } + + void saveOrLoadPascalString(char *str) { + if (_saving) { + int len = strlen(str); + assert(len < 100); + _writeStr->writeByte(len); + _writeStr->write(str, len); + for (; len < 100; ++len) { + _writeStr->writeByte(' '); + } + } else { + int len = _readStr->readByte(); + assert(len < 100); + _readStr->read(str, len); + str[len] = 0; + for (; len < 100; ++len) { + _readStr->readByte(); + } + } + } + + void saveOrLoadWalkData(WalkData &wd) { + saveOrLoadPad(2); + saveOrLoadInt16(wd.x); + saveOrLoadInt16(wd.y); + saveOrLoadByte(wd.posNum); + saveOrLoadByte(wd.frameNum); + saveOrLoadByte(wd.clipSkipX); + saveOrLoadInt16(wd.clipWidth); + saveOrLoadInt16(wd.scaleWidth); + saveOrLoadByte(wd.xPosChanged); + saveOrLoadInt16(wd.dxPos); + saveOrLoadByte(wd.yPosChanged); + saveOrLoadInt16(wd.dyPos); + saveOrLoadByte(wd.scaleHeight); + } + + void saveOrLoadAction(Action &a) { + saveOrLoadByte(a.verb); + saveOrLoadByte(a.object1Num); + saveOrLoadByte(a.object1Type); + saveOrLoadByte(a.verbType); + saveOrLoadByte(a.object2Num); + saveOrLoadByte(a.object2Type); + } + + void saveOrLoadGameState(GameStateData &gs) { + saveOrLoadByte(gs.enableLight); + saveOrLoadByte(gs.colorLum); + for (int i = 0; i < 5; ++i) { + saveOrLoadInt16(gs.counter[i]); + } + saveOrLoadBool(gs.igorMoving); + saveOrLoadBool(gs.dialogueTextRunning); + saveOrLoadBool(gs.updateLight); + saveOrLoadBool(gs.unkF); + saveOrLoadByte(gs.unk10); + saveOrLoadByte(gs.unk11); + saveOrLoadBool(gs.dialogueStarted); + saveOrLoadPad(1); + for (int i = 0; i < 500; ++i) { + saveOrLoadByte(gs.dialogueData[i]); + } + saveOrLoadByte(gs.dialogueChoiceStart); + saveOrLoadByte(gs.dialogueChoiceCount); + saveOrLoadPad(2); + saveOrLoadByte(gs.nextMusicCounter); + saveOrLoadBool(gs.jumpToNextMusic); + saveOrLoadByte(gs.configSoundEnabled); + saveOrLoadByte(gs.talkSpeed); + saveOrLoadByte(gs.talkMode); + saveOrLoadPad(3); + saveOrLoadByte(gs.musicNum); + saveOrLoadByte(gs.musicSequenceIndex); + } + +private: + + bool _saving; + Common::ReadStream *_readStr; + Common::WriteStream *_writeStr; +}; + +void IgorEngine::saveOrLoadGameState(TypeSerializer &typeSerializer) { + for (int i = 0; i < 100; ++i) { + typeSerializer.saveOrLoadWalkData(_walkData[i]); + } + typeSerializer.saveOrLoadPad(20); + typeSerializer.saveOrLoadByte(_walkDataCurrentIndex); + typeSerializer.saveOrLoadByte(_walkDataLastIndex); + typeSerializer.saveOrLoadByte(_walkCurrentFrame); + typeSerializer.saveOrLoadByte(_walkCurrentPos); + typeSerializer.saveOrLoadPad(23); + typeSerializer.saveOrLoadAction(_currentAction); + typeSerializer.saveOrLoadPad(10); + typeSerializer.saveOrLoadInt16(_currentPart); + typeSerializer.saveOrLoadPad(8); + typeSerializer.saveOrLoadByte(_actionCode); + typeSerializer.saveOrLoadByte(_actionWalkPoint); + typeSerializer.saveOrLoadPad(2); + typeSerializer.saveOrLoadInt16(_inputVars[kInputCursorXPos]); + typeSerializer.saveOrLoadInt16(_inputVars[kInputCursorYPos]); + typeSerializer.saveOrLoadGameState(_gameState); + for (int i = 0; i < 112; ++i) { + typeSerializer.saveOrLoadByte(_objectsState[i]); + } + for (int i = 0; i < 74; ++i) { + typeSerializer.saveOrLoadByte(_inventoryInfo[i]); + } +} + +void IgorEngine::loadGameState(int slot) { + char name[64]; + generateGameStateFileName(slot, name, 63); + Common::InSaveFile *isf = _saveFileMan->openForLoading(name); + if (isf) { + TypeSerializer ts(isf); + ts.saveOrLoadPascalString(_saveStateDescriptions[slot]); + saveOrLoadGameState(ts); + delete isf; + + memcpy(_igorPalette, (_currentPart == 760) ? PAL_IGOR_2 : PAL_IGOR_1, 48); + UPDATE_OBJECT_STATE(255); + playMusic(_gameState.musicNum); + _system->warpMouse(_inputVars[kInputCursorXPos], _inputVars[kInputCursorYPos]); + if (_currentPart < 900) { + showCursor(); + } + debug(0, "Loaded state, current part %d", _currentPart); + } +} + +void IgorEngine::saveGameState(int slot) { + char name[64]; + generateGameStateFileName(slot, name, 63); + Common::OutSaveFile *osf = _saveFileMan->openForSaving(name); + if (osf) { + TypeSerializer ts(osf); + ts.saveOrLoadPascalString(_saveStateDescriptions[slot]); + saveOrLoadGameState(ts); + delete osf; + } +} + +void IgorEngine::generateGameStateFileName(int num, char *dst, int len) const { + snprintf(dst, len, "%s.%d", _targetName.c_str(), num); + dst[len] = 0; +} + +} // namespace Igor |