mirror of
https://github.com/scummvm/gamos.git
synced 2026-05-21 05:40:53 +00:00
GAMOS: First working movie player
This commit is contained in:
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
begin_section("Gamos");
|
||||
add_person("Name 1", "Handle 1", "");
|
||||
end_section();
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user