[Scummvm-git-logs] scummvm master -> 3c18f3e9c2ce366722313d146f7778fb1f8bd1ac

whoozle noreply at scummvm.org
Sun Jul 19 23:03:36 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:
3c18f3e9c2 AGDS: Add all currently available steam releases of Black Mirror


Commit: 3c18f3e9c2ce366722313d146f7778fb1f8bd1ac
    https://github.com/scummvm/scummvm/commit/3c18f3e9c2ce366722313d146f7778fb1f8bd1ac
Author: Vladimir Menshakov (vladimir.menshakov at gmail.com)
Date: 2026-07-20T00:03:03+01:00

Commit Message:
AGDS: Add all currently available steam releases of Black Mirror

Add Czech, German, Spanish, French, Italian, Polish, Russian steam releases.
Polish opcodes don't clearly match to the English version, mark it as unsupported.

Changed paths:
    engines/agds/agds.cpp
    engines/agds/agds.h
    engines/agds/detection.h
    engines/agds/detection_tables.h
    engines/agds/object.cpp
    engines/agds/process.cpp
    engines/agds/process.h
    engines/agds/process_opcodes.cpp
    engines/agds/resourceManager.cpp


diff --git a/engines/agds/agds.cpp b/engines/agds/agds.cpp
index 4634733efd5..20b6f31445e 100644
--- a/engines/agds/agds.cpp
+++ b/engines/agds/agds.cpp
@@ -73,6 +73,7 @@ AGDSEngine::AGDSEngine(OSystem *system, const ADGameDescription *gameDesc) : Eng
 																			 _curtainScreen(0),
 																			 _fastMode(true),
 																			 _hintMode(false) {
+	debug("agds engine version %d", version());
 }
 
 AGDSEngine::~AGDSEngine() {
@@ -250,7 +251,7 @@ void AGDSEngine::runProcess(const ObjectPtr &object, uint ip) {
 			return;
 		}
 		if (!process) {
-			process = ProcessPtr(new Process(this, object, ip, version()));
+			process = ProcessPtr(new Process(this, object, ip, version(), language()));
 			process->run();
 			return;
 		}
@@ -866,7 +867,7 @@ AnimationPtr AGDSEngine::loadAnimation(const Common::String &name) {
 	debug("loadAnimation %s", name.c_str());
 
 	Common::SharedPtr<Animation> animation(new Animation(this, name));
-	if (v2()) {
+	if (versionAtLeast(kAGDSVersionNibiru2511)) {
 		debug("v2 stub");
 		return animation;
 	}
@@ -894,7 +895,7 @@ void AGDSEngine::loadCharacter(const Common::String &id, const Common::String &f
 
 	_currentCharacter.reset(new Character(this, id));
 	auto resName = loadText(filename);
-	if (v2()) {
+	if (versionAtLeast(kAGDSVersionNibiru2511)) {
 		debug("character resource name: %s, stub\n", resName.c_str());
 		_currentCharacter->associate(object);
 		return;
@@ -928,7 +929,7 @@ Graphics::ManagedSurface *AGDSEngine::loadFromCache(int id) const {
 }
 
 void AGDSEngine::loadFont(int id, const Common::String &name, int gw, int gh) {
-	if (v2()) {
+	if (versionAtLeast(kAGDSVersionNibiru2511)) {
 		debug("loadTTF %d %s, pixelSize: %d", id, name.c_str(), gh);
 #ifdef USE_FREETYPE2
 		_fonts[id].reset(Graphics::loadTTFFontFromArchive(name, gh));
@@ -1444,16 +1445,22 @@ int AGDSEngine::getRandomNumber(int max) {
 	return max > 0 ? _random.getRandomNumber(max - 1) : 0;
 }
 
-bool AGDSEngine::v2() const {
-	return _gameDescription->flags & AGDS_V2;
-}
-
 int AGDSEngine::version() const {
 	if (_gameDescription->flags & ADGF_DEMO)
-		return 0;
-	if (v2())
-		return 2;
-	return 1;
+		return kAGDSVersionDemo2283;
+	if (_gameDescription->flags & AGDS_2299)
+		return kAGDSVersionBlackMirror2299;
+	if (_gameDescription->flags & AGDS_2511)
+		return kAGDSVersionNibiru2511;
+	return kAGDSVersionBlackMirror2296;
+}
+
+bool AGDSEngine::versionAtLeast(int target) const {
+	return version() >= target;
+}
+
+Common::Language AGDSEngine::language() const {
+	return _gameDescription->language;
 }
 
 } // End of namespace AGDS
diff --git a/engines/agds/agds.h b/engines/agds/agds.h
index 1730e27256d..b2d44c4b96f 100644
--- a/engines/agds/agds.h
+++ b/engines/agds/agds.h
@@ -23,6 +23,7 @@
 #define AGDS_H
 
 #include "agds/database.h"
+#include "agds/detection.h"
 #include "agds/dialog.h"
 #include "agds/inventory.h"
 #include "agds/mouseMap.h"
@@ -281,8 +282,9 @@ public:
 		return _curtainTimer >= 0;
 	}
 
-	bool v2() const;
 	int version() const;
+	bool versionAtLeast(int target) const;
+	Common::Language language() const;
 
 private:
 	void stopAmbientSound();
diff --git a/engines/agds/detection.h b/engines/agds/detection.h
index 740bf9192e5..eeeb984e79a 100644
--- a/engines/agds/detection.h
+++ b/engines/agds/detection.h
@@ -25,9 +25,15 @@
 namespace AGDS {
 
 enum AGDSGameFlag {
-	AGDS_V2 = (1 << 0),
+	AGDS_2511 = (1 << 0),
+	AGDS_2299 = (1 << 1),
 };
 
+static constexpr int kAGDSVersionDemo2283 = 2283;
+static constexpr int kAGDSVersionBlackMirror2296 = 2296;
+static constexpr int kAGDSVersionBlackMirror2299 = 2299;
+static constexpr int kAGDSVersionNibiru2511 = 2511;
+
 } // End of namespace AGDS
 
 #endif // DETECTION_H
diff --git a/engines/agds/detection_tables.h b/engines/agds/detection_tables.h
index 61e97506ecd..831af574ebe 100644
--- a/engines/agds/detection_tables.h
+++ b/engines/agds/detection_tables.h
@@ -24,19 +24,90 @@
 
 namespace AGDS {
 
+// clang-format off
+
 static const ADGameDescription gameDescriptions[] = {
 
 	// Black Mirror
 	{
 		"black-mirror",
-		0,
+		"Steam release",
 		AD_ENTRY2s(
 			"gfx1.grp", "6665ce103cf12a362fd55f863d1ec9e6", 907820240,
 			"data.adb", "3b2d85f16e24ac81c4ede7a1da55f786", 2169482),
 		Common::EN_USA,
 		Common::kPlatformWindows,
-		ADGF_DROPPLATFORM,
+		ADGF_DROPPLATFORM | ADGF_UNSTABLE,
+		GUIO1(GUIO_NONE)},
+	{
+		"black-mirror",
+		"Steam release",
+		AD_ENTRY2s(
+			"gfx1.grp", "8b26006aba4fd22a717fab88a04f78dd", 902508242,
+			"data.adb", "e383a1bb8f415d94ae84076fd1c8a8bf", 2130335),
+		Common::CS_CZE,
+		Common::kPlatformWindows,
+		ADGF_DROPPLATFORM | AGDS_2299 | ADGF_UNSTABLE,
+		GUIO1(GUIO_NONE)},
+	{
+		"black-mirror",
+		"Steam release",
+		AD_ENTRY2s(
+			"gfx1.grp", "a5f84365d1e15a8403237fa3ad339f86", 850840170,
+			"data.adb", "3214d9a1c07df367903e74dc12165d3e", 2181787),
+		Common::DE_DEU,
+		Common::kPlatformWindows,
+		ADGF_DROPPLATFORM | AGDS_2299 | ADGF_UNSTABLE,
+		GUIO1(GUIO_NONE)},
+	{
+		"black-mirror",
+		"Steam release",
+		AD_ENTRY2s(
+			"gfx1.grp", "be3ab3bce4a7740d2d544050c4f29b13", 913426990,
+			"data.adb", "467e6ea3b22e06d879d77d6b9c609ef6", 2180501),
+		Common::ES_ESP,
+		Common::kPlatformWindows,
+		ADGF_DROPPLATFORM | AGDS_2299 | ADGF_UNSTABLE,
+		GUIO1(GUIO_NONE)},
+	{
+		"black-mirror",
+		"Steam release",
+		AD_ENTRY2s(
+			"gfx1.grp", "2ede03d9a50e0bfedd0d7656c47d2de4", 913209074,
+			"data.adb", "cffd38b88a245765987f9ff5cce3c5c9", 2184448),
+		Common::FR_FRA,
+		Common::kPlatformWindows,
+		ADGF_DROPPLATFORM | AGDS_2299 | ADGF_UNSTABLE,
+		GUIO1(GUIO_NONE)},
+	{
+		"black-mirror",
+		"Steam release",
+		AD_ENTRY2s(
+			"gfx1.grp", "a5f84365d1e15a8403237fa3ad339f86", 850840170,
+			"data.adb", "fa24ab2fe18621d73a45af53e36c78f0", 2178282),
+		Common::IT_ITA,
+		Common::kPlatformWindows,
+		ADGF_DROPPLATFORM | AGDS_2299 | ADGF_UNSTABLE,
+		GUIO1(GUIO_NONE)},
+	{
+		"black-mirror",
+		"Steam release - opcodes don't match the other games",
+		AD_ENTRY2s(
+			"gfx1.grp", "a5f84365d1e15a8403237fa3ad339f86", 850840170,
+			"data.adb", "94de43fb7916206e596a516647e76b2f", 2169250),
+		Common::PL_POL,
+		Common::kPlatformWindows,
+		ADGF_DROPPLATFORM | AGDS_2299 | ADGF_UNSUPPORTED,
 		GUIO1(GUIO_NONE)},
+	{"black-mirror",
+	 "Steam release",
+	 AD_ENTRY2s(
+		 "gfx1.grp", "652f931f02c5a79fb9bcbe32abafbdf7", 907732355,
+		 "data.adb", "d8706b17fb89d58d4dba094a73e5490a", 2152794),
+	 Common::RU_RUS,
+	 Common::kPlatformWindows,
+	 ADGF_DROPPLATFORM,
+	 GUIO1(GUIO_NONE)},
 	{"black-mirror",
 	 "CD version protected with StarForce",
 	 AD_ENTRY2s(
@@ -64,15 +135,6 @@ static const ADGameDescription gameDescriptions[] = {
 	 Common::kPlatformWindows,
 	 ADGF_DROPPLATFORM | ADGF_DEMO | ADGF_UNSTABLE,
 	 GUIO1(GUIO_NONE)},
-	{"black-mirror",
-	 0,
-	 AD_ENTRY2s(
-		 "gfx1.grp", "652f931f02c5a79fb9bcbe32abafbdf7", 907732355,
-		 "data.adb", "d8706b17fb89d58d4dba094a73e5490a", 2152794),
-	 Common::RU_RUS,
-	 Common::kPlatformWindows,
-	 ADGF_DROPPLATFORM,
-	 GUIO1(GUIO_NONE)},
 
 	// NiBiRu
 	{
@@ -83,7 +145,7 @@ static const ADGameDescription gameDescriptions[] = {
 			"data.adb", "40a7a88f77c35305b6aba0329ed8a9ac", 1391440),
 		Common::EN_USA,
 		Common::kPlatformWindows,
-		ADGF_DROPPLATFORM | AGDS_V2 | ADGF_UNSTABLE,
+		ADGF_DROPPLATFORM | AGDS_2511 | ADGF_UNSTABLE,
 		GUIO1(GUIO_NONE)},
 	{"nibiru",
 	 0,
@@ -92,9 +154,11 @@ static const ADGameDescription gameDescriptions[] = {
 		 "data.adb", "40a7a88f77c35305b6aba0329ed8a9ac", 1391440),
 	 Common::RU_RUS,
 	 Common::kPlatformWindows,
-	 ADGF_DROPPLATFORM | AGDS_V2 | ADGF_UNSTABLE,
+	 ADGF_DROPPLATFORM | AGDS_2511 | ADGF_UNSTABLE,
 	 GUIO1(GUIO_NONE)},
 
 	AD_TABLE_END_MARKER};
 
+// clang-format on
+
 } // End of namespace AGDS
diff --git a/engines/agds/object.cpp b/engines/agds/object.cpp
index 61c2d35380d..1d9108dbf43 100644
--- a/engines/agds/object.cpp
+++ b/engines/agds/object.cpp
@@ -22,6 +22,7 @@
 #include "agds/object.h"
 #include "agds/agds.h"
 #include "agds/animation.h"
+#include "agds/detection.h"
 #include "agds/font.h"
 #include "agds/region.h"
 #include "agds/systemVariable.h"
@@ -92,7 +93,7 @@ void Object::readStringTable(unsigned resOffset, uint16 resCount) {
 	if (_stringTableLoaded)
 		return;
 
-	resOffset += 5 /*instruction*/ + (_version >= 2 ? 0x13 : 0x11) /*another header*/;
+	resOffset += 5 /*instruction*/ + (_version >= kAGDSVersionNibiru2511 ? 0x13 : 0x11) /*another header*/;
 	if (resOffset >= _code.size())
 		error("invalid resource table offset %u/%u", resOffset, _code.size());
 
diff --git a/engines/agds/process.cpp b/engines/agds/process.cpp
index c508dd925da..d96dba257f4 100644
--- a/engines/agds/process.cpp
+++ b/engines/agds/process.cpp
@@ -27,15 +27,15 @@
 
 namespace AGDS {
 
-Process::Process(AGDSEngine *engine, const ObjectPtr &object, unsigned ip, int version) : _engine(engine), _parentScreen(engine->getCurrentScreenName()), _object(object),
-																						  _entryPoint(ip), _ip(ip), _lastIp(ip),
-																						  _status(kStatusActive), _exited(false), _exitCode(kExitCodeDestroy),
-																						  _tileWidth(16), _tileHeight(16), _tileResource(-1), _tileIndex(0),
-																						  _timer(0),
-																						  _animationCycles(1), _animationLoop(false), _animationZ(0), _animationDelay(-1), _animationRandom(0),
-																						  _phaseVarControlled(false), _animationSpeed(100),
-																						  _samplePeriodic(false), _sampleAmbient(false), _sampleVolume(100),
-																						  _filmSubtitlesResource(-1), _version(version) {
+Process::Process(AGDSEngine *engine, const ObjectPtr &object, unsigned ip, int version, Common::Language language) : _engine(engine), _parentScreen(engine->getCurrentScreenName()), _object(object),
+																													 _entryPoint(ip), _ip(ip), _lastIp(ip),
+																													 _status(kStatusActive), _exited(false), _exitCode(kExitCodeDestroy),
+																													 _tileWidth(16), _tileHeight(16), _tileResource(-1), _tileIndex(0),
+																													 _timer(0),
+																													 _animationCycles(1), _animationLoop(false), _animationZ(0), _animationDelay(-1), _animationRandom(0),
+																													 _phaseVarControlled(false), _animationSpeed(100),
+																													 _samplePeriodic(false), _sampleAmbient(false), _sampleVolume(100),
+																													 _filmSubtitlesResource(-1), _version(version), _language(language) {
 	updateWithCurrentMousePosition();
 }
 
@@ -403,18 +403,40 @@ BINARY_OP(bitXor, ^)
 uint16 Process::nextOpcode() {
 	uint16 op = next();
 	switch (_version) {
-	case 0:
+	case kAGDSVersionDemo2283:
 		return op + 5;
 
-	case 2:
+	case kAGDSVersionBlackMirror2299:
+		switch (_language) {
+		case Common::CS_CZE:
+			return op + 5;
+		case Common::FR_FRA:
+			return op + 1;
+		case Common::DE_DEU:
+			return op - 3;
+		case Common::ES_ESP:
+			return op - 1;
+		// most of the opcodes look good, but it's not working
+		case Common::PL_POL:
+			return 1 + ((op + 41) % 246);
+		case Common::IT_ITA:
+			return 5 + ((op + 54) % 246);
+		default:
+			::error("invalid v2299 language %d", _language);
+		}
+
+	case kAGDSVersionNibiru2511:
 		if (op & 1) {
 			op |= next() << 8;
 			op >>= 1;
 		}
 		return op - 7995;
 
-	default:
+	case kAGDSVersionBlackMirror2296:
 		return op;
+
+	default:
+		::error("unknown version: %d", _version);
 	}
 }
 
@@ -506,13 +528,18 @@ Common::String Process::disassemble(const ObjectPtr &object, int version) {
 	uint ip = 0;
 	while (ip < code.size()) {
 		uint16 op = code[ip++];
-		if (version == 2) {
+		switch (version) {
+		case kAGDSVersionNibiru2511:
 			if (op & 1) {
 				op |= code[ip++] << 8;
 				op >>= 1;
 			}
-		} else if (version == 0) {
+			break;
+		case kAGDSVersionDemo2283:
 			op += 5;
+			break;
+		default:
+			break;
 		}
 
 		source += Common::String::format("%04x: %02x: ", ip - 1, op);
diff --git a/engines/agds/process.h b/engines/agds/process.h
index a9a1a1b8042..81c9f007a6c 100644
--- a/engines/agds/process.h
+++ b/engines/agds/process.h
@@ -26,6 +26,7 @@
 #include "agds/opcode.h"
 #include "agds/processExitCode.h"
 #include "common/debug.h"
+#include "common/language.h"
 #include "common/scummsys.h"
 #include "common/stack.h"
 
@@ -77,6 +78,7 @@ private:
 	int _filmSubtitlesResource;
 	AnimationPtr _processAnimation;
 	int _version;
+	Common::Language _language;
 
 private:
 	void debug(const char *str, ...);
@@ -139,7 +141,7 @@ private:
 	void removeScreenObject(const Common::String &name);
 
 public:
-	Process(AGDSEngine *engine, const ObjectPtr &object, unsigned ip, int version);
+	Process(AGDSEngine *engine, const ObjectPtr &object, unsigned ip, int version, Common::Language language);
 	unsigned entryPoint() const {
 		return _entryPoint;
 	}
diff --git a/engines/agds/process_opcodes.cpp b/engines/agds/process_opcodes.cpp
index 6bb5df3496b..1af843613d3 100644
--- a/engines/agds/process_opcodes.cpp
+++ b/engines/agds/process_opcodes.cpp
@@ -725,7 +725,7 @@ void Process::setAnimationZ() {
 
 void Process::setPanAndVolume() {
 	int pan = 0;
-	if (_version > 0) {
+	if (_version > kAGDSVersionDemo2283) {
 		pan = pop();
 	}
 	int volume = pop();
diff --git a/engines/agds/resourceManager.cpp b/engines/agds/resourceManager.cpp
index 0b06b29df24..ead2ca0a6bf 100644
--- a/engines/agds/resourceManager.cpp
+++ b/engines/agds/resourceManager.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "agds/resourceManager.h"
+#include "agds/detection.h"
 #include "common/algorithm.h"
 #include "common/debug.h"
 #include "common/file.h"
@@ -227,7 +228,7 @@ Common::String ResourceManager::loadText(Common::SeekableReadStream &stream) con
 	while (begin != end && end[-1] == 0)
 		--end;
 
-	if (_version != 0 || (text[0] < ' ' || text[0] >= 0x7f))
+	if (_version >= kAGDSVersionBlackMirror2296 || (text[0] < ' ' || text[0] >= 0x7f))
 		decrypt(reinterpret_cast<uint8 *>(text.data()), end - begin);
 
 	while (begin != end && end[-1] == 0)




More information about the Scummvm-git-logs mailing list