[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