[Scummvm-git-logs] scummvm master -> 039395f0e624792fad2ea283c45e76aaf4ca6ca3
sev-
noreply at scummvm.org
Wed Jul 15 21:30:41 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
039395f0e6 SCUMM: Implemennt ability to replace local scripts with external files
Commit: 039395f0e624792fad2ea283c45e76aaf4ca6ca3
https://github.com/scummvm/scummvm/commit/039395f0e624792fad2ea283c45e76aaf4ca6ca3
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2026-07-15T23:30:19+02:00
Commit Message:
SCUMM: Implemennt ability to replace local scripts with external files
Also comes with fixes from Bosca
Changed paths:
engines/scumm/resource.cpp
engines/scumm/room.cpp
engines/scumm/script.cpp
engines/scumm/scumm.cpp
engines/scumm/scumm.h
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index a02c0a0d252..ccffb701fa5 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -644,6 +644,34 @@ void ScummEngine::ensureResourceLoaded(ResType type, ResId idx) {
VAR(VAR_ROOM_FLAG) = 1;
}
+void ScummEngine::scriptOverride(ResId room, int script) {
+ if (_game.id != GID_BASEBALL2001)
+ return;
+
+ Common::String scriptName;
+
+ if (script == -1)
+ scriptName = Common::String::format("entry-%d.scr", room);
+ else if (script == -2)
+ scriptName = Common::String::format("exit-%d.scr", room);
+ else
+ scriptName = Common::String::format("room-%d-%d.scr", room, script);
+
+ Common::Path resFilename = Common::Path(scriptName);
+ if (Common::File::exists(resFilename)) {
+ Common::File resFile;
+ if (resFile.open(resFilename)) {
+ int size = resFile.size();
+
+ byte *data1 = (byte *)malloc(size);
+ resFile.read(data1, size);
+ debug(1, "scriptOverride(): script loaded from file %s", resFilename.toString().c_str());
+
+ _scriptOverrides[room * 100000 + script] = data1;
+ }
+ }
+}
+
int ScummEngine::loadResource(ResType type, ResId idx) {
int roomNr;
uint32 fileOffs;
diff --git a/engines/scumm/room.cpp b/engines/scumm/room.cpp
index 2b29cdf4df1..9145b896078 100644
--- a/engines/scumm/room.cpp
+++ b/engines/scumm/room.cpp
@@ -363,8 +363,10 @@ void ScummEngine::setupRoomSubBlocks() {
// Look for an exit script
//
ptr = findResourceData(MKTAG('E','X','C','D'), roomResPtr);
- if (ptr)
+ if (ptr) {
_EXCD_offs = ptr - roomResPtr;
+ scriptOverride(_roomResource, -2);
+ }
if (_dumpScripts && _EXCD_offs)
dumpResource("exit-", _roomResource, roomResPtr + _EXCD_offs - _resourceHeaderSize, -1);
@@ -372,8 +374,10 @@ void ScummEngine::setupRoomSubBlocks() {
// Look for an entry script
//
ptr = findResourceData(MKTAG('E','N','C','D'), roomResPtr);
- if (ptr)
+ if (ptr) {
_ENCD_offs = ptr - roomResPtr;
+ scriptOverride(_roomResource, -1);
+ }
if (_dumpScripts && _ENCD_offs)
dumpResource("entry-", _roomResource, roomResPtr + _ENCD_offs - _resourceHeaderSize, -1);
@@ -414,7 +418,9 @@ void ScummEngine::setupRoomSubBlocks() {
id = READ_LE_UINT32(ptr);
assertRange(_numGlobalScripts, id, _numLocalScripts + _numGlobalScripts, "local script");
+
_localScriptOffsets[id - _numGlobalScripts] = ptr + 4 - roomResPtr;
+ scriptOverride(_roomResource, id);
if (_dumpScripts) {
char buf[32];
@@ -431,6 +437,7 @@ void ScummEngine::setupRoomSubBlocks() {
id = ptr[0];
_localScriptOffsets[id - _numGlobalScripts] = ptr + 1 - roomResPtr;
+ scriptOverride(_roomResource, id);
if (_dumpScripts) {
char buf[32];
@@ -630,7 +637,7 @@ void ScummEngine::resetRoomSubBlocks() {
// We need to setup the current palette before initCycl for Indy4 Amiga.
if (_PALS_offs || _CLUT_offs)
setCurrentPalette(0);
-
+
if (_game.id == GID_TENTACLE && VAR(VAR_VIDEOMODE) == 13) {
// This is a hack to avoid color glitches caused by incomplete EGA mode handling in the scripts.
// The original DOTT interpreter (executable and scripts) has various EGA mode handling leftovers
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index ff91a786ec1..0791f4bd19f 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -79,6 +79,8 @@ void ScummEngine::runScript(int script, bool freezeResistant, bool recursive, in
scriptOffs = _localScriptOffsets[script - _numGlobalScripts];
if (scriptOffs == 0)
error("Local script %d is not in room %d", script, _roomResource);
+ if (_scriptOverrides.contains(_roomResource * 100000 + script))
+ scriptOffs = 0;
scriptType = WIO_LOCAL;
debugC(DEBUG_SCRIPTS, "runScript(%d) from %d-%d", script,
@@ -441,6 +443,13 @@ void ScummEngine::getScriptBaseAddress() {
_scriptOrgPointer = getResourceAddress(rtRoom, _roomResource);
assert(_roomResource < _numRooms);
_lastCodePtr = &_res->_types[rtRoom][_roomResource]._address;
+
+ int cacheIdx = _roomResource * 100000 + ss->number;
+ if (_scriptOverrides.contains(cacheIdx)) {
+ _lastCodePtr = (const byte *const *)_scriptOverrides[cacheIdx];
+ // LSC2 block layout: [4 tag][4 BE size][4 LE script id][bytecode]
+ _scriptOrgPointer = (const byte *)_scriptOverrides[cacheIdx] + _resourceHeaderSize + 4;
+ }
}
break;
@@ -505,7 +514,7 @@ void ScummEngine::executeScript() {
_opcode = fetchScriptByte();
if (_game.version > 2) // V0-V2 games didn't use the didexec flag
vm.slot[_currentScript].didexec = true;
- debugC(DEBUG_OPCODES, "Script %d, offset 0x%x: [%X] %s()",
+ debugC(DEBUG_OPCODES, "Script %d, offset 0x%x: [%X] %s()",
vm.slot[_currentScript].number,
(uint)(_scriptPointer - _scriptOrgPointer),
_opcode,
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 0c246907ee2..98ecc12e0b7 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -536,6 +536,9 @@ ScummEngine::~ScummEngine() {
delete _macGui;
+ for (auto &it : _scriptOverrides)
+ delete it._value;
+
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
delete _townsScreen;
#ifdef USE_RGB_COLOR
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index ae7b4bb7cd1..9864f7e95eb 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -890,12 +890,12 @@ public:
byte _sputmCmdEnterCount = 0;
Common::String _sputmCmdBuf;
Common::String _name;
-
+
void reset();
bool tryLoadPlayback(ScummEngine *engine, const Common::Path &path = Common::Path("demo.rec"));
bool startPlayback(ScummEngine *engine);
void playbackPump(ScummEngine *engine);
-
+
//MI2 DOS NI Demo specific playback helpers
void mi2DemoArmPlaybackByRoom(ScummEngine *engine);
void mi2DemoPlaybackJumpRoom(ScummEngine *engine, int room);
@@ -1042,6 +1042,7 @@ protected:
/* Script VM - should be in Script class */
uint32 _localScriptOffsets[1024];
+ Common::HashMap<int, byte *> _scriptOverrides;
const byte *_scriptPointer = nullptr;
const byte *_scriptOrgPointer = nullptr;
const byte * const *_lastCodePtr = nullptr;
@@ -1171,6 +1172,8 @@ protected:
int getResourceRoomNr(ResType type, ResId idx);
virtual uint32 getResourceRoomOffset(ResType type, ResId idx);
+ void scriptOverride(ResId room, int script);
+
public:
int getResourceSize(ResType type, ResId idx);
byte *getResourceAddress(ResType type, ResId idx);
@@ -1736,7 +1739,7 @@ protected:
void wrapSegaCDText();
void debugMessage(const byte *msg);
virtual void showMessageDialog(const byte *msg);
-
+
#ifdef USE_TTS
void sayText(const Common::String &text, Common::TextToSpeechManager::Action action = Common::TextToSpeechManager::QUEUE) const;
void stopTextToSpeech() const;
More information about the Scummvm-git-logs
mailing list