[Scummvm-git-logs] scummvm master -> 34e11c617489c396d591861eb0999c969b956bee
sdelamarre
noreply at scummvm.org
Sat Feb 14 14:48:46 UTC 2026
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
e584710b07 GOB: Add support for launching games in Adi4's gamebox
7b0bce150b GOB: Add "adi.bis" to Adi4 save files and rename some save files
1e33ffdae0 GOB: Allow to create a new save file on a write at offset > 0
ab277297ab GOB: Increase again the (fake) amount of memory returned by o7_getSystemProperty("TotalPhys")
34e11c6174 GOB: More "live" videos improvements (Adi4)
Commit: e584710b07c86e63e34f7299809acd19b59d2b6b
https://github.com/scummvm/scummvm/commit/e584710b07c86e63e34f7299809acd19b59d2b6b
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-02-14T15:19:09+01:00
Commit Message:
GOB: Add support for launching games in Adi4's gamebox
As long as they are supported by ScummVM (only Gobliiins 1-3 at the time
of writing).
The directory where the original engine would expect the minigame
executable must be the path of a target added in ScummVM beforehand.
This target is started using ChainedGamesManager. After the minigame is
exited, we restore the Adi4 state (current child etc.) using an ad-hoc
savegame and several hacks.
Changed paths:
engines/gob/inter.h
engines/gob/inter_playtoons.cpp
engines/gob/inter_v6.cpp
engines/gob/inter_v7.cpp
engines/gob/save/saveload.h
engines/gob/save/saveload_v7.cpp
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 804effe46ea..ffd7479fe66 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -661,6 +661,8 @@ protected:
void o6_fillRect(OpFuncParams ¶ms);
void probe16bitMusic(Common::String &fileName);
+
+ Common::String getFile(const char *path, bool stripPath = true, bool *isCd = nullptr);
};
class Inter_Playtoons : public Inter_v6 {
@@ -687,8 +689,6 @@ protected:
void oPlaytoons_copyFile();
void oPlaytoons_openItk();
- Common::String getFile(const char *path, bool stripPath = true, bool *isCd = nullptr);
-
bool readSprite(Common::String file, int32 dataVar, int32 size, int32 offset);
};
diff --git a/engines/gob/inter_playtoons.cpp b/engines/gob/inter_playtoons.cpp
index f82fc8f3796..5d171017e71 100644
--- a/engines/gob/inter_playtoons.cpp
+++ b/engines/gob/inter_playtoons.cpp
@@ -474,47 +474,6 @@ void Inter_Playtoons::oPlaytoons_openItk() {
_vm->_dataIO->openArchive(file, false);
}
-Common::String Inter_Playtoons::getFile(const char *path, bool stripPath, bool *isCd) {
- const char *orig = path;
-
- if (!strncmp(path, "@:\\", 3))
- path += 3;
- else if (!strncmp(path, "<ME>", 4))
- path += 4;
- else if (!strncmp(path, "<CD>", 4)) {
- path += 4;
- if (isCd)
- *isCd = true;
- } else if (!strncmp(path, "<STK>", 5))
- path += 5;
- else if (!strncmp(path, "<ALLCD>", 7)) {
- path += 7;
- if (isCd)
- *isCd = true;
- }
-
- if (stripPath) {
- const char *backslash = strrchr(path, '\\');
- if (backslash)
- path = backslash + 1;
- }
-
- Common::String newPath = path;
- // Comma in filenames tells this engine that the file handle may be reused for next read/write operations
- // E.g. myfile,0 will keep the file handle for "myfile".
- // If later we request file I/O for "myfile,1" the file handle will be reused.
- // It seems that we can just ignore this, as the seek position of the handle is reset anyway.
- uint32 commaPos = newPath.find(',');
- if (commaPos != Common::String::npos)
- newPath = newPath.substr(0, commaPos);
-
- if (orig != newPath)
- debugC(2, kDebugFileIO, "Inter_Playtoons::getFile(): Evaluating path"
- "\"%s\" to \"%s\"", orig, path);
-
- return newPath;
-}
-
bool Inter_Playtoons::readSprite(Common::String file, int32 dataVar,
int32 size, int32 offset) {
diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp
index 72fc08f4a0c..b9d17ac9f56 100644
--- a/engines/gob/inter_v6.cpp
+++ b/engines/gob/inter_v6.cpp
@@ -25,6 +25,7 @@
*
*/
+#include "common/config-manager.h"
#include "common/str.h"
#include "gob/gob.h"
@@ -39,6 +40,7 @@
#include "gob/draw.h"
#include "gob/sound/sound.h"
#include "gob/videoplayer.h"
+#include "gob/save/saveload.h"
namespace Gob {
@@ -71,6 +73,47 @@ void Inter_v6::setupOpcodesFunc() {
void Inter_v6::setupOpcodesGob() {
}
+Common::String Inter_v6::getFile(const char *path, bool stripPath, bool *isCd) {
+ const char *orig = path;
+
+ if (!strncmp(path, "@:\\", 3))
+ path += 3;
+ else if (!strncmp(path, "<ME>", 4))
+ path += 4;
+ else if (!strncmp(path, "<CD>", 4)) {
+ path += 4;
+ if (isCd)
+ *isCd = true;
+ } else if (!strncmp(path, "<STK>", 5))
+ path += 5;
+ else if (!strncmp(path, "<ALLCD>", 7)) {
+ path += 7;
+ if (isCd)
+ *isCd = true;
+ }
+
+ if (stripPath) {
+ const char *backslash = strrchr(path, '\\');
+ if (backslash)
+ path = backslash + 1;
+ }
+
+ Common::String newPath = path;
+ // Comma in filenames tells this engine that the file handle may be reused for next read/write operations
+ // E.g. myfile,0 will keep the file handle for "myfile".
+ // If later we request file I/O for "myfile,1" the file handle will be reused.
+ // It seems that we can just ignore this, as the seek position of the handle is reset anyway.
+ uint32 commaPos = newPath.find(',');
+ if (commaPos != Common::String::npos)
+ newPath = newPath.substr(0, commaPos);
+
+ if (orig != newPath)
+ debugC(2, kDebugFileIO, "Inter_Playtoons::getFile(): Evaluating path"
+ "\"%s\" to \"%s\"", orig, path);
+
+ return newPath;
+}
+
void Inter_v6::o6_totSub() {
uint8 length = _vm->_game->_script->readByte();
if ((length & 0x7F) > 13)
@@ -85,7 +128,53 @@ void Inter_v6::o6_totSub() {
uint8 flags = _vm->_game->_script->readByte();
if (flags & 0x40) {
- warning("STUB: o6_totSub(), flags & 0x40: starting external program: %s (flags = %X)", totFile.c_str(), flags);
+ // The original engine would start an external program here. The only known use at the time of writing is for
+ // starting a game in the Adi4 gamebox collection.
+ // We emulate it by lanching the ScummVM target whose path matches the external program's directory, if any.
+ // This target must have been added in ScummVM beforehand.
+ Common::Path currentPath = ConfMan.getPath("path");
+ Common::Path programPath(getFile(totFile.c_str(), false), '\\');
+ Common::Path programDirFullPath = currentPath / programPath.getParent();
+ programDirFullPath = programDirFullPath.normalize();
+ Common::String target;
+
+ for (auto iter = ConfMan.beginGameDomains(); iter != ConfMan.endGameDomains(); ++iter) {
+ Common::ConfigManager::Domain &dom = iter->_value;
+ Common::Path targetPath = Common::Path::fromConfig(dom.getVal("path"));
+ targetPath = targetPath.normalize();
+
+ if (targetPath.equalsIgnoreCase(programDirFullPath)) {
+ target = iter->_key;
+ break;
+ }
+ }
+
+ if (target.empty()) {
+ warning("o6_totSub(): Could not find any matching ScummVM target for external program \"%s\"", programPath.toString().c_str());
+ return;
+ }
+
+ debugC(1, kDebugGameFlow, "o6_totSub(): Launching ScummVM target \"%s\" to substitute for external program \"%s\"",
+ target.c_str(),
+ programPath.toString().c_str());
+
+ ChainedGamesMan.push(target);
+ ChainedGamesMan.push(ConfMan.getActiveDomainName(), 100);
+
+ if (_vm->getGameType() == kGameTypeAdi4) {
+ // Save all current game variables in a fictive save file.
+ // Although it is generally not possible to create a snapshot of an arbitrary engine state in Gob,
+ // just saving the current game variables is sufficient here to be able to restore most the engine
+ // state after restarting it through ChainedGamesMan. One simplifying factor is that this opcode
+ // is called from the top-level script.
+ _vm->_saveLoad->save("RETURN_FROM_GAMEBOX", 0, 0, 0);
+ }
+
+ // Force a return to the launcher. This will start the first chained game.
+ Common::EventManager *eventMan = g_system->getEventManager();
+ Common::Event event;
+ event.type = Common::EVENT_RETURN_TO_LAUNCHER;
+ eventMan->pushEvent(event);
} else {
_vm->_game->totSub(flags, totFile);
}
diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp
index ed332185011..6199408e17f 100644
--- a/engines/gob/inter_v7.cpp
+++ b/engines/gob/inter_v7.cpp
@@ -473,6 +473,21 @@ void Inter_v7::o7_deleteFile() {
Common::Path file(_vm->_game->_script->evalString(), '\\');
debugC(2, kDebugFileIO, "Delete file \"%s\"", file.toString().c_str());
+ if (_vm->getGameType() == kGameTypeAdi4 && ConfMan.hasKey("save_slot") && (file == "TEMP" || file.toString().hasSuffix(".DEP"))) {
+ // HACK to prevent reseting some temporary files when returning from Adi4 game box through ChainedGamesManager
+ debugC(2, kDebugFileIO, "o7_deleteFile: skipping deletion of %s when returning from Adi4 game box", file.toString().c_str());
+ if (file == "PAROLE.DEP") {
+ // Last file whose deletion should be skipped when returning from Adi4 game box
+ // Restore the saved state and continue normally
+ _vm->_saveLoad->load("RETURN_FROM_GAMEBOX", 0, 0, 0);
+ ConfMan.removeKey("save_slot", Common::ConfigManager::kTransientDomain);
+ }
+
+ return;
+ }
+
+ if (_vm->getGameType() == kGameTypeAdi4 && file == "TEMP")
+ file /= "*"; // WORKAROUND: This file is actually a directory, and we only support deleting their content using patterns
bool isPattern = file.toString().contains('*') || file.toString().contains('?');
Common::List<Common::Path> files;
@@ -664,6 +679,12 @@ void Inter_v7::o7_playVmdOrMusic() {
props.startFrame = -2;
}
+ if (_vm->getGameType() == kGameTypeAdi4 && ConfMan.hasKey("save_slot") && file == "INTRO") {
+ // HACK to simulate returning from Adi4 game box seamlessly, after relaunching it through ChainedGamesManager
+ debugC(2, kDebugVideo, "o7_playVmdOrMusic: skipping INTRO when returning from Adi4 game box");
+ return;
+ }
+
debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
"paletteCmd %d (%d - %d), flags %X", file.c_str(),
props.x, props.y, props.startFrame, props.lastFrame,
diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h
index c4e450c8488..f0bfb9a683c 100644
--- a/engines/gob/save/saveload.h
+++ b/engines/gob/save/saveload.h
@@ -982,11 +982,11 @@ public:
static const uint32 kAdibou2NbrOfSavedDrawings = 12;
static const uint32 kAdibou2NbrOfConstructionGameFiles = 3;
- static const uint32 kAdi4NbrOfTempFiles = 9;
+ static const uint32 kAdi4NbrOfTempFiles = 3;
static const uint32 kAdi4NbrOfApplications = 2; // Only Math/Language for now
static const uint32 kAdi4NbrOfSchoolYears = 8;
- // 4 isolated files, 1 "config" and "statv" file per child, 1 "dip" and "res" file per app x school year x child
- static const uint32 kAdi4NbrOfGameFiles = 4 + 2 * kChildrenCount + 2 * kAdi4NbrOfApplications * kAdi4NbrOfSchoolYears * kChildrenCount;
+ // 12 isolated files, 1 "config" and "statv" file per child, 1 "dip" and "res" file per app x school year x child
+ static const uint32 kAdi4NbrOfGameFiles = 12 + 2 * kChildrenCount + 2 * kAdi4NbrOfApplications * kAdi4NbrOfSchoolYears * kChildrenCount;
SaveLoad_v7(GobEngine *vm, const char *targetName);
~SaveLoad_v7() override;
diff --git a/engines/gob/save/saveload_v7.cpp b/engines/gob/save/saveload_v7.cpp
index dfa11eef9e8..00420064ced 100644
--- a/engines/gob/save/saveload_v7.cpp
+++ b/engines/gob/save/saveload_v7.cpp
@@ -938,18 +938,20 @@ SaveLoad_v7::SaveFile SaveLoad_v7::_saveFiles[] = {
{"APPLIS/appli_07.ini", kSaveModeSave, nullptr, "app info" },
// Adi 4
- // Temporary ancillary files
- {"DATA/premier.dep", kSaveModeSave, nullptr, nullptr},
- {"DATA/quitter.dep", kSaveModeSave, nullptr, nullptr},
- {"DATA/appel.dep", kSaveModeSave, nullptr, nullptr},
- {"DATA/parole.dep", kSaveModeSave, nullptr, nullptr},
- {"DATA/perso.dep", kSaveModeSave, nullptr, nullptr},
- {"DATA/nouveau.dep", kSaveModeSave, nullptr, nullptr},
+ // Temporary ancillary files,
{"DATA/iduser.tmp", kSaveModeSave, nullptr, nullptr},
{"adi.tmp", kSaveModeSave, nullptr, nullptr},
{"adi4.tmp", kSaveModeSave, nullptr, nullptr},
// Persitent files
+ {"RETURN_FROM_GAMEBOX", kSaveModeSave, nullptr, nullptr}, // Fictive file used to simulate returning from Gamebox in ScummVM
+ {"TEMP/ADI4.PHO", kSaveModeSave, nullptr, nullptr},
+ {"perso.dep", kSaveModeSave, nullptr, nullptr},
+ {"premier.dep", kSaveModeSave, nullptr, nullptr},
+ {"quitter.dep", kSaveModeSave, nullptr, nullptr},
+ {"appel.dep", kSaveModeSave, nullptr, nullptr},
+ {"parole.dep", kSaveModeSave, nullptr, nullptr},
+ {"nouveau.dep", kSaveModeSave, nullptr, nullptr},
{"DATA/iduser.inf", kSaveModeSave, nullptr, nullptr},
{"adi.inf", kSaveModeSave, nullptr, nullptr},
{"DATA/ado4.inf", kSaveModeSave, nullptr, nullptr},
@@ -2102,6 +2104,33 @@ SaveLoad_v7::SaveLoad_v7(GobEngine *vm, const char *targetName) :
}
int indexAdi4file = 0;
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "scummvm_autosave");
+
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "adi4_pho");
+
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "perso_dep");
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "premier_dep");
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "quitter_dep");
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "appel_dep");
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "parole_dep");
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "nouveau_dep");
+
_saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
targetName,
"id_user");
Commit: 7b0bce150b832d49dc155c03e5836d5f02c66cb9
https://github.com/scummvm/scummvm/commit/7b0bce150b832d49dc155c03e5836d5f02c66cb9
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-02-14T15:19:15+01:00
Commit Message:
GOB: Add "adi.bis" to Adi4 save files and rename some save files
Changed paths:
engines/gob/save/saveload.h
engines/gob/save/saveload_v7.cpp
diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h
index f0bfb9a683c..5677c1638d8 100644
--- a/engines/gob/save/saveload.h
+++ b/engines/gob/save/saveload.h
@@ -985,8 +985,8 @@ public:
static const uint32 kAdi4NbrOfTempFiles = 3;
static const uint32 kAdi4NbrOfApplications = 2; // Only Math/Language for now
static const uint32 kAdi4NbrOfSchoolYears = 8;
- // 12 isolated files, 1 "config" and "statv" file per child, 1 "dip" and "res" file per app x school year x child
- static const uint32 kAdi4NbrOfGameFiles = 12 + 2 * kChildrenCount + 2 * kAdi4NbrOfApplications * kAdi4NbrOfSchoolYears * kChildrenCount;
+ // 13 isolated files, 1 "config" and "statv" file per child, 1 "dip" and "res" file per app x school year x child
+ static const uint32 kAdi4NbrOfGameFiles = 13 + 2 * kChildrenCount + 2 * kAdi4NbrOfApplications * kAdi4NbrOfSchoolYears * kChildrenCount;
SaveLoad_v7(GobEngine *vm, const char *targetName);
~SaveLoad_v7() override;
diff --git a/engines/gob/save/saveload_v7.cpp b/engines/gob/save/saveload_v7.cpp
index 00420064ced..86c3ead50a9 100644
--- a/engines/gob/save/saveload_v7.cpp
+++ b/engines/gob/save/saveload_v7.cpp
@@ -954,6 +954,7 @@ SaveLoad_v7::SaveFile SaveLoad_v7::_saveFiles[] = {
{"nouveau.dep", kSaveModeSave, nullptr, nullptr},
{"DATA/iduser.inf", kSaveModeSave, nullptr, nullptr},
{"adi.inf", kSaveModeSave, nullptr, nullptr},
+ {"adi.bis", kSaveModeSave, nullptr, nullptr},
{"DATA/ado4.inf", kSaveModeSave, nullptr, nullptr},
{"DATA/mcurrent.inf", kSaveModeSave, nullptr, nullptr},
@@ -2137,15 +2138,19 @@ SaveLoad_v7::SaveLoad_v7(GobEngine *vm, const char *targetName) :
_saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
targetName,
- "adi");
+ "adi_inf");
_saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
targetName,
- "ado4");
+ "adi_bis");
_saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
targetName,
- "mcurrent");
+ "ado4_inf");
+
+ _saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
+ targetName,
+ "mcurrent_inf");
for (uint32 i = 0; i < kChildrenCount; i++) {
_saveFiles[index++].handler = _adi4GameFileHandler[indexAdi4file++] = new GameFileHandler(_vm,
Commit: 1e33ffdae0ff77f875611cb8f2e2253c300e5d56
https://github.com/scummvm/scummvm/commit/1e33ffdae0ff77f875611cb8f2e2253c300e5d56
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-02-14T15:19:30+01:00
Commit Message:
GOB: Allow to create a new save file on a write at offset > 0
Might happen in some Adi4 edge cases
Changed paths:
engines/gob/save/saveload_v7.cpp
diff --git a/engines/gob/save/saveload_v7.cpp b/engines/gob/save/saveload_v7.cpp
index 86c3ead50a9..d50059ab699 100644
--- a/engines/gob/save/saveload_v7.cpp
+++ b/engines/gob/save/saveload_v7.cpp
@@ -1841,9 +1841,9 @@ bool SaveLoad_v7::GameFileHandler::save(const byte *ptrRaw, int16 dataVar, int32
}
int32 fileSize = getSize();
- int32 newFileSize = size;
- if (fileSize > 0) {
- newFileSize = MAX<int32>(fileSize, size + offset);
+ int32 newFileSize = size + offset;
+ if (fileSize > newFileSize) {
+ newFileSize = fileSize;
}
SavePartVars vars(_vm, newFileSize);
Commit: ab277297ab124ea8ff2b306fb43287c464c6feff
https://github.com/scummvm/scummvm/commit/ab277297ab124ea8ff2b306fb43287c464c6feff
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-02-14T15:20:27+01:00
Commit Message:
GOB: Increase again the (fake) amount of memory returned by o7_getSystemProperty("TotalPhys")
This unlocks some animations in Adi4
Changed paths:
engines/gob/inter_v7.cpp
diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp
index 6199408e17f..3ab24c46c6f 100644
--- a/engines/gob/inter_v7.cpp
+++ b/engines/gob/inter_v7.cpp
@@ -936,13 +936,14 @@ void Inter_v7::o7_getSystemProperty() {
if (!scumm_stricmp(property, "TotalPhys")) {
// HACK
// NOTE: Any value lower than 8 MB will disable the icon bar animations in Adibou2/Sciences
- storeValue(16000000);
+ // NOTE: Any value lower than or equal to 16 MB will disable some animations in Adi4 (e.g. clouds in Adi's room).
+ storeValue(32000000);
return;
}
if (!scumm_stricmp(property, "AvailPhys")) {
// HACK
- storeValue(16000000);
+ storeValue(32000000);
return;
}
Commit: 34e11c617489c396d591861eb0999c969b956bee
https://github.com/scummvm/scummvm/commit/34e11c617489c396d591861eb0999c969b956bee
Author: Simon Delamarre (simon.delamarre14 at gmail.com)
Date: 2026-02-14T15:37:46+01:00
Commit Message:
GOB: More "live" videos improvements (Adi4)
It seems that our former updateLive() function can be called on non-live
videos sometimes, rename it "updateVideos".
The "live" videos are actually advanced by another specific function
("liveVideosLoop"), called in many places in the engine (including in
"upateVideos" itself).
This fixes sound glitches in Adi4, when Adi is talking for a long time.
Changed paths:
engines/gob/draw.cpp
engines/gob/game.cpp
engines/gob/inter.cpp
engines/gob/inter_v1.cpp
engines/gob/inter_v2.cpp
engines/gob/util.cpp
engines/gob/videoplayer.cpp
engines/gob/videoplayer.h
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index fd306ea6b5f..8a39de94b4e 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -240,6 +240,8 @@ void Draw::blitInvalidated() {
((_vm->_global->_videoMode == 5) || (_vm->_global->_videoMode == 7)))
return;
+ _vm->_vidPlayer->liveVideosLoop();
+
if (_cursorIndex == 4)
blitCursor();
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index ea626ce1551..36fee251a0b 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -847,7 +847,7 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
MouseButtons *pButtons, char handleMouse) {
if (_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4)
- _vm->_vidPlayer->updateLive();
+ _vm->_vidPlayer->updateVideos();
_vm->_util->processInput(true);
if (_vm->_mult->_multData && _vm->_inter->_variables &&
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 5d00b4ec444..e6aec51d4f6 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -237,6 +237,8 @@ void Inter::funcBlock(int16 retFlag) {
if (_vm->_game->_script->isFinished())
return;
+ _vm->_vidPlayer->liveVideosLoop();
+
_break = false;
_vm->_game->_script->skip(1);
params.cmdCount = _vm->_game->_script->readByte();
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index b3c316992b4..b3d21aa2dac 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1432,7 +1432,7 @@ void Inter_v1::o1_keyFunc(OpFuncParams ¶ms) {
if (_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4) {
// The engine calls updateLive() every 100ms while waiting there
while (cmd > 100) {
- _vm->_vidPlayer->updateLive();
+ _vm->_vidPlayer->updateVideos();
_vm->_util->longDelay(100);
cmd -= 100;
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index ae5f9805b3a..eaa61e211f5 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1418,6 +1418,7 @@ void Inter_v2::o2_goblinFunc(OpFuncParams ¶ms) {
int16 cmd;
cmd = _vm->_game->_script->readInt16();
+ _vm->_vidPlayer->liveVideosLoop();
gobParams.paramCount = _vm->_game->_script->readInt16();
gobParams.extraData = cmd;
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 1014f4e0a67..9fe84a11d7a 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -102,7 +102,7 @@ void Util::processInput(bool scroll) {
bool hasMove = false;
if (_vm->getGameType() != kGameTypeAdibou2 && _vm->getGameType() != kGameTypeAdi4)
- _vm->_vidPlayer->updateLive();
+ _vm->_vidPlayer->updateVideos();
while (eventMan->pollEvent(event)) {
switch (event.type) {
@@ -475,6 +475,9 @@ void Util::waitEndFrame(bool handleInput) {
if (handleInput)
processInput();
+ if (_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4)
+ _vm->_vidPlayer->updateVideos();
+
_vm->_video->retrace();
time = getTimeKey() - _startFrameTime;
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index 6669af17bb1..5a5346efb12 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -76,7 +76,7 @@ void VideoPlayer::Video::close() {
const char *const VideoPlayer::_extensions[] = { "IMD", "IMD", "VMD", "RMD", "SMD" };
VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm), _needBlit(false),
- _noCursorSwitch(false), _woodruffCohCottWorkaround(false) {
+ _noCursorSwitch(false), _woodruffCohCottWorkaround(false), _lastLiveVideosLoopCall(0) {
}
VideoPlayer::~VideoPlayer() {
@@ -433,7 +433,7 @@ bool VideoPlayer::play(int slot, Properties &properties) {
if (_vm->getGameType() != kGameTypeAdibou2 &&
_vm->getGameType() != kGameTypeAdi4) {
- updateLive(slot, true);
+ updateVideo(slot, true);
return true;
}
}
@@ -529,29 +529,55 @@ bool VideoPlayer::isSoundPlaying() const {
return video && video->decoder && video->decoder->isSoundPlaying();
}
-void VideoPlayer::updateLive(bool force, int exceptSlot) {
+void VideoPlayer::liveVideosLoop() {
+ if (_vm->getGameType() != kGameTypeAdibou2 && _vm->getGameType() != kGameTypeAdi4)
+ return;
+
+ uint32 timeKey = _vm->_util->getTimeKey();
+ if (timeKey - _lastLiveVideosLoopCall < 2)
+ return;
+
+ _lastLiveVideosLoopCall = timeKey;
+
+ for (int slot = 0; slot < kLiveVideoSlotCount; slot++) {
+ Video *video = getVideoBySlot(slot);
+ if (video && video->live) {
+ video->properties.startFrame = video->decoder->getCurFrame() + video->decoder->getNbFramesPastEnd();
+ playFrame(slot, video->properties);
+ }
+ }
+}
+
+void VideoPlayer::updateVideos(bool force, int exceptSlot) {
+ liveVideosLoop();
+
int nbrOfSlots = (_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4) ?
kLiveVideoSlotCount : kVideoSlotCount;
for (int i = 0; i < nbrOfSlots; i++) {
if ((_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4) &&
i >= 0 &&
- i < kVideoSlotWithCurFrameVarCount)
+ i < kVideoSlotWithCurFrameVarCount) {
WRITE_VAR(53 + i, (uint32)-1);
+ Video *video = getVideoBySlot(i);
+ if (video) {
+ WRITE_VAR(53 + i, video->decoder->getCurFrame() + video->decoder->getNbFramesPastEnd());
+ }
+ }
+
if (i != exceptSlot)
- updateLive(i, force);
+ updateVideo(i, force);
}
}
-void VideoPlayer::updateLive(int slot, bool force) {
+void VideoPlayer::updateVideo(int slot, bool force) {
Video *video = getVideoBySlot(slot);
- if (!video || !video->live)
+ if (!video)
return;
- if ((_vm->getGameType() == kGameTypeAdibou2 || _vm->getGameType() == kGameTypeAdi4)
- && slot < kVideoSlotWithCurFrameVarCount)
- WRITE_VAR(53 + slot, video->decoder->getCurFrame() + video->decoder->getNbFramesPastEnd());
+ if (!video->live && _vm->getGameType() != kGameTypeAdibou2 && _vm->getGameType() != kGameTypeAdi4)
+ return;
int nbrOfLiveVideos = 0;
for (int i = 0; i < kVideoSlotCount; i++) {
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
index e4165b5547a..e164487c31c 100644
--- a/engines/gob/videoplayer.h
+++ b/engines/gob/videoplayer.h
@@ -139,7 +139,8 @@ public:
bool isPlayingLive() const;
bool isSoundPlaying() const;
- void updateLive(bool force = false, int exceptSlot = -1);
+ void updateVideos(bool force = false, int exceptSlot = -1);
+ void liveVideosLoop();
bool slotIsOpen(int slot = 0) const;
@@ -208,6 +209,8 @@ private:
bool _noCursorSwitch;
bool _woodruffCohCottWorkaround;
+ uint32 _lastLiveVideosLoopCall;
+
const Video *getVideoBySlot(int slot) const;
Video *getVideoBySlot(int slot);
@@ -228,7 +231,7 @@ private:
void copyPalette(const Video &video, int16 palStart, int16 palEnd);
- void updateLive(int slot, bool force = false);
+ void updateVideo(int slot, bool force = false);
};
} // End of namespace Gob
More information about the Scummvm-git-logs
mailing list