[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