2020-12-24 16:10:32 -03:00
|
|
|
#include "common/scummsys.h"
|
|
|
|
|
2020-12-24 19:02:12 -03:00
|
|
|
#include "audio/decoders/wave.h"
|
|
|
|
#include "audio/audiostream.h"
|
|
|
|
|
2021-01-13 19:27:09 -03:00
|
|
|
#include "common/archive.h"
|
2020-12-24 16:10:32 -03:00
|
|
|
#include "common/config-manager.h"
|
|
|
|
#include "common/debug.h"
|
|
|
|
#include "common/debug-channels.h"
|
|
|
|
#include "common/error.h"
|
|
|
|
#include "common/events.h"
|
|
|
|
#include "common/file.h"
|
|
|
|
#include "common/fs.h"
|
|
|
|
#include "common/system.h"
|
2021-01-02 14:19:23 -03:00
|
|
|
#include "common/str.h"
|
2021-01-12 20:49:12 -03:00
|
|
|
#include "common/savefile.h"
|
2021-01-31 20:15:56 -03:00
|
|
|
#include "common/timer.h"
|
2020-12-24 16:10:32 -03:00
|
|
|
#include "engines/util.h"
|
|
|
|
|
2021-01-02 14:19:23 -03:00
|
|
|
#include "image/bmp.h"
|
2021-01-07 23:10:19 -03:00
|
|
|
#include "graphics/cursorman.h"
|
2021-01-02 14:19:23 -03:00
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
#include "private/cursors.h"
|
2020-12-24 16:10:32 -03:00
|
|
|
#include "private/private.h"
|
2020-12-30 14:34:32 -03:00
|
|
|
#include "private/grammar.tab.h"
|
|
|
|
#include "private/grammar.h"
|
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
namespace Private {
|
|
|
|
|
2021-01-07 23:32:17 -03:00
|
|
|
PrivateEngine *g_private = NULL;
|
2021-01-07 23:10:19 -03:00
|
|
|
|
2020-12-30 17:25:02 -03:00
|
|
|
extern int parse(char*);
|
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
PrivateEngine::PrivateEngine(OSystem *syst)
|
2021-01-07 23:38:18 -03:00
|
|
|
: Engine(syst) {
|
|
|
|
// Put your engine in a sane state, but do nothing big yet;
|
|
|
|
// in particular, do not load data from files; rather, if you
|
|
|
|
// need to do such things, do them from run().
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// Do not initialize graphics here
|
|
|
|
// Do not initialize audio devices here
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// However this is the place to specify all default directories
|
2021-01-13 19:27:09 -03:00
|
|
|
//SearchMan.addSubDirectoryMatching(gameDataDir, "global", 0, 10, false);
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// Here is the right place to set up the engine specific debug channels
|
|
|
|
//DebugMan.addDebugChannel(kPrivateDebugExample, "example", "this is just an example for a engine specific debug channel");
|
|
|
|
//DebugMan.addDebugChannel(kPrivateDebugExample2, "example2", "also an example");
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// Don't forget to register your random source
|
|
|
|
_rnd = new Common::RandomSource("private");
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
g_private = this;
|
2021-01-07 23:32:17 -03:00
|
|
|
|
2021-01-12 20:49:12 -03:00
|
|
|
_saveGameMask = NULL;
|
|
|
|
_loadGameMask = NULL;
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-30 16:28:33 -03:00
|
|
|
_dossierNextSuspectMask = NULL;
|
|
|
|
_dossierPrevSuspectMask = NULL;
|
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
_nextSetting = NULL;
|
2021-01-20 09:21:03 -03:00
|
|
|
_currentSetting = NULL;
|
2021-01-07 23:38:18 -03:00
|
|
|
_nextMovie = NULL;
|
2021-01-16 15:30:00 -03:00
|
|
|
_nextVS = NULL;
|
2021-01-07 23:38:18 -03:00
|
|
|
_modified = false;
|
|
|
|
_mode = -1;
|
2021-01-17 21:50:42 -03:00
|
|
|
_toTake = false;
|
2021-01-09 16:11:30 -03:00
|
|
|
_frame = new Common::String("inface/general/inface2.bmp");
|
2021-01-17 21:50:42 -03:00
|
|
|
_repeatedMovieExit = new Common::String("");
|
2021-01-20 09:21:03 -03:00
|
|
|
_pausedSetting = NULL;
|
2021-01-09 16:11:30 -03:00
|
|
|
|
2021-01-23 20:16:42 -03:00
|
|
|
|
|
|
|
_policeBustEnabled = false;
|
|
|
|
_policeBustSetting = NULL;
|
2021-01-28 23:01:31 -03:00
|
|
|
_numberClicks = 0;
|
|
|
|
policeVideoIndex = 0;
|
2021-01-23 20:16:42 -03:00
|
|
|
|
2021-01-17 15:38:45 -03:00
|
|
|
_paperShuffleSound = new Common::String("global/audio/glsfx0");
|
2021-01-17 21:50:42 -03:00
|
|
|
_takeSound = new Common::String("global/audio/took");
|
|
|
|
_leaveSound = new Common::String("global/audio/left");
|
2021-01-28 23:01:31 -03:00
|
|
|
_sirenSound = new Common::String("po/audio/posfx002.wav");
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
_policeRadioArea = NULL;
|
|
|
|
_AMRadioArea = NULL;
|
|
|
|
_phoneArea = NULL;
|
|
|
|
|
2021-01-28 23:01:31 -03:00
|
|
|
// TODO: use this as a default sound for radio
|
|
|
|
_radioSound = new Common::String("inface/radio/radio.wav");
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
_AMRadioPrefix = new Common::String("inface/radio/comm_/");
|
|
|
|
_policeRadioPrefix = new Common::String("inface/radio/police/");
|
|
|
|
_phonePrefix = new Common::String("inface/telephon/");
|
2021-01-17 21:50:42 -03:00
|
|
|
_phoneCallSound = new Common::String("phone.wav");
|
2021-01-07 23:32:17 -03:00
|
|
|
|
2021-01-30 16:28:33 -03:00
|
|
|
_dossierPage = 0;
|
|
|
|
_dossierSuspect = 0;
|
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
PrivateEngine::~PrivateEngine() {
|
2021-01-07 23:38:18 -03:00
|
|
|
debug("PrivateEngine::~PrivateEngine");
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// Dispose your resources here
|
|
|
|
delete _rnd;
|
2020-12-24 16:10:32 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// Remove all of our debug levels here
|
|
|
|
DebugMan.clearAllDebugChannels();
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
2021-01-13 19:27:09 -03:00
|
|
|
void PrivateEngine::initializePath(const Common::FSNode &gamePath) {
|
|
|
|
SearchMan.addDirectory(gamePath.getPath(), gamePath, 0, 10);
|
|
|
|
}
|
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
Common::Error PrivateEngine::run() {
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-10 20:17:27 -03:00
|
|
|
assert(_installerArchive.open("SUPPORT/ASSETS.Z"));
|
|
|
|
Common::SeekableReadStream *file = NULL;
|
2021-01-10 19:11:02 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
// if the full game is used
|
2021-01-17 21:50:42 -03:00
|
|
|
if (_installerArchive.hasFile("GAME.DAT"))
|
2021-01-10 20:17:27 -03:00
|
|
|
file = _installerArchive.createReadStreamForMember("GAME.DAT");
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
// if the demo from archive.org is used
|
2021-01-17 21:50:42 -03:00
|
|
|
else if (_installerArchive.hasFile("GAME.TXT"))
|
2021-01-10 20:17:27 -03:00
|
|
|
file = _installerArchive.createReadStreamForMember("GAME.TXT");
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
// if the demo from the full retail CDROM is used
|
2021-01-17 21:50:42 -03:00
|
|
|
else if (_installerArchive.hasFile("DEMOGAME.DAT"))
|
2021-01-14 18:48:30 -03:00
|
|
|
file = _installerArchive.createReadStreamForMember("DEMOGAME.DAT");
|
2021-01-09 19:11:41 -03:00
|
|
|
|
2021-01-10 19:11:02 -03:00
|
|
|
assert(file != NULL);
|
2021-01-07 23:38:18 -03:00
|
|
|
void *buf = malloc(191000);
|
|
|
|
file->read(buf, 191000);
|
2021-01-10 11:18:55 -03:00
|
|
|
|
|
|
|
// Initialize stuff
|
2021-01-09 22:08:41 -03:00
|
|
|
initInsts();
|
2021-01-07 23:38:18 -03:00
|
|
|
initFuncs();
|
2021-01-10 11:18:55 -03:00
|
|
|
initCursors();
|
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
parse((char *) buf);
|
|
|
|
assert(constants.size() > 0);
|
|
|
|
|
|
|
|
// Initialize graphics using following:
|
|
|
|
_screenW = 640;
|
|
|
|
_screenH = 480;
|
|
|
|
//_pixelFormat = Graphics::PixelFormat::createFormatCLUT8();
|
|
|
|
_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
2021-01-08 22:42:34 -03:00
|
|
|
_transparentColor = _pixelFormat.RGBToColor(0,255,0);
|
2021-01-07 23:38:18 -03:00
|
|
|
initGraphics(_screenW, _screenH, &_pixelFormat);
|
2021-01-14 18:48:30 -03:00
|
|
|
changeCursor("default");
|
2021-01-10 19:11:02 -03:00
|
|
|
|
2021-01-08 22:42:34 -03:00
|
|
|
_origin = new Common::Point(0, 0);
|
2021-01-07 23:38:18 -03:00
|
|
|
_image = new Image::BitmapDecoder();
|
|
|
|
_compositeSurface = new Graphics::ManagedSurface();
|
|
|
|
_compositeSurface->create(_screenW, _screenH, _pixelFormat);
|
2021-01-08 22:42:34 -03:00
|
|
|
_compositeSurface->setTransparentColor(_transparentColor);
|
2021-01-07 23:38:18 -03:00
|
|
|
|
|
|
|
// Create debugger console. It requires GFX to be initialized
|
|
|
|
Console *console = new Console(this);
|
|
|
|
setDebugger(console);
|
|
|
|
|
|
|
|
// Additional setup.
|
|
|
|
debug("PrivateEngine::init");
|
|
|
|
|
|
|
|
// Simple main event loop
|
|
|
|
Common::Event event;
|
|
|
|
Common::Point mousePos;
|
|
|
|
_videoDecoder = nullptr; //new Video::SmackerDecoder();
|
|
|
|
|
2021-01-13 19:27:09 -03:00
|
|
|
int saveSlot = ConfMan.getInt("save_slot");
|
2021-01-12 20:49:12 -03:00
|
|
|
if (saveSlot >= 0) { // load the savegame
|
|
|
|
loadGameState(saveSlot);
|
|
|
|
} else {
|
2021-01-23 20:16:42 -03:00
|
|
|
_nextSetting = &kGoIntro;
|
2021-01-12 20:49:12 -03:00
|
|
|
}
|
2021-01-07 23:38:18 -03:00
|
|
|
|
|
|
|
while (!shouldQuit()) {
|
2021-01-16 22:27:13 -03:00
|
|
|
checkPhoneCall();
|
|
|
|
|
2021-01-09 17:00:11 -03:00
|
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
2021-01-10 11:18:55 -03:00
|
|
|
mousePos = g_system->getEventManager()->getMousePos();
|
2021-01-09 17:00:11 -03:00
|
|
|
// Events
|
|
|
|
switch (event.type) {
|
2021-01-09 19:11:41 -03:00
|
|
|
case Common::EVENT_KEYDOWN:
|
|
|
|
if (event.kbd.keycode == Common::KEYCODE_ESCAPE && _videoDecoder)
|
|
|
|
skipVideo();
|
2021-01-31 20:15:56 -03:00
|
|
|
|
2021-01-09 19:11:41 -03:00
|
|
|
break;
|
2021-01-09 17:00:11 -03:00
|
|
|
|
2021-01-09 19:11:41 -03:00
|
|
|
case Common::EVENT_QUIT:
|
|
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
|
|
break;
|
2021-01-09 17:00:11 -03:00
|
|
|
|
2021-01-09 19:11:41 -03:00
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
2021-01-30 16:28:33 -03:00
|
|
|
_numberClicks++;
|
|
|
|
if (selectDossierNextSuspect(mousePos))
|
|
|
|
break;
|
|
|
|
else if (selectDossierPrevSuspect(mousePos))
|
|
|
|
break;
|
|
|
|
|
|
|
|
selectPauseMovie(mousePos);
|
2021-01-16 22:27:13 -03:00
|
|
|
selectPhoneArea(mousePos);
|
2021-01-16 15:30:00 -03:00
|
|
|
selectPoliceRadioArea(mousePos);
|
|
|
|
selectAMRadioArea(mousePos);
|
2021-01-12 20:49:12 -03:00
|
|
|
selectLoadGame(mousePos);
|
|
|
|
selectSaveGame(mousePos);
|
2021-01-31 20:15:56 -03:00
|
|
|
if (!_nextSetting)
|
|
|
|
selectMask(mousePos);
|
2021-01-09 19:11:41 -03:00
|
|
|
if (!_nextSetting)
|
|
|
|
selectExit(mousePos);
|
|
|
|
break;
|
2021-01-09 17:00:11 -03:00
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
case Common::EVENT_MOUSEMOVE:
|
2021-01-14 18:48:30 -03:00
|
|
|
changeCursor("default");
|
2021-01-31 20:15:56 -03:00
|
|
|
if (cursorPauseMovie(mousePos)) {}
|
|
|
|
else if (cursorMask(mousePos)) {}
|
|
|
|
else if (cursorExit(mousePos)) {}
|
2021-01-10 11:18:55 -03:00
|
|
|
//
|
|
|
|
break;
|
|
|
|
|
2021-01-09 19:11:41 -03:00
|
|
|
default:
|
|
|
|
{}
|
2021-01-07 23:38:18 -03:00
|
|
|
|
2021-01-09 17:00:11 -03:00
|
|
|
}
|
2021-01-07 23:38:18 -03:00
|
|
|
}
|
|
|
|
|
2021-01-28 23:01:31 -03:00
|
|
|
checkPoliceBust();
|
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
// Movies
|
|
|
|
if (_nextMovie != NULL) {
|
2021-01-31 20:15:56 -03:00
|
|
|
removeTimer();
|
2021-01-07 23:38:18 -03:00
|
|
|
_videoDecoder = new Video::SmackerDecoder();
|
|
|
|
playVideo(*_nextMovie);
|
|
|
|
_nextMovie = NULL;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-31 20:15:56 -03:00
|
|
|
if (_nextVS != NULL && _currentSetting->c_str() == kMainDesktop) {
|
2021-01-16 15:30:00 -03:00
|
|
|
loadImage(*_nextVS, 160, 120, true);
|
|
|
|
}
|
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
if (_videoDecoder) {
|
2021-01-14 18:48:30 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
stopSound();
|
|
|
|
if (_videoDecoder->endOfVideo()) {
|
|
|
|
_videoDecoder->close();
|
|
|
|
delete _videoDecoder;
|
|
|
|
_videoDecoder = nullptr;
|
|
|
|
} else if (_videoDecoder->needsUpdate()) {
|
|
|
|
drawScreen();
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-01-09 19:11:41 -03:00
|
|
|
if (_nextSetting != NULL) {
|
2021-01-31 20:15:56 -03:00
|
|
|
|
|
|
|
removeTimer();
|
2021-01-07 23:38:18 -03:00
|
|
|
debug("Executing %s", _nextSetting->c_str());
|
2021-01-30 16:28:33 -03:00
|
|
|
clearAreas();
|
2021-01-20 09:21:03 -03:00
|
|
|
_currentSetting = _nextSetting;
|
2021-01-07 23:38:18 -03:00
|
|
|
loadSetting(_nextSetting);
|
|
|
|
_nextSetting = NULL;
|
|
|
|
execute(prog);
|
2021-01-14 18:48:30 -03:00
|
|
|
changeCursor("default");
|
2021-01-07 23:38:18 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
g_system->updateScreen();
|
2021-01-09 17:00:11 -03:00
|
|
|
g_system->delayMillis(10);
|
2021-01-07 23:38:18 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return Common::kNoError;
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
2021-01-30 16:28:33 -03:00
|
|
|
void PrivateEngine::clearAreas() {
|
|
|
|
_exits.clear();
|
|
|
|
_masks.clear();
|
|
|
|
_loadGameMask = NULL;
|
|
|
|
_saveGameMask = NULL;
|
|
|
|
_policeRadioArea = NULL;
|
|
|
|
_AMRadioArea = NULL;
|
|
|
|
_phoneArea = NULL;
|
2021-01-31 20:15:56 -03:00
|
|
|
_dossierNextSuspectMask = NULL;
|
|
|
|
_dossierPrevSuspectMask = NULL;
|
|
|
|
|
2021-01-30 16:28:33 -03:00
|
|
|
}
|
|
|
|
|
2021-01-28 23:01:31 -03:00
|
|
|
void PrivateEngine::startPoliceBust() {
|
|
|
|
Common::String k("kPoliceIndex");
|
|
|
|
int policeIndex = variables.getVal(k)->u.val;
|
|
|
|
|
|
|
|
int r = _rnd->getRandomNumber(0xc);
|
|
|
|
if (0x14 < policeIndex) {
|
|
|
|
policeIndex = 0x15;
|
|
|
|
}
|
|
|
|
_maxNumberClicks = r + 0x10 + (policeIndex * 0xe) / -0x15;
|
|
|
|
_sirenWarning = 3 + _rnd->getRandomNumber(0x7);
|
|
|
|
_numberClicks = 0;
|
|
|
|
assert(_sirenWarning < _maxNumberClicks);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrivateEngine::checkPoliceBust() {
|
|
|
|
if (!_policeBustEnabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_numberClicks < _sirenWarning)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_numberClicks == _sirenWarning) {
|
|
|
|
stopSound();
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(*_sirenSound, 0, false);
|
2021-01-28 23:01:31 -03:00
|
|
|
_numberClicks++; // Won't execute again
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_numberClicks == _maxNumberClicks+1) {
|
|
|
|
Common::String k("kPoliceIndex");
|
|
|
|
uint kPoliceIndex = variables.getVal(k)->u.val;
|
|
|
|
|
|
|
|
if (kPoliceIndex <= 12) {
|
|
|
|
assert(policeVideoIndex/2 <= 5);
|
|
|
|
char f[30];
|
|
|
|
sprintf(f, "po/animatio/spoc%02dxs.smk", kPoliceBustVideos[policeVideoIndex/2]);
|
|
|
|
policeVideoIndex++;
|
|
|
|
|
|
|
|
Common::String *pv = new Common::String(f);
|
|
|
|
_nextMovie = pv;
|
|
|
|
}
|
2021-01-30 16:28:33 -03:00
|
|
|
|
2021-01-28 23:01:31 -03:00
|
|
|
_policeBustSetting = _currentSetting;
|
|
|
|
_nextSetting = &kPoliceBustFromMO;
|
2021-01-30 16:28:33 -03:00
|
|
|
clearAreas();
|
2021-01-31 20:15:56 -03:00
|
|
|
_policeBustEnabled = false;
|
2021-01-28 23:01:31 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
bool PrivateEngine::cursorExit(Common::Point mousePos) {
|
|
|
|
//debug("Mousepos %d %d", mousePos.x, mousePos.y);
|
|
|
|
mousePos = mousePos - *_origin;
|
|
|
|
if (mousePos.x < 0 || mousePos.y < 0)
|
|
|
|
return false;
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-14 20:47:06 -03:00
|
|
|
int rs = 100000000;
|
|
|
|
int cs = 0;
|
2021-01-10 11:18:55 -03:00
|
|
|
ExitInfo e;
|
2021-01-14 20:47:06 -03:00
|
|
|
Common::String *cursor = NULL;
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
for (ExitList::iterator it = _exits.begin(); it != _exits.end(); ++it) {
|
|
|
|
e = *it;
|
2021-01-14 20:47:06 -03:00
|
|
|
cs = e.rect->width()*e.rect->height();
|
|
|
|
|
2021-01-17 21:50:42 -03:00
|
|
|
if (e.rect->contains(mousePos)) {
|
2021-01-14 20:47:06 -03:00
|
|
|
if (cs < rs && e.cursor != NULL) {
|
|
|
|
rs = cs;
|
|
|
|
cursor = e.cursor;
|
|
|
|
}
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-14 20:47:06 -03:00
|
|
|
if (cursor != NULL) {
|
|
|
|
changeCursor(*cursor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2021-01-10 11:18:55 -03:00
|
|
|
}
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
bool PrivateEngine::inMask(Graphics::ManagedSurface *surf, Common::Point mousePos) {
|
|
|
|
if (surf == NULL)
|
|
|
|
return false;
|
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
mousePos = mousePos - *_origin;
|
|
|
|
if (mousePos.x < 0 || mousePos.y < 0)
|
|
|
|
return false;
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
if (mousePos.x > surf->w || mousePos.y > surf->h)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return ( *((uint32*) surf->getBasePtr(mousePos.x, mousePos.y)) != _transparentColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool PrivateEngine::cursorMask(Common::Point mousePos) {
|
|
|
|
//debug("Mousepos %d %d", mousePos.x, mousePos.y);
|
2021-01-10 11:18:55 -03:00
|
|
|
MaskInfo m;
|
|
|
|
bool inside = false;
|
|
|
|
for (MaskList::iterator it = _masks.begin(); it != _masks.end(); ++it) {
|
|
|
|
m = *it;
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
if (inMask(m.surf, mousePos)) {
|
2021-01-10 11:18:55 -03:00
|
|
|
//debug("Inside!");
|
2021-01-16 15:30:00 -03:00
|
|
|
if (m.cursor != NULL) { // TODO: check this
|
2021-01-10 11:18:55 -03:00
|
|
|
inside = true;
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Rendering cursor mask %s", m.cursor->c_str());
|
|
|
|
changeCursor(*m.cursor);
|
2021-01-10 11:18:55 -03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return inside;
|
|
|
|
}
|
|
|
|
|
2021-01-31 20:15:56 -03:00
|
|
|
bool PrivateEngine::cursorPauseMovie(Common::Point mousePos) {
|
2021-01-30 16:28:33 -03:00
|
|
|
if (_mode == 1) {
|
|
|
|
Common::Rect window(_origin->x, _origin->y, _screenW - _origin->x, _screenH - _origin->y);
|
2021-01-31 20:15:56 -03:00
|
|
|
if (!window.contains(mousePos)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrivateEngine::selectPauseMovie(Common::Point mousePos) {
|
|
|
|
if (_mode == 1) {
|
|
|
|
Common::Rect window(_origin->x, _origin->y, _screenW - _origin->x, _screenH - _origin->y);
|
|
|
|
//debug("%d, %d", mousePos.x, mousePos.y);
|
|
|
|
//debug("%d, %d", window.top, window.left);
|
|
|
|
//debug("%d, %d", window.bottom, window.right);
|
|
|
|
|
|
|
|
//debug("%d, %d", window.y2, window.y2);
|
2021-01-30 16:28:33 -03:00
|
|
|
if (!window.contains(mousePos)) {
|
|
|
|
if ( _pausedSetting == NULL) {
|
|
|
|
_pausedSetting = _currentSetting;
|
|
|
|
_nextSetting = &kPauseMovie;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-07 23:10:19 -03:00
|
|
|
void PrivateEngine::selectExit(Common::Point mousePos) {
|
2021-01-10 11:18:55 -03:00
|
|
|
//debug("Mousepos %d %d", mousePos.x, mousePos.y);
|
2021-01-09 19:11:41 -03:00
|
|
|
mousePos = mousePos - *_origin;
|
2021-01-10 11:18:55 -03:00
|
|
|
if (mousePos.x < 0 || mousePos.y < 0)
|
|
|
|
return;
|
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
Common::String *ns = NULL;
|
2021-01-08 22:42:34 -03:00
|
|
|
int rs = 100000000;
|
2021-01-07 23:38:18 -03:00
|
|
|
int cs = 0;
|
2021-01-08 22:42:34 -03:00
|
|
|
ExitInfo e;
|
|
|
|
for (ExitList::iterator it = _exits.begin(); it != _exits.end(); ++it) {
|
|
|
|
e = *it;
|
2021-01-09 19:11:41 -03:00
|
|
|
cs = e.rect->width()*e.rect->height();
|
2021-01-10 11:18:55 -03:00
|
|
|
//debug("Testing exit %s %d", e.nextSetting->c_str(), cs);
|
2021-01-07 23:38:18 -03:00
|
|
|
if (e.rect->contains(mousePos)) {
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Inside! %d %d", cs, rs);
|
2021-01-08 22:42:34 -03:00
|
|
|
if (cs < rs && e.nextSetting != NULL) { // TODO: check this
|
2021-01-17 21:50:42 -03:00
|
|
|
// an item was not taken
|
|
|
|
if (_toTake) {
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(* getLeaveSound(), 1, false);
|
2021-01-17 21:50:42 -03:00
|
|
|
_toTake = false;
|
|
|
|
}
|
|
|
|
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Found Exit %s %d", e.nextSetting->c_str(), cs);
|
2021-01-07 23:38:18 -03:00
|
|
|
rs = cs;
|
|
|
|
ns = e.nextSetting;
|
|
|
|
}
|
|
|
|
|
2021-01-07 23:10:19 -03:00
|
|
|
}
|
2021-01-07 23:38:18 -03:00
|
|
|
}
|
2021-01-08 22:42:34 -03:00
|
|
|
if (ns != NULL) {
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Exit selected %s", ns->c_str());
|
2021-01-07 23:38:18 -03:00
|
|
|
_nextSetting = ns;
|
2021-01-08 22:42:34 -03:00
|
|
|
}
|
2021-01-07 23:10:19 -03:00
|
|
|
}
|
|
|
|
|
2021-01-08 22:42:34 -03:00
|
|
|
void PrivateEngine::selectMask(Common::Point mousePos) {
|
|
|
|
Common::String *ns = NULL;
|
|
|
|
MaskInfo m;
|
|
|
|
for (MaskList::iterator it = _masks.begin(); it != _masks.end(); ++it) {
|
|
|
|
m = *it;
|
2021-01-09 19:11:41 -03:00
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
//debug("Testing mask %s", m.nextSetting->c_str());
|
2021-01-16 15:30:00 -03:00
|
|
|
if (inMask(m.surf, mousePos)) {
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Inside!");
|
2021-01-08 22:42:34 -03:00
|
|
|
if (m.nextSetting != NULL) { // TODO: check this
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Found Mask %s", m.nextSetting->c_str());
|
2021-01-08 22:42:34 -03:00
|
|
|
ns = m.nextSetting;
|
|
|
|
}
|
|
|
|
|
2021-01-20 09:21:03 -03:00
|
|
|
if (m.flag1 != NULL) { // TODO: check this
|
|
|
|
setSymbol(m.flag1, 1);
|
2021-01-17 21:50:42 -03:00
|
|
|
// an item was taken
|
|
|
|
if (_toTake) {
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(*getTakeSound(), 1, false);
|
2021-01-17 21:50:42 -03:00
|
|
|
_toTake = false;
|
|
|
|
}
|
2021-01-10 15:38:10 -03:00
|
|
|
}
|
|
|
|
|
2021-01-20 09:21:03 -03:00
|
|
|
if (m.flag2 != NULL) {
|
|
|
|
setSymbol(m.flag2, 1);
|
|
|
|
}
|
|
|
|
|
2021-01-10 15:38:10 -03:00
|
|
|
break;
|
|
|
|
|
2021-01-08 22:42:34 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ns != NULL) {
|
2021-01-14 18:48:30 -03:00
|
|
|
//debug("Mask selected %s", ns->c_str());
|
2021-01-08 22:42:34 -03:00
|
|
|
_nextSetting = ns;
|
|
|
|
}
|
|
|
|
}
|
2021-01-07 23:10:19 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
void PrivateEngine::selectAMRadioArea(Common::Point mousePos) {
|
|
|
|
if (_AMRadioArea == NULL)
|
2021-01-12 20:49:12 -03:00
|
|
|
return;
|
2021-01-16 15:30:00 -03:00
|
|
|
|
|
|
|
if (_AMRadio.empty())
|
2021-01-12 20:49:12 -03:00
|
|
|
return;
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
debug("AMRadio");
|
2021-01-17 21:50:42 -03:00
|
|
|
if (inMask(_AMRadioArea->surf, mousePos)) {
|
2021-01-16 15:30:00 -03:00
|
|
|
Common::String sound = *_AMRadioPrefix + _AMRadio.back() + ".wav";
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(sound.c_str(), 1, false);
|
2021-01-16 15:30:00 -03:00
|
|
|
_AMRadio.pop_back();
|
2021-01-12 20:49:12 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
void PrivateEngine::selectPoliceRadioArea(Common::Point mousePos) {
|
|
|
|
if (_policeRadioArea == NULL)
|
|
|
|
return;
|
2021-01-12 20:49:12 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
if (_policeRadio.empty())
|
|
|
|
return;
|
2021-01-12 20:49:12 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
debug("PoliceRadio");
|
|
|
|
if (inMask(_policeRadioArea->surf, mousePos)) {
|
|
|
|
Common::String sound = *_policeRadioPrefix + _policeRadio.back() + ".wav";
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(sound.c_str(), 1, false);
|
2021-01-16 15:30:00 -03:00
|
|
|
_policeRadio.pop_back();
|
2021-01-12 20:49:12 -03:00
|
|
|
}
|
2021-01-16 15:30:00 -03:00
|
|
|
|
2021-01-12 20:49:12 -03:00
|
|
|
}
|
|
|
|
|
2021-01-16 22:27:13 -03:00
|
|
|
void PrivateEngine::checkPhoneCall() {
|
2021-01-17 15:38:45 -03:00
|
|
|
if (_phoneArea == NULL)
|
|
|
|
return;
|
|
|
|
|
2021-01-16 22:27:13 -03:00
|
|
|
if (_phone.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!_mixer->isSoundHandleActive(_soundHandle))
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(*_phonePrefix + *_phoneCallSound, 1, false);
|
2021-01-16 22:27:13 -03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrivateEngine::selectPhoneArea(Common::Point mousePos) {
|
|
|
|
if (_phoneArea == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_phone.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
debug("Phone");
|
|
|
|
if (inMask(_phoneArea->surf, mousePos)) {
|
|
|
|
PhoneInfo i = _phone.back();
|
|
|
|
Common::String sound(*i.sound);
|
2021-01-17 21:50:42 -03:00
|
|
|
setSymbol(i.flag, i.val);
|
2021-01-16 22:27:13 -03:00
|
|
|
sound = *_phonePrefix + sound + ".wav";
|
2021-01-31 22:09:26 -03:00
|
|
|
playSound(sound.c_str(), 1, true);
|
2021-01-16 22:27:13 -03:00
|
|
|
_phone.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-30 16:28:33 -03:00
|
|
|
void PrivateEngine::loadDossier() {
|
|
|
|
int x = 40;
|
|
|
|
int y = 30;
|
|
|
|
int i = _dossierSuspect;
|
|
|
|
int j = _dossierPage;
|
|
|
|
|
|
|
|
DossierInfo m = _dossiers[i];
|
|
|
|
|
|
|
|
if (j == 0) {
|
|
|
|
loadImage(*m.page1, x, y);
|
|
|
|
} else if (j == 1) {
|
|
|
|
loadImage(*m.page2, x, y);
|
|
|
|
} else
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool PrivateEngine::selectDossierNextSuspect(Common::Point mousePos) {
|
|
|
|
if (_dossierNextSuspectMask == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (inMask(_dossierNextSuspectMask->surf, mousePos)) {
|
|
|
|
if ((_dossierSuspect + 1) < _dossiers.size()) {
|
|
|
|
_dossierSuspect++;
|
|
|
|
_dossierPage = 0;
|
|
|
|
loadDossier();
|
|
|
|
drawMask(_dossierNextSuspectMask->surf);
|
|
|
|
drawMask(_dossierPrevSuspectMask->surf);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PrivateEngine::selectDossierPrevSuspect(Common::Point mousePos) {
|
|
|
|
if (_dossierPrevSuspectMask == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (inMask(_dossierPrevSuspectMask->surf, mousePos)) {
|
|
|
|
if (_dossierSuspect > 0) {
|
|
|
|
_dossierSuspect--;
|
|
|
|
_dossierPage = 0;
|
|
|
|
loadDossier();
|
|
|
|
drawMask(_dossierNextSuspectMask->surf);
|
|
|
|
drawMask(_dossierPrevSuspectMask->surf);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
2021-01-16 22:27:13 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
void PrivateEngine::selectLoadGame(Common::Point mousePos) {
|
|
|
|
if (_loadGameMask == NULL)
|
2021-01-12 20:49:12 -03:00
|
|
|
return;
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
if (inMask(_loadGameMask->surf, mousePos)) {
|
|
|
|
loadGameDialog();
|
2021-01-12 20:49:12 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
void PrivateEngine::selectSaveGame(Common::Point mousePos) {
|
2021-01-12 20:49:12 -03:00
|
|
|
if (_saveGameMask == NULL)
|
2021-01-16 15:30:00 -03:00
|
|
|
return;
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
if (inMask(_saveGameMask->surf, mousePos)) {
|
|
|
|
saveGameDialog();
|
2021-01-12 20:49:12 -03:00
|
|
|
}
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
}
|
2021-01-12 20:49:12 -03:00
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
bool PrivateEngine::hasFeature(EngineFeature f) const {
|
2021-01-07 23:38:18 -03:00
|
|
|
return
|
2021-01-10 15:38:10 -03:00
|
|
|
(f == kSupportsReturnToLauncher);
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
void PrivateEngine::restartGame() {
|
|
|
|
debug("restartGame");
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-16 15:30:00 -03:00
|
|
|
for (VariableList::iterator it = variableList.begin(); it != variableList.end(); ++it) {
|
|
|
|
Private::Symbol *sym = variables.getVal(*it);
|
|
|
|
if (strcmp("kAlternateGame", sym->name->c_str()) != 0)
|
|
|
|
sym->u.val = 0;
|
|
|
|
}
|
2021-01-30 16:28:33 -03:00
|
|
|
// FIXME: reset movies/sound lists
|
2021-01-16 15:30:00 -03:00
|
|
|
}
|
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
Common::Error PrivateEngine::loadGameStream(Common::SeekableReadStream *stream) {
|
2021-01-07 23:38:18 -03:00
|
|
|
Common::Serializer s(stream, nullptr);
|
2021-01-12 20:49:12 -03:00
|
|
|
debug("loadGameStream");
|
2021-01-23 20:16:42 -03:00
|
|
|
_nextSetting = &kMainDesktop;
|
2021-01-12 20:49:12 -03:00
|
|
|
int val;
|
2021-01-17 21:50:42 -03:00
|
|
|
|
2021-01-12 20:49:12 -03:00
|
|
|
for (VariableList::iterator it = variableList.begin(); it != variableList.end(); ++it) {
|
2021-01-17 21:50:42 -03:00
|
|
|
s.syncAsUint32LE(val);
|
2021-01-12 20:49:12 -03:00
|
|
|
Private::Symbol *sym = variables.getVal(*it);
|
|
|
|
sym->u.val = val;
|
|
|
|
}
|
|
|
|
|
2021-01-16 22:27:13 -03:00
|
|
|
uint32 size = 0;
|
|
|
|
Common::String *sound;
|
|
|
|
size = stream->readUint32LE();
|
|
|
|
debug("AMRadio size %d", size);
|
|
|
|
_AMRadio.clear();
|
|
|
|
|
|
|
|
for (uint32 i = 0; i < size; ++i) {
|
|
|
|
sound = new Common::String(stream->readString());
|
|
|
|
debug("sound: %s", sound->c_str());
|
|
|
|
_AMRadio.push_back(*sound);
|
|
|
|
}
|
|
|
|
|
|
|
|
size = stream->readUint32LE();
|
|
|
|
debug("policeRadio size %d", size);
|
|
|
|
_policeRadio.clear();
|
|
|
|
|
|
|
|
for (uint32 i = 0; i < size; ++i) {
|
|
|
|
sound = new Common::String(stream->readString());
|
|
|
|
debug("sound: %s", sound->c_str());
|
|
|
|
_policeRadio.push_back(*sound);
|
|
|
|
}
|
|
|
|
|
|
|
|
size = stream->readUint32LE();
|
2021-01-17 15:38:45 -03:00
|
|
|
_phone.clear();
|
|
|
|
|
2021-01-16 22:27:13 -03:00
|
|
|
for (uint32 j = 0; j < size; ++j) {
|
|
|
|
PhoneInfo *i = (PhoneInfo*) malloc(sizeof(PhoneInfo));
|
|
|
|
|
|
|
|
i->sound = new Common::String(stream->readString());
|
2021-01-17 21:50:42 -03:00
|
|
|
i->flag = variables.getVal(stream->readString());
|
2021-01-16 22:27:13 -03:00
|
|
|
i->val = stream->readUint32LE();
|
|
|
|
_phone.push_back(*i);
|
|
|
|
}
|
|
|
|
|
2021-01-17 15:38:45 -03:00
|
|
|
*_repeatedMovieExit = stream->readString();
|
|
|
|
|
|
|
|
_playedMovies.clear();
|
|
|
|
size = stream->readUint32LE();
|
|
|
|
Common::String *movie;
|
|
|
|
|
|
|
|
for (uint32 i = 0; i < size; ++i) {
|
|
|
|
movie = new Common::String(stream->readString());
|
2021-01-17 21:50:42 -03:00
|
|
|
_playedMovies.setVal(*movie, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
_playedPhoneClips.clear();
|
|
|
|
size = stream->readUint32LE();
|
|
|
|
Common::String *phone;
|
|
|
|
|
|
|
|
for (uint32 i = 0; i < size; ++i) {
|
|
|
|
phone = new Common::String(stream->readString());
|
|
|
|
_playedPhoneClips.setVal(*phone, true);
|
2021-01-17 15:38:45 -03:00
|
|
|
}
|
|
|
|
|
2021-01-12 20:49:12 -03:00
|
|
|
//syncGameStream(s);
|
2021-01-07 23:38:18 -03:00
|
|
|
return Common::kNoError;
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
Common::Error PrivateEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
|
2021-01-12 20:49:12 -03:00
|
|
|
debug("saveGameStream %d", isAutosave);
|
|
|
|
if (isAutosave)
|
|
|
|
return Common::kNoError;
|
2021-01-14 18:48:30 -03:00
|
|
|
|
2021-01-12 20:49:12 -03:00
|
|
|
for (VariableList::iterator it = variableList.begin(); it != variableList.end(); ++it) {
|
|
|
|
Private::Symbol *sym = variables.getVal(*it);
|
|
|
|
stream->writeUint32LE(sym->u.val);
|
|
|
|
}
|
2021-01-16 22:27:13 -03:00
|
|
|
|
|
|
|
stream->writeUint32LE(_AMRadio.size());
|
|
|
|
for (SoundList::iterator it = _AMRadio.begin(); it != _AMRadio.end(); ++it) {
|
|
|
|
stream->writeString(*it);
|
|
|
|
stream->writeByte(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->writeUint32LE(_policeRadio.size());
|
|
|
|
for (SoundList::iterator it = _policeRadio.begin(); it != _policeRadio.end(); ++it) {
|
|
|
|
stream->writeString(*it);
|
|
|
|
stream->writeByte(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->writeUint32LE(_phone.size());
|
|
|
|
for (PhoneList::iterator it = _phone.begin(); it != _phone.end(); ++it) {
|
|
|
|
//PhoneInfo *i = *it;
|
|
|
|
stream->writeString(*it->sound);
|
|
|
|
stream->writeByte(0);
|
|
|
|
stream->writeString(*it->flag->name);
|
|
|
|
stream->writeByte(0);
|
|
|
|
stream->writeUint32LE(it->val);
|
|
|
|
}
|
|
|
|
|
2021-01-17 15:38:45 -03:00
|
|
|
stream->writeString(*_repeatedMovieExit);
|
|
|
|
stream->writeByte(0);
|
|
|
|
|
|
|
|
stream->writeUint32LE(_playedMovies.size());
|
2021-01-17 21:50:42 -03:00
|
|
|
for (PlayedMediaTable::iterator it = _playedMovies.begin(); it != _playedMovies.end(); ++it) {
|
|
|
|
stream->writeString(it->_key);
|
|
|
|
stream->writeByte(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->writeUint32LE(_playedPhoneClips.size());
|
|
|
|
for (PlayedMediaTable::iterator it = _playedPhoneClips.begin(); it != _playedPhoneClips.end(); ++it) {
|
2021-01-17 15:38:45 -03:00
|
|
|
stream->writeString(it->_key);
|
|
|
|
stream->writeByte(0);
|
|
|
|
}
|
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
return Common::kNoError;
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void PrivateEngine::syncGameStream(Common::Serializer &s) {
|
2021-01-12 20:49:12 -03:00
|
|
|
debug("syncGameStream");
|
2021-01-07 23:38:18 -03:00
|
|
|
// Use methods of Serializer to save/load fields
|
2021-01-12 20:49:12 -03:00
|
|
|
//int dummy = 0;
|
|
|
|
//s.syncString(*_currentSetting);
|
2020-12-24 16:10:32 -03:00
|
|
|
}
|
|
|
|
|
2021-01-07 23:32:17 -03:00
|
|
|
Common::String PrivateEngine::convertPath(Common::String name) {
|
2021-01-07 23:38:18 -03:00
|
|
|
Common::String path(name);
|
|
|
|
Common::String s1("\\");
|
|
|
|
Common::String s2("/");
|
2021-01-07 23:32:17 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
while (path.contains(s1))
|
|
|
|
Common::replace(path, s1, s2);
|
2021-01-07 23:32:17 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
s1 = Common::String("\"");
|
|
|
|
s2 = Common::String("");
|
2021-01-07 23:32:17 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
Common::replace(path, s1, s2);
|
|
|
|
Common::replace(path, s1, s2);
|
|
|
|
|
|
|
|
path.toLowercase();
|
|
|
|
return path;
|
2021-01-07 23:32:17 -03:00
|
|
|
}
|
|
|
|
|
2021-01-31 22:09:26 -03:00
|
|
|
void PrivateEngine::playSound(const Common::String &name, uint loops, bool stopOthers) {
|
2021-01-07 23:38:18 -03:00
|
|
|
debugC(1, kPrivateDebugExample, "%s : %s", __FUNCTION__, name.c_str());
|
2021-01-02 10:22:07 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
Common::File *file = new Common::File();
|
|
|
|
Common::String path = convertPath(name);
|
2021-01-02 14:19:23 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
if (!file->open(path))
|
|
|
|
error("unable to find sound file %s", path.c_str());
|
2020-12-24 19:02:12 -03:00
|
|
|
|
2021-01-09 16:11:30 -03:00
|
|
|
Audio::LoopingAudioStream *stream;
|
2021-01-14 20:47:06 -03:00
|
|
|
stream = new Audio::LoopingAudioStream(Audio::makeWAVStream(file, DisposeAfterUse::YES), loops);
|
2021-01-31 22:09:26 -03:00
|
|
|
if (stopOthers) {
|
|
|
|
stopSound();
|
|
|
|
}
|
2021-01-07 23:38:18 -03:00
|
|
|
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream, -1, Audio::Mixer::kMaxChannelVolume);
|
2020-12-24 19:02:12 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void PrivateEngine::playVideo(const Common::String &name) {
|
2021-01-08 22:42:34 -03:00
|
|
|
debug("%s : %s", __FUNCTION__, name.c_str());
|
2021-01-31 22:09:26 -03:00
|
|
|
stopSound();
|
2021-01-07 23:38:18 -03:00
|
|
|
Common::File *file = new Common::File();
|
|
|
|
Common::String path = convertPath(name);
|
2021-01-04 08:14:40 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
if (!file->open(path))
|
|
|
|
error("unable to find video file %s", path.c_str());
|
2020-12-24 19:02:12 -03:00
|
|
|
|
2021-01-07 23:38:18 -03:00
|
|
|
if (!_videoDecoder->loadStream(file))
|
|
|
|
error("unable to load video %s", path.c_str());
|
|
|
|
_videoDecoder->start();
|
2020-12-24 19:02:12 -03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-01-09 16:11:30 -03:00
|
|
|
void PrivateEngine::skipVideo() {
|
|
|
|
_videoDecoder->close();
|
|
|
|
delete _videoDecoder;
|
|
|
|
_videoDecoder = nullptr;
|
|
|
|
}
|
|
|
|
|
2020-12-24 19:02:12 -03:00
|
|
|
void PrivateEngine::stopSound() {
|
2021-01-07 23:38:18 -03:00
|
|
|
debugC(3, kPrivateDebugExample, "%s", __FUNCTION__);
|
|
|
|
if (_mixer->isSoundHandleActive(_soundHandle))
|
|
|
|
_mixer->stopHandle(_soundHandle);
|
2020-12-24 19:02:12 -03:00
|
|
|
}
|
|
|
|
|
2021-01-09 16:11:30 -03:00
|
|
|
void PrivateEngine::loadImage(const Common::String &name, int x, int y, bool drawn) {
|
2021-01-07 23:38:18 -03:00
|
|
|
debugC(1, kPrivateDebugExample, "%s : %s", __FUNCTION__, name.c_str());
|
|
|
|
Common::File file;
|
|
|
|
Common::String path = convertPath(name);
|
|
|
|
if (!file.open(path))
|
|
|
|
error("unable to load image %s", path.c_str());
|
|
|
|
|
|
|
|
_image->loadStream(file);
|
2021-01-31 22:09:26 -03:00
|
|
|
Graphics::Surface *surf = _image->getSurface()->convertTo(_pixelFormat, _image->getPalette());
|
|
|
|
_compositeSurface->transBlitFrom(*surf, *_origin + Common::Point(x,y), _transparentColor);
|
|
|
|
surf->free();
|
|
|
|
delete surf;
|
|
|
|
_image->destroy();
|
2021-01-07 23:38:18 -03:00
|
|
|
drawScreen();
|
2021-01-02 14:19:23 -03:00
|
|
|
}
|
|
|
|
|
2021-01-14 18:48:30 -03:00
|
|
|
void PrivateEngine::drawScreenFrame(Graphics::Surface *screen) {
|
2021-01-09 16:11:30 -03:00
|
|
|
Common::String path = convertPath(*_frame);
|
2021-01-14 18:48:30 -03:00
|
|
|
Common::File file;
|
|
|
|
assert(file.open(path));
|
2021-01-09 16:11:30 -03:00
|
|
|
_image->loadStream(file);
|
2021-01-31 22:09:26 -03:00
|
|
|
Graphics::Surface *csurf = _image->getSurface()->convertTo(_pixelFormat, _image->getPalette());
|
|
|
|
screen->copyRectToSurface(*csurf, 0, 0, Common::Rect(0, 0, _screenW, _screenH));
|
|
|
|
csurf->free();
|
|
|
|
delete csurf;
|
|
|
|
_image->destroy();
|
2021-01-09 16:11:30 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-08 22:42:34 -03:00
|
|
|
Graphics::ManagedSurface *PrivateEngine::loadMask(const Common::String &name, int x, int y, bool drawn) {
|
|
|
|
debugC(1, kPrivateDebugExample, "%s : %s", __FUNCTION__, name.c_str());
|
|
|
|
Common::File file;
|
|
|
|
Common::String path = convertPath(name);
|
|
|
|
if (!file.open(path))
|
|
|
|
error("unable to load mask %s", path.c_str());
|
|
|
|
|
|
|
|
_image->loadStream(file);
|
|
|
|
Graphics::ManagedSurface *surf = new Graphics::ManagedSurface();
|
2021-01-30 16:28:33 -03:00
|
|
|
Graphics::Surface *screen = g_system->lockScreen();
|
|
|
|
|
2021-01-08 22:42:34 -03:00
|
|
|
surf->create(_screenW, _screenH, _pixelFormat);
|
2021-01-30 16:28:33 -03:00
|
|
|
surf->transBlitFrom(*screen);
|
|
|
|
g_system->unlockScreen();
|
2021-01-31 22:09:26 -03:00
|
|
|
Graphics::Surface *csurf = _image->getSurface()->convertTo(_pixelFormat, _image->getPalette());
|
|
|
|
surf->transBlitFrom(*csurf, Common::Point(x,y));
|
|
|
|
csurf->free();
|
|
|
|
delete csurf;
|
|
|
|
_image->destroy();
|
2021-01-08 22:42:34 -03:00
|
|
|
|
|
|
|
if (drawn) {
|
2021-01-31 22:09:26 -03:00
|
|
|
drawMask(surf);
|
2021-01-08 22:42:34 -03:00
|
|
|
}
|
|
|
|
|
2021-01-09 19:11:41 -03:00
|
|
|
return surf;
|
2021-01-08 22:42:34 -03:00
|
|
|
}
|
|
|
|
|
2021-01-30 16:28:33 -03:00
|
|
|
void PrivateEngine::drawMask(Graphics::ManagedSurface *surf) {
|
|
|
|
_compositeSurface->transBlitFrom(surf->rawSurface(), *_origin, _transparentColor);
|
|
|
|
drawScreen();
|
|
|
|
}
|
|
|
|
|
2021-01-10 20:17:27 -03:00
|
|
|
void PrivateEngine::drawScreen() {
|
2021-01-10 11:18:55 -03:00
|
|
|
Graphics::Surface *screen = g_system->lockScreen();
|
|
|
|
Graphics::ManagedSurface *surface = _compositeSurface;
|
|
|
|
int w = surface->w;
|
|
|
|
int h = surface->h;
|
|
|
|
|
|
|
|
if (_videoDecoder) {
|
2021-01-31 22:09:26 -03:00
|
|
|
const Graphics::Surface *frame = _videoDecoder->decodeNextFrame();
|
|
|
|
//frame->create(_videoDecoder->getWidth(), _videoDecoder->getHeight(), _pixelFormat);
|
|
|
|
//frame->copyFrom(*_videoDecoder->decodeNextFrame());
|
2021-01-20 09:21:03 -03:00
|
|
|
Graphics::Surface *cframe = frame->convertTo(_pixelFormat, _videoDecoder->getPalette());
|
2021-01-31 20:15:56 -03:00
|
|
|
Common::Point center((_screenW - _videoDecoder->getWidth())/2, (_screenH - _videoDecoder->getHeight())/2);
|
|
|
|
surface->transBlitFrom(*cframe, center);
|
2021-01-31 22:09:26 -03:00
|
|
|
//frame->free();
|
2021-01-21 20:21:08 -03:00
|
|
|
cframe->free();
|
2021-01-31 22:09:26 -03:00
|
|
|
//delete frame;
|
2021-01-20 09:21:03 -03:00
|
|
|
delete cframe;
|
2021-01-10 11:18:55 -03:00
|
|
|
}
|
2021-01-08 22:42:34 -03:00
|
|
|
|
2021-01-10 11:18:55 -03:00
|
|
|
assert(w == _screenW && h == _screenH);
|
2021-01-08 22:42:34 -03:00
|
|
|
|
2021-01-14 18:48:30 -03:00
|
|
|
if (_mode == 1) {
|
|
|
|
drawScreenFrame(screen);
|
|
|
|
}
|
2021-01-23 09:30:16 -03:00
|
|
|
Common::Rect window(_origin->x, _origin->y, _screenW - _origin->x, _screenH - _origin->y);
|
|
|
|
screen->copyRectToSurface(*surface, _origin->x, _origin->y, window);
|
2021-01-10 11:18:55 -03:00
|
|
|
g_system->unlockScreen();
|
|
|
|
//if (_image->getPalette() != nullptr)
|
|
|
|
// g_system->getPaletteManager()->setPalette(_image->getPalette(), _image->getPaletteStartIndex(), _image->getPaletteColorCount());
|
|
|
|
g_system->updateScreen();
|
2021-01-02 14:19:23 -03:00
|
|
|
|
2020-12-24 19:02:12 -03:00
|
|
|
}
|
|
|
|
|
2021-01-10 15:38:10 -03:00
|
|
|
bool PrivateEngine::getRandomBool(uint p) {
|
|
|
|
uint r = _rnd->getRandomNumber(100);
|
2021-01-10 20:17:27 -03:00
|
|
|
return (r <= p);
|
2021-01-10 15:38:10 -03:00
|
|
|
}
|
2020-12-24 19:02:12 -03:00
|
|
|
|
2021-01-17 15:38:45 -03:00
|
|
|
Common::String *PrivateEngine::getPaperShuffleSound() {
|
2021-01-17 21:50:42 -03:00
|
|
|
uint r = 32 + _rnd->getRandomNumber(7);
|
2021-01-17 15:38:45 -03:00
|
|
|
|
2021-01-17 21:50:42 -03:00
|
|
|
// there is no global/audio/glsfx038.wav,
|
2021-01-17 15:38:45 -03:00
|
|
|
// so we should avoid that number
|
|
|
|
if ( r == 38)
|
2021-01-17 21:50:42 -03:00
|
|
|
r = 39;
|
2021-01-17 15:38:45 -03:00
|
|
|
|
|
|
|
char f[7];
|
|
|
|
sprintf(f, "%d.wav", r);
|
|
|
|
return (new Common::String(*_paperShuffleSound + f));
|
|
|
|
}
|
2020-12-24 19:02:12 -03:00
|
|
|
|
2021-01-17 21:50:42 -03:00
|
|
|
Common::String *PrivateEngine::getTakeSound() {
|
|
|
|
uint r = 1 + _rnd->getRandomNumber(4);
|
|
|
|
|
|
|
|
char f[6];
|
|
|
|
sprintf(f, "%d.wav", r);
|
|
|
|
return (new Common::String(*_takeSound + f));
|
|
|
|
}
|
|
|
|
|
2021-01-28 23:01:31 -03:00
|
|
|
Common::String *PrivateEngine::getTakeLeaveSound() {
|
|
|
|
uint r = _rnd->getRandomNumber(1);
|
|
|
|
if (r == 0) {
|
|
|
|
return (new Common::String("global/audio/mvo001.wav"));
|
|
|
|
} else {
|
|
|
|
return (new Common::String("global/audio/mvo006.wav"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-17 21:50:42 -03:00
|
|
|
Common::String *PrivateEngine::getLeaveSound() {
|
|
|
|
uint r = 1 + _rnd->getRandomNumber(4);
|
|
|
|
|
|
|
|
char f[6];
|
|
|
|
sprintf(f, "%d.wav", r);
|
|
|
|
return (new Common::String(*_leaveSound + f));
|
|
|
|
}
|
|
|
|
|
2021-01-23 09:30:16 -03:00
|
|
|
|
|
|
|
char *PrivateEngine::getRandomPhoneClip(char *clip, int i, int j) {
|
|
|
|
uint r = i + _rnd->getRandomNumber(j - i);
|
|
|
|
|
|
|
|
char *f = (char*) malloc((strlen(clip)+3)*sizeof(char));
|
|
|
|
sprintf(f, "%s%02d", clip, r);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
2021-01-31 20:15:56 -03:00
|
|
|
// Timers
|
|
|
|
|
|
|
|
void timerCallback(void *refCon) {
|
|
|
|
g_private->removeTimer();
|
|
|
|
g_private->_nextSetting = (Common::String*) refCon;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PrivateEngine::installTimer(uint32 delay, Common::String *ns) {
|
|
|
|
return g_system->getTimerManager()->installTimerProc(&timerCallback, delay, (void*) ns, "timerCallback");
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrivateEngine::removeTimer() {
|
|
|
|
g_system->getTimerManager()->removeTimerProc(&timerCallback);
|
|
|
|
}
|
2021-01-23 09:30:16 -03:00
|
|
|
|
2020-12-24 16:10:32 -03:00
|
|
|
} // End of namespace Private
|