mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-01 06:58:34 +00:00
9f175c4053
This removes filename methods when it matched the Engine method. Secondly, ensuring there was an overriden getSaveStateName method for engines that didn't do the standard target.00x save filenames
596 lines
14 KiB
C++
596 lines
14 KiB
C++
/* 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 "common/debug-channels.h"
|
|
#include "audio/mixer.h"
|
|
|
|
#include "engines/util.h"
|
|
#include "graphics/surface.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 = nullptr;
|
|
Vars *g_vars = nullptr;
|
|
|
|
FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc) :
|
|
Engine(syst),
|
|
_gameDescription(gameDesc),
|
|
_rnd("fullpipe"),
|
|
_gameProject(nullptr),
|
|
_modalObject(nullptr),
|
|
_currSoundList1(),
|
|
_mapTable() {
|
|
DebugMan.addDebugChannel(kDebugPathfinding, "path", "Pathfinding");
|
|
DebugMan.addDebugChannel(kDebugDrawing, "drawing", "Drawing");
|
|
DebugMan.addDebugChannel(kDebugLoading, "loading", "Scene loading");
|
|
DebugMan.addDebugChannel(kDebugAnimation, "animation", "Animation");
|
|
DebugMan.addDebugChannel(kDebugBehavior, "behavior", "Behavior");
|
|
DebugMan.addDebugChannel(kDebugMemory, "memory", "Memory management");
|
|
DebugMan.addDebugChannel(kDebugEvents, "events", "Event handling");
|
|
DebugMan.addDebugChannel(kDebugInventory, "inventory", "Inventory");
|
|
DebugMan.addDebugChannel(kDebugSceneLogic, "scenelogic", "Scene Logic");
|
|
DebugMan.addDebugChannel(kDebugInteractions, "interactions", "Interactions");
|
|
DebugMan.addDebugChannel(kDebugXML, "xml", "XML");
|
|
|
|
// Setup mixer
|
|
if (!_mixer->isReady()) {
|
|
warning("Sound initialization failed.");
|
|
}
|
|
|
|
syncSoundSettings();
|
|
_sfxVolume = ConfMan.getInt("sfx_volume") * 39 - 10000;
|
|
_musicVolume = ConfMan.getInt("music_volume");
|
|
|
|
setDebugger(new Console(this));
|
|
|
|
_gameProjectVersion = 0;
|
|
_pictureScale = 8;
|
|
_scrollSpeed = 0;
|
|
_currSoundListCount = 0;
|
|
|
|
_updateTicks = 0;
|
|
_lastInputTicks = 0;
|
|
_lastButtonUpTicks = 0;
|
|
|
|
_currArchive = 0;
|
|
|
|
_soundEnabled = true;
|
|
_flgSoundList = true;
|
|
|
|
_inputController = 0;
|
|
_inputDisabled = false;
|
|
|
|
_normalSpeed = true;
|
|
|
|
_currentCheat = -1;
|
|
_currentCheatPos = 0;
|
|
|
|
_liftEnterMQ = 0;
|
|
_liftExitMQ = 0;
|
|
_lift = 0;
|
|
_lastLiftButton = nullptr;
|
|
_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;
|
|
|
|
_stream2playing = false;
|
|
|
|
_numSceneTracks = 0;
|
|
_sceneTrackHasSequence = false;
|
|
_sceneTrackIsPlaying = false;
|
|
|
|
_aniMan = nullptr;
|
|
_aniMan2 = nullptr;
|
|
_currentScene = nullptr;
|
|
_loaderScene = nullptr;
|
|
_scene2 = nullptr;
|
|
_scene3 = nullptr;
|
|
_messageHandlers = nullptr;
|
|
|
|
_updateScreenCallback = nullptr;
|
|
_updateCursorCallback = nullptr;
|
|
|
|
_msgX = 0;
|
|
_msgY = 0;
|
|
_msgObjectId2 = 0;
|
|
_msgId = 0;
|
|
_mouseVirtX = 0;
|
|
_mouseVirtY = 0;
|
|
|
|
_currSelectedInventoryItemId = 0;
|
|
|
|
_cursorId = 0;
|
|
|
|
_keyState = Common::KEYCODE_INVALID;
|
|
_buttonState = 0;
|
|
|
|
_updateFlag = true;
|
|
_flgCanOpenMap = true;
|
|
|
|
_sceneWidth = 1;
|
|
_sceneHeight = 1;
|
|
|
|
_inventoryScene = nullptr;
|
|
_inventory = nullptr;
|
|
|
|
_minCursorId = 0xffff;
|
|
_maxCursorId = 0;
|
|
_objectAtCursor = 0;
|
|
_objectIdAtCursor = 0;
|
|
|
|
_arcadeOverlay = nullptr;
|
|
_arcadeOverlayHelper = nullptr;
|
|
_arcadeOverlayX = 0;
|
|
_arcadeOverlayY = 0;
|
|
_arcadeOverlayMidX = 0;
|
|
_arcadeOverlayMidY = 0;
|
|
|
|
_isSaveAllowed = true;
|
|
|
|
g_fp = this;
|
|
g_vars = new Vars;
|
|
}
|
|
|
|
FullpipeEngine::~FullpipeEngine() {
|
|
delete g_vars;
|
|
g_vars = nullptr;
|
|
}
|
|
|
|
void FullpipeEngine::restartGame() {
|
|
_floaters->stopAll();
|
|
|
|
clearGlobalMessageQueueList();
|
|
clearMessages();
|
|
|
|
initObjectStates();
|
|
|
|
if (_scene2) {
|
|
_scene2->getAniMan();
|
|
_scene2 = nullptr;
|
|
}
|
|
|
|
if (_currentScene) {
|
|
_gameLoader->unloadScene(_currentScene->_sceneId);
|
|
|
|
_currentScene = nullptr;
|
|
}
|
|
|
|
_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);
|
|
}
|
|
}
|
|
|
|
bool FullpipeEngine::shouldQuit() {
|
|
return !_gameContinue || Engine::shouldQuit();
|
|
}
|
|
|
|
Common::Error FullpipeEngine::loadGameState(int slot) {
|
|
deleteModalObject();
|
|
|
|
if (_gameLoader->readSavegame(getSavegameFile(slot)))
|
|
return Common::kNoError;
|
|
else
|
|
return Common::kUnknownError;
|
|
}
|
|
|
|
Common::Error FullpipeEngine::saveGameState(int slot, const Common::String &description, bool isAutosave) {
|
|
if (_gameLoader->writeSavegame(_currentScene, getSavegameFile(slot), description))
|
|
return Common::kNoError;
|
|
else
|
|
return Common::kUnknownError;
|
|
}
|
|
|
|
Common::String FullpipeEngine::getSaveStateName(int slot) const {
|
|
return Common::String::format("fullpipe.s%02d", slot);
|
|
}
|
|
|
|
Common::Error FullpipeEngine::run() {
|
|
const Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
|
// Initialize backend
|
|
initGraphics(800, 600, &format);
|
|
|
|
_backgroundSurface.create(800, 600, format);
|
|
_origFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
|
|
|
|
_globalMessageQueueList.reset(new GlobalMessageQueueList);
|
|
_behaviorManager.reset(new BehaviorManager);
|
|
|
|
_sceneRect.left = 0;
|
|
_sceneRect.top = 0;
|
|
_sceneRect.right = 799;
|
|
_sceneRect.bottom = 599;
|
|
|
|
_floaters.reset(new Floaters);
|
|
_aniHandler.reset(new AniHandler);
|
|
_globalPalette = &_defaultPalette;
|
|
|
|
_isSaveAllowed = false;
|
|
|
|
if (debugChannelSet(-1, kDebugXML))
|
|
loadGameObjH();
|
|
|
|
int scene = 0;
|
|
if (ConfMan.hasKey("boot_param"))
|
|
scene = convertScene(ConfMan.getInt("boot_param"));
|
|
|
|
if (ConfMan.hasKey("save_slot"))
|
|
scene = -1;
|
|
|
|
if (!loadGam("fullpipe.gam", scene))
|
|
return Common::kNoGameDataFoundError;
|
|
|
|
if (ConfMan.hasKey("save_slot")) {
|
|
loadGameState(ConfMan.getInt("save_slot"));
|
|
}
|
|
|
|
#if 0
|
|
loadAllScenes();
|
|
#endif
|
|
|
|
int time1 = g_fp->_system->getMillis();
|
|
|
|
// Center mouse
|
|
_system->warpMouse(400, 300);
|
|
|
|
for (;;) {
|
|
updateEvents();
|
|
if (shouldQuit()) {
|
|
break;
|
|
}
|
|
|
|
int time2 = g_fp->_system->getMillis();
|
|
|
|
// 30fps
|
|
if (time2 - time1 >= 33 || !_normalSpeed) {
|
|
time1 = time2;
|
|
updateScreen();
|
|
}
|
|
|
|
if (_needRestart) {
|
|
delete _modalObject;
|
|
freeGameLoader();
|
|
_currentScene = nullptr;
|
|
_updateTicks = 0;
|
|
_globalPalette = &_defaultPalette;
|
|
|
|
loadGam("fullpipe.gam");
|
|
_needRestart = false;
|
|
}
|
|
|
|
_system->delayMillis(5);
|
|
_system->updateScreen();
|
|
}
|
|
|
|
delete _modalObject;
|
|
freeGameLoader();
|
|
|
|
cleanup();
|
|
_backgroundSurface.free();
|
|
|
|
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 {
|
|
deleteModalObject();
|
|
}
|
|
} else {
|
|
_gameLoader->updateSystems(42);
|
|
}
|
|
return;
|
|
}
|
|
|
|
ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0);
|
|
ex->_param = 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->_param = event.kbd.keycode;
|
|
ex->_excFlags |= 3;
|
|
ex->handle();
|
|
break;
|
|
case Common::KEYCODE_q:
|
|
return;
|
|
break;
|
|
default:
|
|
ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0);
|
|
ex->_param = 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:
|
|
return;
|
|
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();
|
|
}
|
|
_mouseScreenPos = event.mouse;
|
|
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->_param = getGameLoaderInventory()->getSelectedItemId();
|
|
ex->_excFlags |= 3;
|
|
_lastInputTicks = _updateTicks;
|
|
ex->handle();
|
|
}
|
|
_mouseScreenPos = event.mouse;
|
|
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();
|
|
}
|
|
_mouseScreenPos = event.mouse;
|
|
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);
|
|
_floaters->stopAll();
|
|
_gameLoader.reset();
|
|
_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();
|
|
}
|
|
|
|
void FullpipeEngine::deleteModalObject() {
|
|
if (!_modalObject)
|
|
return;
|
|
|
|
_modalObject->saveload();
|
|
BaseModalObject *tmp = _modalObject->_parentObj;
|
|
|
|
delete _modalObject;
|
|
|
|
_modalObject = tmp;
|
|
}
|
|
|
|
void FullpipeEngine::updateScreen() {
|
|
debugC(4, kDebugDrawing, "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 {
|
|
deleteModalObject();
|
|
}
|
|
}
|
|
} 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 Common::String &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 Common::String &objname) {
|
|
GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
|
|
|
if (var)
|
|
return var->getSubVarAsInt(objname);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void FullpipeEngine::setObjectState(const Common::String &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;
|
|
}
|
|
}
|
|
|
|
// Original was makeing a save on every room entering
|
|
if (_currentScene) {
|
|
_gameLoader->saveScenePicAniInfos(_currentScene->_sceneId);
|
|
// _gameLoader->writeSavegame(_currentScene, "savetmp.sav");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FullpipeEngine::isSaveAllowed() {
|
|
if (!g_fp->_isSaveAllowed)
|
|
return false;
|
|
|
|
bool allowed = true;
|
|
|
|
for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) {
|
|
if (!(*s)->_isFinished && ((*s)->getFlags() & 1))
|
|
allowed = false;
|
|
}
|
|
|
|
return allowed;
|
|
}
|
|
|
|
|
|
} // End of namespace Fullpipe
|