[Scummvm-git-logs] scummvm master -> e4979ab4c79e945b91f9016f4325c189d424776a

neuromancer noreply at scummvm.org
Sat Feb 3 20:59:11 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:
0caf196249 FREESCAPE: enable more hardcoded sounds here and there
e4979ab4c7 FREESCAPE: exe unpack for dos release of castle


Commit: 0caf19624918aa5d9ca8f32ab89ff6c7e1f2acf0
    https://github.com/scummvm/scummvm/commit/0caf19624918aa5d9ca8f32ab89ff6c7e1f2acf0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-02-03T21:59:28+01:00

Commit Message:
FREESCAPE: enable more hardcoded sounds here and there

Changed paths:
    engines/freescape/games/dark/dark.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/eclipse/eclipse.cpp


diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index a1916efb596..d74e037ff80 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -384,6 +384,7 @@ bool DarkEngine::checkIfGameEnded() {
 		} else {
 			restoreECD(*_currentArea, index);
 			insertTemporaryMessage(_messagesList[1], _countdown - 2);
+			playSound(19, true);
 		}
 		_gameStateVars[kVariableDarkECD] = 0;
 	}
@@ -528,11 +529,12 @@ void DarkEngine::gotoArea(uint16 areaID, int entranceID) {
 	if (areaID == _startArea && entranceID == _startEntrance) {
 		_yaw = 90;
 		_pitch = 0;
-	}
+		playSound(9, true);
+	} else
+		playSound(5, false);
 
 	debugC(1, kFreescapeDebugMove, "starting player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
 	clearTemporalMessages();
-	playSound(5, false);
 	// Ignore sky/ground fields
 	_gfx->_keyColor = 0;
 	// Color remaps are not restored in Dark Side
@@ -551,13 +553,18 @@ void DarkEngine::gotoArea(uint16 areaID, int entranceID) {
 void DarkEngine::pressedKey(const int keycode) {
 	if (keycode == Common::KEYCODE_j) {
 		_flyMode = !_flyMode;
+		//debugC(1, kFreescapeDebugMedia, "raw %d, hz: %f", freq, hzFreq);
 
 		if (_flyMode && _gameStateVars[k8bitVariableEnergy] == 0) {
 			_flyMode = false;
 			insertTemporaryMessage(_messagesList[13], _countdown - 2);
-		} else if (_flyMode)
+		} else if (_flyMode) {
+			float hzFreq = 1193180.0 / 0xd537;
+			_speaker->play(Audio::PCSpeaker::kWaveFormSquare, hzFreq, -1);
+			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundFxHandle, _speaker, -1, Audio::Mixer::kMaxChannelVolume / 2, 0, DisposeAfterUse::NO);
 			insertTemporaryMessage(_messagesList[11], _countdown - 2);
-		else {
+		} else {
+			_speaker->stop();
 			resolveCollisions(_position);
 			if (!_hasFallen)
 				insertTemporaryMessage(_messagesList[12], _countdown - 2);
@@ -712,7 +719,7 @@ void DarkEngine::drawInfoMenu() {
 					saveGameDialog();
 					_gfx->setViewport(_viewArea);
 				} else if (isDOS() && event.kbd.keycode == Common::KEYCODE_t) {
-					// TODO
+					playSound(6, true);
 				} else if ((isDOS() || isCPC()) && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
 					_forceEndGame = true;
 					cont = false;
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 60ffa7c2f04..81a1720ed95 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -165,6 +165,7 @@ void DrillerEngine::gotoArea(uint16 areaID, int entranceID) {
 	if (areaID == _startArea && entranceID == _startEntrance) {
 		_yaw = 280;
 		_pitch = 0;
+		playSound(9, true);
 	} else if (areaID == 127) {
 		assert(entranceID == 0);
 		_yaw = 90;
@@ -172,11 +173,11 @@ void DrillerEngine::gotoArea(uint16 areaID, int entranceID) {
 		_flyMode = true; // Avoid falling
 		// Show the number of completed areas
 		_areaMap[127]->_name.replace(0, 3, Common::String::format("%4d", _gameStateVars[32]));
-	}
+	} else
+		playSound(5, false);
 
 	debugC(1, kFreescapeDebugMove, "starting player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
 	clearTemporalMessages();
-	playSound(5, false);
 	// Ignore sky/ground fields
 	_gfx->_keyColor = 0;
 	_gfx->setColorRemaps(&_currentArea->_colorRemaps);
diff --git a/engines/freescape/games/eclipse/eclipse.cpp b/engines/freescape/games/eclipse/eclipse.cpp
index a6c9390d952..9fe07038660 100644
--- a/engines/freescape/games/eclipse/eclipse.cpp
+++ b/engines/freescape/games/eclipse/eclipse.cpp
@@ -142,6 +142,11 @@ void EclipseEngine::gotoArea(uint16 areaID, int entranceID) {
 
 	_lastPosition = _position;
 
+	if (areaID == _startArea && entranceID == _startEntrance)
+		playSound(9, true);
+	else
+		playSound(5, false);
+
 	if (_currentArea->_skyColor > 0 && _currentArea->_skyColor != 255) {
 		_gfx->_keyColor = 0;
 	} else


Commit: e4979ab4c79e945b91f9016f4325c189d424776a
    https://github.com/scummvm/scummvm/commit/e4979ab4c79e945b91f9016f4325c189d424776a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2024-02-03T21:59:28+01:00

Commit Message:
FREESCAPE: exe unpack for dos release of castle

Changed paths:
  A engines/freescape/unpack.cpp
    engines/freescape/games/castle.cpp
    engines/freescape/module.mk


diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index d1b95a2ed6e..4140ee4c6cc 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -129,6 +129,7 @@ Common::SeekableReadStream *CastleEngine::decryptFile(const Common::Path &filena
 }
 
 extern byte kEGADefaultPalette[16][3];
+extern Common::MemoryReadStream *unpackEXE(Common::File &ms);
 
 void CastleEngine::loadAssetsDOSFullGame() {
 	Common::File file;
@@ -137,6 +138,15 @@ void CastleEngine::loadAssetsDOSFullGame() {
 	if (_renderMode == Common::kRenderEGA) {
 		_viewArea = Common::Rect(40, 33, 280, 152);
 
+		file.open("CME.EXE");
+		stream = unpackEXE(file);
+		if (stream) {
+			loadSpeakerFx(stream, 0x636d + 0x200, 0x63ed + 0x200);
+		}
+
+		delete stream;
+		file.close();
+
 		file.open("CMLE.DAT");
 		_title = load8bitBinImage(&file, 0x0);
 		_title->setPalette((byte *)&kEGADefaultPalette, 0, 16);
@@ -261,7 +271,6 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
 	if (entranceID > 0)
 		traverseEntrance(entranceID);
 
-	playSound(5, false);
 	_lastPosition = _position;
 
 	if (_currentArea->_skyColor > 0 && _currentArea->_skyColor != 255) {
@@ -275,11 +284,13 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
 	if (areaID == _startArea && entranceID == _startEntrance) {
 		_yaw = 310;
 		_pitch = 0;
+		playSound(9, false);
+	} else {
+		playSound(5, false);
 	}
 
 	debugC(1, kFreescapeDebugMove, "starting player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
 	clearTemporalMessages();
-	playSound(5, false);
 	// Ignore sky/ground fields
 	_gfx->_keyColor = 0;
 	_gfx->clearColorPairArray();
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index a2d6179a7c9..4eceb0e5bc5 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -36,7 +36,8 @@ MODULE_OBJS := \
 	objects/sensor.o \
 	sweepAABB.o \
 	sound.o \
-	ui.o
+	ui.o \
+	unpack.o
 
 ifdef USE_TINYGL
 MODULE_OBJS += \
diff --git a/engines/freescape/unpack.cpp b/engines/freescape/unpack.cpp
new file mode 100644
index 00000000000..c3790209f25
--- /dev/null
+++ b/engines/freescape/unpack.cpp
@@ -0,0 +1,440 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+
+This code was modified from https://github.com/w4kfu/unEXEPACK/blob/master/unpack.c
+
+*/
+
+#include "common/file.h"
+#include "common/memstream.h"
+
+#include "freescape/freescape.h"
+
+namespace Freescape {
+
+#define DOS_SIGNATURE 0x5A4D
+#define EXEPACK_SIGNATURE 0x4252
+
+struct memstream {
+    unsigned char *buf;
+    unsigned int length;
+    unsigned int pos;
+};
+
+struct dos_header {
+    unsigned short e_magic;
+    unsigned short e_cblp;
+    unsigned short e_cp;
+    unsigned short e_crlc;
+    unsigned short e_cparhdr;
+    unsigned short e_minalloc;
+    unsigned short e_maxalloc;
+    unsigned short e_ss;
+    unsigned short e_sp;
+    unsigned short e_csum;
+    unsigned short e_ip;
+    unsigned short e_cs;
+    unsigned short e_lfarlc;
+    unsigned short e_ovno;
+};
+
+struct exepack_header {
+    unsigned short real_ip;
+    unsigned short real_cs;
+    unsigned short mem_start;
+    unsigned short exepack_size;
+    unsigned short real_sp;
+    unsigned short real_ss;
+    unsigned short dest_len;
+    unsigned short skip_len;
+    unsigned short signature;
+};
+
+void reverse(unsigned char *s, size_t length);
+void unpack_data(unsigned char *unpacked_data, unsigned char *buf, unsigned int *unpacked_data_size, unsigned int packed_data_len);
+Common::MemoryReadStream *unpack(struct memstream *ms);
+unsigned char *create_reloc_table(struct memstream *ms, struct dos_header *dh, struct exepack_header *eh, unsigned int *reloc_table_size);
+Common::MemoryReadStream *writeExe(struct dos_header *dh, unsigned char *unpacked_data, unsigned int unpacked_data_size, unsigned char *reloc, size_t reloc_size, size_t padding);
+Common::MemoryReadStream *craftexec(struct dos_header *dh, struct exepack_header *eh, unsigned char *unpacked_data, unsigned int unpacked_data_size, unsigned char *reloc, unsigned int reloc_size);
+
+// Utils
+int test_dos_header(struct memstream *ms);
+void msopen(Common::File &file, struct memstream *ms);
+unsigned int msread(struct memstream *ms, void *buf, unsigned int count);
+int mscanread(struct memstream *ms, unsigned int count);
+unsigned int msgetavailable(struct memstream *ms);
+void msseek(struct memstream *ms, unsigned int offset);
+void msclose(struct memstream *ms);
+void *memmem(void *l, size_t l_len, const void *s, size_t s_len);
+
+void reverse(unsigned char *s, size_t length)
+{
+    size_t i, j;
+    unsigned char c;
+
+    if (length == 0x00) {
+        return;
+    }
+    for (i = 0, j = length - 1; i < j; i++, j--) {
+        c = s[i];
+        s[i] = s[j];
+        s[j] = c;
+    }
+}
+
+/* buf is already reversed, because EXEPACK use backward processing */
+void unpack_data(unsigned char *unpacked_data, unsigned char *buf, unsigned int *unpacked_data_size, unsigned int packed_data_len)
+{
+    unsigned char opcode;
+    unsigned short count;
+    unsigned char fillbyte;
+    unsigned char *save_buf = NULL;
+    unsigned char *save_unp = NULL;
+    unsigned int cur_unpacked_data_size = 0x00;
+
+    save_buf = buf;
+    save_unp = unpacked_data;
+    while (*buf == 0xFF) {
+        buf++;
+    }
+    while (1) {
+        opcode = *buf++;
+        count = *(buf) * 0x100 + *(buf + 1);
+        buf += 2;
+        if ((opcode & 0xFE) == 0xB0) {
+            fillbyte = *buf++;
+            if ((cur_unpacked_data_size + count) > *unpacked_data_size) {
+            	debug("overflow");
+            }
+            memset(unpacked_data, fillbyte, count);
+            unpacked_data += count;
+            cur_unpacked_data_size += count;
+        }
+        else if ((opcode & 0xFE) == 0xB2) {
+            if ((cur_unpacked_data_size + count) > *unpacked_data_size) {
+                debug("overflow");
+            }
+            memcpy(unpacked_data, buf, count);
+            unpacked_data += count;
+            cur_unpacked_data_size += count;
+            buf += count;
+        }
+        else {
+            debug("unknown opcode");
+        }
+        if ((opcode & 1) == 1) {
+            break;
+        }
+        if (buf - save_buf >= packed_data_len) {
+            break;
+        }
+    }
+    if (buf - save_buf < packed_data_len) {
+        if ((packed_data_len - (buf - save_buf)) > (*unpacked_data_size - (unpacked_data - save_unp))) {
+            debug("Data left are too large!");
+        }
+        memcpy(unpacked_data, buf, packed_data_len - (buf - save_buf));
+        cur_unpacked_data_size += packed_data_len - (buf - save_buf);
+    }
+    *unpacked_data_size = cur_unpacked_data_size;
+}
+
+unsigned char *create_reloc_table(struct memstream *ms, struct dos_header *dh, struct exepack_header *eh, unsigned int *reloc_table_size)
+{
+    unsigned int exepack_offset = 0x00;
+    unsigned int reloc_length;
+    int nb_reloc;
+    unsigned char *buf_reloc = NULL;
+    unsigned char *reloc = NULL;
+    int i, j;
+    unsigned short count = 0x00;
+    unsigned short entry;
+    unsigned int reloc_position = 0x00;
+
+    exepack_offset = (dh->e_cparhdr + dh->e_cs) * 16;
+    msseek(ms, exepack_offset);
+    reloc = (unsigned char*)memmem(ms->buf + exepack_offset, msgetavailable(ms), "Packed file is corrupt", strlen("Packed file is corrupt"));
+    if (!reloc) {
+        debug("Cannot find string \"Packed file is corrupt\", is it really EXEPACK ?");
+    }
+
+    reloc_length = (unsigned int)(eh->exepack_size - ((reloc - (ms->buf + exepack_offset)) & 0xFFFFFFFF) + strlen("Packed file is corrupt"));
+    nb_reloc = (reloc_length - 16 * sizeof (unsigned short)) / 2;
+    *reloc_table_size = nb_reloc * 2 * sizeof(unsigned short);
+    buf_reloc = (unsigned char*)malloc(sizeof (char) * *reloc_table_size);
+    assert(buf_reloc);
+    reloc += strlen("Packed file is corrupt");
+    msseek(ms, (reloc - ms->buf) & 0xFFFFFFFF);
+    for (i = 0; i < 16; i++) {
+        if (msread(ms, &count, sizeof (unsigned short)) != sizeof (unsigned short)) {
+            debug("msread failed");
+        }
+        for (j = 0; j < count; j++) {
+            if (msread(ms, &entry, sizeof (unsigned short)) != sizeof (unsigned short)) {
+                debug("msread failed");
+            }
+            if (reloc_position >= *reloc_table_size) {
+                debug("overflow");
+            }
+            *(unsigned short*)(buf_reloc + reloc_position) = entry;
+            reloc_position += 2;
+            if (reloc_position >= *reloc_table_size) {
+                debug("overflow");
+            }
+            *(unsigned short*)(buf_reloc + reloc_position) = (i * 0x1000) & 0xFFFF;
+            reloc_position += 2;
+        }
+    }
+    *reloc_table_size = reloc_position;
+    return buf_reloc;
+}
+
+Common::MemoryReadStream *writeExe(struct dos_header *dh, unsigned char *unpacked_data, unsigned int unpacked_data_size, unsigned char *reloc, size_t reloc_size, size_t padding)
+{
+    Common::MemoryWriteStreamDynamic buf(DisposeAfterUse::NO);
+
+    buf.write(dh, sizeof (struct dos_header));
+    buf.write(reloc, reloc_size);
+    for (size_t i = 0; i < padding; i++) {
+        buf.write("\x00", 1);
+    }
+    buf.write(unpacked_data, unpacked_data_size);
+	return (new Common::MemoryReadStream(buf.getData(), buf.size()));
+}
+
+Common::MemoryReadStream *craftexec(struct dos_header *dh, struct exepack_header *eh, unsigned char *unpacked_data, unsigned int unpacked_data_size, unsigned char *reloc, unsigned int reloc_size)
+{
+    struct dos_header dhead;
+    int header_size;
+    int total_length;
+    int padding_length;
+
+    memset(&dhead, 0, sizeof (struct dos_header));
+    header_size = sizeof (struct dos_header) + reloc_size;
+    dhead.e_magic = DOS_SIGNATURE;
+    dhead.e_cparhdr = (header_size / 16) & 0xFFFF;
+    dhead.e_cparhdr = (dhead.e_cparhdr / 32 + 1) * 32;
+    padding_length = dhead.e_cparhdr * 16 - header_size;
+    total_length = header_size + padding_length + unpacked_data_size;
+    dhead.e_ss = eh->real_ss;
+    dhead.e_sp = eh->real_sp;
+    dhead.e_ip = eh->real_ip;
+    dhead.e_cs = eh->real_cs;
+    dhead.e_minalloc = dh->e_minalloc;
+    dhead.e_maxalloc = 0xFFFF;
+    dhead.e_lfarlc = sizeof (struct dos_header);
+    dhead.e_crlc = (reloc_size / (2 * sizeof (unsigned short))) & 0xFFFF;
+    dhead.e_cblp = total_length % 512;
+    dhead.e_cp = (total_length / 512 + 1) & 0xFFFF;
+    //print_dos_header(&dhead);
+    return writeExe(&dhead, unpacked_data, unpacked_data_size, reloc, reloc_size, padding_length);
+}
+
+Common::MemoryReadStream *unpack(struct memstream *ms)
+{
+    struct dos_header dh;
+    struct exepack_header eh;
+    unsigned int exepack_offset = 0x00;
+    unsigned char *unpacked_data = NULL;
+    unsigned int unpacked_data_size = 0x00;
+    unsigned int packed_data_start;
+    unsigned int packed_data_end;
+    unsigned int packed_data_len;
+    unsigned int reloc_size;
+    unsigned char *reloc = NULL;
+
+    if (msread(ms, &dh, sizeof (struct dos_header)) != sizeof (struct dos_header)) {
+        return nullptr;
+    }
+    //print_dos_header(&dh);
+    exepack_offset = (dh.e_cparhdr + dh.e_cs) * 16;
+    msseek(ms, exepack_offset);
+    if (msread(ms, &eh, sizeof (struct exepack_header)) != sizeof (struct exepack_header)) {
+        return nullptr;
+    }
+    //print_exepack_header(&eh);
+    if ((eh.signature != EXEPACK_SIGNATURE && eh.skip_len != EXEPACK_SIGNATURE) || eh.exepack_size == 0x00) {
+        debug("This is not a valid EXEPACK executable");
+        return nullptr;
+    }
+    debug("Header exepack = %X\n", exepack_offset);
+    //print_exepack_header(&eh);
+    unpacked_data_size = eh.dest_len * 16;
+    unpacked_data = (unsigned char*)malloc(sizeof (char) * unpacked_data_size);
+    assert(unpacked_data);
+    memset(unpacked_data, 0x00, sizeof (char) * unpacked_data_size);
+    packed_data_start = dh.e_cparhdr * 16;
+    packed_data_end = exepack_offset;
+    packed_data_len = packed_data_end - packed_data_start;
+    msseek(ms, packed_data_start);
+    if (mscanread(ms, packed_data_len) == 0x00) {
+        free(unpacked_data);
+        return nullptr;
+    }
+    reverse(ms->buf + packed_data_start, packed_data_len);
+    unpack_data(unpacked_data, ms->buf + packed_data_start, &unpacked_data_size, packed_data_len);
+    reverse(unpacked_data, unpacked_data_size);
+    reloc = create_reloc_table(ms, &dh, &eh, &reloc_size);
+    Common::MemoryReadStream *ret = craftexec(&dh, &eh, unpacked_data, unpacked_data_size, reloc, reloc_size);
+    free(unpacked_data);
+	return ret;
+}
+
+void *memmem(void *l, size_t l_len, const void *s, size_t s_len)
+{
+    register char *cur, *last;
+    char *cl = (char *)l;
+    const char *cs = (const char *)s;
+
+    if (l_len == 0 || s_len == 0) {
+        return NULL;
+    }
+    if (l_len < s_len) {
+        return NULL;
+    }
+    if (s_len == 1) {
+        return (void *)memchr(l, (int)*cs, l_len);
+    }
+    last = cl + l_len - s_len;
+    for (cur = (char *)cl; cur <= last; cur++) {
+        if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) {
+            return cur;
+        }
+    }
+    return NULL;
+}
+
+void msopen(Common::File &file, struct memstream *ms)
+{
+    assert(ms);
+
+    ms->buf = (unsigned char*)malloc(sizeof (char) * file.size());
+    assert(ms->buf);
+
+    assert(file.read(ms->buf, file.size()) == file.size());
+    ms->pos = 0x00;
+    ms->length = file.size();
+}
+
+unsigned int msread(struct memstream *ms, void *buf, unsigned int count)
+{
+    unsigned int length;
+
+    if (buf == NULL) {
+        return 0;
+    }
+    if (ms->pos > ms->length) {
+        debug("invalid read");
+    }
+    if (count < (ms->length - ms->pos)) {
+        length = count;
+    }
+    else {
+        length = ms->length - ms->pos;
+    }
+    if (length > 0) {
+        memcpy(buf, ms->buf + ms->pos, length);
+    }
+    ms->pos += length;
+    return length;
+}
+
+int mscanread(struct memstream *ms, unsigned int count)
+{
+    if (ms->pos > ms->length) {
+        return 0;
+    }
+    if (count > (ms->length - ms->pos)) {
+        return 0;
+    }
+    return 1;
+}
+
+unsigned int msgetavailable(struct memstream *ms)
+{
+    if (ms->pos > ms->length) {
+        return 0;
+    }
+    return ms->length - ms->pos;
+}
+
+void msseek(struct memstream *ms, unsigned int offset)
+{
+    if (offset > ms->length) {
+        debug("invalid seek : 0x%X", offset);
+    }
+    ms->pos = offset;
+}
+
+void msclose(struct memstream *ms)
+{
+    if (ms != NULL) {
+        if (ms->buf != NULL) {
+            free(ms->buf);
+            ms->buf = NULL;
+        }
+    }
+}
+
+int test_dos_header(struct memstream *ms)
+{
+    struct dos_header dh;
+
+    if (ms == NULL) {
+        return 0;
+    }
+    if (msread(ms, &dh, sizeof (struct dos_header)) != sizeof (struct dos_header)) {
+        return 0;
+    }
+    msseek(ms, 0x00);
+    if (dh.e_magic != DOS_SIGNATURE) {
+        return 0;
+    }
+    /* at least one page */
+    if (dh.e_cp == 0) {
+        return 0;
+    }
+    /* last page must not hold 0 bytes */
+    if (dh.e_cblp == 0) {
+        return 0;
+    }
+    /* not even number of paragraphs */
+    if (dh.e_cparhdr % 2 != 0) {
+        return 0;
+    }
+    return 1;
+}
+
+Common::MemoryReadStream *unpackEXE(Common::File &file) {
+    struct memstream ms;
+    msopen(file, &ms);
+    if (test_dos_header(&ms) == 0) {
+        msclose(&ms);
+        return nullptr;
+    }
+    Common::MemoryReadStream *ret = unpack(&ms);
+    msclose(&ms);
+	return ret;
+}
+
+}
\ No newline at end of file




More information about the Scummvm-git-logs mailing list