Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/dcgf.h"
#include "engines/wintermute/base/file/base_disk_file.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/utils/path_util.h"
#include "common/stream.h"
#include "common/memstream.h"
#include "common/file.h"
#include "common/compression/deflate.h"
#include "common/archive.h"
#include "common/tokenizer.h"
#include "common/config-manager.h"
namespace Wintermute {
Common::Path correctSlashes(const Common::String &fileName) {
Common::String ret(fileName);
for (size_t i = 0; i < ret.size(); i++) {
if (ret[i] == '\\') {
ret.setChar('/', i);
}
}
return Common::Path(ret);
}
// Parse a relative path in the game-folder, and if it exists, return a FSNode to it.
static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
// The filename can be an explicit path, thus we need to chop it up, expecting the path the game
// specifies to follow the Windows-convention of folder\subfolder\file (absolute paths should not happen)
// Absolute path: These should have been handled in openDiskFile.
if (filename.contains(':')) {
// So just return an invalid node.
return Common::FSNode();
}
// Relative path:
Common::Path fixedFilename = correctSlashes(filename);
Common::Path absolutePath(ConfMan.getPath("path"));
absolutePath.joinInPlace(fixedFilename);
Common::FSNode node(absolutePath);
if (node.exists()) {
return node;
} else {
return Common::FSNode();
}
}
bool diskFileExists(const Common::String &filename) {
// Try directly from SearchMan first
Common::ArchiveMemberList files;
SearchMan.listMatchingMembers(files, Common::Path(filename));
for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
if ((*it)->getName() == filename) {
return true;
}
}
// File wasn't found in SearchMan, try to parse the path as a relative path.
Common::FSNode searchNode = getNodeForRelativePath(filename);
if (searchNode.exists() && !searchNode.isDirectory() && searchNode.isReadable()) {
return true;
}
return false;
}
int listMatchingDiskFileMembers(Common::ArchiveMemberList &list, const Common::String &pattern) {
return Common::FSDirectory(ConfMan.getPath("path")).listMatchingMembers(list, Common::Path(pattern));
}
Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
uint32 prefixSize = 0;
Common::SeekableReadStream *file = nullptr;
Common::Path fixedFilename = correctSlashes(filename);
// HACK: There are a few games around which mistakenly refer to absolute paths in the scripts.
// The original interpreter on Windows usually simply ignores them when it can't find them.
// We try to turn the known ones into relative paths.
if (filename.contains(':')) {
const char* const knownPrefixes[] = { // Known absolute paths
"c:/documents and settings/radimk/plocha/projekt/", // Basis Octavus refers to several files named "c:\documents and settings\radimk\plocha\projekt\sprites\clock*.bmp"
"c:/program files/wme devkit beta/projects/amu/data/", // Five Magical Amulets refers to "c:\program files\wme devkit beta\projects\amu\data\scenes\prvnimenu\scr\scene_init.script"
"c:/users/mathieu/desktop/wintermute engine development kit/jeu verve/vervegame/data/", // Machu Mayu refers to "c:\users\mathieu\desktop\wintermute engine development kit\jeu verve\vervegame\data\interface\system\cr<0xE9>dits.script"
"c:/windows/fonts/", // East Side Story refers to "c:\windows\fonts\framd.ttf"
"c:/carol6/svn/data/", // Carol Reed 6: Black Circle refers to "c:\carol6\svn\data\sprites\system\help.png"
("d:/engine/\322\303" "2/tg_ie_080128_1005/data/"), // Tanya Grotter and the Disappearing Floor refers to "d:\engine\<0xD2><0xC3>2\tg_ie_080128_1005\data\interface\pixel\pixel.png"
"e:/users/jonathan/onedrive/knossos/data/", // K'NOSSOS refers to "e:\users\jonathan\onedrive\knossos\data\entities\helprobot\helprobot.script"
"f:/dokument/spel 5/demo/data/", // Carol Reed 5 (non-demo) refers to "f:\dokument\spel 5\demo\data\scenes\credits\op_cred_00\op_cred_00.jpg"
"f:/quest!!!/engine/quest/data/" // Book of Gron Part One refers to several files named "f:\quest!!!\engine\quest\data\entities\dver\*"
};
// There are also some EDITOR_BG_FILE paths that refer to absolute paths
// However, EDITOR_BG_FILE is out of ScummVM scope, so there is currently no need to check for those prefixes:
// "c:\documents and settings\kumilanka\desktop\white.png" is used as EDITOR_BG_FILE at Alpha Polaris
// "c:\documents and settings\nir\desktop\untitled111.bmp" is used as EDITOR_BG_FILE at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
// "c:\documents and settings\user\desktop\untitled111.bmp" is used as EDITOR_BG_FILE at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
// "c:\dokumente und einstellungen\frank\desktop\position_qualm_auf_kaputter_jungfrau_2.png" is used as EDITOR_BG_FILE at 1 1/2 Ritter: Auf der Suche nach der hinreissenden Herzelinde
// "c:\tib_forest_d_2007120_111637000.jpg" is used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
// "c:\<0xC1><0xE5><0xE7><0xFB><0xEC><0xFF><0xED><0xFB><0xE9>.bmp" is used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
// "d:\projects\dirty split\tempfolder\background\sprite_help.png" is used as EDITOR_BG_FILE at Dirty Split
// "d:\<0xCE><0xE1><0xEC><0xE5><0xED>\*" are used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
// "e:\pictures\fraps screenshot\*" are used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
// "e:\work\!<0xC4><0xE5><0xEB><0xE0>\1 computergames\6 gamelet\work\*" are used as EDITOR_BG_FILE at Hamlet or the last game without MMORPG features, shaders and product placement
// "e:\<0xC4><0xE5><0xE5><0xE2>\graphics\*" are used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
// "f:\quest!!!\*" are used as EDITOR_BG_FILE at Book of Gron Part One
// "f:\<0xD2><0xE5><0xEA><0xF1><0xF2><0xF3><0xF0><0xFB>\<0xE1><0xEE><0xF2><0xE0><0xED><0xE8><0xEA><0xE0>\index\barks.jpg" is used as EDITOR_BG_FILE at Tanya Grotter and the Disappearing Floor
// "g:\<0xC4><0xEE><0xEA><0xF3><0xEC><0xE5><0xED><0xF2><0xFB>\<0xCF><0xF0><0xEE><0xE5><0xEA><0xF2><0xFB>\<0xD2><0xE8><0xC1>\*" are used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
// "untitled-1.jpg" & "untitled-1.png" with very various paths (including "c:\untitled-1.jpg" and "d:\untitled-1.jpg") are also used as EDITOR_BG_FILE at Fairy Tales About Toshechka and Boshechka
bool matched = false;
for (uint i = 0; i < ARRAYSIZE(knownPrefixes); i++) {
Common::Path root(knownPrefixes[i], '/');
if (fixedFilename.isRelativeTo(root)) {
fixedFilename = fixedFilename.relativeTo(root);
matched = true;
}
}
if (!matched) {
// fixedFilename is unchanged and thus still broken, none of the above workarounds worked.
// We can only bail out
error("openDiskFile::Absolute path or invalid filename used in %s", filename.c_str());
}
}
// Try directly from SearchMan first
Common::ArchiveMemberList files;
SearchMan.listMatchingMembers(files, fixedFilename);
for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
if ((*it)->getName().equalsIgnoreCase(fixedFilename.baseName())) {
file = (*it)->createReadStream();
break;
}
}
// File wasn't found in SearchMan, try to parse the path as a relative path.
if (!file) {
Common::FSNode searchNode = getNodeForRelativePath(PathUtil::normalizeFileName(filename));
if (searchNode.exists() && !searchNode.isDirectory() && searchNode.isReadable()) {
file = searchNode.createReadStream();
}
}
if (file) {
uint32 magic1, magic2;
magic1 = file->readUint32LE();
magic2 = file->readUint32LE();
bool compressed = false;
if (magic1 == DCGF_MAGIC && magic2 == COMPRESSED_FILE_MAGIC) {
compressed = true;
}
if (compressed) {
uint32 dataOffset, compSize;
unsigned long uncompSize;
dataOffset = file->readUint32LE();
compSize = file->readUint32LE();
uncompSize = file->readUint32LE();
byte *compBuffer = new byte[compSize];
if (!compBuffer) {
delete file;
error("Error allocating memory for compressed file '%s'", filename.c_str());
return nullptr;
}
byte *data = new byte[uncompSize];
if (!data) {
delete[] compBuffer;
delete file;
error("Error allocating buffer for file '%s'", filename.c_str());
return nullptr;
}
file->seek(dataOffset + prefixSize, SEEK_SET);
file->read(compBuffer, compSize);
if (Common::inflateZlib(data, &uncompSize, compBuffer, compSize) != true) {
delete[] compBuffer;
delete file;
error("Error uncompressing file '%s'", filename.c_str());
return nullptr;
}
delete[] compBuffer;
delete file;
return new Common::MemoryReadStream(data, uncompSize, DisposeAfterUse::YES);
} else {
file->seek(0, SEEK_SET);
return file;
}
return file;
}
return nullptr;
}
} // End of namespace Wintermute

View File

@@ -0,0 +1,42 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#ifndef WINTERMUTE_BASE_DISKFILE_H
#define WINTERMUTE_BASE_DISKFILE_H
#include "common/archive.h"
#include "common/stream.h"
namespace Wintermute {
Common::SeekableReadStream *openDiskFile(const Common::String &filename);
bool diskFileExists(const Common::String &filename);
int listMatchingDiskFileMembers(Common::ArchiveMemberList &list, const Common::String &pattern);
} // End of namespace Wintermute
#endif

View File

@@ -0,0 +1,76 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/base/file/base_file_entry.h"
#include "engines/wintermute/base/file/base_package.h"
#include "common/stream.h"
#include "common/substream.h"
#include "common/compression/deflate.h"
namespace Wintermute {
Common::SeekableReadStream *BaseFileEntry::createReadStream() const {
Common::SeekableReadStream *file = _package->getFilePointer();
if (!file) {
return nullptr;
}
bool compressed = (_compressedLength != 0);
if (compressed) {
file = Common::wrapCompressedReadStream(new Common::SeekableSubReadStream(file, _offset, _offset + _compressedLength, DisposeAfterUse::YES), DisposeAfterUse::YES, _length); //
} else {
file = new Common::SeekableSubReadStream(file, _offset, _offset + _length, DisposeAfterUse::YES);
}
file->seek(0);
return file;
}
Common::SeekableReadStream *BaseFileEntry::createReadStreamForAltStream(Common::AltStreamType altStreamType) const {
return nullptr;
}
//////////////////////////////////////////////////////////////////////////
BaseFileEntry::BaseFileEntry() {
_package = nullptr;
_length = _compressedLength = _offset = _flags = 0;
_filename = "";
_timeDate1 = _timeDate2 = 0;
_journalTime = 0;
}
//////////////////////////////////////////////////////////////////////////
BaseFileEntry::~BaseFileEntry() {
_package = nullptr; // ref only
}
} // End of namespace Wintermute

View File

@@ -0,0 +1,62 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#ifndef WINTERMUTE_BASE_FILEENTRY_H
#define WINTERMUTE_BASE_FILEENTRY_H
#include "common/archive.h"
#include "common/str.h"
#include "common/stream.h"
namespace Wintermute {
class BasePackage;
class BaseFileEntry : public Common::ArchiveMember {
public:
Common::SeekableReadStream *createReadStream() const override;
Common::SeekableReadStream *createReadStreamForAltStream(Common::AltStreamType altStreamType) const override;
Common::String getName() const override { return _filename.baseName(); }
Common::Path getPathInArchive() const override { return _filename; }
Common::String getFileName() const override { return _filename.baseName(); }
uint32 _timeDate2;
uint32 _timeDate1;
uint32 _flags;
uint32 _journalTime;
Common::Path _filename;
uint32 _compressedLength;
uint32 _length;
uint32 _offset;
BasePackage *_package;
BaseFileEntry();
~BaseFileEntry() override;
};
} // End of namespace Wintermute
#endif

View File

@@ -0,0 +1,288 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/base/base_engine.h"
#include "engines/wintermute/base/file/base_package.h"
#include "engines/wintermute/base/file/base_file_entry.h"
#include "engines/wintermute/base/file/dcpackage.h"
#include "engines/wintermute/wintermute.h"
#include "common/file.h"
#include "common/stream.h"
#include "common/debug.h"
namespace Wintermute {
BasePackage::BasePackage() {
_name = "";
_cd = 0;
_priority = 0;
_boundToExe = false;
}
Common::SeekableReadStream *BasePackage::getFilePointer() {
Common::SeekableReadStream *stream = _fsnode.createReadStream();
return stream;
}
static bool findPackageSignature(Common::SeekableReadStream *f, uint32 *offset) {
byte buf[32768];
byte signature[8];
WRITE_LE_UINT32(signature + 0, PACKAGE_MAGIC_1);
WRITE_LE_UINT32(signature + 4, PACKAGE_MAGIC_2);
uint32 fileSize = (uint32)f->size();
uint32 startPos = 1024 * 1024;
uint32 bytesRead = startPos;
while (bytesRead < fileSize - 16) {
uint32 toRead = MIN<unsigned int>((unsigned int)32768, fileSize - bytesRead);
f->seek((int32)startPos, SEEK_SET);
uint32 actuallyRead = f->read(buf, toRead);
if (actuallyRead != toRead) {
return false;
}
for (uint32 i = 0; i < toRead - 8; i++)
if (!memcmp(buf + i, signature, 8)) {
*offset = startPos + i;
return true;
}
bytesRead = bytesRead + toRead - 16;
startPos = startPos + toRead - 16;
}
return false;
}
void TPackageHeader::readFromStream(Common::ReadStream *stream) {
_magic1 = stream->readUint32LE();
_magic2 = stream->readUint32LE();
_packageVersion = stream->readUint32LE();
_gameVersion = stream->readUint32LE();
_priority = stream->readByte();
// HACK: reversion1 and reversion2 for Linux & Mac use some hacked Wintermute
// They provide "xlanguage_*.dcp" packages with 0x00 priority and change priority for a single package in runtime
// We already filter unwanted "xlanguage_*.dcp" packages at BaseFileManager::registerPackages()
// So, let's just raise the priority for all "xlanguage_*.dcp" here to the value of Windows version packages
if (_priority == 0 && BaseEngine::instance().getGameId().hasPrefix("reversion")) {
_priority = 0x02;
}
_cd = stream->readByte();
_masterIndex = stream->readByte();
stream->readByte(); // To align the next byte...
_creationTime = stream->readUint32LE();
stream->read(_desc, 100);
_numDirs = stream->readUint32LE();
}
PackageSet::PackageSet(Common::FSNode file, const Common::String &filename, bool searchSignature) {
uint32 absoluteOffset = 0;
_priority = 0;
bool boundToExe = false;
Common::SeekableReadStream *stream = file.createReadStream();
if (!stream) {
return;
}
if (searchSignature) {
uint32 offset;
if (!findPackageSignature(stream, &offset)) {
delete stream;
return;
} else {
stream->seek(offset, SEEK_SET);
absoluteOffset = offset;
boundToExe = true;
}
}
TPackageHeader hdr;
hdr.readFromStream(stream);
if (hdr._magic1 != PACKAGE_MAGIC_1 || hdr._magic2 != PACKAGE_MAGIC_2 || hdr._packageVersion > PACKAGE_VERSION) {
debugC(kWintermuteDebugFileAccess, " Invalid header in package file '%s'. Ignoring.", filename.c_str());
delete stream;
return;
}
if (hdr._packageVersion != PACKAGE_VERSION) {
debugC(kWintermuteDebugFileAccess, " Warning: package file '%s' is outdated.", filename.c_str());
}
_priority = hdr._priority;
_version = hdr._gameVersion;
// new in v2
if (hdr._packageVersion == PACKAGE_VERSION) {
uint32 dirOffset;
dirOffset = stream->readUint32LE();
dirOffset += absoluteOffset;
stream->seek(dirOffset, SEEK_SET);
}
assert(hdr._numDirs == 1);
for (uint32 i = 0; i < hdr._numDirs; i++) {
BasePackage *pkg = new BasePackage();
if (!pkg) {
return;
}
pkg->_fsnode = file;
pkg->_boundToExe = boundToExe;
// read package info
byte nameLength = stream->readByte();
char *pkgName = new char[nameLength];
stream->read(pkgName, nameLength);
pkg->_name = pkgName;
pkg->_cd = stream->readByte();
pkg->_priority = hdr._priority;
delete[] pkgName;
pkgName = nullptr;
if (!hdr._masterIndex) {
pkg->_cd = 0; // override CD to fixed disk
}
_packages.push_back(pkg);
// read file entries
uint32 numFiles = stream->readUint32LE();
for (uint32 j = 0; j < numFiles; j++) {
char *name;
uint32 offset, length, compLength, flags;/*, timeDate1, timeDate2;*/
nameLength = stream->readByte();
if (stream->eos()) {
debugC(kWintermuteDebugFileAccess, " Warning: end of package file '%s'.", filename.c_str());
break;
}
name = new char[nameLength];
stream->read(name, nameLength);
// v2 - xor name
if (hdr._packageVersion == PACKAGE_VERSION) {
for (int k = 0; k < nameLength; k++) {
((byte *)name)[k] ^= 'D';
}
}
debugC(kWintermuteDebugFileAccess, "Package contains %s", name);
Common::Path path(name, '\\');
delete[] name;
name = nullptr;
offset = stream->readUint32LE();
offset += absoluteOffset;
length = stream->readUint32LE();
compLength = stream->readUint32LE();
flags = stream->readUint32LE();
if (hdr._packageVersion == PACKAGE_VERSION) {
/* timeDate1 = */ stream->readUint32LE();
/* timeDate2 = */ stream->readUint32LE();
}
FilesMap::iterator _filesIter;
_filesIter = _files.find(path);
if (_filesIter == _files.end()) {
BaseFileEntry *fileEntry = new BaseFileEntry();
fileEntry->_package = pkg;
fileEntry->_offset = offset;
fileEntry->_length = length;
fileEntry->_compressedLength = compLength;
fileEntry->_flags = flags;
fileEntry->_filename = path;
_files[path] = Common::ArchiveMemberPtr(fileEntry);
} else {
// current package has higher priority than the registered
// TODO: This cast might be a bit ugly.
BaseFileEntry *filePtr = (BaseFileEntry *) &*(_filesIter->_value);
if (pkg->_priority > filePtr->_package->_priority) {
filePtr->_package = pkg;
filePtr->_offset = offset;
filePtr->_length = length;
filePtr->_compressedLength = compLength;
filePtr->_flags = flags;
}
}
}
}
debugC(kWintermuteDebugFileAccess, " Registered %d files in %d package(s)", _files.size(), _packages.size());
delete stream;
}
PackageSet::~PackageSet() {
for (Common::Array<BasePackage *>::iterator it = _packages.begin(); it != _packages.end(); ++it) {
delete *it;
}
_packages.clear();
}
bool PackageSet::hasFile(const Common::Path &path) const {
FilesMap::const_iterator it;
it = _files.find(path);
return (it != _files.end());
}
int PackageSet::listMembers(Common::ArchiveMemberList &list) const {
FilesMap::const_iterator it = _files.begin();
FilesMap::const_iterator end = _files.end();
int count = 0;
for (; it != end; ++it) {
const Common::ArchiveMemberPtr ptr(it->_value);
list.push_back(ptr);
count++;
}
return count;
}
const Common::ArchiveMemberPtr PackageSet::getMember(const Common::Path &path) const {
FilesMap::const_iterator it;
it = _files.find(path);
return Common::ArchiveMemberPtr(it->_value);
}
Common::SeekableReadStream *PackageSet::createReadStreamForMember(const Common::Path &path) const {
FilesMap::const_iterator it;
it = _files.find(path);
if (it != _files.end()) {
return it->_value->createReadStream();
}
return nullptr;
}
} // End of namespace Wintermute

View File

@@ -0,0 +1,92 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#ifndef WINTERMUTE_BASE_PACKAGE_H
#define WINTERMUTE_BASE_PACKAGE_H
#include "common/archive.h"
#include "common/stream.h"
#include "common/fs.h"
namespace Wintermute {
class BasePackage {
public:
Common::SeekableReadStream *getFilePointer();
Common::FSNode _fsnode;
bool _boundToExe;
byte _priority;
Common::String _name;
int32 _cd;
BasePackage();
};
class PackageSet : public Common::Archive {
public:
~PackageSet() override;
PackageSet(Common::FSNode package, const Common::String &filename = "", bool searchSignature = false);
/**
* Check if a member with the given name is present in the Archive.
* Patterns are not allowed, as this is meant to be a quick File::exists()
* replacement.
*/
bool hasFile(const Common::Path &path) const override;
/**
* Add all members of the Archive to list.
* Must only append to list, and not remove elements from it.
*
* @return the number of names added to list
*/
int listMembers(Common::ArchiveMemberList &list) const override;
/**
* Returns a ArchiveMember representation of the given file.
*/
const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
/**
* Create a stream bound to a member with the specified name in the
* archive. If no member with this name exists, 0 is returned.
* @return the newly created input stream
*/
Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
int getPriority() const { return _priority; }
uint32 getVersion() const { return _version; }
private:
byte _priority;
uint32 _version{};
Common::Array<BasePackage *> _packages;
typedef Common::HashMap<Common::Path, Common::ArchiveMemberPtr, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FilesMap;
FilesMap _files;
};
} // End of namespace Wintermute
#endif

View File

@@ -0,0 +1,79 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/base/base_persistence_manager.h"
#include "engines/wintermute/base/file/base_save_thumb_file.h"
#include "engines/wintermute/base/base.h"
#include "common/memstream.h"
namespace Wintermute {
Common::SeekableReadStream *openThumbFile(const Common::String &filename) {
if (scumm_strnicmp(filename.c_str(), "savegame:", 9) != 0) {
return nullptr;
}
size_t filenameSize = strlen(filename.c_str()) - 9 + 1;
char *tempFilename = new char[filenameSize];
Common::strcpy_s(tempFilename, filenameSize, filename.c_str() + 9);
for (uint32 i = 0; i < strlen(tempFilename); i++) {
if (tempFilename[i] < '0' || tempFilename[i] > '9') {
tempFilename[i] = '\0';
break;
}
}
// get slot number from name
int slot = atoi(tempFilename);
delete[] tempFilename;
BasePersistenceManager *pm = new BasePersistenceManager();
if (!pm) {
return nullptr;
}
Common::String slotFilename = pm->getFilenameForSlot(slot);
if (DID_FAIL(pm->initLoad(slotFilename))) {
delete pm;
return nullptr;
}
if (pm->_thumbnailDataSize == 0) {
delete pm;
return nullptr;
}
uint32 size = pm->_thumbnailDataSize;
byte *data = (byte *)malloc(size);
memcpy(data, pm->_thumbnailData, size);
delete pm;
return new Common::MemoryReadStream(data, size, DisposeAfterUse::YES);
}
} // End of namespace Wintermute

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/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#ifndef WINTERMUTE_BASE_SAVETHUMBFILE_H
#define WINTERMUTE_BASE_SAVETHUMBFILE_H
#include "common/str.h"
#include "common/stream.h"
namespace Wintermute {
Common::SeekableReadStream *openThumbFile(const Common::String &filename);
} // End of namespace Wintermute
#endif

View File

@@ -0,0 +1,86 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#include "engines/wintermute/base/file/base_savefile_manager_file.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/base_engine.h"
#include "common/system.h"
#include "common/savefile.h"
namespace Wintermute {
Common::String makeSfmFilename(const Common::String &filename) {
Common::String smFilename = filename;
for (size_t i = 0; i < smFilename.size(); i++) {
if (smFilename[i] == '/' || smFilename[i] == '\\') {
smFilename.setChar('_', i);
}
}
while (smFilename.hasPrefix("._")) {
smFilename = smFilename.substr(2);
}
return BaseEngine::instance().getGameTargetName() + "." + smFilename;
}
bool sfmFileExists(const Common::String &filename) {
Common::String smFilename = makeSfmFilename(filename);
return g_system->getSavefileManager()->listSavefiles(smFilename).size() > 0;
}
Common::SeekableReadStream *openSfmFile(const Common::String &filename) {
Common::String smFilename = makeSfmFilename(filename);
return g_system->getSavefileManager()->openRawFile(smFilename);
}
Common::WriteStream *openSfmFileForWrite(const Common::String &filename) {
Common::String smFilename = makeSfmFilename(filename);
return g_system->getSavefileManager()->openForSaving(smFilename, false);
}
Common::StringArray sfmFileList(const Common::String &mask) {
Common::String prefix = BaseEngine::instance().getGameTargetName() + ".";
Common::String smMask = makeSfmFilename(mask);
Common::StringArray array = g_system->getSavefileManager()->listSavefiles(smMask);
for (uint32 i = 0; i < array.size(); i++) {
array[i] = array[i].substr(prefix.size());
}
return array;
}
bool sfmFileRemove(const Common::String &filename) {
Common::String smFilename = makeSfmFilename(filename);
return g_system->getSavefileManager()->removeSavefile(smFilename);
}
bool sfmFileRename(const Common::String &oldName, const Common::String &newName) {
Common::String smOldName = makeSfmFilename(oldName);
Common::String smNewName = makeSfmFilename(newName);
return g_system->getSavefileManager()->renameSavefile(smOldName, smNewName, false);
}
} // End of namespace Wintermute

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/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#ifndef WINTERMUTE_BASE_SAVEFILEMANAGERFILE_H
#define WINTERMUTE_BASE_SAVEFILEMANAGERFILE_H
#include "common/str-array.h"
#include "common/stream.h"
namespace Wintermute {
Common::SeekableReadStream *openSfmFile(const Common::String &filename);
Common::WriteStream *openSfmFileForWrite(const Common::String &filename);
bool sfmFileExists(const Common::String &filename);
Common::StringArray sfmFileList(const Common::String &mask);
bool sfmFileRemove(const Common::String &filename);
bool sfmFileRename(const Common::String &oldName, const Common::String &newName);
} // End of namespace Wintermute
#endif

View File

@@ -0,0 +1,79 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* This file is based on WME Lite.
* http://dead-code.org/redir.php?target=wmelite
* Copyright (c) 2011 Jan Nedoma
*/
#ifndef _DCPACKAGE_H_
#define _DCPACKAGE_H_
#define PACKAGE_MAGIC_1 0xDEC0ADDE
#define PACKAGE_MAGIC_2 0x4B4E554A // "JUNK"
#define PACKAGE_VERSION 0x00000200
#define PACKAGE_EXTENSION "dcp"
#include "common/stream.h"
namespace Wintermute {
struct TPackageHeader {
uint32 _magic1;
uint32 _magic2;
uint32 _packageVersion;
uint32 _gameVersion;
byte _priority;
byte _cd;
bool _masterIndex;
uint32 _creationTime;
char _desc[100];
uint32 _numDirs;
// base_package.cpp:
void readFromStream(Common::ReadStream *stream);
};
/*
v2: uint32 DirOffset
Dir: byte NameLength
char Name [NameLength]
byte CD;
uint32 NumEntries
Entry: byte NameLength
char Name [NameLength]
uint32 Offset
uint32 Length
uint32 CompLength
uint32 Flags
v2: uint32 TimeDate1
uint32 TimeDate2 // not used
*/
} // End of namespace Wintermute
#endif