[Scummvm-git-logs] scummvm master -> 9e0d874a67da96609e39005774d1bcd9d8ec9923
whoozle
noreply at scummvm.org
Thu Jan 8 18:19:47 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:
9e0d874a67 AGDS: add support for the demo version of Black Mirror
Commit: 9e0d874a67da96609e39005774d1bcd9d8ec9923
https://github.com/scummvm/scummvm/commit/9e0d874a67da96609e39005774d1bcd9d8ec9923
Author: Vladimir Menshakov (vladimir.menshakov at gmail.com)
Date: 2026-01-08T18:19:19Z
Commit Message:
AGDS: add support for the demo version of Black Mirror
Changed paths:
engines/agds/agds.cpp
engines/agds/agds.h
engines/agds/detection_tables.h
engines/agds/object.cpp
engines/agds/object.h
engines/agds/process.cpp
engines/agds/process.h
engines/agds/process_opcodes.cpp
engines/agds/resourceManager.cpp
engines/agds/resourceManager.h
diff --git a/engines/agds/agds.cpp b/engines/agds/agds.cpp
index 04121063d2f..4634733efd5 100644
--- a/engines/agds/agds.cpp
+++ b/engines/agds/agds.cpp
@@ -49,20 +49,22 @@
namespace AGDS {
AGDSEngine::AGDSEngine(OSystem *system, const ADGameDescription *gameDesc) : Engine(system),
- _gameDescription(gameDesc), _pictureCacheId(1), _sharedStorageIndex(-2),
- _shadowIntensity(0),
+ _gameDescription(gameDesc),
+ _resourceManager(version()),
+ _soundManager(this, system->getMixer()), _pictureCacheId(1),
_processes(MaxProcesses),
- _mjpgPlayer(), _filmStarted(0),
+ _sharedStorageIndex(-2),
+ _shadowIntensity(0), _mjpgPlayer(),
+ _filmStarted(0),
_currentScreen(),
_currentCharacter(),
- _defaultMouseCursor(),
_nextScreenType(ScreenLoadingType::Normal),
- _mouse(400, 300),
- _userEnabled(true), _systemUserEnabled(true),
+ _defaultMouseCursor(),
+ _mouse(400, 300), _userEnabled(true),
+ _systemUserEnabled(true),
_random("agds"),
- _inventoryRegion(),
- _soundManager(this, system->getMixer()),
_inventory(this),
+ _inventoryRegion(),
_dialog(this),
_tellTextTimer(0),
_syncSoundId(-1),
@@ -144,9 +146,13 @@ bool AGDSEngine::load() {
Common::INIFile::SectionKeyList values = config.getKeys("core");
for (Common::INIFile::SectionKeyList::iterator i = values.begin(); i != values.end(); ++i) {
- if (i->key == "path")
- if (!_resourceManager.addPath(Common::Path{i->value}))
+ if (i->key == "path") {
+ auto path = i->value;
+ if (path.hasPrefix(".\\"))
+ path = path.substr(2);
+ if (!_resourceManager.addPath(Common::Path{path, '\\'}))
return false;
+ }
}
if (!_data.open("data.adb"))
@@ -190,7 +196,7 @@ Common::String AGDSEngine::loadText(const Common::String &entryName) {
if (entryName.empty())
return Common::String();
Common::ScopedPtr<Common::SeekableReadStream> stream(_data.getEntry(entryName));
- return ResourceManager::loadText(*stream);
+ return _resourceManager.loadText(*stream);
}
ObjectPtr AGDSEngine::loadObject(const Common::String &name, const Common::String &prototype, bool allowInitialise) {
@@ -200,7 +206,7 @@ ObjectPtr AGDSEngine::loadObject(const Common::String &name, const Common::Strin
if (!stream)
error("no database entry for %s\n", clone.c_str());
- ObjectPtr object(new Object(name, *stream, v2()));
+ ObjectPtr object(new Object(name, *stream, version()));
object->allowInitialise(allowInitialise);
if (!prototype.empty()) {
object->persistent(false);
@@ -244,7 +250,7 @@ void AGDSEngine::runProcess(const ObjectPtr &object, uint ip) {
return;
}
if (!process) {
- process = ProcessPtr(new Process(this, object, ip, v2()));
+ process = ProcessPtr(new Process(this, object, ip, version()));
process->run();
return;
}
@@ -396,8 +402,10 @@ Console *AGDSEngine::getConsole() {
void AGDSEngine::newGame() {
SystemVariable *doneVar = getSystemVariable("done_resources");
Common::String done = doneVar->getString();
- debug("running engine resource dtor: %s", done.c_str());
- runObject(done);
+ if (!done.empty()) {
+ debug("running engine resource dtor: %s", done.c_str());
+ runObject(done);
+ }
_patches.clear();
_objectPatches.clear();
@@ -409,8 +417,10 @@ void AGDSEngine::newGame() {
SystemVariable *initVar = getSystemVariable("init_resources");
Common::String init = initVar->getString();
- debug("running engine resource ctor: %s", init.c_str());
- runObject(init);
+ if (!init.empty()) {
+ debug("running engine resource ctor: %s", init.c_str());
+ runObject(init);
+ }
}
void AGDSEngine::curtain(const Common::String &process, int screen, int sound, int music, bool updateGlobals) {
@@ -1438,4 +1448,12 @@ 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;
+}
+
} // End of namespace AGDS
diff --git a/engines/agds/agds.h b/engines/agds/agds.h
index 6ee5a2c4e6c..1730e27256d 100644
--- a/engines/agds/agds.h
+++ b/engines/agds/agds.h
@@ -53,7 +53,7 @@
namespace Graphics {
class Font;
class ManagedSurface;
-}
+} // namespace Graphics
namespace AGDS {
@@ -280,7 +280,9 @@ public:
bool activeCurtain() const {
return _curtainTimer >= 0;
}
+
bool v2() const;
+ int version() const;
private:
void stopAmbientSound();
diff --git a/engines/agds/detection_tables.h b/engines/agds/detection_tables.h
index 128eb76c3f5..61e97506ecd 100644
--- a/engines/agds/detection_tables.h
+++ b/engines/agds/detection_tables.h
@@ -56,7 +56,7 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_DROPPLATFORM | ADGF_CD,
GUIO1(GUIO_NONE)},
{"black-mirror",
- 0,
+ "Demo",
AD_ENTRY2s(
"gfx_en.grp", "7539f35f9242461114c8746b62f884a6", 67516239,
"data.adb", "56680d118afddf9477c57e508d118dc8", 114764),
diff --git a/engines/agds/object.cpp b/engines/agds/object.cpp
index b6accc550e6..61c2d35380d 100644
--- a/engines/agds/object.cpp
+++ b/engines/agds/object.cpp
@@ -33,16 +33,16 @@
namespace AGDS {
-Object::Object(const Common::String &name, Common::SeekableReadStream &stream, bool v2) : _name(name), _stringTableLoaded(false),
- _picture(), _rotatedPicture(), _region(),
- _animation(), _mouseCursor(),
- _pos(), _z(10), _rotation(0),
- _clickHandler(0), _examineHandler(0), _userUseHandler(0),
- _throwHandler(0), _useOnHandler(0),
- _handlerBD(0), _handlerC1(0),
- _alpha(255), _scale(100), _locked(0), _alive(true),
- _persistent(true), _allowInitialise(true),
- _ignoreRegion(false), _v2(v2) {
+Object::Object(const Common::String &name, Common::SeekableReadStream &stream, int version) : _name(name), _stringTableLoaded(false),
+ _picture(), _rotatedPicture(), _region(),
+ _animation(), _mouseCursor(),
+ _pos(), _z(10), _rotation(0),
+ _clickHandler(0), _examineHandler(0), _userUseHandler(0),
+ _throwHandler(0), _useOnHandler(0),
+ _handlerBD(0), _handlerC1(0),
+ _alpha(255), _scale(100), _locked(0), _alive(true),
+ _persistent(true), _allowInitialise(true),
+ _ignoreRegion(false), _version(version) {
uint16 id = stream.readUint16LE();
debug("id: 0x%02x %u", id, id);
@@ -92,7 +92,7 @@ void Object::readStringTable(unsigned resOffset, uint16 resCount) {
if (_stringTableLoaded)
return;
- resOffset += 5 /*instruction*/ + (_v2 ? 0x13 : 0x11) /*another header*/;
+ resOffset += 5 /*instruction*/ + (_version >= 2 ? 0x13 : 0x11) /*another header*/;
if (resOffset >= _code.size())
error("invalid resource table offset %u/%u", resOffset, _code.size());
diff --git a/engines/agds/object.h b/engines/agds/object.h
index 3d7feb3c079..fe4a00a7cc5 100644
--- a/engines/agds/object.h
+++ b/engines/agds/object.h
@@ -95,7 +95,7 @@ private:
bool _persistent;
bool _allowInitialise;
bool _ignoreRegion;
- bool _v2;
+ int _version;
private:
void freeRotated();
@@ -103,7 +103,7 @@ private:
void createRotated();
public:
- Object(const Common::String &name, Common::SeekableReadStream &stream, bool v2);
+ Object(const Common::String &name, Common::SeekableReadStream &stream, int version);
~Object();
bool allowInitialise() const {
diff --git a/engines/agds/process.cpp b/engines/agds/process.cpp
index 86179780612..c508dd925da 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, bool v2) : _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), _v2(v2) {
+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) {
updateWithCurrentMousePosition();
}
@@ -319,14 +319,14 @@ void Process::run() {
#define UNARY_OP(NAME, OP) \
void Process::NAME() { \
- int32 arg = pop(); \
+ int32 arg = pop(); \
debug(#NAME " %d", arg); \
push(OP arg); \
}
#define BINARY_OP(NAME, OP) \
void Process::NAME() { \
- int32 arg2 = pop(); \
- int32 arg1 = pop(); \
+ int32 arg2 = pop(); \
+ int32 arg1 = pop(); \
debug(" %d " #NAME " %d", arg1, arg2); \
push(arg1 OP arg2); \
}
@@ -400,6 +400,24 @@ BINARY_OP(bitXor, ^)
METHOD(static_cast<int32>(arg1 | (arg2 << 16))); \
} break;
+uint16 Process::nextOpcode() {
+ uint16 op = next();
+ switch (_version) {
+ case 0:
+ return op + 5;
+
+ case 2:
+ if (op & 1) {
+ op |= next() << 8;
+ op >>= 1;
+ }
+ return op - 7995;
+
+ default:
+ return op;
+ }
+}
+
ProcessExitCode Process::resume() {
_exitCode = kExitCodeDestroy;
if (_timer) {
@@ -413,14 +431,7 @@ ProcessExitCode Process::resume() {
return kExitCodeSuspend;
}
_lastIp = _ip;
- uint16 op = next();
- if (_v2) {
- if (op & 1) {
- op |= next() << 8;
- op >>= 1;
- }
- op -= 7995;
- }
+ auto op = nextOpcode();
// debug("CODE %04x: %u", _lastIp, (uint)op);
switch (op) {
AGDS_OPCODE_LIST(
@@ -488,18 +499,20 @@ ProcessExitCode Process::resume() {
source += Common::String::format("%s %u\n", #NAME, (uint)(arg1 | (arg2 << 16))); \
} break;
-Common::String Process::disassemble(const ObjectPtr &object, bool v2) {
+Common::String Process::disassemble(const ObjectPtr &object, int version) {
Common::String source = Common::String::format("Object %s disassembly:\n", object->getName().c_str());
const auto &code = object->getCode();
uint ip = 0;
while (ip < code.size()) {
uint16 op = code[ip++];
- if (v2) {
+ if (version == 2) {
if (op & 1) {
op |= code[ip++] << 8;
op >>= 1;
}
+ } else if (version == 0) {
+ op += 5;
}
source += Common::String::format("%04x: %02x: ", ip - 1, op);
diff --git a/engines/agds/process.h b/engines/agds/process.h
index 9d0a94c9744..a9a1a1b8042 100644
--- a/engines/agds/process.h
+++ b/engines/agds/process.h
@@ -76,7 +76,7 @@ private:
Common::Point _mousePosition;
int _filmSubtitlesResource;
AnimationPtr _processAnimation;
- bool _v2;
+ int _version;
private:
void debug(const char *str, ...);
@@ -90,6 +90,7 @@ private:
uint16 h = next();
return (h << 8) | l;
}
+ uint16 nextOpcode();
int32 pop();
int32 top();
@@ -138,12 +139,12 @@ private:
void removeScreenObject(const Common::String &name);
public:
- Process(AGDSEngine *engine, const ObjectPtr &object, unsigned ip, bool v2);
+ Process(AGDSEngine *engine, const ObjectPtr &object, unsigned ip, int version);
unsigned entryPoint() const {
return _entryPoint;
}
- static Common::String disassemble(const ObjectPtr &object, bool v2);
+ static Common::String disassemble(const ObjectPtr &object, int version);
ObjectPtr getObject() const {
return _object;
diff --git a/engines/agds/process_opcodes.cpp b/engines/agds/process_opcodes.cpp
index ef6667a2b65..6bb5df3496b 100644
--- a/engines/agds/process_opcodes.cpp
+++ b/engines/agds/process_opcodes.cpp
@@ -724,7 +724,10 @@ void Process::setAnimationZ() {
}
void Process::setPanAndVolume() {
- int pan = pop();
+ int pan = 0;
+ if (_version > 0) {
+ pan = pop();
+ }
int volume = pop();
debug("setPanAndVolume: pan %d volume %d", pan, volume);
}
diff --git a/engines/agds/resourceManager.cpp b/engines/agds/resourceManager.cpp
index 172d70ce6a0..0b06b29df24 100644
--- a/engines/agds/resourceManager.cpp
+++ b/engines/agds/resourceManager.cpp
@@ -32,7 +32,7 @@
#include "video/flic_decoder.h"
namespace AGDS {
-ResourceManager::ResourceManager() {}
+ResourceManager::ResourceManager(int version) : _version(version) {}
ResourceManager::~ResourceManager() {}
@@ -63,10 +63,17 @@ bool ResourceManager::GrpFile::load(const Common::Path &grpPath) {
return false;
}
- decrypt(header, 0x10);
if (strncmp(reinterpret_cast<const char *>(header), kSignature, 0x10) != 0) {
- warning("invalid signature");
- return false;
+ decrypt(header, 0x10);
+ if (strncmp(reinterpret_cast<const char *>(header), kSignature, 0x10) != 0) {
+ warning("invalid signature");
+ return false;
+ }
+ debug("load grp file %s, encrypted", grpPath.toString().c_str());
+ _encrypted = true;
+ } else {
+ debug("load grp file %s, unencrypted", grpPath.toString().c_str());
+ _encrypted = false;
}
Common::MemoryReadStreamEndian reader(header + 0x10, sizeof(header) - 0x10, false);
@@ -109,7 +116,8 @@ bool ResourceManager::GrpFile::load(const Common::Path &grpPath) {
}
unsigned nameLength = nameEnd - dirData;
- decrypt(dirData, nameLength);
+ if (_encrypted)
+ decrypt(dirData, nameLength);
Common::String name(reinterpret_cast<char *>(dirData), nameLength);
Common::MemoryReadStreamEndian dirReader(dirData + 0x21, 8, false);
@@ -206,7 +214,7 @@ Graphics::Surface *ResourceManager::loadPicture(const Common::String &name, cons
return NULL;
}
-Common::String ResourceManager::loadText(Common::SeekableReadStream &stream) {
+Common::String ResourceManager::loadText(Common::SeekableReadStream &stream) const {
Common::Array<char> text(stream.size());
if (stream.read(text.data(), text.size()) != text.size())
error("short read from text resource");
@@ -219,7 +227,8 @@ Common::String ResourceManager::loadText(Common::SeekableReadStream &stream) {
while (begin != end && end[-1] == 0)
--end;
- decrypt(reinterpret_cast<uint8 *>(text.data()), end - begin);
+ if (_version != 0 || (text[0] < ' ' || text[0] >= 0x7f))
+ decrypt(reinterpret_cast<uint8 *>(text.data()), end - begin);
while (begin != end && end[-1] == 0)
--end;
diff --git a/engines/agds/resourceManager.h b/engines/agds/resourceManager.h
index 8ff5864cce8..a4c9712adf9 100644
--- a/engines/agds/resourceManager.h
+++ b/engines/agds/resourceManager.h
@@ -67,6 +67,7 @@ private:
class GrpFile : public Common::Archive {
Common::File _file;
+ bool _encrypted;
using MembersType = Common::HashMap<Common::String, ArchiveMemberPtr, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>;
MembersType _members;
@@ -84,11 +85,14 @@ private:
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &name) const override;
};
+ static void decrypt(uint8 *data, unsigned size);
+
+ int _version;
+
public:
- ResourceManager();
+ ResourceManager(int version);
~ResourceManager();
- static void decrypt(uint8 *data, unsigned size);
static bool IsBMP(Common::SeekableReadStream &stream);
bool addPath(const Common::Path &grpFilename);
@@ -96,7 +100,7 @@ public:
Common::SeekableReadStream *getResource(const Common::String &name) const;
Graphics::Surface *loadPicture(const Common::String &name, const Graphics::PixelFormat &format);
- static Common::String loadText(Common::SeekableReadStream &stream);
+ Common::String loadText(Common::SeekableReadStream &stream) const;
Common::String loadText(const Common::String &name) const;
};
More information about the Scummvm-git-logs
mailing list