/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "base/plugins.h" #include "common/archive.h" #include "common/config-manager.h" #include "audio/mixer.h" #include "engines/util.h" #include "fullpipe/fullpipe.h" #include "fullpipe/gameloader.h" #include "fullpipe/messages.h" #include "fullpipe/behavior.h" #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" #include "fullpipe/constants.h" namespace Fullpipe { FullpipeEngine *g_fp = 0; Vars *g_vars = 0; FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { // Setup mixer if (!_mixer->isReady()) { warning("Sound initialization failed."); } _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); _rnd = new Common::RandomSource("fullpipe"); _console = 0; _gameProjectVersion = 0; _pictureScale = 8; _scrollSpeed = 0; _currSoundListCount = 0; _globalPalette = 0; _updateTicks = 0; _lastInputTicks = 0; _lastButtonUpTicks = 0; _currArchive = 0; _soundEnabled = true; _flgSoundList = true; _sfxVolume = 0; _musicVolume = 0; _inputController = 0; _inputDisabled = false; _normalSpeed = true; _currentCheat = -1; _currentCheatPos = 0; _modalObject = 0; _origFormat = 0; _liftEnterMQ = 0; _liftExitMQ = 0; _lift = 0; _lastLiftButton = 0; _liftX = 0; _liftY = 0; _gameContinue = true; _needRestart = false; _flgPlayIntro = true; _gamePaused = false; _inputArFlag = false; _recordEvents = false; _mainMenu_debugEnabled = false; _flgGameIsRunning = true; _isProcessingMessages = false; _musicAllowed = -1; _musicGameVar = 0; _musicMinDelay = 0; _musicMaxDelay = 0; _musicLocal = 0; _trackStartDelay = 0; _sceneTrackHandle = new Audio::SoundHandle(); memset(_sceneTracks, 0, sizeof(_sceneTracks)); memset(_trackName, 0, sizeof(_trackName)); memset(_sceneTracksCurrentTrack, 0, sizeof(_sceneTracksCurrentTrack)); _numSceneTracks = 0; _sceneTrackHasSequence = false; _sceneTrackIsPlaying = false; _aniMan = 0; _aniMan2 = 0; _currentScene = 0; _loaderScene = 0; _scene2 = 0; _scene3 = 0; _movTable = 0; _floaters = 0; _mgm = 0; _globalMessageQueueList = 0; _messageHandlers = 0; _updateScreenCallback = 0; _updateCursorCallback = 0; _msgX = 0; _msgY = 0; _msgObjectId2 = 0; _msgId = 0; _mouseVirtX = 0; _mouseVirtY = 0; _currSelectedInventoryItemId = 0; _behaviorManager = 0; _cursorId = 0; _keyState = Common::KEYCODE_INVALID; _buttonState = 0; _gameLoader = 0; _gameProject = 0; _updateFlag = true; _flgCanOpenMap = true; _sceneWidth = 1; _sceneHeight = 1; for (int i = 0; i < 11; i++) _currSoundList1[i] = 0; for (int i = 0; i < 200; i++) _mapTable[i] = 0; _inventoryScene = 0; _inventory = 0; _minCursorId = 0xffff; _maxCursorId = 0; _objectAtCursor = 0; _objectIdAtCursor = 0; _arcadeOverlay = 0; _arcadeOverlayHelper = 0; _arcadeOverlayX = 0; _arcadeOverlayY = 0; _arcadeOverlayMidX = 0; _arcadeOverlayMidY = 0; _isSaveAllowed = true; g_fp = this; g_vars = new Vars; } FullpipeEngine::~FullpipeEngine() { delete _rnd; delete _console; delete _globalMessageQueueList; delete _sceneTrackHandle; } void FullpipeEngine::initialize() { _globalMessageQueueList = new GlobalMessageQueueList; _behaviorManager = new BehaviorManager; _sceneRect.left = 0; _sceneRect.top = 0; _sceneRect.right = 799; _sceneRect.bottom = 599; _floaters = new Floaters; _mgm = new MGM; } void FullpipeEngine::restartGame() { _floaters->stopAll(); clearGlobalMessageQueueList(); clearMessages(); initObjectStates(); if (_scene2) { _scene2->getAniMan(); _scene2 = 0; } if (_currentScene) { _gameLoader->unloadScene(_currentScene->_sceneId); _currentScene = 0; } _gameLoader->restoreDefPicAniInfos(); getGameLoaderInventory()->clear(); getGameLoaderInventory()->addItem(ANI_INV_MAP, 1); getGameLoaderInventory()->rebuildItemRects(); initMap(); if (_flgPlayIntro) { _gameLoader->loadScene(SC_INTRO1); _gameLoader->gotoScene(SC_INTRO1, TrubaUp); } else { _gameLoader->loadScene(SC_1); _gameLoader->gotoScene(SC_1, TrubaLeft); } } Common::Error FullpipeEngine::run() { const Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0); // Initialize backend initGraphics(800, 600, true, &format); _backgroundSurface.create(800, 600, format); _origFormat = new Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); _console = new Console(this); initialize(); _isSaveAllowed = false; int scene = 0; if (ConfMan.hasKey("boot_param")) scene = convertScene(ConfMan.getInt("boot_param")); if (!loadGam("fullpipe.gam", scene)) return Common::kNoGameDataFoundError; #if 0 loadAllScenes(); #endif _gameContinue = true; while (_gameContinue) { updateEvents(); updateScreen(); if (_needRestart) { if (_modalObject) { delete _modalObject; _modalObject = 0; } freeGameLoader(); _currentScene = 0; _updateTicks = 0; loadGam("fullpipe.gam"); _needRestart = false; } if (_normalSpeed) _system->delayMillis(10); _system->updateScreen(); } freeGameLoader(); cleanup(); return Common::kNoError; } void FullpipeEngine::updateEvents() { Common::Event event; Common::EventManager *eventMan = _system->getEventManager(); ExCommand *ex; while (eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_KEYDOWN: _keyState = event.kbd.keycode; switch (event.kbd.keycode) { case Common::KEYCODE_SPACE: if (_gamePaused) { if (_modalObject) { if (_modalObject->init(42)) { _modalObject->update(); } else { _modalObject->saveload(); BaseModalObject *obj = _modalObject->_parentObj; if (obj) delete _modalObject; _modalObject = obj; } } else { _gameLoader->updateSystems(42); } return; } ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0); ex->_keyCode = 32; ex->_excFlags |= 3; ex->handle(); break; case Common::KEYCODE_s: if (_gamePaused) { _gamePaused = 0; _flgGameIsRunning = true; return; } ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0); ex->_keyCode = event.kbd.keycode; ex->_excFlags |= 3; ex->handle(); break; case Common::KEYCODE_q: return; break; default: if (event.kbd.keycode == Common::KEYCODE_d && event.kbd.hasFlags(Common::KBD_CTRL)) { // Start the debugger getDebugger()->attach(); getDebugger()->onFrame(); } ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0); ex->_keyCode = event.kbd.keycode; ex->_excFlags |= 3; ex->handle(); break; } break; case Common::EVENT_KEYUP: if (!_inputArFlag) { ex = new ExCommand(0, 17, 37, 0, 0, 0, 1, 0, 0, 0); ex->_excFlags |= 3; ex->handle(); } _keyState = Common::KEYCODE_INVALID; break; case Common::EVENT_MOUSEMOVE: if (_recordEvents) { ex = new ExCommand(0, 17, 31, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0); ex->_excFlags |= 3; ex->handle(); } _mouseScreenPos = event.mouse; break; case Common::EVENT_QUIT: _gameContinue = false; break; case Common::EVENT_RBUTTONDOWN: if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) { ex = new ExCommand(0, 17, 107, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0); ex->_excFlags |= 3; _lastInputTicks = _updateTicks; ex->handle(); } break; case Common::EVENT_LBUTTONDOWN: if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) { ex = new ExCommand(0, 17, 29, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0); ex->_sceneClickX = _sceneRect.left + ex->_x; ex->_sceneClickY = _sceneRect.top + ex->_y; ex->_keyCode = getGameLoaderInventory()->getSelectedItemId(); ex->_excFlags |= 3; _lastInputTicks = _updateTicks; ex->handle(); } break; case Common::EVENT_LBUTTONUP: if (!_inputArFlag && (_updateTicks - _lastButtonUpTicks) >= 2) { ex = new ExCommand(0, 17, 30, 0, 0, 0, 1, 0, 0, 0); ex->_excFlags |= 3; _lastButtonUpTicks = _updateTicks; ex->handle(); } break; default: break; } } // pollEvent() is implemented only for video player. So skip it. //if (event.kbd.keycode == MSG_SC11_SHOWSWING && _modalObject) { // _modalObject->pollEvent(); //} } void FullpipeEngine::freeGameLoader() { setCursor(0); delete _movTable; _floaters->stopAll(); delete _gameLoader; _currentScene = 0; _scene2 = 0; _loaderScene = 0; } void FullpipeEngine::cleanup() { //cleanRecorder(); clearMessageHandlers(); clearMessages(); _globalMessageQueueList->compact(); for (uint i = 0; i < _globalMessageQueueList->size(); i++) delete (*_globalMessageQueueList)[i]; stopAllSoundStreams(); delete _origFormat; } void FullpipeEngine::updateScreen() { debug(4, "FullpipeEngine::updateScreen()"); _mouseVirtX = _mouseScreenPos.x + _sceneRect.left; _mouseVirtY = _mouseScreenPos.y + _sceneRect.top; //if (inputArFlag) // updateGame_inputArFlag(); if (_modalObject || (_flgGameIsRunning && (_gameLoader->updateSystems(42), _modalObject != 0))) { if (_flgGameIsRunning) { if (_modalObject->init(42)) { _modalObject->update(); } else { _modalObject->saveload(); BaseModalObject *tmp = _modalObject->_parentObj; delete _modalObject; _modalObject = tmp; } } } else if (_currentScene) { _currentScene->draw(); if (_inventoryScene) _inventory->draw(); if (_updateScreenCallback) _updateScreenCallback(); //if (inputArFlag && _currentScene) { // vrtTextOut(*(_DWORD *)g_vrtHandle, smallNftData, "DEMO", 4, 380, 580); // vrtTextOut(*(_DWORD *)g_vrtHandle, smallNftData, "Alt+F4 - exit", 14, 695, 580); //} } else { //vrtRectangle(*(_DWORD *)g_vrtHandle, 0, 0, 0, 800, 600); } _inputController->drawCursor(_mouseScreenPos.x, _mouseScreenPos.y); ++_updateTicks; } int FullpipeEngine::getObjectEnumState(const char *name, const char *state) { GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES"); if (!var) { var = _gameLoader->_gameVar->addSubVarAsInt("OBJSTATES", 0); } var = var->getSubVarByName(name); if (var) { var = var->getSubVarByName("ENUMSTATES"); if (var) return var->getSubVarAsInt(state); } return 0; } int FullpipeEngine::getObjectState(const char *objname) { GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES"); if (var) return var->getSubVarAsInt(objname); return 0; } void FullpipeEngine::setObjectState(const char *name, int state) { GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES"); if (!var) { var = _gameLoader->_gameVar->addSubVarAsInt("OBJSTATES", 0); } var->setSubVarAsInt(name, state); } void FullpipeEngine::disableSaves(ExCommand *ex) { if (_isSaveAllowed) { _isSaveAllowed = false; if (_globalMessageQueueList->size() && (*_globalMessageQueueList)[0] != 0) { for (uint i = 0; i < _globalMessageQueueList->size(); i++) { if ((*_globalMessageQueueList)[i]->_flags & 1) if ((*_globalMessageQueueList)[i]->_id != ex->_parId && !(*_globalMessageQueueList)[i]->_isFinished) return; } } if (_currentScene) _gameLoader->writeSavegame(_currentScene, "savetmp.sav"); } } } // End of namespace Fullpipe