GAMOS: Add support loading games with engine version 0x12 and 0x0b

This commit is contained in:
Marisa-Chan
2025-12-26 15:08:10 +07:00
parent 0a1563c1cd
commit 8ef1b1b362
5 changed files with 149 additions and 58 deletions
+20 -5
View File
@@ -37,7 +37,9 @@ bool Archive::open(const Common::Path &name) {
seek(-12, SEEK_END);
_dirOffset = 12 + readUint32LE();
const uint32 dirInfSize = readUint32LE();
_dirOffset = 12 + dirInfSize;
skip(4);
uint32 magic = readUint32LE();
@@ -46,8 +48,16 @@ bool Archive::open(const Common::Path &name) {
seek(-_dirOffset, SEEK_END);
_dirCount = readUint32LE();
_dataOffset = readUint32LE();
byte tmpbuf[8] = {0, 0 ,0, 0, 0, 0, 0, 0};
/* read it into buffer firs, because it's can be less than 8 bytes */
if (dirInfSize > 8)
read(tmpbuf, 8);
else
read(tmpbuf, dirInfSize);
_dirCount = READ_LE_UINT32(tmpbuf);
_dataOffset = READ_LE_UINT32(tmpbuf + 4);
seek(-(_dirOffset + _dirCount * 5), SEEK_END);
@@ -141,12 +151,17 @@ bool Archive::readCompressedData(RawData *out) {
/* read size */
const byte szsize = (t & 3) + 1;
if (_version == 0xb)
skip(szsize);
/* big data size */
for (uint i = 0; i < szsize; ++i)
_lastReadSize |= readByte() << (i << 3);
/* is compressed */
if (t & 0xC) {
if (_version == 0xb) {
skip(szsize + 1);
} else if (t & 0xC) {
for (uint i = 0; i < szsize; ++i)
_lastReadDecompressedSize |= readByte() << (i << 3);
}
@@ -159,7 +174,7 @@ bool Archive::readCompressedData(RawData *out) {
out->resize(_lastReadSize);
read(out->data(), _lastReadSize);
if (!_lastReadDecompressedSize)
if (!_lastReadDecompressedSize || _version != 0x18)
return true;
/* looks hacky but we just allocate array for decompressed and swap it with compressed */
+6
View File
@@ -61,6 +61,10 @@ public:
static void decompress(RawData const *in, RawData *out);
void setVersion(int v) {
_version = v;
}
public:
uint32 _lastReadSize = 0;
@@ -76,6 +80,8 @@ private:
Common::Array<ArchiveDir> _directories;
int _version = 0x18;
//bool _error;
};
+90 -24
View File
@@ -86,6 +86,10 @@ Common::Error GamosEngine::run() {
else
setCP1252();
_engineVersion = getEngineVersion() & 0xFF;
_arch.setVersion(_engineVersion);
init(getRunFile());
Common::Event e;
@@ -564,30 +568,43 @@ bool GamosEngine::initMainDatas() {
}
/* skip count of pages 1kb size */
dataStream.skip(4);
/* skip read buffer size */
dataStream.skip(4);
_width = dataStream.readUint32LE();
_height = dataStream.readUint32LE();
_gridCellW = dataStream.readSint32LE();
_gridCellH = dataStream.readSint32LE();
_movieCount = dataStream.readUint32LE();
dataStream.skip(3); // skip unknown unused
_fps = dataStream.readByte();
dataStream.skip(1); // skip unknown unused
_drawCursor = dataStream.readByte();
_fadeEffectID = dataStream.readByte();
_playIntro = dataStream.readByte();
dataStream.skip(4); // 4
if (_engineVersion >= 0x12) {
/* skip read buffer size */
dataStream.skip(4); // 8
}
_width = dataStream.readUint32LE(); // c
_height = dataStream.readUint32LE(); // 10
_gridCellW = dataStream.readSint32LE(); // 14
_gridCellH = dataStream.readSint32LE(); // 18
_movieCount = dataStream.readUint32LE(); // 1c
dataStream.skip(3); // skip unknown unused 20
_fps = dataStream.readByte(); // 23
dataStream.skip(1); // skip unknown unused 24
_drawCursor = dataStream.readByte(); // 25
_introPos.x = dataStream.readSint32LE();
_introPos.y = dataStream.readSint32LE();
_introSize.x = dataStream.readSint32LE();
_introSize.y = dataStream.readSint32LE();
if (_engineVersion >= 0x12) {
_fadeEffectID = dataStream.readByte(); // 26
_playIntro = dataStream.readByte(); // 27
} else {
_playIntro = dataStream.readByte();
_fadeEffectID = dataStream.readByte();
}
int64 pos = dataStream.pos();
_string1 = dataStream.readString(0, 64);
dataStream.seek(pos + 64);
_winCaption = dataStream.readString(0, 9);
if (_engineVersion >= 0x12) {
_introPos.x = dataStream.readSint32LE(); // 28
_introPos.y = dataStream.readSint32LE(); // 2c
_introSize.x = dataStream.readSint32LE(); // 30
_introSize.y = dataStream.readSint32LE(); // 34
int64 pos = dataStream.pos();
_string1 = dataStream.readString(0, 64); // 38
dataStream.seek(pos + 64);
} else {
_string1 = "";
}
_winCaption = dataStream.readString(0, 32); // 78
if (!_screen) {
initGraphics(_width, _height);
@@ -1085,7 +1102,7 @@ void GamosEngine::readData2(const RawData &data) {
//warning("Game data size %d", data.size());
if (getEngineVersion() == 0x80000018) {
if (_engineVersion == 0x18) {
_stateExt = dataStream.readString(0, 4); // FIX ME
dataStream.seek(4);
_messageProc._inputFlags = dataStream.readByte(); //4
@@ -1121,7 +1138,7 @@ void GamosEngine::readData2(const RawData &data) {
for (int i = 0; i < 12; i++) {
_messageProc._keyCodes[i] = dataStream.readByte();
}
} else if (getEngineVersion() == 0x80000016) {
} else if (_engineVersion >= 0x12 && _engineVersion <= 0x16) {
_stateExt = dataStream.readString(0, 4); // FIX ME
dataStream.seek(4);
_messageProc._inputFlags = dataStream.readByte(); //4
@@ -1156,6 +1173,52 @@ void GamosEngine::readData2(const RawData &data) {
for (int i = 0; i < 12; i++) {
_messageProc._keyCodes[i] = dataStream.readByte();
}
} else if (_engineVersion == 0xb) {
_stateExt = dataStream.readString(0, 4); // FIX ME
dataStream.seek(4);
_messageProc._inputFlags = dataStream.readByte(); //4
dataStream.seek(8);
_svModuleId = dataStream.readSint32LE(); // 8
_svGameScreen = dataStream.readSint32LE(); // c
_d2_fld10 = dataStream.readUint32LE(); // 10
_enableSounds = dataStream.readByte() != 0 ? true : false; // x14
_enableMidi = dataStream.readByte() != 0 ? true : false; //x15
_enableInput = dataStream.readByte() != 0 ? true : false; // x16
_enableMovie = dataStream.readByte() != 0 ? true : false; // x17
_enableCDAudio = false;
_cdAudioTrack = -1;
_scrollX = 0;
_scrollY = 0;
_scrollTrackObj = -1;
_scrollSpeed = 16;
_scrollCutoff = 80;
_scrollSpeedReduce = -1;
_scrollBorderL = 0;
_scrollBorderR = 0;
_scrollBorderU = 0;
_scrollBorderB = 0;
_sndChannels = dataStream.readByte(); // x18
_sndVolume = dataStream.readByte(); // x19
_midiVolume = dataStream.readByte(); // x1a
_svFps = dataStream.readByte(); // x1b
_svFrame = dataStream.readSint32LE(); // x1c
_midiTrack = dataStream.readUint32LE(); // x20
_mouseCursorImgId = dataStream.readSint32LE(); // x24
//0x28
_messageProc._keyCodes[0] = KeyCodes::WIN_UP;
_messageProc._keyCodes[1] = KeyCodes::WIN_PRIOR;
_messageProc._keyCodes[2] = KeyCodes::WIN_RIGHT;
_messageProc._keyCodes[3] = KeyCodes::WIN_NEXT;
_messageProc._keyCodes[4] = KeyCodes::WIN_DOWN;
_messageProc._keyCodes[5] = KeyCodes::WIN_END;
_messageProc._keyCodes[6] = KeyCodes::WIN_LEFT;
_messageProc._keyCodes[7] = KeyCodes::WIN_HOME;
_messageProc._keyCodes[8] = KeyCodes::WIN_SPACE;
_messageProc._keyCodes[9] = KeyCodes::WIN_RETURN;
_messageProc._keyCodes[10] = KeyCodes::WIN_TAB;
_messageProc._keyCodes[11] = KeyCodes::WIN_INVALID;
_messageProc._keyCodes[12] = KeyCodes::WIN_INVALID;
}
}
@@ -2292,6 +2355,9 @@ uint32 GamosEngine::doScript(uint32 scriptAddress) {
void GamosEngine::vmCallDispatcher(VM::Context *ctx, uint32 funcID) {
uint32 arg1 = 0, arg2 = 0;
if (_engineVersion <= 0x12 && funcID >= 47) // skip 47 func for old versions
funcID++;
switch (funcID) {
case 0:
_restartUpdateObject = true;
+2
View File
@@ -594,6 +594,8 @@ private:
bool _needReload = false;
uint32 _engineVersion = 0x18;
protected:
// Engine APIs
Common::Error run() override;
+31 -29
View File
@@ -45,36 +45,38 @@ void SystemProc::processMessage(const Common::Event &ev) {
if (_rawKeyCode == 0)
_rawKeyCode = ACT_NONE;
if (winKey == _keyCodes[0])
_act1 = 0;
else if (winKey == _keyCodes[1])
_act1 = 1;
else if (winKey == _keyCodes[2])
_act1 = 2;
else if (winKey == _keyCodes[3])
_act1 = 3;
else if (winKey == _keyCodes[4])
_act1 = 4;
else if (winKey == _keyCodes[5])
_act1 = 5;
else if (winKey == _keyCodes[6])
_act1 = 6;
else if (winKey == _keyCodes[7])
_act1 = 7;
else {
if (winKey == _keyCodes[8])
_act2 = ACT2_MOUSEUP_L;
else if (winKey == _keyCodes[9])
_act2 = ACT2_MOUSEUP_R;
else if (winKey == _keyCodes[10])
_act2 = ACT2_TAB;
else if (winKey == _keyCodes[11])
_act2 = ACT2_HELP;
else
return;
if (winKey != KeyCodes::WIN_INVALID) {
if (winKey == _keyCodes[0])
_act1 = 0;
else if (winKey == _keyCodes[1])
_act1 = 1;
else if (winKey == _keyCodes[2])
_act1 = 2;
else if (winKey == _keyCodes[3])
_act1 = 3;
else if (winKey == _keyCodes[4])
_act1 = 4;
else if (winKey == _keyCodes[5])
_act1 = 5;
else if (winKey == _keyCodes[6])
_act1 = 6;
else if (winKey == _keyCodes[7])
_act1 = 7;
else {
if (winKey == _keyCodes[8])
_act2 = ACT2_MOUSEUP_L;
else if (winKey == _keyCodes[9])
_act2 = ACT2_MOUSEUP_R;
else if (winKey == _keyCodes[10])
_act2 = ACT2_TAB;
else if (winKey == _keyCodes[11])
_act2 = ACT2_HELP;
else
return;
_rawKeyCode = winKey;
return;
_rawKeyCode = winKey;
return;
}
}
if ((_act1 < 8) && (ev.kbd.flags & Common::KBD_SHIFT))