scummvm/engines/private/funcs.cpp

780 lines
23 KiB
C++
Raw Normal View History

2021-02-13 14:55:30 -03:00
/* 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.
*
*/
2021-01-02 00:58:58 -03:00
#include "common/str.h"
2021-01-31 20:15:56 -03:00
#include "common/timer.h"
2021-01-02 00:58:58 -03:00
#include "common/debug.h"
#include "common/system.h"
2021-01-02 00:58:58 -03:00
#include "private/grammar.h"
#include "private/tokens.h"
#include "private/private.h"
2021-01-02 00:58:58 -03:00
namespace Private {
void fChgMode(ArgArray args) {
// assert types
2021-02-07 14:08:28 -03:00
assert (args.size() == 2 || args.size() == 3);
if (args.size() == 2)
debugC(1, kPrivateDebugScript, "ChgMode(%d, %s)", args[0].u.val, args[1].u.str);
2021-02-07 14:08:28 -03:00
else if (args.size() == 3)
debugC(1, kPrivateDebugScript, "ChgMode(%d, %s, %s)", args[0].u.val, args[1].u.str, args[2].u.sym->name->c_str());
2021-02-07 17:36:09 -03:00
else
2021-02-07 14:08:28 -03:00
assert(0);
2021-01-07 23:32:17 -03:00
g_private->_mode = args[0].u.val;
2021-01-05 21:03:34 -03:00
Common::String *s = new Common::String(args[1].u.str);
2021-01-07 23:32:17 -03:00
g_private->_nextSetting = s;
2021-01-08 22:42:34 -03:00
2021-01-17 21:50:42 -03:00
if (g_private->_mode == 0) {
g_private->setOrigin(kOriginZero);
2021-02-13 19:11:11 -03:00
} else if (g_private->_mode == 1) {
g_private->setOrigin(kOriginOne);
2021-02-13 19:11:11 -03:00
} else
2021-01-08 22:42:34 -03:00
assert(0);
2021-02-07 14:08:28 -03:00
if (args.size() == 3)
setSymbol(args[2].u.sym, true);
2021-02-13 11:37:03 -03:00
// This is the only place where this should be used
2021-02-13 11:38:10 -03:00
if (g_private->_noStopSounds) {
2021-02-07 17:34:19 -03:00
g_private->_noStopSounds = false;
2021-02-13 11:37:03 -03:00
} else {
g_private->stopSound(true);
2021-02-07 17:34:19 -03:00
}
2021-01-08 22:42:34 -03:00
}
void fVSPicture(ArgArray args) {
2021-01-08 22:42:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "VSPicture(%s)", args[0].u.str);
2021-01-08 22:42:34 -03:00
g_private->_nextVS = new Common::String(args[0].u.str);
2021-01-02 10:22:07 -03:00
}
2021-01-08 22:42:34 -03:00
void fDiaryLocList(ArgArray args) {
2021-02-07 14:08:28 -03:00
int x1, y1, x2, y2;
debugC(1, kPrivateDebugScript, "DiaryLocList(%d, %d, %d, %d)", args[0].u.val, args[1].u.val, args[2].u.val, args[3].u.val);
2021-02-07 14:08:28 -03:00
x2 = args[0].u.val;
y2 = args[1].u.val;
x1 = args[2].u.val;
y1 = args[3].u.val;
Common::Rect *rect = new Common::Rect(x1, y1, x2, y2);
g_private->loadLocations(rect);
}
void fDiaryGoLoc(ArgArray args) {
debugC(1, kPrivateDebugScript, "WARNING: DiaryGoLoc not implemented");
2021-02-07 14:08:28 -03:00
}
void fDiaryInvList(ArgArray args) {
2021-02-07 14:08:28 -03:00
Common::Rect *r1, *r2;
debugC(1, kPrivateDebugScript, "DiaryInvList(%d, ..)", args[0].u.val);
2021-02-07 14:08:28 -03:00
r1 = args[1].u.rect;
r2 = args[2].u.rect;
g_private->loadInventory(args[0].u.val, r1, r2);
}
void fgoto(ArgArray args) {
2021-01-05 21:03:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "goto(%s)", args[0].u.str);
2021-01-05 21:03:34 -03:00
Common::String *s = new Common::String(args[0].u.str);
2021-01-07 23:32:17 -03:00
g_private->_nextSetting = s;
2021-01-02 10:22:07 -03:00
}
2021-01-10 15:38:10 -03:00
void fSyncSound(ArgArray args) {
2021-01-10 15:38:10 -03:00
// assert types
debugC(1, kPrivateDebugScript, "SyncSound(%s, %s)", args[0].u.str, args[1].u.str);
2021-01-17 15:38:45 -03:00
Common::String *nextSetting = new Common::String(args[1].u.str);
g_private->_nextSetting = nextSetting;
2021-01-16 15:30:00 -03:00
if (strcmp("\"\"", args[0].u.str) != 0) {
Common::String s(args[0].u.str);
g_private->playSound(s, 1, true, false);
2021-02-13 19:11:11 -03:00
}
2021-01-10 15:38:10 -03:00
}
void fQuit(ArgArray args) {
debugC(1, kPrivateDebugScript, "Quit()");
g_private->quitGame();
}
void fLoadGame(ArgArray args) {
2021-01-09 22:08:41 -03:00
// assert types
debugC(1, kPrivateDebugScript, "LoadGame(%s, %s)", args[0].u.str, args[2].u.sym->name->c_str());
2021-01-12 20:49:12 -03:00
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-12 20:49:12 -03:00
m->surf = g_private->loadMask(*s, 0, 0, true);
m->cursor = args[2].u.sym->name;
2021-01-16 15:30:00 -03:00
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
2021-01-12 20:49:12 -03:00
g_private->_loadGameMask = m;
2021-01-16 15:30:00 -03:00
g_private->_masks.push_front(*m);
2021-01-12 20:49:12 -03:00
}
void fSaveGame(ArgArray args) {
2021-01-12 20:49:12 -03:00
// assert types
debugC(1, kPrivateDebugScript, "SaveGame(%s, %s)", args[0].u.str, args[1].u.sym->name->c_str());
2021-01-12 20:49:12 -03:00
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-12 20:49:12 -03:00
m->surf = g_private->loadMask(*s, 0, 0, true);
m->cursor = args[1].u.sym->name;
2021-01-16 15:30:00 -03:00
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
2021-01-12 20:49:12 -03:00
g_private->_saveGameMask = m;
2021-01-16 15:30:00 -03:00
g_private->_masks.push_front(*m);
2021-01-09 22:08:41 -03:00
}
void fRestartGame(ArgArray args) {
assert(args.size() == 0);
2021-01-16 15:30:00 -03:00
g_private->restartGame();
2021-01-08 22:42:34 -03:00
}
void fPoliceBust(ArgArray args) {
2021-01-10 01:00:05 -03:00
// assert types
assert (args.size() == 1 || args.size() == 2);
g_private->_policeBustEnabled = args[0].u.val;
2021-01-28 23:01:31 -03:00
//debug("Number of clicks %d", g_private->computePoliceIndex());
if (g_private->_policeBustEnabled)
g_private->startPoliceBust();
if (args.size() == 2) {
if (args[1].u.val == 2) {
2021-02-13 19:11:11 -03:00
// Unclear what it means
} else if (args[1].u.val == 3) {
g_private->_nextSetting = new Common::String(kMainDesktop);
2021-01-28 23:01:31 -03:00
g_private->_mode = 0;
g_private->setOrigin(kOriginZero);
} else
assert(0);
}
debugC(1, kPrivateDebugScript, "PoliceBust(%d, ..)", args[0].u.val);
debugC(1, kPrivateDebugScript, "WARNING: PoliceBust partially implemented");
2021-01-10 01:00:05 -03:00
}
void fBustMovie(ArgArray args) {
2021-02-08 21:46:25 -03:00
// assert types
assert (args.size() == 1);
debugC(1, kPrivateDebugScript, "BustMovie(%s)", args[0].u.str);
2021-02-08 21:46:25 -03:00
uint policeIndex = variables.getVal(kPoliceIndex)->u.val;
2021-02-13 11:37:03 -03:00
int videoIndex = policeIndex/2 - 1;
if (videoIndex < 0)
videoIndex = 0;
assert(videoIndex <= 5);
Common::String pv =
Common::String::format("po/animatio/spoc%02dxs.smk",
kPoliceBustVideos[videoIndex]);
2021-02-13 11:37:03 -03:00
if (kPoliceBustVideos[videoIndex] == 2) {
Common::String s("global/transiti/audio/spoc02VO.wav");
g_private->playSound(s, 1, false, false);
2021-02-13 11:37:03 -03:00
}
2021-02-08 21:46:25 -03:00
g_private->_nextMovie = new Common::String(pv);
2021-02-08 21:46:25 -03:00
g_private->_nextSetting = new Common::String(args[0].u.str);
}
void fDossierAdd(ArgArray args) {
assert (args.size() == 2);
Common::String *s1 = new Common::String(args[0].u.str);
DossierInfo *m = (DossierInfo *)malloc(sizeof(DossierInfo));
m->page1 = s1;
if (strcmp(args[1].u.str, "\"\"") != 0) {
Common::String *s2 = new Common::String(args[1].u.str);
m->page2 = s2;
} else {
m->page2 = NULL;
}
g_private->_dossiers.push_back(*m);
}
void fDossierBitmap(ArgArray args) {
assert (args.size() == 2);
int x = args[0].u.val;
int y = args[1].u.val;
assert(x == 40 && y == 30);
g_private->loadDossier();
}
void fDossierChgSheet(ArgArray args) {
debugC(1, kPrivateDebugScript, "WARNING: DossierChgSheet is not implemented");
}
void fDossierPrevSuspect(ArgArray args) {
assert (args.size() == 3);
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
int x = args[1].u.val;
int y = args[2].u.val;
m->surf = g_private->loadMask(*s, x, y, true);
m->cursor = new Common::String("kExit");
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
g_private->_dossierPrevSuspectMask = m;
g_private->_masks.push_front(*m);
}
void fDossierNextSuspect(ArgArray args) {
assert (args.size() == 3);
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
int x = args[1].u.val;
int y = args[2].u.val;
m->surf = g_private->loadMask(*s, x, y, true);
m->cursor = new Common::String("kExit");
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
g_private->_dossierNextSuspectMask = m;
g_private->_masks.push_front(*m);
2021-01-08 22:42:34 -03:00
}
void fNoStopSounds(ArgArray args) {
2021-02-07 17:34:19 -03:00
assert(args.size() == 0);
debugC(1, kPrivateDebugScript, "NoStopSounds()");
2021-02-07 17:34:19 -03:00
g_private->_noStopSounds = true;
2021-01-10 15:38:10 -03:00
}
void fLoseInventory(ArgArray args) {
2021-02-13 11:37:03 -03:00
assert(args.size() == 0);
debugC(1, kPrivateDebugScript, "LoveInventory()");
2021-02-13 11:37:03 -03:00
g_private->inventory.clear();
}
void fInventory(ArgArray args) {
2021-01-09 16:11:30 -03:00
// assert types
2021-01-10 20:17:27 -03:00
Datum b1 = args[0];
2021-01-10 15:38:10 -03:00
Datum v1 = args[1];
Datum v2 = args[2];
Datum e = args[3];
2021-02-07 14:08:28 -03:00
Datum i = args[4];
Datum c = args[5];
2021-01-10 15:38:10 -03:00
Datum snd = args[8];
assert(v1.type == STRING || v1.type == NAME);
assert(b1.type == STRING);
assert(e.type == STRING || e.type == NUM);
assert(snd.type == STRING);
2021-02-07 14:08:28 -03:00
assert(i.type == STRING);
2021-01-10 15:38:10 -03:00
2021-02-07 14:08:28 -03:00
Common::String *bmp = new Common::String(i.u.str);
2021-02-11 22:26:04 -03:00
assert(g_private->isDemo() || strcmp(bmp->c_str(), "\"\"") != 0);
2021-02-07 17:36:09 -03:00
2021-01-10 15:38:10 -03:00
if (v1.type == STRING)
assert(strcmp(v1.u.str, "\"\"") == 0);
debugC(1, kPrivateDebugScript, "Inventory(...)");
2021-01-10 15:38:10 -03:00
if (strcmp(b1.u.str, "\"\"") != 0) {
Common::String *s = new Common::String(b1.u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-10 15:38:10 -03:00
m->surf = g_private->loadMask(*s, 0, 0, true);
2021-01-10 20:17:27 -03:00
2021-01-10 15:38:10 -03:00
if (e.type == NUM)
m->nextSetting = NULL;
else
m->nextSetting = new Common::String(e.u.str);
m->cursor = new Common::String("kInventory");
m->point = new Common::Point(0,0);
if (v1.type == NAME)
m->flag1 = v1.u.sym;
else
m->flag1 = NULL;
2021-01-17 21:50:42 -03:00
if (v2.type == NAME)
m->flag2 = v2.u.sym;
2021-01-10 15:38:10 -03:00
else
m->flag2 = NULL;
2021-01-10 20:17:27 -03:00
2021-01-10 15:38:10 -03:00
g_private->_masks.push_front(*m);
2021-01-17 21:50:42 -03:00
g_private->_toTake = true;
2021-01-28 23:01:31 -03:00
if (strcmp(snd.u.str, "\"\"") != 0) {
g_private->playSound(Common::String(snd.u.str), 1, false, false);
2021-01-28 23:01:31 -03:00
} else {
g_private->playSound(g_private->getTakeLeaveSound(), 1, false, false);
2021-01-28 23:01:31 -03:00
}
2021-02-07 14:08:28 -03:00
g_private->inventory.push_back(*bmp);
2021-02-07 17:36:09 -03:00
} else {
if (v1.type == NAME) {
2021-02-07 14:08:28 -03:00
if (strcmp(c.u.str, "\"REMOVE\"") == 0) {
v1.u.sym->u.val = 0;
2021-02-07 14:08:28 -03:00
g_private->inventory.remove(*bmp);
} else {
v1.u.sym->u.val = 1;
2021-02-07 14:08:28 -03:00
g_private->inventory.push_back(*bmp);
}
2021-02-13 19:11:11 -03:00
} else {
2021-02-07 14:08:28 -03:00
g_private->inventory.push_back(*bmp);
}
if (v2.type == NAME)
v2.u.sym->u.val = 1;
}
2021-01-09 16:11:30 -03:00
}
void fSetFlag(ArgArray args) {
assert(args.size() == 2);
assert(args[0].type == NAME && args[1].type == NUM);
debugC(1, kPrivateDebugScript, "SetFlag(%s, %d)", args[0].u.sym->name->c_str(), args[1].u.val);
2021-01-05 21:03:34 -03:00
args[0].u.sym->u.val = args[1].u.val;
2021-01-02 10:22:07 -03:00
}
void fExit(ArgArray args) {
// assert types
assert(args[2].type == RECT || args[2].type == NAME);
debugC(1, kPrivateDebugScript, "Exit(%d %d %d)", args[0].type, args[1].type, args[2].type); //, args[0].u.str, args[1].u.sym->name->c_str(), "RECT");
ExitInfo *e = (ExitInfo *)malloc(sizeof(ExitInfo));
2021-01-08 22:42:34 -03:00
if (args[0].type == NUM && args[0].u.val == 0)
e->nextSetting = NULL;
else
e->nextSetting = new Common::String(args[0].u.str);
if (args[1].type == NUM && args[1].u.val == 0)
e->cursor = NULL;
else
e->cursor = args[1].u.sym->name;
2021-01-09 16:11:30 -03:00
if (args[2].type == NAME) {
2021-01-09 19:11:41 -03:00
assert(args[2].u.sym->type == RECT);
args[2].u.rect = args[2].u.sym->u.rect;
2021-01-09 16:11:30 -03:00
}
e->rect = args[2].u.rect;
2021-01-07 23:32:17 -03:00
g_private->_exits.push_front(*e);
}
void fSetModifiedFlag(ArgArray args) {
2021-01-05 21:03:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "SetModifiedFlag(%d)", args[0].u.val);
2021-02-14 13:42:34 -03:00
g_private->_modified = args[0].u.val != 0;
2021-01-04 08:14:40 -03:00
}
void fPaperShuffleSound(ArgArray args) {
assert(args.size() == 0);
debugC(1, kPrivateDebugScript, "PaperShuffleSound()");
g_private->playSound(g_private->getPaperShuffleSound(), 1, false, false);
}
void fSoundEffect(ArgArray args) {
// assert types
debugC(1, kPrivateDebugScript, "SoundEffect(%s)", args[0].u.str);
if (strcmp("\"\"", args[0].u.str) != 0) {
Common::String s(args[0].u.str);
g_private->playSound(s, 1, false, false);
//assert(0);
} else {
2021-02-07 14:08:28 -03:00
g_private->stopSound(true);
}
2021-01-17 15:38:45 -03:00
}
void fSound(ArgArray args) {
2021-01-05 21:03:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "Sound(%s)", args[0].u.str);
2021-02-07 14:08:28 -03:00
if (args.size() == 4) {
2021-02-14 13:42:34 -03:00
bool b1 = args[1].u.val != 0;
bool b2 = args[2].u.val != 0;
2021-02-07 14:08:28 -03:00
int c = args[3].u.val;
if (!b1 && !b2 && c == 1) {
g_private->stopSound(true);
} else if (!b1 && !b2 && c == 2) {
g_private->stopSound(false);
} else
assert(0);
}
2021-01-05 21:03:34 -03:00
if (strcmp("\"\"", args[0].u.str) != 0) {
Common::String s(args[0].u.str);
g_private->playSound(s, 1, false, false);
//assert(0);
2021-01-02 10:22:07 -03:00
} else {
2021-02-07 14:08:28 -03:00
g_private->stopSound(true);
2021-01-02 10:22:07 -03:00
}
}
void fLoopedSound(ArgArray args) {
2021-01-09 16:11:30 -03:00
// assert types
assert(args.size() == 1);
debugC(1, kPrivateDebugScript, "LoopedSound(%s)", args[0].u.str);
2021-01-09 16:11:30 -03:00
if (strcmp("\"\"", args[0].u.str) != 0) {
Common::String s(args[0].u.str);
g_private->playSound(s, 0, true, true);
2021-01-09 16:11:30 -03:00
//assert(0);
} else {
2021-02-07 14:08:28 -03:00
g_private->stopSound(true);
2021-01-09 16:11:30 -03:00
}
}
void fViewScreen(ArgArray args) {
2021-01-10 15:38:10 -03:00
// assert types
debugC(1, kPrivateDebugScript, "WARNING: ViewScreen not implemented!");
2021-01-10 15:38:10 -03:00
}
void fTransition(ArgArray args) {
2021-01-05 21:03:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "Transition(%s, %s)", args[0].u.str, args[1].u.str);
2021-01-09 16:11:30 -03:00
g_private->_nextMovie = new Common::String(args[0].u.str);
2021-01-08 22:42:34 -03:00
g_private->_nextSetting = new Common::String(args[1].u.str);
}
void fResume(ArgArray args) {
// assert types
debugC(1, kPrivateDebugScript, "Resume(%d)", args[0].u.val); // this value is always 1
g_private->_nextSetting = g_private->_pausedSetting;
g_private->_pausedSetting = NULL;
g_private->_mode = 1;
g_private->setOrigin(kOriginOne);
}
void fMovie(ArgArray args) {
2021-01-08 22:42:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "Movie(%s, %s)", args[0].u.str, args[1].u.str);
2021-01-17 15:38:45 -03:00
Common::String *movie = new Common::String(args[0].u.str);
Common::String *nextSetting = new Common::String(args[1].u.str);
bool isEmptyString = strcmp(args[0].u.str, "\"\"") == 0;
if (!g_private->_playedMovies.contains(*movie) && !isEmptyString) {
g_private->_nextMovie = movie;
g_private->_playedMovies.setVal(*movie, true);
g_private->_nextSetting = nextSetting;
} else if (isEmptyString) {
g_private->_repeatedMovieExit = nextSetting;
debugC(1, kPrivateDebugScript, "repeated movie exit is %s", nextSetting->c_str());
2021-01-17 15:38:45 -03:00
} else {
debugC(1, kPrivateDebugScript, "movie %s already played", movie->c_str());
2021-01-17 15:38:45 -03:00
g_private->_nextSetting = g_private->_repeatedMovieExit;
}
2021-01-05 21:03:34 -03:00
}
void fCRect(ArgArray args) {
2021-01-05 21:03:34 -03:00
// assert types
debugC(1, kPrivateDebugScript, "CRect(%d, %d, %d, %d)", args[0].u.val, args[1].u.val, args[2].u.val, args[3].u.val);
2021-02-15 10:52:09 -03:00
int x1, y1, x2, y2;
2021-01-05 21:03:34 -03:00
x1 = args[0].u.val;
y1 = args[1].u.val;
x2 = args[2].u.val;
y2 = args[3].u.val;
Datum *d = new Datum();
Common::Rect *rect = new Common::Rect(x1, y1, x2, y2);
d->type = RECT;
2021-01-05 21:03:34 -03:00
d->u.rect = rect;
push(*d);
2021-01-04 08:14:40 -03:00
}
void fBitmap(ArgArray args) {
assert(args.size() == 1 || args.size() == 3);
int x = 0;
int y = 0;
2021-01-05 21:03:34 -03:00
char *f = args[0].u.str;
if (args.size() == 3) {
x = args[1].u.val;
y = args[2].u.val;
}
debugC(1, kPrivateDebugScript, "Bitmap(%s, %d, %d)", f, x, y);
2021-01-05 21:03:34 -03:00
Common::String *s = new Common::String(args[0].u.str);
2021-01-07 23:32:17 -03:00
g_private->loadImage(*s, x, y);
}
void _fMask(ArgArray args, bool drawn) {
2021-01-08 22:42:34 -03:00
assert(args.size() == 3 || args.size() == 5);
int x = 0;
int y = 0;
char *f = args[0].u.str;
char *e = args[1].u.str;
Common::String *c = args[2].u.sym->name;
2021-01-09 19:11:41 -03:00
2021-01-08 22:42:34 -03:00
if (args.size() == 5) {
x = args[3].u.val;
y = args[4].u.val;
}
debugC(1, kPrivateDebugScript, "Mask(%s, %s, %s, %d, %d)", f, e, c->c_str(), x, y);
2021-01-08 22:42:34 -03:00
const Common::String *s = new Common::String(f);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-08 22:42:34 -03:00
m->surf = g_private->loadMask(*s, x, y, drawn);
m->nextSetting = new Common::String(e);
m->cursor = c;
m->flag1 = NULL;
m->flag2 = NULL;
2021-01-08 22:42:34 -03:00
m->point = new Common::Point(x,y);
g_private->_masks.push_front(*m);
}
void fMask(ArgArray args) {
_fMask(args, false);
2021-01-10 20:17:27 -03:00
}
void fMaskDrawn(ArgArray args) {
_fMask(args, true);
2021-01-10 20:17:27 -03:00
}
2021-01-08 22:42:34 -03:00
void fAddSound(char *s, char *t, Symbol *flag = NULL, int val = 0) {
2021-01-16 22:27:13 -03:00
if (strcmp(s, "\"\"") == 0)
return;
2021-01-16 15:30:00 -03:00
Common::String *sound = new Common::String(s);
if (strcmp(t, "AMRadioClip") == 0)
2021-01-16 22:27:13 -03:00
g_private->_AMRadio.push_back(*sound);
else if (strcmp(t, "PoliceClip") == 0)
2021-01-16 22:27:13 -03:00
g_private->_policeRadio.push_back(*sound);
2021-01-16 15:30:00 -03:00
else if (strcmp(t, "PhoneClip") == 0) {
2021-01-16 22:27:13 -03:00
// This condition will avoid adding the same phone call twice,
// it is unclear why this could be useful, but it looks like a bug
2021-01-17 21:50:42 -03:00
// in the original scripts
if (g_private->_playedPhoneClips.contains(*sound))
2021-01-16 22:27:13 -03:00
return;
2021-01-17 21:50:42 -03:00
g_private->_playedPhoneClips.setVal(*sound, true);
PhoneInfo *p = (PhoneInfo *)malloc(sizeof(PhoneInfo));
2021-01-17 21:50:42 -03:00
p->sound = sound;
p->flag = flag;
p->val = val;
2021-01-16 22:27:13 -03:00
g_private->_phone.push_back(*p);
2021-02-16 08:19:12 -03:00
} else
error("error: invalid sound type %s", t);
}
void fAMRadioClip(ArgArray args) {
2021-01-17 15:38:45 -03:00
assert(args.size() <= 4);
fAddSound(args[0].u.str, "AMRadioClip");
2021-01-10 20:17:27 -03:00
}
2021-02-15 10:52:09 -03:00
void fPoliceClip(ArgArray args) {
2021-01-17 15:38:45 -03:00
assert(args.size() <= 4);
fAddSound(args[0].u.str, "PoliceClip");
2021-01-10 20:17:27 -03:00
}
2021-02-15 10:52:09 -03:00
void fPhoneClip(ArgArray args) {
2021-01-16 15:30:00 -03:00
if (args.size() == 2) {
debugC(1, kPrivateDebugScript, "Unimplemented PhoneClip special case");
2021-01-16 15:30:00 -03:00
return;
}
2021-01-23 09:30:16 -03:00
int i = args[2].u.val;
int j = args[3].u.val;
if (i == j)
fAddSound(args[0].u.str, "PhoneClip", args[4].u.sym, args[5].u.val);
2021-01-23 09:30:16 -03:00
else {
assert(i < j);
char *clip = g_private->getRandomPhoneClip(args[0].u.str, i, j);
fAddSound(clip, "PhoneClip", args[4].u.sym, args[5].u.val);
2021-01-23 09:30:16 -03:00
}
2021-01-10 20:17:27 -03:00
}
void fSoundArea(ArgArray args) {
// assert types
2021-01-16 15:30:00 -03:00
char *n;
if (args[1].type == NAME)
n = (char *)args[1].u.sym->name->c_str();
2021-01-16 15:30:00 -03:00
else if (args[1].type == STRING)
n = args[1].u.str;
else
assert(0);
debugC(1, kPrivateDebugScript, "SoundArea(%s, %s)", args[0].u.str, n);
2021-01-16 15:30:00 -03:00
if (strcmp(n, "kAMRadio") == 0) {
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-16 15:30:00 -03:00
m->surf = g_private->loadMask(*s, 0, 0, true);
m->cursor = args[2].u.sym->name;
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
2021-01-16 15:30:00 -03:00
g_private->_AMRadioArea = m;
g_private->_masks.push_front(*m);
} else if (strcmp(n, "kPoliceRadio") == 0) {
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-16 15:30:00 -03:00
m->surf = g_private->loadMask(*s, 0, 0, true);
m->cursor = args[2].u.sym->name;
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
2021-01-16 15:30:00 -03:00
g_private->_policeRadioArea = m;
g_private->_masks.push_front(*m);
2021-01-16 22:27:13 -03:00
} else if (strcmp(n, "kPhone") == 0) {
Common::String *s = new Common::String(args[0].u.str);
MaskInfo *m = (MaskInfo *)malloc(sizeof(MaskInfo));
2021-01-16 22:27:13 -03:00
m->surf = g_private->loadMask(*s, 0, 0, true);
m->cursor = args[2].u.sym->name;
m->nextSetting = NULL;
m->flag1 = NULL;
m->flag2 = NULL;
2021-01-16 22:27:13 -03:00
g_private->_phoneArea = m;
g_private->_masks.push_front(*m);
2021-01-16 15:30:00 -03:00
}
}
void fSafeDigit(ArgArray args) {
debugC(1, kPrivateDebugScript, "WARNING: SafeDigit is not implemented");
2021-02-13 11:37:03 -03:00
}
void fAskSave(ArgArray args) {
2021-01-12 20:49:12 -03:00
// This is not needed, since scummvm will take care of this
debugC(1, kPrivateDebugScript, "WARNING: AskSave is partially implemented");
2021-01-12 20:49:12 -03:00
Common::String *s = new Common::String(args[0].u.str);
g_private->_nextSetting = s;
}
void fTimer(ArgArray args) {
2021-01-09 16:11:30 -03:00
assert (args.size() == 2 || args.size() == 3);
if (args.size() == 3)
debugC(1, kPrivateDebugScript, "Timer(%d, %s, %s)", args[0].u.val, args[1].u.str, args[2].u.str);
2021-01-09 19:11:41 -03:00
else
debugC(1, kPrivateDebugScript, "Timer(%d, %s)", args[0].u.val, args[1].u.str);
2021-01-09 19:11:41 -03:00
2021-01-31 20:15:56 -03:00
int32 delay = 1000000 * args[0].u.val;
2021-01-05 21:03:34 -03:00
Common::String *s = new Common::String(args[1].u.str);
2021-01-31 20:15:56 -03:00
if (delay > 0) {
assert(g_private->installTimer(delay, s));
} else if (delay == 0) {
g_private->_nextSetting = s;
} else {
assert(0);
}
}
2021-01-09 22:08:41 -03:00
static struct FuncTable {
void (*func)(Private::ArgArray);
const char *name;
} funcTable[] = {
2021-02-15 10:52:09 -03:00
// Control flow
{ fChgMode, "ChgMode"},
{ fResume, "Resume"},
{ fgoto, "goto"},
{ fTimer, "Timer"},
2021-02-15 10:52:09 -03:00
// Variables
{ fSetFlag, "SetFlag"},
{ fSetModifiedFlag, "SetModifiedFlag"},
// Sounds
{ fSound, "Sound"},
{ fSoundEffect, "SoundEffect"},
{ fLoopedSound, "LoopedSound"},
{ fNoStopSounds, "NoStopSounds"},
{ fSyncSound, "SyncSound"},
{ fAMRadioClip, "AMRadioClip"},
{ fPoliceClip, "PoliceClip"},
{ fPhoneClip, "PhoneClip"},
{ fSoundArea, "SoundArea"},
{ fPaperShuffleSound, "PaperShuffleSound"},
2021-01-10 20:17:27 -03:00
// Images
{ fBitmap, "Bitmap"},
{ fMask, "Mask"},
{ fMaskDrawn, "MaskDrawn"},
{ fVSPicture, "VSPicture"},
{ fViewScreen, "ViewScreen"},
2021-02-15 10:52:09 -03:00
{ fExit, "Exit"},
2021-01-10 20:17:27 -03:00
// Video
{ fTransition, "Transition"},
{ fMovie, "Movie"},
2021-02-07 14:08:28 -03:00
// Diary
{ fDiaryLocList, "DiaryLocList"},
{ fDiaryInvList, "DiaryInvList"},
{ fDiaryGoLoc, "DiaryGoLoc"},
2021-02-15 10:52:09 -03:00
// Main menu
{ fQuit, "Quit"},
{ fLoadGame, "LoadGame"},
{ fSaveGame, "SaveGame"},
{ fAskSave, "AskSave"},
2021-02-15 10:52:09 -03:00
{ fRestartGame, "RestartGame"},
2021-01-17 21:50:42 -03:00
// Dossiers
{ fDossierAdd, "DossierAdd"},
{ fDossierChgSheet, "DossierChgSheet"},
{ fDossierBitmap, "DossierBitmap"},
{ fDossierPrevSuspect, "DossierPrevSuspect"},
{ fDossierNextSuspect, "DossierNextSuspect"},
2021-02-07 17:36:09 -03:00
2021-02-15 10:52:09 -03:00
// Inventory
{ fLoseInventory, "LoseInventory"},
{ fInventory, "Inventory"},
2021-02-08 21:46:25 -03:00
// PoliceBust
{ fPoliceBust, "PoliceBust"},
{ fBustMovie, "BustMovie"},
2021-02-08 21:46:25 -03:00
2021-02-13 11:37:03 -03:00
// Others
{ fSafeDigit, "SafeDigit"},
2021-02-15 10:52:09 -03:00
{ fCRect, "CRect"},
2021-02-13 11:37:03 -03:00
2021-01-09 22:08:41 -03:00
{ 0, 0}
};
NameToPtr _functions;
void initFuncs() {
for (Private::FuncTable *fnc = funcTable; fnc->name; fnc++) {
Common::String *name = new Common::String(fnc->name);
_functions.setVal(*name, (void *)fnc->func);
2021-01-08 22:42:34 -03:00
}
2021-01-09 22:08:41 -03:00
}
2021-01-09 19:11:41 -03:00
2021-01-09 22:08:41 -03:00
void call(char *name, ArgArray args) {
Common::String n(name);
if (!_functions.contains(n)) {
error("I don't know how to execute %s", name);
2021-01-04 08:14:40 -03:00
}
2021-01-10 20:17:27 -03:00
2021-01-09 22:08:41 -03:00
void (*func)(ArgArray) = (void (*)(ArgArray)) _functions.getVal(n);
func(args);
2021-01-02 00:58:58 -03:00
}
2021-02-13 18:27:24 -03:00
} // End of namespace Private