Initial commit
This commit is contained in:
375
engines/twine/resources/hqr.cpp
Normal file
375
engines/twine/resources/hqr.cpp
Normal file
@@ -0,0 +1,375 @@
|
||||
/* 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 "twine/resources/hqr.h"
|
||||
#include "twine/resources/lzss.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/system.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
namespace HQR {
|
||||
|
||||
#define wrap(cmd) \
|
||||
if ((cmd) == 0) { \
|
||||
warning("Failed to execute " #cmd); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress entry based in Yaz0r and Zink decompression code
|
||||
* @param dst destination pointer where will be the decompressed entry
|
||||
* @param compBuf compressed data pointer
|
||||
* @param compSize @p compBuf buffer size
|
||||
* @param decompsize real file size after decompression
|
||||
* @param mode compression mode used
|
||||
*/
|
||||
static void decompressEntry(uint8 *dst, const uint8 *compBuf, uint32 compSize, int32 decompsize, int32 mode) {
|
||||
Common::MemoryReadStream stream(compBuf, compSize);
|
||||
do {
|
||||
uint8 b = stream.readByte();
|
||||
for (int32 d = 0; d < 8; d++) {
|
||||
int32 length;
|
||||
if (!(b & (1 << d))) {
|
||||
const uint16 offset = stream.readUint16LE();
|
||||
length = (offset & 0x0F) + (mode + 1);
|
||||
const uint8 *ptr = dst - (offset >> 4) - 1;
|
||||
for (int32 i = 0; i < length; i++) {
|
||||
*(dst++) = *(ptr++);
|
||||
}
|
||||
} else {
|
||||
length = 1;
|
||||
*(dst++) = stream.readByte();
|
||||
}
|
||||
decompsize -= length;
|
||||
if (decompsize <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (decompsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a HQR entry pointer
|
||||
* @param filename HQR file name
|
||||
* @param index entry index to extract
|
||||
* @return entry real size
|
||||
*/
|
||||
static int voxEntrySize(const char *filename, int32 index, int32 hiddenIndex) {
|
||||
if (!filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::File file;
|
||||
if (!file.open(filename)) {
|
||||
warning("HQR: Could not open %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 headerSize = file.readUint32LE();
|
||||
if ((uint32)index >= headerSize / 4) {
|
||||
warning("HQR: Invalid entry index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wrap(file.seek(index * 4))
|
||||
uint32 offsetToData = file.readUint32LE();
|
||||
|
||||
wrap(file.seek(offsetToData))
|
||||
uint32 realSize = file.readUint32LE();
|
||||
uint32 compSize = file.readUint32LE();
|
||||
|
||||
// exist hidden entries
|
||||
for (int32 i = 0; i < hiddenIndex; i++) {
|
||||
wrap(file.seek(offsetToData + compSize + 10)) // hidden entry
|
||||
offsetToData = offsetToData + compSize + 10; // current hidden offset
|
||||
|
||||
realSize = file.readUint32LE();
|
||||
compSize = file.readUint32LE();
|
||||
}
|
||||
|
||||
return realSize;
|
||||
}
|
||||
|
||||
int32 getEntry(uint8 *ptr, const char *filename, int32 index) {
|
||||
if (!ptr) {
|
||||
return 0;
|
||||
}
|
||||
if (!filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::File file;
|
||||
if (!file.open(filename)) {
|
||||
warning("HQR: Could not open %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 headerSize = file.readUint32LE();
|
||||
|
||||
if ((uint32)index >= headerSize / 4) {
|
||||
warning("HQR: Invalid entry index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wrap(file.seek(index * 4))
|
||||
uint32 offsetToData = file.readUint32LE();
|
||||
|
||||
wrap(file.seek(offsetToData))
|
||||
uint32 realSize = file.readUint32LE();
|
||||
uint32 compSize = file.readUint32LE();
|
||||
uint16 mode = file.readUint16LE();
|
||||
|
||||
// uncompressed
|
||||
if (mode == 0) {
|
||||
wrap(file.read(ptr, realSize))
|
||||
}
|
||||
// compressed: modes (1 & 2)
|
||||
else if (mode == 1 || mode == 2) {
|
||||
uint8 *compDataPtr = (uint8 *)malloc(compSize);
|
||||
wrap(file.read(compDataPtr, compSize))
|
||||
decompressEntry(ptr, compDataPtr, compSize, realSize, mode);
|
||||
free(compDataPtr);
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "Loaded entry from %s for index %i with %i bytes", filename, index, realSize);
|
||||
return realSize;
|
||||
}
|
||||
|
||||
int32 entrySize(const char *filename, int32 index) {
|
||||
if (!filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::File file;
|
||||
if (!file.open(filename)) {
|
||||
warning("HQR: Could not open %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 headerSize = file.readUint32LE();
|
||||
if ((uint32)index >= headerSize / 4) {
|
||||
warning("HQR: Invalid entry index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wrap(file.seek(index * 4))
|
||||
uint32 offsetToData = file.readUint32LE();
|
||||
|
||||
wrap(file.seek(offsetToData))
|
||||
uint32 realSize = file.readUint32LE();
|
||||
|
||||
return realSize;
|
||||
}
|
||||
|
||||
int32 numEntries(const char *filename) {
|
||||
if (!filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::File file;
|
||||
if (!file.open(filename)) {
|
||||
warning("HQR: Could not open %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 headerSize = file.readUint32LE();
|
||||
return ((int)headerSize / 4) - 1;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *makeReadStream(const char *filename, int index) {
|
||||
Common::File *file = new Common::File();
|
||||
if (!file->open(filename)) {
|
||||
delete file;
|
||||
warning("HQR: Could not open %s", filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint32 headerSize = file->readUint32LE();
|
||||
if ((uint32)index >= headerSize / 4) {
|
||||
warning("HQR: Invalid entry index: %i", index);
|
||||
delete file;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!file->seek(index * 4)) {
|
||||
warning("HQR: Invalid index: %i", index);
|
||||
delete file;
|
||||
return nullptr;
|
||||
}
|
||||
const uint32 offsetToData = file->readUint32LE();
|
||||
if (!file->seek(offsetToData)) {
|
||||
warning("HQR: Invalid index: %i", index);
|
||||
delete file;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint32 realSize = file->readUint32LE();
|
||||
const uint32 compressedSize = file->readUint32LE();
|
||||
const uint16 mode = file->readUint16LE();
|
||||
|
||||
const uint32 begin = offsetToData + 10;
|
||||
uint32 end = 0;
|
||||
if (mode == 0) {
|
||||
end = begin + realSize;
|
||||
} else {
|
||||
end = begin + compressedSize;
|
||||
}
|
||||
Common::SeekableReadStream *stream = new Common::SeekableSubReadStream(file, begin, end, DisposeAfterUse::YES);
|
||||
if (mode != 0) {
|
||||
stream = new LzssReadStream(stream, mode, realSize);
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "Loaded entry from %s for index %i with %i bytes", filename, index, realSize);
|
||||
return stream;
|
||||
}
|
||||
|
||||
int32 getAllocEntry(uint8 **ptr, const char *filename, int32 index) {
|
||||
if (*ptr) {
|
||||
free(*ptr);
|
||||
}
|
||||
const int32 size = entrySize(filename, index);
|
||||
if (size <= 0) {
|
||||
*ptr = nullptr;
|
||||
warning("HQR: failed to get entry for index %i from file: %s", index, filename);
|
||||
return 0;
|
||||
}
|
||||
*ptr = (uint8 *)malloc(size * sizeof(uint8));
|
||||
if (!*ptr) {
|
||||
warning("HQR: unable to allocate entry memory");
|
||||
return 0;
|
||||
}
|
||||
const int32 entrySize = getEntry(*ptr, filename, index);
|
||||
assert(entrySize == size);
|
||||
return entrySize;
|
||||
}
|
||||
|
||||
bool dumpEntry(const char *filename, int32 index, const char *targetFileName) {
|
||||
Common::DumpFile out;
|
||||
if (!out.open(targetFileName, true)) {
|
||||
warning("Failed to save to %s", targetFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 *content = nullptr;
|
||||
const int size = getAllocEntry(&content, filename, index);
|
||||
if (size == 0) {
|
||||
warning("Could not get hqr entry in %s for index %i", filename, index);
|
||||
return false;
|
||||
}
|
||||
out.write(content, size);
|
||||
out.flush();
|
||||
out.close();
|
||||
free(content);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 getVoxEntry(uint8 *ptr, const char *filename, int32 index, int32 hiddenIndex) {
|
||||
if (!ptr) {
|
||||
return 0;
|
||||
}
|
||||
if (!filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Common::File file;
|
||||
if (!file.open(filename)) {
|
||||
warning("HQR: Could not open %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 headerSize = file.readUint32LE();
|
||||
|
||||
if ((uint32)index >= headerSize / 4) {
|
||||
warning("HQR: Invalid entry index");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wrap(file.seek(index * 4))
|
||||
uint32 offsetToData = file.readUint32LE();
|
||||
|
||||
wrap(file.seek(offsetToData))
|
||||
uint32 realSize = file.readUint32LE();
|
||||
uint32 compSize = file.readUint32LE();
|
||||
uint16 mode = file.readSint16LE();
|
||||
|
||||
// exist hidden entries
|
||||
for (int32 i = 0; i < hiddenIndex; i++) {
|
||||
wrap(file.seek(offsetToData + compSize + 10)) // hidden entry
|
||||
offsetToData = offsetToData + compSize + 10; // current hidden offset
|
||||
|
||||
realSize = file.readUint32LE();
|
||||
compSize = file.readUint32LE();
|
||||
mode = file.readUint16LE();
|
||||
}
|
||||
|
||||
// uncompressed
|
||||
if (mode == 0) {
|
||||
wrap(file.read(ptr, realSize))
|
||||
}
|
||||
// compressed: modes (1 & 2)
|
||||
else if (mode == 1 || mode == 2) {
|
||||
uint8 *compDataPtr = (uint8 *)malloc(compSize);
|
||||
wrap(file.read(compDataPtr, compSize))
|
||||
decompressEntry(ptr, compDataPtr, compSize, realSize, mode);
|
||||
free(compDataPtr);
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "Loaded vox entry from %s for index %i with %i bytes", filename, index, realSize);
|
||||
return realSize;
|
||||
}
|
||||
|
||||
bool getPaletteEntry(Graphics::Palette &palette, const char *filename, int32 index) {
|
||||
byte paletteBuffer[NUMOFCOLORS * 3];
|
||||
int32 size = HQR::getEntry(paletteBuffer, filename, index);
|
||||
if (size <= 0) {
|
||||
debugC(1, TwinE::kDebugResources, "Failed to load palette from %s for index %i", filename, index);
|
||||
return false;
|
||||
}
|
||||
palette = Graphics::Palette(paletteBuffer, size / 3);
|
||||
debugC(1, TwinE::kDebugResources, "Loaded palette from %s for index %i with %i color entries", filename, index, (int)palette.size());
|
||||
debugC(1, TwinE::kDebugPalette, "Loaded palette from %s for index %i with %i color entries", filename, index, (int)palette.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 getAllocVoxEntry(uint8 **ptr, const char *filename, int32 index, int32 hiddenIndex) {
|
||||
const int32 size = voxEntrySize(filename, index, hiddenIndex);
|
||||
if (size == 0) {
|
||||
warning("HQR: vox entry with 0 size found for index: %d", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ptr = (uint8 *)malloc(size * sizeof(uint8));
|
||||
if (!*ptr) {
|
||||
warning("HQR: unable to allocate entry memory of size %d for index: %d", size, index);
|
||||
return 0;
|
||||
}
|
||||
const int32 entrySize = getVoxEntry(*ptr, filename, index, hiddenIndex);
|
||||
assert(entrySize == size);
|
||||
return entrySize;
|
||||
}
|
||||
|
||||
#undef wrap
|
||||
|
||||
} // namespace HQR
|
||||
|
||||
} // namespace TwinE
|
||||
124
engines/twine/resources/hqr.h
Normal file
124
engines/twine/resources/hqr.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* 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 TWINE_RESOURCES_HQR_H
|
||||
#define TWINE_RESOURCES_HQR_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/stream.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "twine/shared.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
class TwinEEngine;
|
||||
|
||||
/**
|
||||
* High Quality Resource
|
||||
*
|
||||
* https://web.archive.org/web/20181218233826/http://lbafileinfo.kazekr.net/index.php?title=High_quality_resource
|
||||
*/
|
||||
namespace HQR {
|
||||
|
||||
|
||||
/**
|
||||
* Get a HQR entry pointer
|
||||
* @param ptr pointer to save the entry
|
||||
* @param filename HQR file name
|
||||
* @param index entry index to extract
|
||||
* @return entry real size
|
||||
*/
|
||||
int32 getEntry(uint8 *ptr, const char *filename, int32 index);
|
||||
inline int32 getEntry(uint8 *ptr, const TwineResource &resource) {
|
||||
return getEntry(ptr, resource.hqr, resource.index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a HQR entry pointer
|
||||
* @param filename HQR file name
|
||||
* @param index entry index to extract
|
||||
* @return entry real size
|
||||
*/
|
||||
int32 entrySize(const char *filename, int32 index);
|
||||
inline int32 entrySize(const TwineResource &resource) {
|
||||
return entrySize(resource.hqr, resource.index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a HQR total number of entries
|
||||
* @param filename HQR file name
|
||||
* @return total number of entries
|
||||
*/
|
||||
int32 numEntries(const char *filename);
|
||||
|
||||
/**
|
||||
* Get a HQR entry pointer with memory allocation
|
||||
* @param ptr pointer to save the entry. This pointer is automatically freed and therefore must be initialized
|
||||
* to @c nullptr on the first run.
|
||||
* @param filename HQR file name
|
||||
* @param index entry index to extract
|
||||
* @return entry real size
|
||||
*/
|
||||
int32 getAllocEntry(uint8 **ptr, const char *filename, int32 index);
|
||||
inline int32 getAllocEntry(uint8 **ptr, const TwineResource &resource) {
|
||||
return getAllocEntry(ptr, resource.hqr, resource.index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper method to dump the content of the given hqr index to a file
|
||||
*/
|
||||
bool dumpEntry(const char *filename, int32 index, const char *targetFileName);
|
||||
inline bool dumpEntry(const TwineResource &resource, const char *targetFileName) {
|
||||
return dumpEntry(resource.hqr, resource.index, targetFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a HQR entry pointer
|
||||
* @param ptr pointer to save the entry
|
||||
* @param filename HQR file name
|
||||
* @param index entry index to extract
|
||||
* @return entry real size
|
||||
*/
|
||||
int32 getVoxEntry(uint8 *ptr, const char *filename, int32 index, int32 hiddenIndex);
|
||||
/**
|
||||
* Get a HQR entry pointer with memory allocation
|
||||
* @param ptr pointer to save the entry. This pointer is automatically freed and therefore must be initialized
|
||||
* to @c nullptr on the first run.
|
||||
* @param filename HQR file name
|
||||
* @param index entry index to extract
|
||||
* @return entry real size
|
||||
*/
|
||||
int32 getAllocVoxEntry(uint8 **ptr, const char *filename, int32 index, int32 hiddenIndex);
|
||||
|
||||
bool getPaletteEntry(Graphics::Palette &palette, const char *filename, int32 index);
|
||||
inline bool getPaletteEntry(Graphics::Palette &palette, const TwineResource &resource) {
|
||||
return getPaletteEntry(palette, resource.hqr, resource.index);
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *makeReadStream(const char *filename, int index);
|
||||
inline Common::SeekableReadStream *makeReadStream(const TwineResource &resource) {
|
||||
return makeReadStream(resource.hqr, resource.index);
|
||||
}
|
||||
} // namespace HQR
|
||||
|
||||
} // namespace TwinE
|
||||
|
||||
#endif
|
||||
110
engines/twine/resources/lzss.cpp
Normal file
110
engines/twine/resources/lzss.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/* 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 "twine/resources/lzss.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
LzssReadStream::LzssReadStream(Common::ReadStream *indata, uint32 mode, uint32 realsize) {
|
||||
_outLzssBufData = new uint8[realsize]();
|
||||
decodeLZSS(indata, mode, realsize);
|
||||
_size = realsize;
|
||||
_pos = 0;
|
||||
delete indata;
|
||||
}
|
||||
|
||||
LzssReadStream::~LzssReadStream() {
|
||||
delete[] _outLzssBufData;
|
||||
}
|
||||
|
||||
void LzssReadStream::decodeLZSS(Common::ReadStream *in, uint32 mode, uint32 dataSize) {
|
||||
if (in->eos() || in->err() || dataSize == 0) {
|
||||
_err = dataSize > 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 *dst = _outLzssBufData;
|
||||
int32 remainingBytes = (int32)dataSize;
|
||||
|
||||
do {
|
||||
uint8 b = in->readByte();
|
||||
for (int32 d = 0; d < 8; d++) {
|
||||
if (in->eos() || in->err()) {
|
||||
_err = dataSize > 0;
|
||||
return;
|
||||
}
|
||||
int32 length;
|
||||
if (!(b & (1 << d))) {
|
||||
const uint16 offset = in->readUint16LE();
|
||||
length = (offset & 0x0F) + (mode + 1);
|
||||
const uint8 *ptr = dst - (offset >> 4) - 1;
|
||||
if (remainingBytes < length) {
|
||||
_err = true;
|
||||
return;
|
||||
}
|
||||
remainingBytes -= length;
|
||||
for (int32 i = 0; i < length; i++) {
|
||||
*dst++ = *ptr++;
|
||||
}
|
||||
} else {
|
||||
length = 1;
|
||||
if (remainingBytes < length) {
|
||||
_err = true;
|
||||
return;
|
||||
}
|
||||
remainingBytes -= length;
|
||||
*dst++ = in->readByte();
|
||||
}
|
||||
dataSize -= length;
|
||||
if (dataSize <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (dataSize);
|
||||
}
|
||||
|
||||
bool LzssReadStream::eos() const {
|
||||
return _pos >= _size;
|
||||
}
|
||||
|
||||
uint32 LzssReadStream::read(void *buf, uint32 dataSize) {
|
||||
if (dataSize > _size - _pos) {
|
||||
_err = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(buf, &_outLzssBufData[_pos], dataSize);
|
||||
_pos += dataSize;
|
||||
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
bool LzssReadStream::seek(int64 offset, int whence) {
|
||||
if (whence == SEEK_SET) {
|
||||
_pos = offset;
|
||||
} else if (whence == SEEK_CUR) {
|
||||
_pos += offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace TwinE
|
||||
54
engines/twine/resources/lzss.h
Normal file
54
engines/twine/resources/lzss.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 TWINE_RESOURCES_LZSS_H
|
||||
#define TWINE_RESOURCES_LZSS_H
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
class LzssReadStream : public Common::SeekableReadStream {
|
||||
private:
|
||||
uint8 *_outLzssBufData;
|
||||
uint32 _size;
|
||||
uint32 _pos;
|
||||
bool _err = false;
|
||||
|
||||
void decodeLZSS(Common::ReadStream *indata, uint32 mode, uint32 length);
|
||||
|
||||
public:
|
||||
LzssReadStream(Common::ReadStream *indata, uint32 mode, uint32 realsize);
|
||||
virtual ~LzssReadStream();
|
||||
|
||||
void clearErr() override { _err = false; }
|
||||
bool err() const override { return _err; }
|
||||
int64 pos() const override { return _pos; }
|
||||
int64 size() const override { return _size; }
|
||||
bool seek(int64 offset, int whence = SEEK_SET) override;
|
||||
|
||||
bool eos() const override;
|
||||
uint32 read(void *buf, uint32 size) override;
|
||||
};
|
||||
|
||||
} // namespace TwinE
|
||||
|
||||
#endif
|
||||
325
engines/twine/resources/resources.cpp
Normal file
325
engines/twine/resources/resources.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
/* 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 "twine/resources/resources.h"
|
||||
#include "common/file.h"
|
||||
#include "common/tokenizer.h"
|
||||
#include "common/util.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "twine/audio/sound.h"
|
||||
#include "twine/parser/anim3ds.h"
|
||||
#include "twine/renderer/renderer.h"
|
||||
#include "twine/renderer/screens.h"
|
||||
#include "twine/resources/hqr.h"
|
||||
#include "twine/scene/animations.h"
|
||||
#include "twine/scene/scene.h"
|
||||
#include "twine/shared.h"
|
||||
#include "twine/text.h"
|
||||
#include "twine/twine.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
Resources::~Resources() {
|
||||
for (size_t i = 0; i < ARRAYSIZE(_spriteTable); ++i) {
|
||||
free(_spriteTable[i]);
|
||||
}
|
||||
for (size_t i = 0; i < ARRAYSIZE(_samplesTable); ++i) {
|
||||
free(_samplesTable[i]);
|
||||
}
|
||||
free(_fontPtr);
|
||||
free(_sjisFontPtr);
|
||||
}
|
||||
|
||||
void Resources::initPalettes() {
|
||||
if (!HQR::getPaletteEntry(_engine->_screens->_ptrPal, Resources::HQR_RESS_FILE, RESSHQR_MAINPAL)) {
|
||||
error("Failed to load main palette");
|
||||
}
|
||||
_engine->setPalette(_engine->_screens->_ptrPal);
|
||||
}
|
||||
|
||||
void Resources::preloadAnim3DS() {
|
||||
const int index = HQR::numEntries(Resources::HQR_ANIM3DS_FILE) - 1;
|
||||
_anim3DSData.loadFromHQR(Resources::HQR_ANIM3DS_FILE, index, _engine->isLBA1());
|
||||
}
|
||||
|
||||
void Resources::loadEntityData(EntityData &entityData, int32 &index) {
|
||||
if (_engine->isLBA1()) {
|
||||
TwineResource modelRes(Resources::HQR_FILE3D_FILE, index);
|
||||
if (!entityData.loadFromHQR(modelRes, _engine->isLBA1())) {
|
||||
error("Failed to load actor 3d data for index: %i", index);
|
||||
}
|
||||
} else {
|
||||
// TODO: don't allocate each time
|
||||
TwineResource modelRes(Resources::HQR_RESS_FILE, 44);
|
||||
uint8 *file3dBuf = nullptr;
|
||||
const int32 holomapImageSize = HQR::getAllocEntry(&file3dBuf, modelRes);
|
||||
if (!entityData.loadFromBuffer((uint8 *)(file3dBuf + *(((uint32 *)file3dBuf) + (index))), holomapImageSize, _engine->isLBA1())) {
|
||||
delete file3dBuf;
|
||||
error("Failed to load actor 3d data for index: %i", index);
|
||||
}
|
||||
delete file3dBuf;
|
||||
}
|
||||
}
|
||||
|
||||
const T_ANIM_3DS *Resources::getAnim(int index) const {
|
||||
if (index < 0 || index >= (int)_anim3DSData.getAnims().size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &_anim3DSData.getAnims()[index];
|
||||
}
|
||||
|
||||
void Resources::preloadSprites() {
|
||||
const int32 numEntries = HQR::numEntries(Resources::HQR_SPRITES_FILE);
|
||||
const int32 maxSprites = _engine->isLBA1() ? 200 : NUM_SPRITES;
|
||||
if (numEntries > maxSprites) {
|
||||
error("Max allowed sprites exceeded: %i/%i", numEntries, maxSprites);
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "preload %i sprites", numEntries);
|
||||
for (int32 i = 0; i < numEntries; i++) {
|
||||
_spriteSizeTable[i] = HQR::getAllocEntry(&_spriteTable[i], Resources::HQR_SPRITES_FILE, i);
|
||||
if (!_spriteData[i].loadFromBuffer(_spriteTable[i], _spriteSizeTable[i], _engine->isLBA1())) {
|
||||
warning("Failed to load sprite %i", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resources::preloadAnimations() {
|
||||
const int32 numEntries = HQR::numEntries(Resources::HQR_ANIM_FILE);
|
||||
const int32 maxAnims = _engine->isLBA1() ? 600 : NUM_ANIMS;
|
||||
if (numEntries > maxAnims) {
|
||||
error("Max allowed animations exceeded: %i/%i", numEntries, maxAnims);
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "preload %i animations", numEntries);
|
||||
for (int32 i = 0; i < numEntries; i++) {
|
||||
_animData[i].loadFromHQR(Resources::HQR_ANIM_FILE, i, _engine->isLBA1());
|
||||
}
|
||||
}
|
||||
|
||||
static bool isLba1BlankSampleEntry(int32 index) {
|
||||
// these indices contain blank hqr entries
|
||||
const int32 blankIndices[] = {80, 81, 82, 83, 115, 118, 120, 124, 125, 139, 140, 154, 155};
|
||||
for (int j = 0; j < ARRAYSIZE(blankIndices); ++j) {
|
||||
if (index == blankIndices[j]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Resources::preloadSamples() {
|
||||
const int32 numEntries = HQR::numEntries(Resources::HQR_SAMPLES_FILE);
|
||||
const int32 maxSamples = _engine->isLBA1() ? 243 : NUM_SAMPLES;
|
||||
if (numEntries > maxSamples) {
|
||||
error("Max allowed samples exceeded: %i/%i", numEntries, maxSamples);
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "preload %i samples", numEntries);
|
||||
for (int32 i = 0; i < numEntries; i++) {
|
||||
if (_engine->isLBA1() && isLba1BlankSampleEntry(i)) {
|
||||
_samplesSizeTable[i] = 0;
|
||||
_samplesTable[i] = nullptr;
|
||||
continue;
|
||||
}
|
||||
_samplesSizeTable[i] = HQR::getAllocEntry(&_samplesTable[i], Resources::HQR_SAMPLES_FILE, i);
|
||||
if (_samplesSizeTable[i] == 0) {
|
||||
warning("Failed to load sample %i", i);
|
||||
continue;
|
||||
}
|
||||
// Fix incorrect sample files first byte
|
||||
if (*_samplesTable[i] != 'C') {
|
||||
debugC(1, TwinE::kDebugResources, "Sample %i has incorrect magic id (size: %u)", i, _samplesSizeTable[i]);
|
||||
*_samplesTable[i] = 'C';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Resources::preloadInventoryItems() {
|
||||
if (!_engine->isLBA1()) {
|
||||
// lba2 has this data in code
|
||||
return;
|
||||
}
|
||||
int32 numEntries = HQR::numEntries(Resources::HQR_INVOBJ_FILE);
|
||||
if (_engine->isPreview()) {
|
||||
if (numEntries != 32) {
|
||||
error("Unexpected inventory items for lba1 preview version: %i/32", numEntries);
|
||||
}
|
||||
// TODO: this is obviously a hack
|
||||
numEntries = NUM_INVENTORY_ITEMS;
|
||||
} else {
|
||||
if (numEntries > NUM_INVENTORY_ITEMS) {
|
||||
error("Max allowed inventory items exceeded: %i/%i", numEntries, NUM_INVENTORY_ITEMS);
|
||||
}
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "preload %i inventory items", numEntries);
|
||||
for (int32 i = 0; i < numEntries; i++) {
|
||||
_inventoryTable[i].loadFromHQR(Resources::HQR_INVOBJ_FILE, i, _engine->isLBA1());
|
||||
}
|
||||
}
|
||||
|
||||
void Resources::initResources() {
|
||||
initPalettes();
|
||||
|
||||
_fontBufSize = HQR::getAllocEntry(&_fontPtr, Resources::HQR_RESS_FILE, RESSHQR_LBAFONT);
|
||||
if (_fontBufSize == 0) {
|
||||
error("Failed to load font");
|
||||
}
|
||||
|
||||
const int kMinSjisSize = 11072 * 24 * 3;
|
||||
Common::File f24;
|
||||
if (f24.open("FNT24.DAT") && f24.size() >= kMinSjisSize) {
|
||||
// Rest is garbage
|
||||
_sjisFontPtr = (byte *)malloc(kMinSjisSize);
|
||||
assert(_sjisFontPtr);
|
||||
f24.read(_sjisFontPtr, kMinSjisSize);
|
||||
}
|
||||
|
||||
_engine->_text->setFont(INTER_LEAVE, INTER_SPACE);
|
||||
_engine->_text->setFontColor(COLOR_14);
|
||||
_engine->_text->setTextCrossColor(136, 143, 2);
|
||||
|
||||
if (_engine->isLBA1()) {
|
||||
if (!_spriteShadowPtr.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_SPRITESHADOW), _engine->isLBA1())) {
|
||||
error("Failed to load shadow sprites");
|
||||
}
|
||||
|
||||
if (!_spriteBoundingBox.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_SPRITEBOXDATA), _engine->isLBA1())) {
|
||||
error("Failed to load sprite bounding box data");
|
||||
}
|
||||
|
||||
if (!_holomapTwinsenModelPtr.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_HOLOTWINMDL), _engine->isLBA1())) {
|
||||
error("Failed to load holomap twinsen model");
|
||||
}
|
||||
|
||||
if (!_holomapPointModelPtr.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_HOLOPOINTMDL), _engine->isLBA1())) {
|
||||
if (!_engine->isPreview()) {
|
||||
error("Failed to load holomap point model");
|
||||
}
|
||||
}
|
||||
|
||||
if (!_holomapArrowPtr.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_HOLOARROWMDL), _engine->isLBA1())) {
|
||||
error("Failed to load holomap arrow model");
|
||||
}
|
||||
|
||||
if (!_holomapTwinsenArrowPtr.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_HOLOTWINARROWMDL), _engine->isLBA1())) {
|
||||
error("Failed to load holomap twinsen arrow model");
|
||||
}
|
||||
|
||||
if (!_trajectories.loadFromHQR(TwineResource(Resources::HQR_RESS_FILE, RESSHQR_HOLOPOINTANIM), _engine->isLBA1())) {
|
||||
if (!_engine->isPreview()) {
|
||||
error("Failed to parse trajectory data");
|
||||
}
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "preload %i trajectories", (int)_trajectories.getTrajectories().size());
|
||||
} else if (_engine->isLBA2()) {
|
||||
preloadAnim3DS();
|
||||
}
|
||||
|
||||
preloadSprites();
|
||||
preloadAnimations();
|
||||
preloadSamples();
|
||||
preloadInventoryItems();
|
||||
|
||||
loadMovieInfo();
|
||||
|
||||
if (!_engine->isPreview()) {
|
||||
// TODO: where is the text in the preview version?
|
||||
const int32 textEntryCount = _engine->isLBA1() ? 28 : 30;
|
||||
for (int32 i = 0; i < textEntryCount / 2; ++i) {
|
||||
if (!_textData.loadFromHQR(Resources::HQR_TEXT_FILE, (TextBankId)i, _engine->_cfgfile._languageId, _engine->isLBA1(), textEntryCount)) {
|
||||
error("HQR ERROR: Parsing textbank %i failed for language %i (%i entries)", i, _engine->_cfgfile._languageId, textEntryCount);
|
||||
}
|
||||
}
|
||||
debugC(1, TwinE::kDebugResources, "Loaded %i text banks", textEntryCount / 2);
|
||||
}
|
||||
}
|
||||
|
||||
const TextEntry *Resources::getText(TextBankId textBankId, TextId index) const {
|
||||
return _textData.getText(textBankId, index);
|
||||
}
|
||||
|
||||
const Trajectory *Resources::giveTrajPtr(int index) const {
|
||||
return _trajectories.getTrajectory(index);
|
||||
}
|
||||
|
||||
int Resources::findSmkMovieIndex(const char *name) const {
|
||||
Common::String smkName = name;
|
||||
smkName.toLowercase();
|
||||
if (!_movieInfo.contains(smkName)) {
|
||||
warning("Movie '%s' not found in movie info", smkName.c_str());
|
||||
return -1;
|
||||
}
|
||||
const Common::Array<int32> &info = getMovieInfo(smkName);
|
||||
return info[0];
|
||||
}
|
||||
|
||||
void Resources::loadMovieInfo() {
|
||||
uint8 *content = nullptr;
|
||||
int32 size;
|
||||
if (_engine->isLBA1()) {
|
||||
if (_engine->isPreview()) {
|
||||
size = 0;
|
||||
} else {
|
||||
size = HQR::getAllocEntry(&content, Resources::HQR_RESS_FILE, RESSHQR_FLAINFO);
|
||||
}
|
||||
} else {
|
||||
size = HQR::getAllocEntry(&content, Resources::HQR_RESS_FILE, 48);
|
||||
}
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
const Common::String str((const char *)content, size);
|
||||
free(content);
|
||||
debugC(2, TwinE::kDebugResources, "movie info:\n%s", str.c_str());
|
||||
Common::StringTokenizer tok(str, "\r\n");
|
||||
int videoIndex = 0;
|
||||
while (!tok.empty()) {
|
||||
Common::String line = tok.nextToken();
|
||||
if (_engine->isLBA1()) {
|
||||
Common::StringTokenizer lineTok(line);
|
||||
if (lineTok.empty()) {
|
||||
continue;
|
||||
}
|
||||
const Common::String &name = lineTok.nextToken();
|
||||
Common::Array<int32> frames;
|
||||
while (!lineTok.empty()) {
|
||||
const Common::String &frame = lineTok.nextToken();
|
||||
const int32 frameIdx = atoi(frame.c_str());
|
||||
frames.push_back(frameIdx);
|
||||
}
|
||||
_movieInfo.setVal(name, frames);
|
||||
} else {
|
||||
Common::Array<int32> info(1);
|
||||
info[0] = videoIndex;
|
||||
line.toLowercase();
|
||||
if (line.hasSuffix(".smk")) {
|
||||
line = line.substr(0, line.size() - 4);
|
||||
}
|
||||
_movieInfo.setVal(line, info);
|
||||
debugC(1, TwinE::kDebugResources, "movie name %s mapped to hqr index %i", line.c_str(), videoIndex);
|
||||
++videoIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Common::Array<int32> &Resources::getMovieInfo(const Common::String &name) const {
|
||||
return _movieInfo.getVal(name);
|
||||
}
|
||||
|
||||
} // namespace TwinE
|
||||
304
engines/twine/resources/resources.h
Normal file
304
engines/twine/resources/resources.h
Normal file
@@ -0,0 +1,304 @@
|
||||
/* 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 TWINE_RESOURCES_RESOURCES_H
|
||||
#define TWINE_RESOURCES_RESOURCES_H
|
||||
|
||||
#include "common/hashmap.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "twine/parser/anim3ds.h"
|
||||
#include "twine/parser/body.h"
|
||||
#include "twine/parser/holomap.h"
|
||||
#include "twine/parser/sprite.h"
|
||||
#include "twine/parser/text.h"
|
||||
#include "twine/resources/hqr.h"
|
||||
#include "twine/scene/gamestate.h"
|
||||
#include "twine/scene/scene.h"
|
||||
|
||||
namespace TwinE {
|
||||
|
||||
/** RESS.HQR FILE */
|
||||
#define RESSHQR_MAINPAL 0
|
||||
#define RESSHQR_LBAFONT 1
|
||||
#define RESSHQR_BLANK 2
|
||||
#define RESSHQR_SPRITEBOXDATA 3
|
||||
#define RESSHQR_SPRITESHADOW 4
|
||||
#define RESSHQR_HOLOPAL 5 // lba1
|
||||
#define RESSHQR_HOLOSURFACE 6 // lba1
|
||||
#define RESSHQR_HOLOIMG 7 // lba1
|
||||
#define RESSHQR_HOLOARROWINFO 8 // lba1
|
||||
#define RESSHQR_HOLOTWINMDL 9 // lba1
|
||||
#define RESSHQR_HOLOARROWMDL 10 // lba1
|
||||
#define RESSHQR_HOLOTWINARROWMDL 11 // lba1
|
||||
|
||||
#define RESSHQR_BLACKPAL 9 // lba2
|
||||
#define RESSHQR_ECLAIRPAL 10 // lba2
|
||||
#define RESSHQR_ARROWBIN 12 // lba2
|
||||
#define SAMPLE_RAIN 13
|
||||
|
||||
#define RESSHQR_GAMEOVERMDL 21
|
||||
|
||||
#define RESSHQR_ALARMREDPAL 22
|
||||
#define RESSHQR_FLAINFO 23
|
||||
#define RESSHQR_DARKPAL 24
|
||||
|
||||
#define RESSHQR_HOLOPOINTMDL 29
|
||||
#define RESSHQR_HOLOPOINTANIM 30
|
||||
|
||||
#define RESSHQR_PLASMAEFFECT 51
|
||||
|
||||
#define FLA_DRAGON3 "dragon3"
|
||||
#define FLA_INTROD "introd"
|
||||
#define FLA_THEEND "the_end"
|
||||
#define FLA_BATEAU "bateau"
|
||||
|
||||
#define ACF_INTRO "INTRO"
|
||||
|
||||
#define FILE3DHQR_HERONORMAL 0
|
||||
#define FILE3DHQR_HEROATHLETIC 1
|
||||
#define FILE3DHQR_HEROAGGRESSIVE 2
|
||||
#define FILE3DHQR_HERODISCRETE 3
|
||||
#define FILE3DHQR_HEROPROTOPACK 4
|
||||
|
||||
/** Behaviour menu sprite values */
|
||||
#define SPRITEHQR_KASHES 3
|
||||
#define SPRITEHQR_LIFEPOINTS 4
|
||||
#define SPRITEHQR_MAGICPOINTS 5
|
||||
#define SPRITEHQR_KEY 6
|
||||
#define SPRITEHQR_CLOVERLEAF 7
|
||||
#define SPRITEHQR_CLOVERLEAFBOX 41
|
||||
|
||||
#define SPRITEHQR_MAGICBALL_YELLOW 1
|
||||
#define SPRITEHQR_MAGICBALL_FIRE 13
|
||||
#define SPRITEHQR_MAGICBALL_GREEN 42
|
||||
#define SPRITEHQR_MAGICBALL_RED 43
|
||||
#define SPRITEHQR_MAGICBALL_YELLOW_TRANS 44
|
||||
#define SPRITEHQR_EXPLOSION_FIRST_FRAME 97 // 7 frames
|
||||
#define SPRITEHQR_FENCE_1 18
|
||||
#define SPRITEHQR_FENCE_2 19
|
||||
#define SPRITEHQR_FENCE_3 22
|
||||
#define SPRITEHQR_FENCE_4 23
|
||||
#define SPRITEHQR_FENCE_METAL 35
|
||||
#define SPRITEHQR_FENCE_METAL_2 54
|
||||
#define SPRITEHQR_FENCE_METAL_3 83
|
||||
#define SPRITEHQR_MUSHROOM 92
|
||||
#define SPRITEHQR_DOOR_WODDEN_1 31
|
||||
#define SPRITEHQR_DOOR_WODDEN_2 32
|
||||
#define SPRITEHQR_DOOR_PRISON_WODDEN 37
|
||||
#define SPRITEHQR_DOOR_PADLOCK 58
|
||||
#define SPRITEHQR_DOOR_BRICKED_UP 76
|
||||
#define SPRITEHQR_DOOR_1 104
|
||||
#define SPRITEHQR_DOOR_2 107
|
||||
#define SPRITEHQR_DOOR_3 24
|
||||
#define SPRITEHQR_DOOR_4 11
|
||||
#define SPRITEHQR_DOOR_5 12
|
||||
#define SPRITEHQR_DOOR_PRISON_GRID 15
|
||||
#define SPRITEHQR_DOOR_PRISON_HARMED 16
|
||||
#define SPRITEHQR_DOOR_PRISON_WITH_F_LETTER 17
|
||||
#define SPRITEHQR_MAGICBALL_GREEN_TRANS 109
|
||||
#define SPRITEHQR_MAGICBALL_RED_TRANS 110
|
||||
|
||||
#define SPRITEHQR_DIAG_BUBBLE_RIGHT 90
|
||||
#define SPRITEHQR_DIAG_BUBBLE_LEFT 91
|
||||
|
||||
/** Total number of animations allowed in the game */
|
||||
#define NUM_ANIMS 2083 // 600 for lba1
|
||||
|
||||
/** Total number of samples allowed in the game */
|
||||
#define NUM_SAMPLES 895 // 243 for lba1
|
||||
|
||||
class TwinEEngine;
|
||||
|
||||
class Resources {
|
||||
private:
|
||||
TwinEEngine *_engine;
|
||||
|
||||
void preloadInventoryItems();
|
||||
/** Init standard menu and in-game palette */
|
||||
void initPalettes();
|
||||
/** Preload all sprites */
|
||||
void preloadSprites();
|
||||
|
||||
/** Preload all animations */
|
||||
void preloadAnimations();
|
||||
void preloadAnim3DS();
|
||||
void preloadSamples();
|
||||
void loadMovieInfo();
|
||||
|
||||
using MovieInfoMap = Common::HashMap<Common::String, Common::Array<int32> >;
|
||||
MovieInfoMap _movieInfo;
|
||||
|
||||
TrajectoryData _trajectories;
|
||||
|
||||
TextData _textData;
|
||||
Anim3DSData _anim3DSData;
|
||||
public:
|
||||
Resources(TwinEEngine *engine) : _engine(engine) {}
|
||||
~Resources();
|
||||
|
||||
/**
|
||||
* For lba1 this is returning the gif images that are used as a placeholder for the fla movies
|
||||
* For lba2 this is the list of videos that are mapped by their entry index
|
||||
*/
|
||||
const Common::Array<int32> &getMovieInfo(const Common::String &name) const;
|
||||
|
||||
/** Table with all loaded samples */
|
||||
BodyData _inventoryTable[NUM_INVENTORY_ITEMS];
|
||||
|
||||
/** Table with all loaded sprites */
|
||||
uint8 *_spriteTable[NUM_SPRITES]{nullptr};
|
||||
/** Table with all loaded sprite sizes */
|
||||
uint32 _spriteSizeTable[NUM_SPRITES]{0};
|
||||
SpriteData _spriteData[NUM_SPRITES];
|
||||
|
||||
AnimData _animData[NUM_ANIMS]; // HQR_Anims
|
||||
|
||||
/** Table with all loaded samples */
|
||||
uint8 *_samplesTable[NUM_SAMPLES]{nullptr};
|
||||
/** Table with all loaded samples sizes */
|
||||
uint32 _samplesSizeTable[NUM_SAMPLES]{0};
|
||||
|
||||
/** Font buffer pointer */
|
||||
int32 _fontBufSize = 0;
|
||||
uint8 *_fontPtr = nullptr;
|
||||
uint8 *_sjisFontPtr = nullptr;
|
||||
|
||||
SpriteData _spriteShadowPtr;
|
||||
SpriteBoundingBoxData _spriteBoundingBox;
|
||||
|
||||
BodyData _holomapPointModelPtr;
|
||||
BodyData _holomapTwinsenModelPtr;
|
||||
BodyData _holomapTwinsenArrowPtr;
|
||||
BodyData _holomapArrowPtr;
|
||||
|
||||
/** Initialize resource pointers */
|
||||
void initResources();
|
||||
|
||||
const Trajectory *giveTrajPtr(int index) const;
|
||||
const TrajectoryData &getTrajectories() const {
|
||||
return _trajectories;
|
||||
}
|
||||
void loadEntityData(EntityData &entityData, int32 &index);
|
||||
|
||||
const TextEntry *getText(TextBankId textBankId, TextId index) const;
|
||||
const T_ANIM_3DS *getAnim(int index) const;
|
||||
|
||||
int findSmkMovieIndex(const char *name) const;
|
||||
|
||||
// main palette
|
||||
static constexpr const char *HQR_RESS_FILE = "ress.hqr";
|
||||
// dialoges
|
||||
static constexpr const char *HQR_TEXT_FILE = "text.hqr";
|
||||
// samples
|
||||
static constexpr const char *HQR_SAMPLES_FILE = "samples.hqr";
|
||||
/**
|
||||
* This file contains isometric grids that are used to display area backgrounds and define 3D shape of the surface.
|
||||
* Each of the entries is associated with the entry of lba_bll.hqr with the same index. lba_bll entries define block
|
||||
* sets for use with the grids. Each grid may use only one set of blocks (one entry of lba_bll.hqr).
|
||||
*/
|
||||
static constexpr const char *HQR_LBA_GRI_FILE = "lba_gri.hqr";
|
||||
// isometric libraries for use in grids.
|
||||
static constexpr const char *HQR_LBA_BLL_FILE = "lba_bll.hqr";
|
||||
/**
|
||||
* isometric bricks, which are some kind of tiles, that are used for building the terrains in LBA 1 isometric scenes.
|
||||
* One brick is the tiniest piece of a grid, which has 64 x 64 x 25 cells. Bricks cannot be used directly on a grid,
|
||||
* but instead they are grouped into blocks by block libraries, which are then referenced by grids
|
||||
* Bricks are images or sprites in a special format.
|
||||
*/
|
||||
static constexpr const char *HQR_LBA_BRK_FILE = "lba_brk.hqr";
|
||||
// scenes (active area content (actors, scripts, etc.))
|
||||
static constexpr const char *HQR_SCENE_FILE = "scene.hqr";
|
||||
// full screen images (lba2)
|
||||
static constexpr const char *HQR_SCREEN_FILE = "screen.hqr";
|
||||
// sprites
|
||||
static constexpr const char *HQR_SPRITES_FILE = "sprites.hqr";
|
||||
/**
|
||||
* model/animation entities
|
||||
* contains data associating 3D models (Body.hqr) with animations (Anim.hqr) for the game characters.
|
||||
*/
|
||||
static constexpr const char *HQR_FILE3D_FILE = "file3d.hqr";
|
||||
// 3d model data
|
||||
static constexpr const char *HQR_BODY_FILE = "body.hqr";
|
||||
// animations
|
||||
static constexpr const char *HQR_ANIM_FILE = "anim.hqr";
|
||||
static constexpr const char *HQR_ANIM3DS_FILE = "anim3ds.hqr";
|
||||
// inventory objects
|
||||
static constexpr const char *HQR_INVOBJ_FILE = "invobj.hqr";
|
||||
// lba2 holomap
|
||||
static constexpr const char *HQR_HOLOMAP_FILE = "holomap.hqr";
|
||||
|
||||
/**
|
||||
* @brief Floppy version of the game uses gifs for replacing the videos
|
||||
*/
|
||||
static constexpr const char *HQR_FLAGIF_FILE = "fla_gif.hqr";
|
||||
static constexpr const char *HQR_FLASAMP_FILE = "flasamp.hqr";
|
||||
static constexpr const char *HQR_MIDI_MI_DOS_FILE = "midi_mi.hqr";
|
||||
static constexpr const char *HQR_MIDI_MI_WIN_FILE = "midi_mi_win.hqr";
|
||||
|
||||
static constexpr const char *HQR_VIDEO_FILE = "video.hqr"; // lba2 - smk files
|
||||
|
||||
TwineImage adelineLogo() const {
|
||||
if (_engine->isLBA1()) {
|
||||
return TwineImage(Resources::HQR_RESS_FILE, 27, 28);
|
||||
}
|
||||
return TwineImage(Resources::HQR_SCREEN_FILE, 0, 1);
|
||||
}
|
||||
|
||||
TwineImage lbaLogo() const {
|
||||
if (_engine->isLBA1()) {
|
||||
return TwineImage(Resources::HQR_RESS_FILE, 49, 50);
|
||||
}
|
||||
return TwineImage(Resources::HQR_SCREEN_FILE, 60, 61);
|
||||
}
|
||||
|
||||
TwineImage eaLogo() const {
|
||||
if (_engine->isLBA1()) {
|
||||
return TwineImage(Resources::HQR_RESS_FILE, 52, 53);
|
||||
}
|
||||
return TwineImage(Resources::HQR_SCREEN_FILE, 74, 75);
|
||||
}
|
||||
|
||||
TwineImage activisionLogo() const {
|
||||
assert(_engine->isLBA2());
|
||||
return TwineImage(Resources::HQR_SCREEN_FILE, 72, 73);
|
||||
}
|
||||
|
||||
TwineImage virginLogo() const {
|
||||
assert(_engine->isLBA2());
|
||||
return TwineImage(Resources::HQR_SCREEN_FILE, 76, 77);
|
||||
}
|
||||
|
||||
TwineImage relentLogo() const {
|
||||
assert(_engine->isLBA1());
|
||||
return TwineImage(Resources::HQR_RESS_FILE, 12, 13);
|
||||
}
|
||||
|
||||
TwineImage menuBackground() const {
|
||||
if (_engine->isLBA1()) {
|
||||
return TwineImage(Resources::HQR_RESS_FILE, 14, -1);
|
||||
}
|
||||
return TwineImage(Resources::HQR_SCREEN_FILE, 4, 5);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace TwinE
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user