[Scummvm-git-logs] scummvm master -> 34a1e5aac4478854f98bab7567e77e76ffc4170e
sluicebox
noreply at scummvm.org
Tue Jan 16 17:12:32 UTC 2024
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
a5656b43fe AGI: Detect V3 volume format in V2 games
34a1e5aac4 AGI: Add error check when loading sounds
Commit: a5656b43fe9a9d037a4603e7c4b022b0cfe58036
https://github.com/scummvm/scummvm/commit/a5656b43fe9a9d037a4603e7c4b022b0cfe58036
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-01-16T10:11:13-07:00
Commit Message:
AGI: Detect V3 volume format in V2 games
The CoCo3 version of Xmas Card 86 has a volume file with a V3 format.
The V2 loader now detects this and ignores the extra header bytes.
Fixes bug #14699
Changed paths:
engines/agi/agi.h
engines/agi/loader_v2.cpp
engines/agi/loader_v3.cpp
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 499bcf7ae17..2dae7fad816 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -639,14 +639,17 @@ public:
class AgiLoader_v2 : public AgiLoader {
private:
AgiEngine *_vm;
+ bool _hasV3VolumeFormat;
int loadDir(AgiDir *agid, const char *fname);
uint8 *loadVolRes(AgiDir *agid);
+ bool detectV3VolumeFormat();
public:
AgiLoader_v2(AgiEngine *vm) {
_vm = vm;
+ _hasV3VolumeFormat = false;
}
int init() override;
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index 6af7a657958..e2b9c5dfad2 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -83,6 +83,51 @@ int AgiLoader_v2::loadDir(AgiDir *agid, const char *fname) {
return errOK;
}
+/**
+ * Detects if the volume format is really V3.
+ *
+ * The volume format for a V2 game should have 5 byte headers.
+ * The CoCo3 version of Xmas Card 86 has 7 byte headers.
+ * The resource length repeats as if it were a V3 volume with no compression.
+ *
+ * This function detects if a volume has this unusual structure so that
+ * loadVolRes() can ignore the two extra header bytes.
+ */
+bool AgiLoader_v2::detectV3VolumeFormat() {
+ uint8 volume = _vm->_game.dirLogic[0].volume;
+ Common::Path path(Common::String::format("vol.%i", volume));
+ Common::File volumeFile;
+ if (!volumeFile.open(path)) {
+ return false;
+ }
+
+ // read the first few entries and see if they match the 7 byte header
+ uint8 volumeHeader[7];
+ for (int i = 0; i < 5; i++) {
+ if (volumeFile.read(&volumeHeader, 7) != 7) {
+ return false;
+ }
+ // signature
+ if (READ_BE_UINT16(volumeHeader) != 0x1234) {
+ return false;
+ }
+ // volume number
+ if (volumeHeader[2] != volume) {
+ return false;
+ }
+ // duplicate resource lengths
+ uint16 resourceLength1 = READ_LE_UINT16(volumeHeader + 3);
+ uint16 resourceLength2 = READ_LE_UINT16(volumeHeader + 5);
+ if (resourceLength1 != resourceLength2) {
+ return false;
+ }
+ if (!volumeFile.seek(resourceLength1, SEEK_CUR)) {
+ return false;
+ }
+ }
+ return true;
+}
+
int AgiLoader_v2::init() {
int ec = errOK;
@@ -94,6 +139,8 @@ int AgiLoader_v2::init() {
ec = loadDir(_vm->_game.dirView, VIEWDIR);
if (ec == errOK)
ec = loadDir(_vm->_game.dirSound, SNDDIR);
+ if (ec == errOK)
+ _hasV3VolumeFormat = detectV3VolumeFormat();
return ec;
}
@@ -138,11 +185,11 @@ int AgiLoader_v2::unloadResource(int16 resourceType, int16 resourceNr) {
/**
* This function loads a raw resource into memory,
* if further decoding is required, it must be done by another
- * routine. NULL is returned if unsucsessfull.
+ * routine. NULL is returned if unsuccessful.
*/
uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) {
uint8 *data = nullptr;
- char x[6];
+ uint8 volumeHeader[7];
Common::File fp;
unsigned int sig;
Common::Path path(Common::String::format("vol.%i", agid->volume));
@@ -152,9 +199,9 @@ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) {
if (agid->offset != _EMPTY && fp.open(path)) {
debugC(3, kDebugLevelResources, "loading resource at offset %d", agid->offset);
fp.seek(agid->offset, SEEK_SET);
- fp.read(&x, 5);
- if ((sig = READ_BE_UINT16((uint8 *) x)) == 0x1234) {
- agid->len = READ_LE_UINT16((uint8 *) x + 3);
+ fp.read(&volumeHeader, _hasV3VolumeFormat ? 7 : 5);
+ if ((sig = READ_BE_UINT16(volumeHeader)) == 0x1234) {
+ agid->len = READ_LE_UINT16(volumeHeader + 3);
data = (uint8 *)calloc(1, agid->len + 32);
if (data != nullptr) {
fp.read(data, agid->len);
diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp
index 8f82ee02018..246c85dfa6c 100644
--- a/engines/agi/loader_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -194,7 +194,7 @@ int AgiLoader_v3::unloadResource(int16 resourceType, int16 resourceNr) {
* If further decoding is required, it must be done by another
* routine.
*
- * NULL is returned if unsucsessful.
+ * NULL is returned if unsuccessful.
*/
uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) {
char x[8];
Commit: 34a1e5aac4478854f98bab7567e77e76ffc4170e
https://github.com/scummvm/scummvm/commit/34a1e5aac4478854f98bab7567e77e76ffc4170e
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2024-01-16T10:11:13-07:00
Commit Message:
AGI: Add error check when loading sounds
Fixes the CoCo3 version of Xmas Card 86 crashing on startup.
The sound format isn't supported yet but the return value from
AgiSound::createFromRawResource wasn't tested.
Changed paths:
engines/agi/loader_v2.cpp
diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp
index e2b9c5dfad2..65c7cc9bb3c 100644
--- a/engines/agi/loader_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -281,11 +281,12 @@ int AgiLoader_v2::loadResource(int16 resourceType, int16 resourceNr) {
data = loadVolRes(&_vm->_game.dirSound[resourceNr]);
- if (data != nullptr) {
- // Freeing of the raw resource from memory is delegated to the createFromRawResource-function
- _vm->_game.sounds[resourceNr] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[resourceNr].len, resourceNr, _vm->_soundemu);
+ // "data" is freed by objects created by createFromRawResource on success
+ _vm->_game.sounds[resourceNr] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[resourceNr].len, resourceNr, _vm->_soundemu);
+ if (_vm->_game.sounds[resourceNr] != nullptr) {
_vm->_game.dirSound[resourceNr].flags |= RES_LOADED;
} else {
+ free(data);
ec = errBadResource;
}
break;
More information about the Scummvm-git-logs
mailing list