GAMOS: First working movie player

This commit is contained in:
Marisa-Chan
2025-08-14 15:45:32 +07:00
committed by Eugene Sandulenko
commit 7ba3dc1a30
22 changed files with 3028 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
engines/gamos/metaengine.cpp
+3
View File
@@ -0,0 +1,3 @@
# This file is included from the main "configure" script
# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
add_engine gamos "Gamos" no "" "" "highres" "midi"
+38
View File
@@ -0,0 +1,38 @@
/* 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/>.
*
*/
#include "gamos/console.h"
namespace Gamos {
Console::Console() : GUI::Debugger() {
registerCmd("test", WRAP_METHOD(Console, Cmd_test));
}
Console::~Console() {
}
bool Console::Cmd_test(int argc, const char **argv) {
debugPrintf("Test\n");
return true;
}
} // End of namespace Gamos
+40
View File
@@ -0,0 +1,40 @@
/* 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/>.
*
*/
#ifndef GAMOS_CONSOLE_H
#define GAMOS_CONSOLE_H
#include "gui/debugger.h"
namespace Gamos {
class Console : public GUI::Debugger {
private:
bool Cmd_test(int argc, const char **argv);
public:
Console();
~Console() override;
};
} // End of namespace Gamos
#endif // GAMOS_CONSOLE_H
+3
View File
@@ -0,0 +1,3 @@
begin_section("Gamos");
add_person("Name 1", "Handle 1", "");
end_section();
+45
View File
@@ -0,0 +1,45 @@
/* 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/>.
*
*/
#include "base/plugins.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "common/md5.h"
#include "common/str-array.h"
#include "common/translation.h"
#include "common/util.h"
#include "gamos/detection.h"
#include "gamos/detection_tables.h"
const DebugChannelDef GamosMetaEngineDetection::debugFlagList[] = {
{ Gamos::kDebugGraphics, "Graphics", "Graphics debug level" },
{ Gamos::kDebugPath, "Path", "Pathfinding debug level" },
{ Gamos::kDebugFilePath, "FilePath", "File path debug level" },
{ Gamos::kDebugScan, "Scan", "Scan for unrecognised games" },
{ Gamos::kDebugScript, "Script", "Enable debug script dump" },
DEBUG_CHANNEL_END
};
GamosMetaEngineDetection::GamosMetaEngineDetection() : AdvancedMetaEngineDetection(
Gamos::gameDescriptions, Gamos::gamosGames) {
}
REGISTER_PLUGIN_STATIC(GAMOS_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, GamosMetaEngineDetection);
+69
View File
@@ -0,0 +1,69 @@
/* 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/>.
*
*/
#ifndef GAMOS_DETECTION_H
#define GAMOS_DETECTION_H
#include "engines/advancedDetector.h"
namespace Gamos {
enum GamosDebugChannels {
kDebugGraphics = 1,
kDebugPath,
kDebugScan,
kDebugFilePath,
kDebugScript,
};
extern const PlainGameDescriptor gamosGames[];
extern const ADGameDescription gameDescriptions[];
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS1
} // End of namespace Gamos
class GamosMetaEngineDetection : public AdvancedMetaEngineDetection<ADGameDescription> {
static const DebugChannelDef debugFlagList[];
public:
GamosMetaEngineDetection();
~GamosMetaEngineDetection() override {}
const char *getName() const override {
return "gamos";
}
const char *getEngineName() const override {
return "Gamos";
}
const char *getOriginalCopyright() const override {
return "Gamos (C)";
}
const DebugChannelDef *getDebugChannels() const override {
return debugFlagList;
}
};
#endif // GAMOS_DETECTION_H
+43
View File
@@ -0,0 +1,43 @@
/* 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/>.
*
*/
namespace Gamos {
const PlainGameDescriptor gamosGames[] = {
{ "gamos", "Gamos" },
{ 0, 0 }
};
const ADGameDescription gameDescriptions[] = {
{
"solgamer",
0,
AD_ENTRY1s("solgamer.exe", "6049dd1645071da1b60cdd395e6999ba", 24658521),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_UNSTABLE,
GUIO1(GUIO_NONE)
},
AD_TABLE_END_MARKER
};
} // End of namespace Gamos
+211
View File
@@ -0,0 +1,211 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "gamos/gamos.h"
namespace Gamos {
Archive::Archive() {
};
Archive::~Archive() {
};
bool Archive::open(const Common::Path &name) {
bool res = File::open(name);
if (!res)
return false;
seek(-12, SEEK_END);
_dirOffset = 12 + readUint32LE();
skip(4);
uint32 magic = readUint32LE();
if (magic != 0x3d53563d) // =VS=
return false;
seek(-_dirOffset, SEEK_END);
_dirCount = readUint32LE();
_dataOffset = readUint32LE();
seek(-(_dirOffset + _dirCount * 5), SEEK_END);
_directories.resize(_dirCount);
for(uint i = 0; i < _dirCount; ++i) {
ArchiveDir &dir = _directories[i];
dir.offset = readUint32LE();
dir.id = readByte();
}
return true;
}
bool Archive::seekDir(uint id) {
int16 idx = findDirByID(id);
if (idx < 0)
return false;
const ArchiveDir &dir = _directories[idx];
if ( !seek(_dataOffset + dir.offset, SEEK_SET) )
return false;
return true;
}
int32 Archive::readPackedInt() {
byte b = readByte();
if ( !(b & 0x80) )
return b;
byte num = 0;
byte skipsz = 0;
if ( !(b & 0x20) )
num = b & 0x1f;
else
num = 1 + ((b >> 2) & 3);
if (num > 4) {
skipsz = num - 4;
num = 4;
}
int32 val = 0;
for(int i = 0; i < num; ++i)
val |= readByte() << (i << 3);
if (skipsz) {
skip(skipsz);
/* warning !!!! */
printf("readPackedInt skipped %d\n", skipsz);
}
static int32 negs[4] {0, -1, -1025, -263169};
static int32 adds[4] {0, 0x80, 0x480, 0x40480};
if (b & 0x20) {
val += (b & 3) * (1 << ((num << 3) & 0x1f));
if (b & 0x10)
val = negs[num] - val;
else
val += adds[num];
}
return val;
}
RawData *Archive::readCompressedData() {
RawData *data = new RawData();
if (!readCompressedData(data)) {
delete data;
data = nullptr;
}
return data;
}
bool Archive::readCompressedData(RawData *out) {
const byte t = readByte();
if ((t & 0x80) == 0)
return false;
_lastReadDecompressedSize = 0;
_lastReadSize = 0;
if (t & 0x40) {
/* small uncompressed data */
_lastReadSize = t & 0x1F;
} else {
/* read size */
const byte szsize = (t & 3) + 1;
/* big data size */
for (uint i = 0; i < szsize; ++i)
_lastReadSize |= readByte() << (i << 3);
/* is compressed */
if (t & 0xC) {
for (uint i = 0; i < szsize; ++i)
_lastReadDecompressedSize |= readByte() << (i << 3);
}
}
if (!_lastReadSize)
return false;
_lastReadDataOffset = pos();
out->resize(_lastReadSize);
read(out->data(), _lastReadSize);
if (!_lastReadDecompressedSize)
return true;
/* looks hacky but we just allocate array for decompressed and swap it with compressed */
RawData compressed(_lastReadDecompressedSize);
out->swap(compressed);
decompress(&compressed, out);
return true;
}
void Archive::decompress(RawData const *in, RawData *out) {
uint pos = 0;
uint outPos = 0;
while (pos < in->size()) {
byte ctrlBits = (*in)[pos];
pos++;
for(int bitsLeft = 8; bitsLeft > 0; --bitsLeft) {
if (pos >= in->size())
return;
if (ctrlBits & 1) {
(*out)[outPos] = (*in)[pos];
outPos++;
pos++;
} else {
byte b1 = (*in)[pos];
byte b2 = (*in)[pos + 1];
pos += 2;
byte num = (b2 & 0xF) + 3;
uint16 distance = b1 | ((b2 & 0xF0) << 4);
for(int i = 0; i < num; ++i) {
(*out)[outPos] = (*out)[outPos - distance];
outPos++;
}
}
ctrlBits >>= 1;
}
}
}
};
+66
View File
@@ -0,0 +1,66 @@
#ifndef GAMOS_FILE_H
#define GAMOS_FILE_H
#include "common/file.h"
namespace Gamos {
typedef Common::Array<byte> RawData;
struct ArchiveDir {
uint32 offset;
byte id;
};
class Archive : public Common::File {
public:
Archive();
~Archive() override;
bool open(const Common::Path &name) override;
uint16 getDirCount() const {
return _dirCount;
}
int16 findDirByID(uint id) const {
for (uint i = 0; i < _directories.size(); ++i) {
if (_directories[i].id == id)
return i;
}
return -1;
}
bool seekDir(uint id);
int32 readPackedInt();
RawData *readCompressedData();
bool readCompressedData(RawData *out);
static void decompress(RawData const *in, RawData *out);
public:
uint32 _lastReadSize = 0;
uint32 _lastReadDecompressedSize = 0;
uint32 _lastReadDataOffset = 0;
private:
int32 _dirOffset;
byte _dirCount;
uint32 _dataOffset;
Common::Array<ArchiveDir> _directories;
bool _error;
};
}; // namespace Gamos
#endif // GAMOS_FILE_H
+660
View File
@@ -0,0 +1,660 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#define FORBIDDEN_SYMBOL_EXCEPTION_sprintf
#define FORBIDDEN_SYMBOL_EXCEPTION_exit
#define FORBIDDEN_SYMBOL_EXCEPTION_rand
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#define FORBIDDEN_SYMBOL_EXCEPTION_fopen
#define FORBIDDEN_SYMBOL_EXCEPTION_fwrite
#define FORBIDDEN_SYMBOL_EXCEPTION_fclose
#include "gamos/gamos.h"
#include "graphics/framelimiter.h"
#include "gamos/detection.h"
#include "gamos/console.h"
#include "common/scummsys.h"
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
#include "common/system.h"
#include "common/rect.h"
#include "engines/util.h"
#include "graphics/paletteman.h"
#include "common/keyboard.h"
#include "endian.h"
#include "audio/mididrv.h"
#include "audio/midiplayer.h"
#include <cstdio>
namespace Gamos {
GamosEngine *g_engine;
const byte GamosEngine::_xorKeys[32] = {0xa7, 0x15, 0xf0, 0x56, 0xf3, 0xfa, 0x84, 0x2c,
0xfd, 0x81, 0x38, 0xac, 0x73, 0xd2, 0x22, 0x47,
0xa0, 0x12, 0xb8, 0x19, 0x20, 0x6a, 0x26, 0x7c,
0x32, 0x57, 0xdd, 0xb2, 0x38, 0xa7, 0x95, 0x7a};
GamosEngine::GamosEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst),
_gameDescription(gameDesc), _randomSource("Gamos") {
g_engine = this;
}
GamosEngine::~GamosEngine() {
delete _screen;
}
uint32 GamosEngine::getFeatures() const {
return _gameDescription->flags;
}
Common::String GamosEngine::getGameId() const {
return _gameDescription->gameId;
}
Common::Error GamosEngine::run() {
// Set the engine's debugger console
setDebugger(new Console());
// If a savegame was selected from the launcher, load it
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot != -1)
(void)loadGameState(saveSlot);
Common::String mname("solgamer.exe");
init(mname);
Common::Event e;
Graphics::FrameLimiter limiter(g_system, 60);
while (!shouldQuit()) {
while (g_system->getEventManager()->pollEvent(e)) {
}
// g_system->getPaletteManager()->setPalette(pal, 0, 256);
limiter.delayBeforeSwap();
_screen->update();
limiter.startFrame();
}
return Common::kNoError;
}
Common::Error GamosEngine::syncGame(Common::Serializer &s) {
// The Serializer has methods isLoading() and isSaving()
// if you need to specific steps; for example setting
// an array size after reading it's length, whereas
// for saving it would write the existing array's length
int dummy = 0;
s.syncAsUint32LE(dummy);
return Common::kNoError;
}
bool GamosEngine::loader2() {
int32 skipsz = _arch.readSint32LE();
_arch.skip(skipsz);
if (_arch.readByte() != 7)
return false;
RawData data;
if (!_arch.readCompressedData(&data))
return false;
int32 p1 = 0;
int32 p2 = 0;
int32 pid = 0;
byte resType = 0;
int32 resSize = 0;
Common::MemoryReadStream dataStream(data.data(), data.size());
while (!dataStream.eos()) {
byte curByte = dataStream.readByte();
if (curByte == 0) {
break;
} else if (curByte == 0x80) {
p1 = 0;
p2 = 0;
pid = dataStream.readSint32LE();
} else if (curByte == 1) {
p1 = dataStream.readSint32LE();
} else if (curByte == 2) {
p2 = dataStream.readSint32LE();
} else if (curByte == 7) {
int32 needsz = dataStream.readSint32LE(); // check free mem ?
printf("7777 want %d\n", needsz);
} else if (curByte == 0x40) {
resSize = 4;
resType = 0x40;
if (!loadResHandler(resType, pid, p1, p2, 0, data.data() + dataStream.pos(), resSize))
return false;
dataStream.skip(resSize);
} else if (curByte == 0x41 || curByte == 0x42) {
resSize = dataStream.readSint32LE();
resType = curByte;
if (!loadResHandler(resType, pid, p1, p2, 0, data.data() + dataStream.pos(), resSize))
return false;
dataStream.skip(resSize);
} else if (curByte == 0x43) {
resSize = 0x10;
resType = 0x43;
if (!loadResHandler(resType, pid, p1, p2, 0, data.data() + dataStream.pos(), resSize))
return false;
dataStream.skip(resSize);
} else if (curByte == 0xff) {
printf("0xFF %d %d %d ", pid, p1, p2);
if (!reuseLastResource(resType, pid, p1, p2, 0))
return false;
} else {
printf("loader2 want %x\n", curByte);
return false;
}
}
return true;
}
bool GamosEngine::loadModule(uint id) {
if ( (!_runReadDataMod && !initOrLoadSave(_saveLoadID)) ||
!_arch.seekDir(1) )
return false;
_currentModuleID = id;
const byte targetDir = 2 + id;
bool prefixLoaded = false;
byte prevByte = 0;
bool doLoad = true;
int32 p1 = 0;
int32 p2 = 0;
int32 p3 = 0;
int32 pid = 0;
while(doLoad) {
byte curByte = _arch.readByte();
switch(curByte) {
case 0:
if (prefixLoaded) {
doLoad = false;
break;
}
prefixLoaded = true;
if (!_arch.seekDir(targetDir))
return false;
break;
case CONFTP_P1:
p1 = _arch.readPackedInt();
break;
case CONFTP_P2:
p2 = _arch.readPackedInt();
break;
case CONFTP_P3:
p3 = _arch.readPackedInt();
break;
case 4: {
_resReadOffset = _arch.pos();
bool isResource = true;
if (prevByte == RESTP_F) {
RawData data;
if (!_arch.readCompressedData(&data))
return false;
if (_runReadDataMod && BYTE_004177f7 == 0)
readData2(data);
if (BYTE_004177f7 == 0) {
//FUN_00403868();
}
isResource = false; /* do not loadResHandler */
} else if (prevByte == RESTP_10) {
if (!initMainDatas())
return false;
isResource = false; /* do not loadResHandler */
} else if (prevByte == RESTP_11) {
RawData data;
if (!_arch.readCompressedData(&data))
return false;
if (pid == id)
readElementsConfig(data);
isResource = false; /* do not loadResHandler */
} else if (prevByte == RESTP_18) {
/* free elements ? */
}
if (isResource) {
RawData data;
if (!_arch.readCompressedData(&data))
return false;
if (!loadResHandler(prevByte, pid, p1, p2, p3, data))
return false;
}
/* memory management
if (prevByte == RESTP_43) {
} else if (prevByte != RESTP_11 && prevByte != RESTP_20) {
// grow used space
}
*/
break;
}
case 5: {
byte t = _arch.readByte();
if (t == 0 || (t & 0xec) != 0xec)
return false;
byte sz = (t & 3) + 1;
int32 movieSize = 0;
for(uint i = 0; i < sz; ++i)
movieSize |= _arch.readByte() << (i * 8);
if (prevByte == 0x14)
_movieOffsets[pid] = _arch.pos();
_arch.skip(movieSize);
break;
}
case 6:
if (!loader2())
return false;
break;
case 0xFF:
return false;
break;
default:
p1 = 0;
p2 = 0;
p3 = 0;
pid = 0;
prevByte = curByte & CONFTP_RESMASK;
if ( (curByte & CONFTP_IDFLG) == 0 )
pid = _arch.readPackedInt();
break;
}
}
_screen->addDirtyRect(_screen->getBounds());
_screen->update();
return true;
}
bool GamosEngine::loadResHandler(uint tp, uint pid, uint p1, uint p2, uint p3, const byte *data, size_t dataSize) {
if (tp == RESTP_12) {
setFPS(_fps);
} else if (tp == RESTP_18) {
printf("18 size %d\n", dataSize);
} else if (tp == RESTP_40) {
return loadRes40(pid, data, dataSize);
} else if (tp == RESTP_41) {
return loadRes41(pid, data, dataSize);
} else if (tp == RESTP_42) {
return loadRes42(pid, p1, data, dataSize);
} else if (tp == RESTP_43) {
return loadRes43(pid, p1, p2, data, dataSize);
} else if (tp == RESTP_50) {
//printf("data 50 size %d\n", dataSize);
} else if (tp == RESTP_51) {
//printf("sound size %d\n", dataSize);
} else if (tp == RESTP_52) {
return loadRes52(pid, data, dataSize);
//printf("midi size %d\n", dataSize);
} else if (tp == RESTP_XORSEQ0) {
loadXorSeq(data, dataSize, 0);
} else if (tp == RESTP_XORSEQ1) {
loadXorSeq(data, dataSize, 1);
} else if (tp == RESTP_XORSEQ2) {
loadXorSeq(data, dataSize, 2);
} else {
//printf("Unk Res %x\n", tp);
}
return true;
}
bool GamosEngine::loadResHandler(uint tp, uint pid, uint p1, uint p2, uint p3, const RawData &data) {
return loadResHandler(tp, pid, p1, p2, p3, data.data(), data.size());
}
bool GamosEngine::reuseLastResource(uint tp, uint pid, uint p1, uint p2, uint p3) {
if (tp == RESTP_43) {
_sprites[pid].sequences[p1][p2].image = _images.back();
} else {
return false;
}
return true;
}
bool GamosEngine::initOrLoadSave(int32) {
return false;
}
bool GamosEngine::initMainDatas() {
RawData rawdata;
if (!_arch.readCompressedData(&rawdata))
return false;
Common::MemoryReadStream dataStream(rawdata.data(), rawdata.size(), DisposeAfterUse::NO);
_magic = dataStream.readUint32LE();
_pages1kbCount = dataStream.readUint32LE();
_readBufSize = dataStream.readUint32LE();
_width = dataStream.readUint32LE();
_height = dataStream.readUint32LE();
_unk2 = dataStream.readUint32LE();
_unk3 = dataStream.readUint32LE();
_movieCount = dataStream.readUint32LE();
_unk5 = dataStream.readByte();
_unk6 = dataStream.readByte();
_unk7 = dataStream.readByte();
_fps = dataStream.readByte();
_unk8 = dataStream.readByte();
_unk9 = dataStream.readByte();
_fadeEffectID = dataStream.readByte();
_unk11 = dataStream.readByte();
/*_winX = dataStream.readUint32LE();
_winY = dataStream.readUint32LE();
_winW = dataStream.readUint32LE();
_winH = dataStream.readUint32LE();*/
dataStream.skip(16);
int64 pos = dataStream.pos();
_string1 = dataStream.readString(0, 64);
dataStream.seek(pos + 64);
_winCaption = dataStream.readString(0, 9);
if (!_screen) {
initGraphics(_width, _height);
_screen = new Graphics::Screen();
}
_movieOffsets.clear();
_movieOffsets.resize(_movieCount, 0);
return true;
}
bool GamosEngine::init(const Common::String &moduleName) {
BYTE_004177f7 = 0;
if (!_arch.open(Common::Path(moduleName)))
return false;
if (!loadInitModule())
return false;
if (!playIntro())
return false;
return true;
}
bool GamosEngine::loadInitModule() {
_runReadDataMod = true;
return loadModule(0);
}
void GamosEngine::setFPS(uint fps) {
_delayTime = 0;
if (fps)
_delayTime = 1000 / fps;
}
void GamosEngine::readElementsConfig(const RawData &data) {
Common::MemoryReadStream dataStream(data.data(), data.size(), DisposeAfterUse::NO);
uint32 bkgnum1 = dataStream.readUint32LE(); // 0
uint32 bkgnum2 = dataStream.readUint32LE(); // 4
dataStream.readUint32LE(); // 8
dataStream.readUint32LE(); // c
dataStream.readUint32LE(); // 10
dataStream.readUint32LE(); // 14
dataStream.readUint32LE(); // 18
dataStream.readUint32LE(); // 1c
dataStream.readUint32LE(); // 20
uint32 imageCount = dataStream.readUint32LE(); // 24
dataStream.readUint32LE(); // 28
uint32 midiCount = dataStream.readUint32LE(); // 2c
dataStream.readUint32LE(); // 30
_bkgImages.clear();
_bkgImages.resize(bkgnum1 * bkgnum2);
_sprites.clear();
_sprites.resize(imageCount);
_midiTracks.clear();
_midiTracks.resize(midiCount);
}
void GamosEngine::loadXorSeq(const byte *data, size_t dataSize, int id) {
Common::MemoryReadStream dataStream(data, dataSize);
Common::Array<XorArg> &seq = _xorSeq[id];
uint32 num = dataStream.readUint32LE();
seq.resize(num);
for(uint i = 0; i < num; ++i) {
seq[i].len = dataStream.readUint32LE();
seq[i].pos = dataStream.readUint32LE();
}
}
bool GamosEngine::loadRes40(int32 id, const byte *data, size_t dataSize) {
if (dataSize < 4)
return false;
_sprites[id].field_0 = data[0];
_sprites[id].field_1 = data[1];
_sprites[id].field_2 = data[2];
_sprites[id].field_3 = data[3];
return true;
}
bool GamosEngine::loadRes41(int32 id, const byte *data, size_t dataSize) {
if (*(const uint32 *)data != 0) {
printf("41 not null!!!\n");
exit(0);
}
_sprites[id].sequences.resize(dataSize / 4);
return true;
}
bool GamosEngine::loadRes42(int32 id, int32 p1, const byte *data, size_t dataSize) {
//printf("loadRes42 pid %d p %d sz %x\n",id, p1, dataSize);
if (_sprites[id].sequences.size() == 0)
_sprites[id].sequences.resize(1);
int32 count = dataSize / 8;
_sprites[id].sequences[p1].resize(count);
Common::MemoryReadStream strm(data, dataSize);
for(int i = 0; i < count; ++i) {
int32 dataz = strm.readSint32LE();
if (dataz != 0) {
printf("42 nut null \n");
exit(0);
}
ImagePos &imgpos = _sprites[id].sequences[p1][i];
imgpos.xoffset = strm.readSint16LE();
imgpos.yoffset = strm.readSint16LE();
}
return true;
}
bool GamosEngine::loadRes43(int32 id, int32 p1, int32 p2, const byte *data, size_t dataSize) {
_images.push_back( new Image() );
_sprites[id].sequences[p1][p2].image = _images.back();
Image *img = _sprites[id].sequences[p1][p2].image;
Common::MemoryReadStream s(data, dataSize);
img->surface.pitch = img->surface.w = s.readSint16LE();
img->surface.h = s.readSint16LE();
img->loaded = false;
uint32 token = s.readUint32LE();
/* token 'Disk' */
if (token == 0x4469736b) {
img->offset = s.readSint32LE();
img->cSize = s.readSint32LE();
} else {
if (_sprites[id].field_1 & 0x80) {
img->offset = _arch._lastReadDataOffset;
img->cSize = _arch._lastReadSize;
} else {
img->loaded = true;
img->rawData.assign(data + 4, data + dataSize);
img->surface.setPixels(img->rawData.data());
img->surface.format = Graphics::PixelFormat::createFormatCLUT8();
}
}
return true;
}
bool GamosEngine::loadRes52(int32 id, const byte *data, size_t dataSize) {
_midiTracks[id].assign(data, data + dataSize);
return true;
}
bool GamosEngine::playIntro() {
if (_movieCount != 0 && _unk11 == 1)
return scriptFunc18(0);
return true;
}
bool GamosEngine::scriptFunc18(int id) {
if (true) {
_isMoviePlay++;
bool res = _moviePlayer.playMovie(&_arch, _movieOffsets[id], this);
_isMoviePlay--;
return res;
}
return true;
}
void GamosEngine::stopMidi() {
_musicPlayer.stopMusic();
_midiStarted = false;
}
void GamosEngine::stopMCI() {
}
void GamosEngine::stopSounds() {
}
void GamosEngine::setErrMessage(const Common::String &msg) {
if (_errSet)
return;
_errMessage = msg;
_errSet = true;
}
void GamosEngine::updateScreen(bool checkers, Common::Rect rect) {
if (_width == 0 || _height == 0)
return;
if (!checkers) {
_screen->addDirtyRect(rect);
return;
}
static const Common::Point checkerCoords[16] = {
{0, 0}, {16, 32}, {48, 16}, {16, 48},
{0, 32}, {32, 48}, {16, 16}, {48, 0},
{32, 32}, {0, 48}, {32, 16}, {16, 0},
{48, 32}, {32, 0}, {0, 16}, {48, 48}};
const int16 maxDelay = (500 / 10) - 1;
for (int16 p = 0; p < 16; p++) {
uint32 val = g_system->getMillis();
const Common::Point point = checkerCoords[p];
for (uint32 x = point.x; x < _width; x += 64) {
for (uint32 y = point.y; y < _height; y += 64) {
_screen->addDirtyRect(Common::Rect(x, y, x + 16, y + 16));
}
}
_screen->update();
val = g_system->getMillis() - val;
if (val > maxDelay)
g_system->delayMillis(maxDelay - val);
}
}
void GamosEngine::readData2(const RawData &data) {
Common::MemoryReadStream dataStream(data.data(), data.size());
dataStream.skip(4); // FIX ME
_messageProc._gd2flags = dataStream.readByte();
dataStream.skip(0x40 - 5); // FIX ME
for (int i = 0; i < 12; i++) {
_messageProc._keyCodes[i] = _winkeyMap[dataStream.readByte()];
}
}
void GamosEngine::playMidi(Common::Array<byte> *buffer) {
_musicPlayer.stopMusic();
_musicPlayer.playMusic(buffer);
_midiStarted = true;
}
} // End of namespace Gamos
+320
View File
@@ -0,0 +1,320 @@
/* 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/>.
*
*/
#ifndef GAMOS_H
#define GAMOS_H
#include "common/events.h"
#include "common/rect.h"
#include "common/scummsys.h"
#include "common/system.h"
#include "common/error.h"
#include "common/fs.h"
#include "common/hash-str.h"
#include "common/random.h"
#include "common/serializer.h"
#include "common/util.h"
#include "common/array.h"
#include "common/memstream.h"
#include "engines/engine.h"
#include "engines/savestate.h"
#include "graphics/screen.h"
#include "gamos/proc.h"
#include "gamos/music.h"
#include "gamos/movie.h"
#include "gamos/detection.h"
#include "gamos/file.h"
namespace Gamos {
struct GamosGameDescription;
enum CONFTYPE {
CONFTP_P1 = 1,
CONFTP_P2 = 2,
CONFTP_P3 = 3,
CONFTP_IDFLG = 0x80,
CONFTP_RESMASK = 0x7f,
};
enum ACT2 {
ACT_NONE = 0xe,
ACT2_81 = 0x81,
ACT2_82 = 0x82,
ACT2_83 = 0x83,
ACT2_84 = 0x84,
ACT2_8f = 0x8f,
};
enum RESTYPE {
RESTP_F = 0xf,
RESTP_10 = 0x10,
RESTP_11 = 0x11,
RESTP_12 = 0x12,
RESTP_18 = 0x18,
RESTP_19 = 0x19,
RESTP_20 = 0x20,
RESTP_40 = 0x40,
RESTP_41 = 0x41,
RESTP_42 = 0x42,
RESTP_43 = 0x43,
RESTP_50 = 0x50,
RESTP_51 = 0x51,
RESTP_52 = 0x52,
RESTP_XORSEQ0 = 0x7c,
RESTP_XORSEQ1 = 0x7d,
RESTP_XORSEQ2 = 0x7e,
};
struct BkgImage {
bool loaded = false;
uint32 offset = 0;
Graphics::Surface surface;
RawData rawData;
};
struct Image {
bool loaded = false;
int32 offset = 0;
int32 size = 0;
int32 cSize = 0;
Graphics::Surface surface;
RawData rawData;
};
struct ImagePos {
int16 xoffset = 0;
int16 yoffset = 0;
Image *image = nullptr;
};
typedef Common::Array<ImagePos> ImageSeq;
struct Sprite {
byte field_0;
byte field_1;
byte field_2;
byte field_3;
Common::Array<ImageSeq> sequences;
};
/* Used to xor savedata */
struct XorArg {
uint32 pos;
uint32 len;
};
class GamosEngine : public Engine {
friend class MoviePlayer;
private:
const ADGameDescription *_gameDescription;
Common::RandomSource _randomSource;
bool _errSet = false;;
Common::String _errMessage;
Archive _arch;
byte _cmdByte;
bool _runReadDataMod;
bool _currentModuleID;
byte _saveLoadID;
uint32 _magic;
uint32 _pages1kbCount;
uint32 _readBufSize;
uint32 _width;
uint32 _height;
uint32 _unk2;
uint32 _unk3;
uint32 _movieCount;
byte _unk5;
byte _unk6;
byte _unk7;
byte _fps;
byte _unk8;
byte _unk9;
byte _fadeEffectID;
byte _unk11;
int _isMoviePlay = 0;
bool _onlyScanImage = false;
int32 _resReadOffset = 0;
Common::String _string1;
Common::String _winCaption;
Common::Array<uint32> _movieOffsets;
Common::Array<Image *> _images;
Common::Array<BkgImage> _bkgImages;
Common::Array<Sprite> _sprites;
Common::Array< Common::Array<byte> > _midiTracks;
uint32 _delayTime = 0;
Common::Array<XorArg> _xorSeq[3];
static const byte _xorKeys[32];
uint8 BYTE_004177f7 = 0;
bool _midiStarted = false;
/* Data2 */
MidiMusic _musicPlayer;
SystemProc _messageProc;
MoviePlayer _moviePlayer;
private:
static const uint16 _winkeyMap[256];
protected:
// Engine APIs
Common::Error run() override;
void readCMDByte() {
_cmdByte = _arch.readByte();
}
bool loadModule(uint id);
bool loader2();
bool loadResHandler(uint tp, uint pid, uint p1, uint p2, uint p3, const byte *data, size_t dataSize);
bool loadResHandler(uint tp, uint pid, uint p1, uint p2, uint p3, const RawData &data);
bool reuseLastResource(uint tp, uint pid, uint p1, uint p2, uint p3);
bool initOrLoadSave(int32);
bool initMainDatas();
bool init(const Common::String &moduleName);
bool loadInitModule();
void readElementsConfig(const RawData &data);
void setFPS(uint fps);
void loadXorSeq(const byte *data, size_t dataSize, int id);
bool loadRes40(int32 id, const byte *data, size_t dataSize);
bool loadRes41(int32 id, const byte *data, size_t dataSize);
bool loadRes42(int32 id, int32 p1, const byte *data, size_t dataSize);
bool loadRes43(int32 id, int32 p1, int32 p2, const byte *data, size_t dataSize);
bool loadRes52(int32 id, const byte *data, size_t dataSize);
void playMidi(Common::Array<byte> *buffer);
void stopMidi();
void stopMCI();
void stopSounds();
bool playIntro();
bool scriptFunc18(int id);
void setErrMessage(const Common::String &msg);
void updateScreen(bool checkers, Common::Rect rect);
void readData2(const RawData &data);
public:
Graphics::Screen *_screen = nullptr;
public:
GamosEngine(OSystem *syst, const ADGameDescription *gameDesc);
~GamosEngine() override;
uint32 getFeatures() const;
/**
* Returns the game Id
*/
Common::String getGameId() const;
/**
* Gets a random number
*/
uint32 getRandomNumber(uint maxNum) {
return _randomSource.getRandomNumber(maxNum);
}
bool hasFeature(EngineFeature f) const override {
return
(f == kSupportsLoadingDuringRuntime) ||
(f == kSupportsSavingDuringRuntime) ||
(f == kSupportsReturnToLauncher);
};
bool canLoadGameStateCurrently(Common::U32String *msg = nullptr) override {
return true;
}
bool canSaveGameStateCurrently(Common::U32String *msg = nullptr) override {
return true;
}
/**
* Uses a serializer to allow implementing savegame
* loading and saving using a single method
*/
Common::Error syncGame(Common::Serializer &s);
Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave = false) override {
Common::Serializer s(nullptr, stream);
return syncGame(s);
}
Common::Error loadGameStream(Common::SeekableReadStream *stream) override {
Common::Serializer s(stream, nullptr);
return syncGame(s);
}
};
extern GamosEngine *g_engine;
#define SHOULD_QUIT ::Gamos::g_engine->shouldQuit()
} // End of namespace Gamos
#endif // GAMOS_H
+284
View File
@@ -0,0 +1,284 @@
/* 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/>.
*
*/
#include "gamos/gamos.h"
namespace Gamos {
const uint16 GamosEngine::_winkeyMap[256] = {
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_CANCEL,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_BACKSPACE,
Common::KEYCODE_TAB,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_RETURN,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_MENU,
Common::KEYCODE_PAUSE,
Common::KEYCODE_CAPSLOCK,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_ESCAPE,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_SPACE,
Common::KEYCODE_PAGEUP,
Common::KEYCODE_PAGEDOWN,
Common::KEYCODE_END,
Common::KEYCODE_HOME,
Common::KEYCODE_LEFT,
Common::KEYCODE_UP,
Common::KEYCODE_RIGHT,
Common::KEYCODE_DOWN,
Common::KEYCODE_SELECT,
Common::KEYCODE_PRINT,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INSERT,
Common::KEYCODE_DELETE,
Common::KEYCODE_HELP,
Common::KEYCODE_0,
Common::KEYCODE_1,
Common::KEYCODE_2,
Common::KEYCODE_3,
Common::KEYCODE_4,
Common::KEYCODE_5,
Common::KEYCODE_6,
Common::KEYCODE_7,
Common::KEYCODE_8,
Common::KEYCODE_9,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_a,
Common::KEYCODE_b,
Common::KEYCODE_c,
Common::KEYCODE_d,
Common::KEYCODE_e,
Common::KEYCODE_f,
Common::KEYCODE_g,
Common::KEYCODE_h,
Common::KEYCODE_i,
Common::KEYCODE_j,
Common::KEYCODE_k,
Common::KEYCODE_l,
Common::KEYCODE_m,
Common::KEYCODE_n,
Common::KEYCODE_o,
Common::KEYCODE_p,
Common::KEYCODE_q,
Common::KEYCODE_r,
Common::KEYCODE_s,
Common::KEYCODE_t,
Common::KEYCODE_u,
Common::KEYCODE_v,
Common::KEYCODE_w,
Common::KEYCODE_x,
Common::KEYCODE_y,
Common::KEYCODE_z,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_SLEEP,
Common::KEYCODE_KP0,
Common::KEYCODE_KP1,
Common::KEYCODE_KP2,
Common::KEYCODE_KP3,
Common::KEYCODE_KP4,
Common::KEYCODE_KP5,
Common::KEYCODE_KP6,
Common::KEYCODE_KP7,
Common::KEYCODE_KP8,
Common::KEYCODE_KP9,
Common::KEYCODE_KP_MULTIPLY,
Common::KEYCODE_KP_PLUS,
Common::KEYCODE_INVALID,
Common::KEYCODE_KP_MINUS,
Common::KEYCODE_INVALID,
Common::KEYCODE_KP_DIVIDE,
Common::KEYCODE_F1,
Common::KEYCODE_F2,
Common::KEYCODE_F3,
Common::KEYCODE_F4,
Common::KEYCODE_F5,
Common::KEYCODE_F6,
Common::KEYCODE_F7,
Common::KEYCODE_F8,
Common::KEYCODE_F9,
Common::KEYCODE_F10,
Common::KEYCODE_F11,
Common::KEYCODE_F12,
Common::KEYCODE_F13,
Common::KEYCODE_F14,
Common::KEYCODE_F15,
Common::KEYCODE_F16,
Common::KEYCODE_F17,
Common::KEYCODE_F18,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_NUMLOCK,
Common::KEYCODE_SCROLLOCK,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID,
Common::KEYCODE_INVALID
};
}
+69
View File
@@ -0,0 +1,69 @@
/* 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/>.
*
*/
#include "common/translation.h"
#include "gamos/metaengine.h"
#include "gamos/detection.h"
#include "gamos/gamos.h"
namespace Gamos {
static const ADExtraGuiOptionsMap optionsList[] = {
{
GAMEOPTION_ORIGINAL_SAVELOAD,
{
_s("Use original save/load screens"),
_s("Use the original save/load screens instead of the ScummVM ones"),
"original_menus",
false,
0,
0
}
},
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
} // End of namespace Gamos
const char *GamosMetaEngine::getName() const {
return "gamos";
}
const ADExtraGuiOptionsMap *GamosMetaEngine::getAdvancedExtraGuiOptions() const {
return Gamos::optionsList;
}
Common::Error GamosMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
*engine = new Gamos::GamosEngine(syst, desc);
return Common::kNoError;
}
bool GamosMetaEngine::hasFeature(MetaEngineFeature f) const {
return checkExtendedSaves(f) ||
(f == kSupportsLoadingDuringStartup);
}
#if PLUGIN_ENABLED_DYNAMIC(GAMOS)
REGISTER_PLUGIN_DYNAMIC(GAMOS, PLUGIN_TYPE_ENGINE, GamosMetaEngine);
#else
REGISTER_PLUGIN_STATIC(GAMOS, PLUGIN_TYPE_ENGINE, GamosMetaEngine);
#endif
+43
View File
@@ -0,0 +1,43 @@
/* 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/>.
*
*/
#ifndef GAMOS_METAENGINE_H
#define GAMOS_METAENGINE_H
#include "engines/advancedDetector.h"
class GamosMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
public:
const char *getName() const override;
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
/**
* Determine whether the engine supports the specified MetaEngine feature.
*
* Used by e.g. the launcher to determine whether to enable the Load button.
*/
bool hasFeature(MetaEngineFeature f) const override;
const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override;
};
#endif // GAMOS_METAENGINE_H
+22
View File
@@ -0,0 +1,22 @@
MODULE := engines/gamos
MODULE_OBJS = \
gamos.o \
file.o \
console.o \
metaengine.o \
keycodes.o \
music.o \
proc.o \
movie.o
# This module can be built as a plugin
ifeq ($(ENABLE_GAMOS), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk
# Detection objects
DETECT_OBJS += $(MODULE)/detection.o
+621
View File
@@ -0,0 +1,621 @@
/* 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/>.
*
*/
#define FORBIDDEN_SYMBOL_EXCEPTION_printf
#include "gamos/gamos.h"
namespace Gamos {
bool MoviePlayer::init(Common::File *file, uint32 offset, GamosEngine *gamos) {
_gamos = gamos;
_screen = _gamos->_screen;
_messageProc = &_gamos->_messageProc;
_loopCount = 1;
_pos = Common::Point();
_midiBufferSize = 0;
_soundBufferSize = 0;
_paletteBufferSize = 0;
_bufferSize = 0;
_packedBufferSize = 0;
_frameTime = 0;
_loopPoint = 0;
_midiBuffer.clear();
_soundBuffer.clear();
_paletteBuffer.clear();
_buffer.clear();
_packedBuffer.clear();
_midiStarted = false;
_soundPlaying = false;
_frameSize = Common::Point(_screen->w, _screen->h);
_gamos->stopMidi();
_gamos->stopMCI();
_file = file;
return _file->seek(offset, SEEK_SET);
}
bool MoviePlayer::deinit() {
if (_soundPlaying)
_gamos->stopSounds();
_gamos->stopMidi();
_gamos->stopMCI();
_file = nullptr;
return true;
}
bool MoviePlayer::playMovie(Common::File *file, uint32 offset, GamosEngine *gamos) {
if (!init(file, offset, gamos))
return error();
while (true) {
int status = 0;
readHdr();
switch(_hdrBytes[0]) {
case 0:
status = processControlChunk();
break;
case 1:
status = processImageChunk();
break;
case 2:
status = processPaletteChunk();
break;
case 3:
status = processSoundChunk();
break;
case 4:
status = proccessMidiChunk();
break;
default:
break;
}
while(true)
{
if (status == 2) {
while(true) {
if ( !readHdr() )
return error();
if (_hdrBytes[0] == 0) {
if (_hdrBytes[1] == 0 || _hdrBytes[1] == 1)
break;
} else {
if (!_file->seek(_hdrValue1, SEEK_CUR))
return error();
}
}
status = processControlChunk();
} else if (status == 0) {
return error();
} else if (status == 3) {
return deinit();
} else {
break;
}
}
}
return deinit();
}
bool MoviePlayer::error() {
deinit();
_gamos->setErrMessage("Movie playback error.");
return false;
}
int MoviePlayer::processControlChunk() {
printf("%x movieProcessControl %d\n", _file->pos(), _hdrBytes[1]);
switch(_hdrBytes[1]) {
case 0:
if ((uint32_t)_hdrValue1 != 0x563d2d5b || (uint32_t)_hdrValue2 != 0x5d2d3d53) {
error();
return 0;
}
return 3;
case 1:
_loopCount = 1;
_loopPoint = 0;
if (_hdrBytes[2] != 0)
_loopCount = _hdrValue1;
if (_hdrBytes[3] != 0)
_frameTime = _hdrValue2;
break;
case 2:
if (_hdrBytes[2] != 0) {
_packedBufferSize = _hdrValue1;
_packedBuffer.resize(_hdrValue1);
}
break;
case 3:
if (_hdrBytes[2] != 0) {
_bufferSize = _hdrValue1;
_buffer.resize(_hdrValue1);
}
if (_hdrBytes[3] != 0) {
_paletteBufferSize = _hdrValue2;
_paletteBuffer.resize(_hdrValue2);
}
break;
case 4:
if (_hdrBytes[2] != 0) {
_soundBufferSize = _hdrValue1;
_soundBuffer.resize(_hdrValue1);
}
if (_hdrBytes[3] != 0) {
_midiBufferSize = _hdrValue2;
_midiBuffer.resize(_hdrValue2);
}
break;
case 5:
if (_hdrBytes[2] != 0) {
_pos.x = _hdrValue1;
}
if (_hdrBytes[3] != 0) {
_pos.y = _hdrValue2; /* BUG? Originally here same _pos.x */
}
break;
case 6:
if (_hdrBytes[2] != 0) {
_frameSize.x = _hdrValue1;
}
if (_hdrBytes[3] != 0) {
_frameSize.y = _hdrValue2;
}
break;
}
return 1;
}
int MoviePlayer::processImageChunk() {
printf("%x movieProcessImageChunk %d\n", _file->pos(), _hdrValue1);
if (!readCompressed(_bufferSize, &_buffer))
return 0;
bool keepAct = true;
if (_hdrBytes[1] == 1) {
_forceStopMidi = false;
//waveoutrestart()
_screen->fillRect(_screen->getBounds(), _hdrBytes[3]);
if (_loopCount > 1)
_loopPoint = _file->pos();
keepAct = false;
_doUpdateScreen = false;
}
else if (_hdrBytes[1] == 2) {
_forceStopMidi = true;
_loopCount--;
if (_loopCount != 0)
_file->seek(_loopPoint, 0);
}
if (_hdrValue1 != 0) {
byte *pdata = _buffer.data();
Common::Point xy;
Common::Point wh;
while (true) {
byte val = *pdata;
pdata++;
if ( (val & 0x40) == 0 ) {
xy.x = _pos.x + *pdata;
pdata++;
if ( (val & 4) != 0 ) {
xy.x += *pdata * 256;
pdata++;
}
xy.y = _pos.y + *pdata;
pdata++;
if ( (val & 8) != 0 ) {
xy.y += *pdata * 256;
pdata++;
}
wh.x = *pdata;
pdata++;
if ( (val & 0x10) != 0 ) {
wh.x += *pdata * 256;
pdata++;
}
wh.y = *pdata;
pdata++;
if ( (val & 0x20) != 0 ) {
wh.y += *pdata * 256;
pdata++;
}
} else {
xy = _pos;
wh = _frameSize;
}
printf("movie blit%d %d %d %d %d\n", val & 3, xy.x, xy.y, wh.x, wh.y);
static byte *(*blitters[4])(Common::Rect, byte *, Graphics::Surface *) =
{&blit0,
&blit1,
&blit2,
&blit3};
pdata = blitters[val & 3](Common::Rect(xy, xy + wh), pdata, _screen->surfacePtr());
if (_doUpdateScreen) {
_gamos->updateScreen(false, Common::Rect(xy, xy + wh));
}
if (val & 0x80)
break;
}
}
if (_doUpdateScreen) {
//FUN_00403c70(true);
}
uint32 tstamp = 0;
uint8 act = processMessages(keepAct, &tstamp);
if (act == ACT2_82)
return 2;
if (act == ACT2_83)
return 3;
if (_hdrBytes[1] == 1) {
_gamos->updateScreen(_gamos->_fadeEffectID != 0, Common::Rect(_pos, _pos + _frameSize));
_firstFrameTime = g_system->getMillis();
_currentFrame = 0;
_skippedFrames = 0;
_doUpdateScreen = true;
} else if (_frameTime == 0) {
_doUpdateScreen = true;
} else {
int32 dtime = (tstamp - _firstFrameTime) / _currentFrame;
if (dtime > _frameTime) {
if (_soundBufferSize) {
_skippedFrames++;
if (_skippedFrames != 8)
_doUpdateScreen = false;
}
}
else if (dtime < _frameTime) {
while (true) {
act = processMessages(false, &tstamp);
if (act == ACT2_82)
return 2;
if (act == ACT2_83)
return 3;
if ((tstamp - _firstFrameTime) / _currentFrame >= _frameTime)
break;
g_system->delayMillis(1);
}
}
_skippedFrames = 0;
_doUpdateScreen = true;
}
_screen->update();
_currentFrame++;
return 1;
}
int MoviePlayer::processPaletteChunk() {
printf("%x movieProcessPaletteChunk\n", _file->pos());
if (!readCompressed(_paletteBufferSize, &_paletteBuffer))
return 0;
_screen->setPalette(_paletteBuffer.data());
//g_system->getPaletteManager()->setPalette(PalColors.data(), 0, 256);
return 1;
}
int MoviePlayer::processSoundChunk() {
printf("%x movieProcessSoundChunk\n", _file->pos());
if (!readCompressed(_soundBufferSize, &_soundBuffer))
return 0;
return 1;
}
int MoviePlayer::proccessMidiChunk() {
printf("%x movieProccessMidiChunk\n", _file->pos());
if (_midiStarted && (_forceStopMidi == false || _hdrBytes[1] != 0)) {
_gamos->stopMidi();
_midiStarted = false;
}
if (_hdrValue1 == 0)
return 1;
if (_midiStarted) {
if ( !_file->seek(_hdrValue1, SEEK_CUR) )
return 0;
return 1;
}
if (!readCompressed(_midiBufferSize, &_midiBuffer)) {
_midiStarted = false;
return 0;
}
_gamos->playMidi(&_midiBuffer);
_midiStarted = true;
return 1;
}
bool MoviePlayer::readHdr() {
_file->read(_hdrBytes, 4);
_hdrValue1 = _file->readSint32LE();
_hdrValue2 = _file->readSint32LE();
return true;
}
bool MoviePlayer::readCompressed(int32_t count, Common::Array<byte> *buf) {
if (_hdrValue1 == 0)
return true;
if (_hdrValue1 != _hdrValue2) {
_packedBuffer.resize(_hdrValue1);
_file->read(_packedBuffer.data(), _hdrValue1);
buf->resize(_hdrValue2);
Archive::decompress(&_packedBuffer, buf);
}
else {
buf->resize(_hdrValue1);
_file->read(buf->data(), _hdrValue1);
}
return true;
}
byte* MoviePlayer::blit0(Common::Rect rect, byte *in, Graphics::Surface *surface) {
int16 y = rect.top;
while (y < rect.bottom) {
const int count = rect.width();
byte *out = (byte *)surface->getBasePtr(rect.left, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
y++;
}
return in;
}
byte* MoviePlayer::blit1(Common::Rect rect, byte *in, Graphics::Surface *surface) {
int16 y = rect.top;
int16 x = rect.left;
while (y < rect.bottom) {
byte b = *in;
in++;
if (b & 0x80) {
if ((b & 0x40) == 0) {
int count = (b & 0x3f) + 1;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
x += count;
} else {
if ((b & 0x3f) == 0)
x = rect.right;
else {
if ((b & 0x3f) != 1) {
int count = (b & 0x3f) + 1;
byte val = *in;
in++;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += val;
out++;
}
x += count;
} else {
int count = rect.right - x;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
x = rect.right;
}
}
}
} else {
x += b + 1;
}
if (x >= rect.right) {
y++;
x = rect.left;
}
}
return in;
}
byte* MoviePlayer::blit2(Common::Rect rect, byte *in, Graphics::Surface *surface) {
int16 y = rect.top;
int16 x = rect.left;
while (y < rect.bottom) {
byte b = *in;
in++;
if (b & 0x80) {
if ((b & 0x40) == 0) {
x += (b & 0x3f) + 1;
} else {
int count = (b & 0x3f) + 1;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
x += count;
}
} else if (b == 0) {
x += b + 1;
} else if (b != 1) {
int count = b + 1;
byte val = *in;
in++;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += val;
out++;
}
x += count;
} else {
int count = rect.right - x;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
x = rect.right;
}
if (x >= rect.right) {
y++;
x = rect.left;
}
}
return in;
}
byte* MoviePlayer::blit3(Common::Rect rect, byte *in, Graphics::Surface *surface) {
int16 y = rect.top;
int16 x = rect.left;
while (y < rect.bottom) {
byte b = *in;
in++;
if (b & 0x80) {
if ((b & 0x40) == 0) {
x += (b & 0x3f) + 1;
} else {
if ((b & 0x3f) == 0)
x = rect.right;
else {
if ((b & 0x3f) != 1) {
int count = (b & 0x3f) + 1;
byte val = *in;
in++;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += val;
out++;
}
x += count;
} else {
int count = rect.right - x;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
x = rect.right;
}
}
}
} else {
int count = b + 1;
byte *out = (byte *)surface->getBasePtr(x, y);
for (int i = 0; i < count; i++) {
*out += *in;
in++;
out++;
}
x += count;
}
if (x >= rect.right) {
y++;
x = rect.left;
}
}
return in;
}
uint8 MoviePlayer::processMessages(bool keepAct, uint32 *msecs) {
if (!keepAct)
_messageProc->_act2 = ACT_NONE;
Common::Event e;
while (g_system->getEventManager()->pollEvent(e)) {
if (e.type == Common::EVENT_QUIT) {
//_errMessage = 1;
return ACT2_83;
}
_messageProc->processMessage(e);
}
uint8 act = _messageProc->_act2;
_messageProc->_act2 = ACT_NONE;
*msecs = g_system->getMillis();
return act;
}
}
+108
View File
@@ -0,0 +1,108 @@
/* 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/>.
*
*/
#ifndef GAMOS_MOVIE_H
#define GAMOS_MOVIE_H
#include "common/file.h"
namespace Gamos
{
class GamosEngine;
class MoviePlayer {
public:
bool playMovie(Common::File *file, uint32 offset, GamosEngine *gamos);
private:
bool init(Common::File *file, uint32 offset, GamosEngine *gamos);
bool deinit();
bool error();
int processControlChunk();
int processImageChunk();
int processPaletteChunk();
int processSoundChunk();
int proccessMidiChunk();
bool readHdr();
bool readCompressed(int32_t count, Common::Array<byte> *buf);
uint8 processMessages(bool keepAct, uint32 *msecs);
static byte* blit0(Common::Rect rect, byte *in, Graphics::Surface *surface);
static byte* blit1(Common::Rect rect, byte *in, Graphics::Surface *surface);
static byte* blit2(Common::Rect rect, byte *in, Graphics::Surface *surface);
static byte* blit3(Common::Rect rect, byte *in, Graphics::Surface *surface);
private:
GamosEngine *_gamos = nullptr;
Graphics::Screen *_screen = nullptr;
SystemProc *_messageProc = nullptr;
bool _doUpdateScreen = false;
uint32 _skippedFrames = 0;
uint32 _currentFrame = 0;
uint32 _firstFrameTime = 0;
bool _forceStopMidi = false;
int _loopCount = 1;
int _loopPoint = 0;
Common::Point _pos; /* Movie frame leftup corner */
Common::Point _frameSize; /* Sizes of movie frame */
int _midiBufferSize = 0;
int _soundBufferSize = 0;
int _paletteBufferSize = 0;
int _bufferSize = 0;
int _packedBufferSize = 0;
int _frameTime = 0;
Common::Array<byte> _midiBuffer;
Common::Array<byte> _soundBuffer;
Common::Array<byte> _paletteBuffer;
Common::Array<byte> _buffer;
Common::Array<byte> _packedBuffer;
bool _midiStarted = false;
bool _soundPlaying = false;
Common::File *_file = nullptr;
byte _hdrBytes[4];
int32_t _hdrValue1 = 0;
int32_t _hdrValue2 = 0;
};
}
#endif //GAMOS_MOVIE_H
+185
View File
@@ -0,0 +1,185 @@
/* 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/>.
*
*/
#include "common/system.h"
#include "gamos/gamos.h"
namespace Gamos {
MidiMusic::MidiMusic() {
MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_PREFER_GM);
_driver = MidiDriver::createMidi(dev);
_driver->open();
_driver->sendGMReset();
}
MidiMusic::~MidiMusic() {
if (_driver) {
_driver->stopAllNotes(true);
_driver->close();
delete _driver;
}
}
void MidiMusic::stopMusic() {
g_system->getTimerManager()->removeTimerProc(_timerProc);
if (_mutex.lock()) {
_driver->stopAllNotes(true);
_mutex.unlock();
}
}
void MidiMusic::playMusic(Common::Array<byte> *midiData) {
stopMusic();
if (!midiData || midiData->size() <= 4)
return;
if (_mutex.lock()) {
_pMidiData.clear();
_pMidiData.swap(*midiData);
_dataPos = 4;
_midiDelayTicks = 1;
_midiDelayCount = 1;
if (_pMidiData[_dataPos] == 0xf8) {
_dataPos++;
midi2low();
_dataPos++;
}
g_system->getTimerManager()->installTimerProc(_timerProc, 10 * 1000, this, "Gamos::Music");
_mutex.unlock();
}
}
void MidiMusic::update() {
while (true) {
if (_dataPos >= _pMidiData.size())
return;
uint8 b = _pMidiData[_dataPos];
if (b > 0x7f) {
/* only if new event type then update _midiOp */
_midiOp = b;
_dataPos++;
}
bool doDelay = true;
if (_midiOp == 0xf0 || _midiOp == 0xf7) {
int16 skipLen = midi2low();
if (skipLen >= 0)
_dataPos += skipLen;
} else if (_midiOp == 0xff) {
if (_midiDelayTicks != -1) {
_midiDelayCount = _midiDelayTicks;
_dataPos = _dataStart;
} else {
g_system->getTimerManager()->removeTimerProc(_timerProc);
_driver->stopAllNotes(true);
}
break;
} else {
uint8 param1 = _pMidiData[_dataPos];
uint8 param2 = 0;
_dataPos++;
bool doSend = true;
uint8 cmd = _midiOp & 0xf0;
if (cmd != MidiDriver_BASE::MIDI_COMMAND_PROGRAM_CHANGE &&
cmd != MidiDriver_BASE::MIDI_COMMAND_CHANNEL_AFTERTOUCH) {
if (cmd == MidiDriver_BASE::MIDI_COMMAND_NOTE_OFF ||
cmd == MidiDriver_BASE::MIDI_COMMAND_NOTE_ON) {
if (_midiMute)
doSend = false;
}
b = _pMidiData[_dataPos];
_dataPos++;
doDelay = (b & 0x80) == 0;
param2 = b & 0x7f;
}
if (doSend)
_driver->send(_midiOp, param1, param2);
}
if (doDelay) {
int16 ln = midi2low();
if (ln > 0) {
_midiTimeStamp += ln * 10;
if (g_system->getMillis() < _midiTimeStamp)
break;
}
}
}
}
int16 MidiMusic::midi2low() {
if (_dataPos >= _pMidiData.size())
return -1;
int16 dat = _pMidiData[_dataPos];
_dataPos++;
if (dat & 0x80) {
if (_dataPos >= _pMidiData.size())
return -1;
dat &= 0x7f;
dat |= _pMidiData[_dataPos] << 7;
_dataPos++;
}
return dat;
}
void MidiMusic::_timerProc(void *data) {
if (!data)
return;
MidiMusic *_this = (MidiMusic *)data;
if (_this->_midiDelayCount != 0) {
_this->_midiDelayCount--;
if (_this->_midiDelayCount != 0)
return;
_this->_midiTimeStamp = g_system->getMillis();
}
if (_this->_midiTimeStamp <= g_system->getMillis() && _this->_mutex.lock()) {
_this->update();
_this->_mutex.unlock();
}
}
};
+67
View File
@@ -0,0 +1,67 @@
/* 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/>.
*
*/
#ifndef GAMOS_MUSIC_H
#define GAMOS_MUSIC_H
#include "audio/mididrv.h"
#include "common/memstream.h"
#include "common/mutex.h"
#include "common/scummsys.h"
#include "common/timer.h"
#include "common/system.h"
namespace Gamos {
class MidiMusic {
private:
MidiDriver *_driver = nullptr;
Common::Array<byte> _pMidiData;
Common::Mutex _mutex;
uint32 _dataPos = 0;
uint32 _dataStart = 0;
int32 _midiDelayTicks = 0;
int32 _midiDelayCount = 0;
uint32 _midiTimeStamp = 0;
uint32 _midiOp = 0; /* save midi event type between update cycles */
bool _midiMute = false;
public:
MidiMusic();
~MidiMusic();
void stopMusic();
void playMusic(Common::Array<byte> *midiData);
void update();
int16 midi2low();
static void _timerProc(void *data);
};
};
#endif //GAMOS_MUSIC_H
+80
View File
@@ -0,0 +1,80 @@
/* 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/>.
*
*/
#include "gamos/gamos.h"
namespace Gamos {
void SystemProc::processMessage(const Common::Event &ev) {
switch(ev.type) {
case Common::EVENT_KEYDOWN:
if ((_gd2flags & 1) == 0)
return;
if (ev.kbd.keycode == _keyCodes[0])
_act1 = 0;
else if (ev.kbd.keycode == _keyCodes[1])
_act1 = 1;
else if (ev.kbd.keycode == _keyCodes[2])
_act1 = 2;
else if (ev.kbd.keycode == _keyCodes[3])
_act1 = 3;
else if (ev.kbd.keycode == _keyCodes[4])
_act1 = 4;
else if (ev.kbd.keycode == _keyCodes[5])
_act1 = 5;
else if (ev.kbd.keycode == _keyCodes[6])
_act1 = 6;
else if (ev.kbd.keycode == _keyCodes[7])
_act1 = 7;
else {
if (ev.kbd.keycode == _keyCodes[8])
_act2 = ACT2_82;
else if (ev.kbd.keycode == _keyCodes[9])
_act2 = ACT2_83;
else if (ev.kbd.keycode == _keyCodes[10])
_act2 = ACT2_8f;
else if (ev.kbd.keycode == _keyCodes[11])
_act2 = ACT2_84;
return;
}
if ((_act1 < 8) && (ev.kbd.flags & Common::KBD_SHIFT))
_act1 |= 8;
_mouseAct = _mouseReported;
break;
case Common::EVENT_MOUSEMOVE:
if ((_gd2flags & 1) == 0)
return;
_mouseReported = ev.mouse;
break;
default:
break;
}
}
}
+50
View File
@@ -0,0 +1,50 @@
/* 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/>.
*
*/
#ifndef GAMOS_PROC_H
#define GAMOS_PROC_H
#include <common/events.h>
namespace Gamos {
class SystemProc {
public:
void processMessage(const Common::Event &ev);
public:
uint8 _act1 = 0;
uint8 _act2 = 0;
Common::Point _mouseReported;
Common::Point _mouseAct;
uint8 _gd2flags = 0; /* 0x4 */
uint16 _keyCodes[12]; /* 0x40 */
};
}
#endif //GAMOS_PROC_H