mirror of
https://github.com/libretro/scummvm.git
synced 2025-05-13 09:36:21 +00:00

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
808 lines
20 KiB
C++
808 lines
20 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 "common/scummsys.h"
|
|
#include "common/algorithm.h"
|
|
#include "common/config-manager.h"
|
|
#include "common/debug-channels.h"
|
|
#include "common/events.h"
|
|
#include "common/file.h"
|
|
#include "common/installshield_cab.h"
|
|
#include "common/translation.h"
|
|
#include "tony/tony.h"
|
|
#include "tony/custom.h"
|
|
#include "tony/debugger.h"
|
|
#include "tony/game.h"
|
|
#include "tony/mpal/mpal.h"
|
|
|
|
namespace Tony {
|
|
|
|
TonyEngine *g_vm;
|
|
|
|
TonyEngine::TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc) : Engine(syst),
|
|
_gameDescription(gameDesc), _randomSource("tony") {
|
|
g_vm = this;
|
|
_loadSlotNumber = -1;
|
|
|
|
// Set the up the debugger
|
|
setDebugger(new Debugger());
|
|
DebugMan.addDebugChannel(kTonyDebugAnimations, "animations", "Animations debugging");
|
|
DebugMan.addDebugChannel(kTonyDebugActions, "actions", "Actions debugging");
|
|
DebugMan.addDebugChannel(kTonyDebugSound, "sound", "Sound debugging");
|
|
DebugMan.addDebugChannel(kTonyDebugMusic, "music", "Music debugging");
|
|
|
|
// Add folders to the search directory list
|
|
const Common::FSNode gameDataDir(ConfMan.get("path"));
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "Voices");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "Roasted");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "Music");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "Music/utilsfx");
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "Music/Layer");
|
|
|
|
// Set up load slot number
|
|
_initialLoadSlotNumber = -1;
|
|
if (ConfMan.hasKey("save_slot")) {
|
|
int slotNumber = ConfMan.getInt("save_slot");
|
|
if (slotNumber >= 0 && slotNumber <= 99)
|
|
_initialLoadSlotNumber = slotNumber;
|
|
}
|
|
|
|
// Load the ScummVM sound settings
|
|
syncSoundSettings();
|
|
|
|
_hEndOfFrame = 0;
|
|
for (int i = 0; i < 6; i++)
|
|
_stream[i] = NULL;
|
|
for (int i = 0; i < MAX_SFX_CHANNELS; i++) {
|
|
_sfx[i] = NULL;
|
|
_utilSfx[i] = NULL;
|
|
}
|
|
_bPaused = false;
|
|
_bDrawLocation = false;
|
|
_startTime = 0;
|
|
_curThumbnail = NULL;
|
|
_bQuitNow = false;
|
|
_bTimeFreezed = false;
|
|
_nTimeFreezed = 0;
|
|
_vdbCodec = FPCODEC_UNKNOWN;
|
|
|
|
memset(_funcList, 0, sizeof(_funcList));
|
|
}
|
|
|
|
TonyEngine::~TonyEngine() {
|
|
// Close the voice database
|
|
closeVoiceDatabase();
|
|
|
|
// Reset the coroutine scheduler
|
|
CoroScheduler.reset();
|
|
CoroScheduler.setResourceCallback(NULL);
|
|
}
|
|
|
|
/**
|
|
* Run the game
|
|
*/
|
|
Common::Error TonyEngine::run() {
|
|
Common::ErrorCode result = init();
|
|
if (result != Common::kNoError)
|
|
return result;
|
|
|
|
play();
|
|
close();
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
/**
|
|
* Initialize the game
|
|
*/
|
|
Common::ErrorCode TonyEngine::init() {
|
|
// Load DAT file (used by font manager)
|
|
if (!loadTonyDat())
|
|
return Common::kUnknownError;
|
|
|
|
if (isCompressed()) {
|
|
Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember("data1.cab");
|
|
if (!stream)
|
|
error("Failed to open data1.cab");
|
|
|
|
Common::Archive *cabinet = Common::makeInstallShieldArchive(stream);
|
|
if (!cabinet)
|
|
error("Failed to parse data1.cab");
|
|
|
|
SearchMan.add("data1.cab", cabinet);
|
|
}
|
|
|
|
_hEndOfFrame = CoroScheduler.createEvent(false, false);
|
|
|
|
_bPaused = false;
|
|
_bDrawLocation = true;
|
|
_startTime = g_system->getMillis();
|
|
|
|
// Init static class fields
|
|
RMText::initStatics();
|
|
RMTony::initStatics();
|
|
|
|
// Reset the scheduler
|
|
CoroScheduler.reset();
|
|
|
|
// Initialize the graphics window
|
|
_window.init();
|
|
|
|
// Initialize the function list
|
|
Common::fill(_funcList, _funcList + 300, (LPCUSTOMFUNCTION)NULL);
|
|
initCustomFunctionMap();
|
|
|
|
// Initializes MPAL system, passing the custom functions list
|
|
Common::File f;
|
|
if (!f.open("ROASTED.MPC"))
|
|
return Common::kReadingFailed;
|
|
f.close();
|
|
|
|
if (!mpalInit("ROASTED.MPC", "ROASTED.MPR", _funcList, _funcListStrings))
|
|
return Common::kUnknownError;
|
|
|
|
// Initialize the update resources
|
|
_resUpdate.init("ROASTED.MPU");
|
|
|
|
// Initialize the music
|
|
initMusic();
|
|
|
|
// Initialize the voices database
|
|
if (!openVoiceDatabase())
|
|
return Common::kReadingFailed;
|
|
|
|
// Initialize the boxes
|
|
_theBoxes.init();
|
|
|
|
// Link to the custom graphics engine
|
|
_theEngine.initCustomDll();
|
|
_theEngine.init();
|
|
|
|
// Allocate space for thumbnails when saving the game
|
|
_curThumbnail = new uint16[160 * 120];
|
|
|
|
_bQuitNow = false;
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
bool TonyEngine::loadTonyDat() {
|
|
Common::String msg;
|
|
Common::File in;
|
|
Common::String filename = "tony.dat";
|
|
|
|
in.open(filename.c_str());
|
|
|
|
if (!in.isOpen()) {
|
|
msg = Common::String::format(_("Unable to locate the '%s' engine data file."), filename.c_str());
|
|
GUIErrorMessage(msg);
|
|
warning("%s", msg.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Read header
|
|
char buf[4+1];
|
|
in.read(buf, 4);
|
|
buf[4] = '\0';
|
|
|
|
if (strcmp(buf, "TONY")) {
|
|
msg = Common::String::format(_("The '%s' engine data file is corrupt."), filename.c_str());
|
|
GUIErrorMessage(msg);
|
|
warning("%s", msg.c_str());
|
|
return false;
|
|
}
|
|
|
|
int majVer = in.readByte();
|
|
int minVer = in.readByte();
|
|
|
|
if ((majVer != TONY_DAT_VER_MAJ) || (minVer != TONY_DAT_VER_MIN)) {
|
|
msg = Common::String::format(
|
|
_("Incorrect version of the '%s' engine data file found. Expected %d.%d but got %d.%d."),
|
|
filename.c_str(), TONY_DAT_VER_MAJ, TONY_DAT_VER_MIN, majVer, minVer);
|
|
GUIErrorMessage(msg);
|
|
warning("%s", msg.c_str());
|
|
|
|
return false;
|
|
}
|
|
|
|
int expectedLangVariant = -1;
|
|
switch (g_vm->getLanguage()) {
|
|
case Common::IT_ITA:
|
|
case Common::EN_ANY:
|
|
expectedLangVariant = 0;
|
|
break;
|
|
case Common::PL_POL:
|
|
expectedLangVariant = 1;
|
|
break;
|
|
case Common::RU_RUS:
|
|
expectedLangVariant = 2;
|
|
break;
|
|
case Common::CZ_CZE:
|
|
expectedLangVariant = 3;
|
|
break;
|
|
case Common::FR_FRA:
|
|
expectedLangVariant = 4;
|
|
break;
|
|
case Common::DE_DEU:
|
|
expectedLangVariant = 5;
|
|
break;
|
|
default:
|
|
warning("Unhandled language, falling back to English/Italian fonts.");
|
|
expectedLangVariant = 0;
|
|
break;
|
|
}
|
|
|
|
int numVariant = in.readUint16BE();
|
|
if (expectedLangVariant > numVariant - 1) {
|
|
msg = Common::String::format(_("Font variant not present in '%s' engine data file."), filename.c_str());
|
|
GUIErrorMessage(msg);
|
|
warning("%s", msg.c_str());
|
|
|
|
return false;
|
|
}
|
|
|
|
in.seek(in.pos() + (2 * 256 * 8 * expectedLangVariant));
|
|
for (int i = 0; i < 256; i++) {
|
|
_cTableDialog[i] = in.readSint16BE();
|
|
_lTableDialog[i] = in.readSint16BE();
|
|
_cTableMacc[i] = in.readSint16BE();
|
|
_lTableMacc[i] = in.readSint16BE();
|
|
_cTableCred[i] = in.readSint16BE();
|
|
_lTableCred[i] = in.readSint16BE();
|
|
_cTableObj[i] = in.readSint16BE();
|
|
_lTableObj[i] = in.readSint16BE();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void TonyEngine::initCustomFunctionMap() {
|
|
INIT_CUSTOM_FUNCTION(_funcList, _funcListStrings);
|
|
}
|
|
|
|
void TonyEngine::playMusic(int nChannel, const Common::String &fname, int nFX, bool bLoop, int nSync) {
|
|
if (nChannel < 4) {
|
|
if (GLOBALS._flipflop)
|
|
nChannel = nChannel + 1;
|
|
}
|
|
|
|
switch (nFX) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
_stream[nChannel]->stop();
|
|
_stream[nChannel]->unloadFile();
|
|
break;
|
|
|
|
case 22:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (nFX == 22) { // Sync a tempo
|
|
GLOBALS._curChannel = nChannel;
|
|
GLOBALS._nextLoop = bLoop;
|
|
GLOBALS._nextSync = nSync;
|
|
GLOBALS._nextMusic = fname;
|
|
|
|
if (GLOBALS._flipflop)
|
|
GLOBALS._nextChannel = nChannel - 1;
|
|
else
|
|
GLOBALS._nextChannel = nChannel + 1;
|
|
|
|
uint32 hThread = CoroScheduler.createProcess(doNextMusic, NULL, 0);
|
|
assert(hThread != CORO_INVALID_PID_VALUE);
|
|
|
|
} else if (nFX == 44) { // Change the channel and let the first finish
|
|
if (GLOBALS._flipflop)
|
|
GLOBALS._nextChannel = nChannel - 1;
|
|
else
|
|
GLOBALS._nextChannel = nChannel + 1;
|
|
|
|
_stream[GLOBALS._nextChannel]->stop();
|
|
_stream[GLOBALS._nextChannel]->unloadFile();
|
|
|
|
if (!getIsDemo()) {
|
|
if (!_stream[GLOBALS._nextChannel]->loadFile(fname, nSync))
|
|
error("failed to open music file '%s'", fname.c_str());
|
|
} else {
|
|
_stream[GLOBALS._nextChannel]->loadFile(fname, nSync);
|
|
}
|
|
|
|
_stream[GLOBALS._nextChannel]->setLoop(bLoop);
|
|
_stream[GLOBALS._nextChannel]->play();
|
|
|
|
GLOBALS._flipflop = 1 - GLOBALS._flipflop;
|
|
} else {
|
|
if (!getIsDemo()) {
|
|
if (!_stream[nChannel]->loadFile(fname, nSync))
|
|
error("failed to open music file '%s'", fname.c_str());
|
|
} else {
|
|
_stream[nChannel]->loadFile(fname, nSync);
|
|
}
|
|
|
|
_stream[nChannel]->setLoop(bLoop);
|
|
_stream[nChannel]->play();
|
|
}
|
|
}
|
|
|
|
void TonyEngine::doNextMusic(CORO_PARAM, const void *param) {
|
|
CORO_BEGIN_CONTEXT;
|
|
Common::String fn;
|
|
CORO_END_CONTEXT(_ctx);
|
|
|
|
FPStream **streams = g_vm->_stream;
|
|
|
|
CORO_BEGIN_CODE(_ctx);
|
|
|
|
if (!g_vm->getIsDemo()) {
|
|
if (!streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, GLOBALS._nextSync))
|
|
error("failed to open next music file '%s'", GLOBALS._nextMusic.c_str());
|
|
} else {
|
|
streams[GLOBALS._nextChannel]->loadFile(GLOBALS._nextMusic, GLOBALS._nextSync);
|
|
}
|
|
|
|
streams[GLOBALS._nextChannel]->setLoop(GLOBALS._nextLoop);
|
|
//streams[GLOBALS._nextChannel]->prefetch();
|
|
|
|
streams[GLOBALS._curChannel]->waitForSync(streams[GLOBALS._nextChannel]);
|
|
|
|
streams[GLOBALS._curChannel]->unloadFile();
|
|
|
|
GLOBALS._flipflop = 1 - GLOBALS._flipflop;
|
|
|
|
CORO_END_CODE;
|
|
}
|
|
|
|
void TonyEngine::playSFX(int nChannel, int nFX) {
|
|
if (_sfx[nChannel] == NULL)
|
|
return;
|
|
|
|
switch (nFX) {
|
|
case 0:
|
|
_sfx[nChannel]->setLoop(false);
|
|
break;
|
|
|
|
case 1:
|
|
_sfx[nChannel]->setLoop(true);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_sfx[nChannel]->play();
|
|
}
|
|
|
|
void TonyEngine::stopMusic(int nChannel) {
|
|
if (nChannel < 4)
|
|
_stream[nChannel + GLOBALS._flipflop]->stop();
|
|
else
|
|
_stream[nChannel]->stop();
|
|
}
|
|
|
|
void TonyEngine::stopSFX(int nChannel) {
|
|
_sfx[nChannel]->stop();
|
|
}
|
|
|
|
void TonyEngine::playUtilSFX(int nChannel, int nFX) {
|
|
if (_utilSfx[nChannel] == NULL)
|
|
return;
|
|
|
|
switch (nFX) {
|
|
case 0:
|
|
_utilSfx[nChannel]->setLoop(false);
|
|
break;
|
|
|
|
case 1:
|
|
_utilSfx[nChannel]->setLoop(true);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_utilSfx[nChannel]->setVolume(52);
|
|
_utilSfx[nChannel]->play();
|
|
}
|
|
|
|
void TonyEngine::stopUtilSFX(int nChannel) {
|
|
_utilSfx[nChannel]->stop();
|
|
}
|
|
|
|
void TonyEngine::preloadSFX(int nChannel, const char *fn) {
|
|
if (_sfx[nChannel] != NULL) {
|
|
_sfx[nChannel]->stop();
|
|
_sfx[nChannel]->release();
|
|
_sfx[nChannel] = NULL;
|
|
}
|
|
|
|
_theSound.createSfx(&_sfx[nChannel]);
|
|
|
|
_sfx[nChannel]->loadFile(fn);
|
|
}
|
|
|
|
FPSfx *TonyEngine::createSFX(Common::SeekableReadStream *stream) {
|
|
FPSfx *sfx;
|
|
|
|
_theSound.createSfx(&sfx);
|
|
sfx->loadWave(stream);
|
|
return sfx;
|
|
}
|
|
|
|
void TonyEngine::preloadUtilSFX(int nChannel, const char *fn) {
|
|
if (_utilSfx[nChannel] != NULL) {
|
|
_utilSfx[nChannel]->stop();
|
|
_utilSfx[nChannel]->release();
|
|
_utilSfx[nChannel] = NULL;
|
|
}
|
|
|
|
_theSound.createSfx(&_utilSfx[nChannel]);
|
|
|
|
_utilSfx[nChannel]->loadFile(fn);
|
|
_utilSfx[nChannel]->setVolume(63);
|
|
}
|
|
|
|
void TonyEngine::unloadAllSFX() {
|
|
for (int i = 0; i < MAX_SFX_CHANNELS; i++) {
|
|
if (_sfx[i] != NULL) {
|
|
_sfx[i]->stop();
|
|
_sfx[i]->release();
|
|
_sfx[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TonyEngine::unloadAllUtilSFX() {
|
|
for (int i = 0; i < MAX_SFX_CHANNELS; i++) {
|
|
if (_utilSfx[i] != NULL) {
|
|
_utilSfx[i]->stop();
|
|
_utilSfx[i]->release();
|
|
_utilSfx[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TonyEngine::initMusic() {
|
|
int i;
|
|
|
|
_theSound.init();
|
|
_theSound.setMasterVolume(63);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
_theSound.createStream(&_stream[i]);
|
|
|
|
for (i = 0; i < MAX_SFX_CHANNELS; i++) {
|
|
_sfx[i] = _utilSfx[i] = NULL;
|
|
}
|
|
|
|
// Preload sound effects
|
|
preloadUtilSFX(0, "U01.ADP"); // Reversed!!
|
|
preloadUtilSFX(1, "U02.ADP");
|
|
|
|
// Start check processes for sound
|
|
CoroScheduler.createProcess(FPSfx::soundCheckProcess, NULL);
|
|
}
|
|
|
|
void TonyEngine::closeMusic() {
|
|
for (int i = 0; i < 6; i++) {
|
|
_stream[i]->stop();
|
|
_stream[i]->unloadFile();
|
|
_stream[i]->release();
|
|
}
|
|
|
|
unloadAllSFX();
|
|
unloadAllUtilSFX();
|
|
}
|
|
|
|
void TonyEngine::pauseSound(bool bPause) {
|
|
_theEngine.pauseSound(bPause);
|
|
|
|
for (uint i = 0; i < 6; i++)
|
|
if (_stream[i])
|
|
_stream[i]->setPause(bPause);
|
|
|
|
for (uint i = 0; i < MAX_SFX_CHANNELS; i++) {
|
|
if (_sfx[i])
|
|
_sfx[i]->setPause(bPause);
|
|
if (_utilSfx[i])
|
|
_utilSfx[i]->setPause(bPause);
|
|
}
|
|
}
|
|
|
|
void TonyEngine::setMusicVolume(int nChannel, int volume) {
|
|
_stream[nChannel + GLOBALS._flipflop]->setVolume(volume);
|
|
}
|
|
|
|
int TonyEngine::getMusicVolume(int nChannel) {
|
|
int volume;
|
|
_stream[nChannel + GLOBALS._flipflop]->getVolume(&volume);
|
|
return volume;
|
|
}
|
|
|
|
Common::String TonyEngine::getSaveStateFileName(int n) {
|
|
return Common::String::format("tony.%03d", n);
|
|
}
|
|
|
|
Common::String TonyEngine::getSaveStateName(int slot) const {
|
|
return getSaveStateFileName(slot);
|
|
}
|
|
|
|
void TonyEngine::autoSave(CORO_PARAM) {
|
|
CORO_BEGIN_CONTEXT;
|
|
Common::String buf;
|
|
CORO_END_CONTEXT(_ctx);
|
|
|
|
CORO_BEGIN_CODE(_ctx);
|
|
|
|
grabThumbnail();
|
|
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
|
|
CORO_INVOKE_2(CoroScheduler.waitForSingleObject, g_vm->_hEndOfFrame, CORO_INFINITE);
|
|
_ctx->buf = getSaveStateFileName(0);
|
|
_theEngine.saveState(_ctx->buf, (byte *)_curThumbnail, "Autosave");
|
|
|
|
CORO_END_CODE;
|
|
}
|
|
|
|
void TonyEngine::saveState(int n, const char *name) {
|
|
Common::String buf = getSaveStateFileName(n);
|
|
_theEngine.saveState(buf.c_str(), (byte *)_curThumbnail, name);
|
|
}
|
|
|
|
void TonyEngine::loadState(CORO_PARAM, int n) {
|
|
CORO_BEGIN_CONTEXT;
|
|
Common::String buf;
|
|
CORO_END_CONTEXT(_ctx);
|
|
|
|
CORO_BEGIN_CODE(_ctx);
|
|
|
|
_ctx->buf = getSaveStateFileName(n);
|
|
CORO_INVOKE_1(_theEngine.loadState, _ctx->buf.c_str());
|
|
|
|
CORO_END_CODE;
|
|
}
|
|
|
|
bool TonyEngine::openVoiceDatabase() {
|
|
// Open the voices database
|
|
if (!_vdbFP.open("voices.vdb"))
|
|
if (!_vdbFP.open("voices.mdb"))
|
|
if (!_vdbFP.open("voices.odb"))
|
|
if (!_vdbFP.open("voices.fdb"))
|
|
return false;
|
|
|
|
_vdbFP.seek(-8, SEEK_END);
|
|
uint32 numfiles = _vdbFP.readUint32LE();
|
|
int32 id = _vdbFP.readUint32BE();
|
|
|
|
if (id == MKTAG('V', 'D', 'B', '1'))
|
|
_vdbCodec = FPCODEC_ADPCM;
|
|
else if (id == MKTAG('M', 'D', 'B', '1'))
|
|
_vdbCodec = FPCODEC_MP3;
|
|
else if (id == MKTAG('O', 'D', 'B', '1'))
|
|
_vdbCodec = FPCODEC_OGG;
|
|
else if (id == MKTAG('F', 'D', 'B', '1'))
|
|
_vdbCodec = FPCODEC_FLAC;
|
|
else {
|
|
_vdbFP.close();
|
|
return false;
|
|
}
|
|
|
|
// Read in the index
|
|
_vdbFP.seek(-8 - (numfiles * VOICE_HEADER_SIZE), SEEK_END);
|
|
|
|
for (uint32 i = 0; i < numfiles; ++i) {
|
|
VoiceHeader vh;
|
|
vh._offset = _vdbFP.readUint32LE();
|
|
vh._code = _vdbFP.readUint32LE();
|
|
vh._parts = _vdbFP.readUint32LE();
|
|
|
|
_voices.push_back(vh);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void TonyEngine::closeVoiceDatabase() {
|
|
if (_vdbFP.isOpen())
|
|
_vdbFP.close();
|
|
|
|
if (_voices.size() > 0)
|
|
_voices.clear();
|
|
}
|
|
|
|
void TonyEngine::grabThumbnail() {
|
|
_window.grabThumbnail(_curThumbnail);
|
|
}
|
|
|
|
uint16 *TonyEngine::getThumbnail() {
|
|
return _curThumbnail;
|
|
}
|
|
|
|
void TonyEngine::quitGame() {
|
|
_bQuitNow = true;
|
|
}
|
|
|
|
void TonyEngine::openInitLoadMenu(CORO_PARAM) {
|
|
_theEngine.openOptionScreen(coroParam, 1);
|
|
}
|
|
|
|
void TonyEngine::openInitOptions(CORO_PARAM) {
|
|
_theEngine.openOptionScreen(coroParam, 2);
|
|
}
|
|
|
|
/**
|
|
* Main process for playing the game.
|
|
*
|
|
* @remarks This needs to be in a separate process, since there are some things that can briefly
|
|
* block the execution of process. For now, all ScummVm event handling is dispatched to within the context of this
|
|
* process. If it ever proves a problem, we may have to look into whether it's feasible to have it still remain
|
|
* in the outer 'main' process.
|
|
*/
|
|
void TonyEngine::playProcess(CORO_PARAM, const void *param) {
|
|
CORO_BEGIN_CONTEXT;
|
|
Common::String fn;
|
|
CORO_END_CONTEXT(_ctx);
|
|
|
|
|
|
CORO_BEGIN_CODE(_ctx);
|
|
|
|
// Game loop. We rely on the outer main process to detect if a shutdown is required,
|
|
// and kill the scheudler and all the processes, including this one
|
|
for (;;) {
|
|
// If a savegame needs to be loaded, then do so
|
|
if (g_vm->_loadSlotNumber != -1 && GLOBALS._gfxEngine != NULL) {
|
|
_ctx->fn = getSaveStateFileName(g_vm->_loadSlotNumber);
|
|
CORO_INVOKE_1(GLOBALS._gfxEngine->loadState, _ctx->fn);
|
|
g_vm->_loadSlotNumber = -1;
|
|
}
|
|
|
|
// Wait for the next frame
|
|
CORO_INVOKE_1(CoroScheduler.sleep, 50);
|
|
|
|
// Call the engine to handle the next frame
|
|
CORO_INVOKE_1(g_vm->_theEngine.doFrame, g_vm->_bDrawLocation);
|
|
|
|
// Warns that a frame is finished
|
|
CoroScheduler.pulseEvent(g_vm->_hEndOfFrame);
|
|
|
|
// Handle drawing the frame
|
|
if (!g_vm->_bPaused) {
|
|
if (!g_vm->_theEngine._bWiping)
|
|
g_vm->_window.getNewFrame(g_vm->_theEngine, NULL);
|
|
else
|
|
g_vm->_window.getNewFrame(g_vm->_theEngine, &g_vm->_theEngine._rcWipeEllipse);
|
|
}
|
|
|
|
// Paint the frame onto the screen
|
|
g_vm->_window.repaint();
|
|
}
|
|
|
|
CORO_END_CODE;
|
|
}
|
|
|
|
/**
|
|
* Play the game
|
|
*/
|
|
void TonyEngine::play() {
|
|
// Create the game player process
|
|
CoroScheduler.createProcess(playProcess, NULL);
|
|
|
|
// Loop through calling the scheduler until it's time for the game to quit
|
|
while (!shouldQuit() && !_bQuitNow) {
|
|
// Delay for a brief amount
|
|
g_system->delayMillis(10);
|
|
|
|
// Call any scheduled processes
|
|
CoroScheduler.schedule();
|
|
}
|
|
}
|
|
|
|
void TonyEngine::close() {
|
|
closeMusic();
|
|
CoroScheduler.closeEvent(_hEndOfFrame);
|
|
_theBoxes.close();
|
|
_theEngine.close();
|
|
_window.close();
|
|
mpalFree();
|
|
freeMpc();
|
|
delete[] _curThumbnail;
|
|
}
|
|
|
|
void TonyEngine::freezeTime() {
|
|
_bTimeFreezed = true;
|
|
_nTimeFreezed = getTime() - _startTime;
|
|
}
|
|
|
|
void TonyEngine::unfreezeTime() {
|
|
_bTimeFreezed = false;
|
|
}
|
|
|
|
/**
|
|
* Returns the millisecond timer
|
|
*/
|
|
uint32 TonyEngine::getTime() {
|
|
return g_system->getMillis();
|
|
}
|
|
|
|
bool TonyEngine::canLoadGameStateCurrently() {
|
|
return GLOBALS._gfxEngine != NULL && GLOBALS._gfxEngine->canLoadSave();
|
|
}
|
|
|
|
bool TonyEngine::canSaveGameStateCurrently() {
|
|
return GLOBALS._gfxEngine != NULL && GLOBALS._gfxEngine->canLoadSave();
|
|
}
|
|
|
|
Common::Error TonyEngine::loadGameState(int slot) {
|
|
_loadSlotNumber = slot;
|
|
return Common::kNoError;
|
|
}
|
|
|
|
Common::Error TonyEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
|
|
if (!GLOBALS._gfxEngine)
|
|
return Common::kUnknownError;
|
|
|
|
RMGfxTargetBuffer &bigBuf = *GLOBALS._gfxEngine;
|
|
RMSnapshot s;
|
|
s.grabScreenshot(bigBuf, 4, _curThumbnail);
|
|
|
|
GLOBALS._gfxEngine->saveState(getSaveStateFileName(slot), (byte *)_curThumbnail, desc);
|
|
return Common::kNoError;
|
|
}
|
|
|
|
void TonyEngine::syncSoundSettings() {
|
|
Engine::syncSoundSettings();
|
|
|
|
GLOBALS._bCfgDubbing = !ConfMan.getBool("mute") && !ConfMan.getBool("speech_mute");
|
|
GLOBALS._bCfgSFX = !ConfMan.getBool("mute") && !ConfMan.getBool("sfx_mute");
|
|
GLOBALS._bCfgMusic = !ConfMan.getBool("mute") && !ConfMan.getBool("music_mute");
|
|
|
|
GLOBALS._nCfgDubbingVolume = ConfMan.getInt("speech_volume") * 10 / 256;
|
|
GLOBALS._nCfgSFXVolume = ConfMan.getInt("sfx_volume") * 10 / 256;
|
|
GLOBALS._nCfgMusicVolume = ConfMan.getInt("music_volume") * 10 / 256;
|
|
|
|
GLOBALS._bShowSubtitles = ConfMan.getBool("subtitles");
|
|
GLOBALS._nCfgTextSpeed = ConfMan.getInt("talkspeed") * 10 / 256;
|
|
}
|
|
|
|
void TonyEngine::saveSoundSettings() {
|
|
ConfMan.setBool("speech_mute", !GLOBALS._bCfgDubbing);
|
|
ConfMan.setBool("sfx_mute", !GLOBALS._bCfgSFX);
|
|
ConfMan.setBool("music_mute", !GLOBALS._bCfgMusic);
|
|
|
|
ConfMan.setInt("speech_volume", GLOBALS._nCfgDubbingVolume * 256 / 10);
|
|
ConfMan.setInt("sfx_volume", GLOBALS._nCfgSFXVolume * 256 / 10);
|
|
ConfMan.setInt("music_volume", GLOBALS._nCfgMusicVolume * 256 / 10);
|
|
|
|
ConfMan.setBool("subtitles", GLOBALS._bShowSubtitles);
|
|
ConfMan.setInt("talkspeed", GLOBALS._nCfgTextSpeed * 256 / 10);
|
|
}
|
|
|
|
void TonyEngine::showLocation() {
|
|
_bDrawLocation = true;
|
|
}
|
|
|
|
void TonyEngine::hideLocation() {
|
|
_bDrawLocation = false;
|
|
}
|
|
|
|
} // End of namespace Tony
|