aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/gob/game.cpp245
-rw-r--r--engines/gob/game.h50
-rw-r--r--engines/gob/inter_v7.cpp20
3 files changed, 303 insertions, 12 deletions
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 6bf0f3c1f5..98e4d9b77b 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -247,7 +247,205 @@ bool Environments::getMedia(uint8 env) {
}
-Game::Game(GobEngine *vm) : _vm(vm), _environments(_vm) {
+TotFunctions::TotFunctions(GobEngine *vm) : _vm(vm) {
+ for (uint8 i = 0; i < kTotCount; i++) {
+ _tots[i].script = 0;
+ _tots[i].resources = 0;
+ }
+}
+
+TotFunctions::~TotFunctions() {
+ for (uint8 i = 0; i < kTotCount; i++)
+ freeTot(_tots[i]);
+}
+
+bool TotFunctions::loadTot(Tot &tot, const Common::String &file) {
+ tot.script = new Script(_vm);
+ tot.resources = new Resources(_vm);
+
+ if (!tot.script->load(file) || !tot.resources->load(file)) {
+ freeTot(tot);
+ return false;
+ }
+
+ return true;
+}
+
+void TotFunctions::freeTot(Tot &tot) {
+ delete tot.script;
+ delete tot.resources;
+
+ tot.script = 0;
+ tot.resources = 0;
+
+ tot.file.clear();
+ tot.functions.clear();
+}
+
+bool TotFunctions::loadIDE(Tot &tot) {
+ // Mapping file of function names -> function numbers/offsets
+ Common::String ideFile = Util::setExtension(tot.file, ".IDE");
+ Common::SeekableReadStream *ide = _vm->_dataIO->getFile(ideFile);
+ if (!ide)
+ // No mapping file => No named functions
+ return true;
+
+ char buffer[17];
+
+ uint32 count = ide->readUint16LE();
+ for (uint32 i = 0; i < count; i++) {
+ Function function;
+
+ function.type = ide->readByte();
+
+ ide->read(buffer, 17);
+ buffer[16] = '\0';
+
+ function.name = buffer;
+
+ ide->skip(2); // Unknown;
+ function.offset = ide->readUint16LE();
+ ide->skip(2); // Unknown;
+
+ if ((function.type != 0x47) && (function.type != 0x67))
+ continue;
+
+ tot.script->seek(function.offset);
+
+ if (tot.script->readByte() != 1) {
+ warning("TotFunctions::loadIDE(): IDE corrupt");
+ return false;
+ }
+
+ debugC(5, kDebugGameFlow, "Function 0x%02X: \"%s\"", function.type,
+ function.name.c_str());
+ tot.functions.push_back(function);
+ }
+
+ tot.script->seek(0);
+ return true;
+}
+
+int TotFunctions::find(const Common::String &totFile) const {
+ for (int i = 0; i < kTotCount; i++)
+ if (_tots[i].file.equalsIgnoreCase(totFile))
+ return i;
+
+ return -1;
+}
+
+int TotFunctions::findFree() const {
+ for (int i = 0; i < kTotCount; i++)
+ if (_tots[i].file.empty())
+ return i;
+
+ return -1;
+}
+
+bool TotFunctions::load(const Common::String &totFile) {
+ if (find(totFile) >= 0) {
+ warning("TotFunctions::load(): \"%s\" already loaded", totFile.c_str());
+ return false;
+ }
+
+ int index = findFree();
+ if (index < 0) {
+ warning("TotFunctions::load(): No free space for \"%s\"", totFile.c_str());
+ return false;
+ }
+
+ Tot &tot = _tots[index];
+ if (!loadTot(tot, totFile))
+ return false;
+
+ tot.file = totFile;
+
+ if (!loadIDE(tot)) {
+ freeTot(tot);
+ return false;
+ }
+
+ return true;
+}
+
+bool TotFunctions::unload(const Common::String &totFile) {
+ int index = find(totFile);
+ if (index < 0) {
+ warning("TotFunctions::unload(): \"%s\" not loaded", totFile.c_str());
+ return false;
+ }
+
+ Tot &tot = _tots[index];
+
+ if (_vm->_game->_script == tot.script)
+ _vm->_game->_script = 0;
+ if (_vm->_game->_resources == tot.resources)
+ _vm->_game->_resources = 0;
+
+ freeTot(tot);
+
+ return true;
+}
+
+bool TotFunctions::call(const Common::String &totFile,
+ const Common::String &function) const {
+
+ int index = find(totFile);
+ if (index < 0) {
+ warning("TotFunctions::call(): No such TOT \"%s\"", totFile.c_str());
+ return false;
+ }
+
+ const Tot &tot = _tots[index];
+
+ uint16 offset = 0;
+ Common::List<Function>::const_iterator it;
+ for (it = tot.functions.begin(); it != tot.functions.end(); ++it) {
+ if (it->name.equalsIgnoreCase(function)) {
+ offset = it->offset;
+ break;
+ }
+ }
+
+ if (offset == 0) {
+ warning("TotFunctions::call(): No such function \"%s\" in \"%s\"",
+ function.c_str(), totFile.c_str());
+ return false;
+ }
+
+ return call(tot, offset);
+}
+
+bool TotFunctions::call(const Common::String &totFile, uint16 offset) const {
+ int index = find(totFile);
+ if (index < 0) {
+ warning("TotFunctions::call(): No such TOT \"%s\"", totFile.c_str());
+ return false;
+ }
+
+ return call(_tots[index], offset);
+}
+
+bool TotFunctions::call(const Tot &tot, uint16 offset) const {
+ Script *script = _vm->_game->_script;
+ Resources *resources = _vm->_game->_resources;
+ Common::String curtotFile = _vm->_game->_curTotFile;
+
+ _vm->_game->_script = tot.script;
+ _vm->_game->_resources = tot.resources;
+ _vm->_game->_curTotFile = tot.file;
+
+ _vm->_game->playTot(offset);
+
+ _vm->_game->_script = script;
+ _vm->_game->_resources = resources;
+ _vm->_game->_curTotFile = curtotFile;
+
+ return true;
+}
+
+
+Game::Game(GobEngine *vm) : _vm(vm), _environments(_vm), _totFunctions(_vm) {
_captureCount = 0;
_startTimeKey = 0;
@@ -438,10 +636,9 @@ void Game::playTot(int16 function) {
_vm->_inter->initControlVars(0);
_vm->_scenery->_pCaptureCounter = oldCaptureCounter;
- if (function > 13) {
- warning("Addy: function = %d", function);
- _script->skip(function);
- } else
+ if (function > 13)
+ _script->seek(function);
+ else
_script->seek(_script->getFunctionOffset(function + 1));
_vm->_inter->callSub(2);
@@ -763,4 +960,42 @@ void Game::clearUnusedEnvironment() {
}
}
+bool Game::loadFunctions(const Common::String &tot, uint16 flags) {
+ if ((flags & 0xFFFE) != 0) {
+ warning("Game::loadFunctions(): Unknown flags 0x%04X", flags);
+ return false;
+ }
+
+ bool unload = (flags & 0x1) != 0;
+
+ if (unload) {
+ debugC(4, kDebugGameFlow, "Unloading function for \"%s\"", tot.c_str());
+ return _totFunctions.unload(tot);
+ }
+
+ debugC(4, kDebugGameFlow, "Loading function for \"%s\"", tot.c_str());
+ return _totFunctions.load(tot);
+}
+
+bool Game::callFunction(const Common::String &tot, const Common::String &function,
+ int16 param) {
+
+ if (param != 0) {
+ warning("Game::callFunction(): param != 0 (%d)", param);
+ return false;
+ }
+
+ debugC(4, kDebugGameFlow, "Calling function \"%s\":\"%s\"",
+ tot.c_str(), function.c_str());
+
+ uint16 offset = atoi(function.c_str());
+ if (offset != 0)
+ return _totFunctions.call(tot, offset);
+
+ if (function.size() > 16)
+ return _totFunctions.call(tot, Common::String(function.c_str(), 16));
+
+ return _totFunctions.call(tot, function);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 82e73678d5..f529f7c025 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -83,6 +83,51 @@ private:
Media _media[kEnvironmentCount];
};
+class TotFunctions {
+public:
+ TotFunctions(GobEngine *vm);
+ ~TotFunctions();
+
+ int find(const Common::String &totFile) const;
+
+ bool load(const Common::String &totFile);
+ bool unload(const Common::String &totFile);
+
+ bool call(const Common::String &totFile, const Common::String &function) const;
+ bool call(const Common::String &totFile, uint16 offset) const;
+
+private:
+ static const uint8 kTotCount = 100;
+
+ struct Function {
+ Common::String name;
+ byte type;
+ uint16 offset;
+ };
+
+ struct Tot {
+ Common::String file;
+
+ Common::List<Function> functions;
+
+ Script *script;
+ Resources *resources;
+ };
+
+ GobEngine *_vm;
+
+ Tot _tots[kTotCount];
+
+ bool loadTot(Tot &tot, const Common::String &file);
+ void freeTot(Tot &tot);
+
+ bool loadIDE(Tot &tot);
+
+ int findFree() const;
+
+ bool call(const Tot &tot, uint16 offset) const;
+};
+
class Game {
public:
Script *_script;
@@ -127,6 +172,9 @@ public:
void totSub(int8 flags, const Common::String &totFile);
void switchTotSub(int16 index, int16 function);
+ bool loadFunctions(const Common::String &tot, uint16 flags);
+ bool callFunction(const Common::String &tot, const Common::String &function, int16 param);
+
protected:
GobEngine *_vm;
@@ -141,6 +189,8 @@ protected:
int8 _numEnvironments;
Environments _environments;
+ TotFunctions _totFunctions;
+
void clearUnusedEnvironment();
};
diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp
index 731d494938..b718a26998 100644
--- a/engines/gob/inter_v7.cpp
+++ b/engines/gob/inter_v7.cpp
@@ -131,20 +131,26 @@ void Inter_v7::o7_intToString() {
}
void Inter_v7::o7_callFunction() {
- Common::String str0 = _vm->_game->_script->evalString();
- Common::String str1 = _vm->_game->_script->evalString();
+ Common::String tot = _vm->_game->_script->evalString();
+ Common::String function = _vm->_game->_script->evalString();
- int16 expr0 = _vm->_game->_script->readValExpr();
+ int16 param = _vm->_game->_script->readValExpr();
+
+ if (!tot.contains('.'))
+ tot += ".TOT";
- warning("Addy Stub: Call function: \"%s\", \"%s\", %d", str0.c_str(), str1.c_str(), expr0);
+ _vm->_game->callFunction(tot, function, param);
}
void Inter_v7::o7_loadFunctions() {
- Common::String str0 = _vm->_game->_script->evalString();
+ Common::String tot = _vm->_game->_script->evalString();
- int16 expr0 = _vm->_game->_script->readValExpr();
+ int16 flags = _vm->_game->_script->readValExpr();
+
+ if (!tot.contains('.'))
+ tot += ".TOT";
- warning("Addy Stub: Load functions: \"%s\", %d", str0.c_str(), expr0);
+ _vm->_game->loadFunctions(tot, flags);
}
void Inter_v7::o7_draw0x89() {