void Game::runObjectsScript() { debug(DBG_GAME, "Game::runObjectsScript()"); _objectScript.nextScene = -1; assert(_loadDataState != 3); // unneeded code if (_varsTable[309]) { memset(_keysPressed, 0, sizeof(_keysPressed)); } if (_loadDataState == 2) { int start = _workaroundRaftFlySceneBug ? 1 : 0; _workaroundRaftFlySceneBug = false; for (int i = start; i < _sceneObjectsCount; ++i) { SceneObject *so = &_sceneObjectsTable[i]; if (so->statePrev == 0 || so->statePrev == -1) { continue; } debug(DBG_GAME, "Game::runObjectsScript() currentObjectNum=%d", i); _objectScript.currentObjectNum = i; int anim = _sceneObjectMotionsTable[so->motionNum1].animNum; assert(anim >= 0 && anim < _animationsCount); _objectScript.data = _animationsTable[anim].scriptData; int endOfDataOffset = _animationsTable[anim].scriptSize; // endOfDataOffset2 _objectScript.dataOffset = 0; int statement = 0; while (_objectScript.dataOffset < endOfDataOffset) { _objectScript.statementNum = statement; int endOfStatementDataOffset = _objectScript.fetchNextWord(); // endOfDataOffset1 _objectScript.testObjectNum = -1; _objectScript.testDataOffset = endOfStatementDataOffset; bool loop = true; while (loop) { int op = _objectScript.fetchNextWord(); debug(DBG_OPCODES, "statement %d condition %d op %d", statement, i, op); if (op == 0) { break; } loop = executeConditionOpcode(op); } if (loop) { while (_objectScript.dataOffset < endOfStatementDataOffset) { int op = _objectScript.fetchNextWord(); debug(DBG_OPCODES, "statement %d operator %d op %d", statement, i, op); if (op == 100) { // &Game::oop_breakObjectScript endOfStatementDataOffset = _objectScript.dataOffset = endOfDataOffset; break; } executeOperatorOpcode(op); } } _objectScript.dataOffset = endOfStatementDataOffset; ++statement; } } _dialogueEndedFlag = 0; if (_objectScript.nextScene != -1 && _objectScript.nextScene < _sceneConditionsCount) { strcpy(_tempTextBuffer, _nextScenesTable[_objectScript.nextScene].name); _switchScene = true; _currentSceneSav[0] = 0; if (stringEndsWith(_tempTextBuffer, "SAV")) { // debug(DBG_GAME, "End of demo interactive part"); // strcpy(_tempTextBuffer, "A03.SCN"); FileHolder fh(_fs, _tempTextBuffer); if (!fh._fp) { warning("Unable to load game state from file '%s'", _tempTextBuffer); } else { strcpy(_currentSceneSav, _tempTextBuffer); loadState(fh._fp, kDemoSavSlot, true); _loadState = _switchScene; // load on scene switch } } } for (int i = 0; i < _sceneObjectsCount; ++i) { reinitializeObject(i); } if (kCheatNoHit) { _varsTable[0] = 0; } if (_varsTable[0] >= 10 && !_gameOver) { strcpy(_musicName, "..\\midi\\gameover.mid"); playMusic(_musicName); _gameOver = true; // _skipUpdateScreen = false; } if (_loadDataState == 2) { updateObjects(); } } // _skipUpdateScreen = false; if (_varsTable[241] == 1) { // _startEndingScene = true; stopMusic(); clearSceneData(-1); _varsTable[241] = 2; playVideo("DATA/FINAL.AVI"); strcpy(_tempTextBuffer, "END.SCN"); _switchScene = true; } }
void Game::fini() { clearSceneData(-1); deallocateTables(); unloadCommonSprites(); _stub->destroy(); }
void Game::runObjectsScript() { debug(DBG_GAME, "Game::runObjectsScript()"); _objectScript.nextScene = -1; assert(_loadDataState != 3); // unneeded code if (_varsTable[309]) { memset(_keysPressed, 0, sizeof(_keysPressed)); } if (_loadDataState == 2) { int start = _workaroundRaftFlySceneBug ? 1 : 0; _workaroundRaftFlySceneBug = false; for (int i = start; i < _sceneObjectsCount; ++i) { SceneObject *so = &_sceneObjectsTable[i]; if (so->statePrev == 0 || so->statePrev == -1) { continue; } debug(DBG_GAME, "Game::runObjectsScript() currentObjectNum=%d", i); _objectScript.currentObjectNum = i; int anim = _sceneObjectMotionsTable[so->motionNum1].animNum; assert(anim >= 0 && anim < _animationsCount); _objectScript.data = _animationsTable[anim].scriptData; int endOfDataOffset = _animationsTable[anim].scriptSize; // endOfDataOffset2 _objectScript.dataOffset = 0; int statement = 0; while (_objectScript.dataOffset < endOfDataOffset) { _objectScript.statementNum = statement; int endOfStatementDataOffset = _objectScript.fetchNextWord(); // endOfDataOffset1 _objectScript.testObjectNum = -1; _objectScript.testDataOffset = endOfStatementDataOffset; bool loop = true; while (loop) { int op = _objectScript.fetchNextWord(); debug(DBG_OPCODES, "statement %d condition %d op %d", statement, i, op); if (op == 0) { break; } const GameConditionOpcode *cop = findConditionOpcode(op); if (!cop) { error("Invalid condition %d", op); } loop = (this->*(cop->pf))(); } if (loop) { while (_objectScript.dataOffset < endOfStatementDataOffset) { int op = _objectScript.fetchNextWord(); debug(DBG_OPCODES, "statement %d operator %d op %d", statement, i, op); if (op == 100) { // &Game::oop_breakObjectScript endOfStatementDataOffset = _objectScript.dataOffset = endOfDataOffset; break; } const GameOperatorOpcode *oop = findOperatorOpcode(op); if (!oop) { error("Invalid operator %d", op); } (this->*(oop->pf))(); } } _objectScript.dataOffset = endOfStatementDataOffset; ++statement; } } _dialogueEndedFlag = 0; if (_objectScript.nextScene != -1 && _objectScript.nextScene < _sceneConditionsCount) { strcpy(_tempTextBuffer, _nextScenesTable[_objectScript.nextScene].name); _switchScene = true; } for (int i = 0; i < _sceneObjectsCount; ++i) { reinitializeObject(i); } #if 0 // cheat: no hit _varsTable[0] = 0; #endif if (_varsTable[0] >= 10 && !_gameOver) { strcpy(_musicName, "..\\midi\\gameover.mid"); playMusic(_musicName); _gameOver = true; // _skipUpdateScreen = false; } if (_loadDataState == 2) { updateObjects(); } } // _skipUpdateScreen = false; if (_varsTable[241] == 1) { // _startEndingScene = true; stopMusic(); clearSceneData(-1); _varsTable[241] = 2; playVideo("DATA/FINAL.AVI"); strcpy(_tempTextBuffer, "END.SCN"); _switchScene = true; } }
void Game::parseSCN(const char *fileName) { debug(DBG_GAME, "Game::parseSCN()"); FileHolder fp(_fs, fileName); _sceneDescriptionSize = fp->size(); _sceneDescriptionBuffer = (char *)malloc(_sceneDescriptionSize + 1); if (!_sceneDescriptionBuffer) { error("Unable to allocate %d bytes", _sceneDescriptionSize + 1); } fp->read(_sceneDescriptionBuffer, _sceneDescriptionSize); _sceneDescriptionBuffer[_sceneDescriptionSize] = 0; stringStripComments(_sceneDescriptionBuffer); int anim = 0; bool loadMovData = false; _sceneNumber = 0; _currentSceneObject = 0; memcpy(_defaultVarsTable, _varsTable, sizeof(_varsTable)); _currentState = kParserStateDef; _stopParsing = false; for (char *s = _sceneDescriptionBuffer; !_stopParsing && s; ) { bool didTest = false; bool compareTest = true; while ((_currentToken = getNextToken(&s)) == kParserTokenGlobalMemory) { compareTest = compareTest && parseToken_GlobalMemory(&s, this); didTest = true; } if (didTest) { if (!compareTest) { // condition statement is false, skip to next line stringNextTokenEOL(&s); continue; } if (_currentToken != kParserTokenThen) { error("Unexpected token %d", _currentToken); } _currentToken = getNextToken(&s); } if (_currentState != kParserStateDef) { switch (_currentState) { case kParserStateMovies: if (_currentToken == kParserTokenMoviesEnd) { if (!loadMovData) { clearSceneData(anim - 1); } _currentState = kParserStateDef; } else { if (!loadMovData) { if (anim < _animationsCount && strcasecmp(_animationsTable[anim].name, _currentTokenStr) == 0) { ++anim; } else { if (_animationsCount != 0) { clearSceneData(anim - 1); } _loadDataState = 1; loadMovData = true; } } if (loadMovData) { loadMOV(_currentTokenStr); } } break; case kParserStateBag: if (_currentToken == kParserTokenBagEnd) { _currentState = kParserStateDef; } else { parse_BagObject(&s, this); } break; case kParserStateScene: if (_currentToken == kParserTokenSceneEnd) { _currentState = kParserStateDef; } else { parse_SceneCondition(&s, this); } break; case kParserStateObject: if (_currentToken == kParserTokenObjectEnd) { _currentState = kParserStateDef; } else { parse_Object(&s, this); } break; case kParserStateNewObject: if (_currentToken == kParserTokenObjectEnd) { _currentState = kParserStateDef; } else { if (_currentSceneObject) { if (_sceneObjectMotionsTable[_currentSceneObject->motionInit].animNum < anim) { _currentSceneObject = 0; } } parse_Object(&s, this); } break; case kParserStateBox: if (_currentToken == kParserTokenBoxEnd) { _currentState = kParserStateDef; } else { parse_BoxDescription(&s, this); } break; } } else { switch (_currentToken) { case kParserTokenEnd: _stopParsing = true; break; case kParserTokenMovies: _currentState = kParserStateMovies; break; case kParserTokenScene: _currentState = kParserStateScene; break; case kParserTokenScreen: parseToken_Screen(&s, this); break; case kParserTokenSceneNumber: getNextToken_Int(&s, &_sceneNumber); break; case kParserTokenMidi: parseToken_Midi(&s, this); break; case kParserTokenObject: _currentState = kParserStateObject; parseToken_Object(&s, this); break; case kParserTokenIfNewObject: _currentState = kParserStateNewObject; parseToken_Object(&s, this); break; case kParserTokenBag: _currentState = kParserStateBag; parseToken_Bag(&s, this); break; case kParserTokenBox: _currentState = kParserStateBox; break; default: error("Unexpected token %d state %d", _currentToken, _currentState); break; } } } free(_sceneDescriptionBuffer); _sceneDescriptionBuffer = 0; _sceneDescriptionSize = 0; }
void Game::mainLoop() { _stub->init(_gameWindowTitle, kGameScreenWidth, kGameScreenHeight); allocateTables(); loadCommonSprites(); _mixer->open(); restart(); if (_isDemo) { playBitmapSequenceDemo(); } else { playVideo("DATA/LOGO.AVI"); playVideo("DATA/INTRO.AVI"); } _lastFrameTimeStamp = _stub->getTimeStamp(); while (!_stub->_quit) { if (_switchScene) { _switchScene = false; if (stringEndsWith(_tempTextBuffer, "SCN")) { win16_sndPlaySound(6); debug(DBG_GAME, "switch to scene '%s'", _tempTextBuffer); if (strcmp(_tempTextBuffer, "PIC4.SCN") == 0) { debug(DBG_INFO, "End of game"); break; } strcpy(_currentSceneScn, _tempTextBuffer); parseSCN(_tempTextBuffer); } else if (stringEndsWith(_tempTextBuffer, "SAV")) { if (_isDemo && strcmp(_tempTextBuffer, "A16.SAV") == 0) { debug(DBG_GAME, "End of demo interactive part"); restart(); continue; } warning("Ignoring savestate load '%s'", _tempTextBuffer); // should work though, as the original savestates load fine // now, but this "feature" is only used in the demo AFAICT, // so no need to bother... } else { debug(DBG_GAME, "load mov '%s'", _tempTextBuffer); loadMOV(_tempTextBuffer); } if (_loadState) { _loadState = false; loadState(_stateSlot, false); playMusic(_musicName); memset(_keysPressed, 0, sizeof(_keysPressed)); } assert(_sceneObjectsCount != 0); if (_currentBagObject == -1) { _currentBagObject = _bagObjectsCount - 1; if (_currentBagObject > 0) { _currentBagObject = 0; } } if (_loadDataState != 0) { setupScreenPalette(_bitmapBuffer0 + kOffsetBitmapPalette); } _gameOver = false; _workaroundRaftFlySceneBug = strncmp(_currentSceneScn, "FLY", 3) == 0; } updateKeysPressedTable(); updateMouseButtonsPressed(); runObjectsScript(); if (!_switchScene) { _stub->updateScreen(); uint32 end = _lastFrameTimeStamp + kCycleDelay; do { _stub->sleep(10); _stub->processEvents(); } while (!_stub->_pi.fastMode && _stub->getTimeStamp() < end); _lastFrameTimeStamp = _stub->getTimeStamp(); } if (_startDialogue) { _startDialogue = false; handleDialogue(); } } clearSceneData(-1); deallocateTables(); unloadCommonSprites(); _mixer->close(); _stub->destroy(); }