2019-05-10 18:56:19 +02:00
|
|
|
#ifndef SUBFILE_H
|
|
|
|
#define SUBFILE_H
|
|
|
|
|
|
|
|
#include <QVector>
|
|
|
|
#include <QDebug>
|
2020-02-09 23:24:48 +01:00
|
|
|
#include <QFile>
|
|
|
|
#include "img.h"
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2020-02-09 23:24:48 +01:00
|
|
|
|
2020-02-10 19:40:04 +01:00
|
|
|
#define BLOCK_SIZE 4096
|
2019-05-10 18:56:19 +02:00
|
|
|
|
|
|
|
class SubFile
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP};
|
|
|
|
|
2020-02-09 23:24:48 +01:00
|
|
|
class Handle
|
2019-05-10 18:56:19 +02:00
|
|
|
{
|
2020-02-09 23:24:48 +01:00
|
|
|
public:
|
|
|
|
Handle(const SubFile *subFile)
|
|
|
|
: _file(0), _blockNum(-1), _blockPos(-1), _pos(-1)
|
|
|
|
{
|
|
|
|
if (subFile && subFile->_path) {
|
|
|
|
_file = new QFile(*(subFile->_path));
|
|
|
|
_file->open(QIODevice::ReadOnly);
|
|
|
|
_data.resize(BLOCK_SIZE);
|
|
|
|
} else if (subFile)
|
|
|
|
_data.resize(subFile->_img->blockSize());
|
|
|
|
}
|
|
|
|
~Handle() {delete _file;}
|
|
|
|
|
|
|
|
int pos() const {return _pos;}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2020-02-09 23:24:48 +01:00
|
|
|
private:
|
|
|
|
friend class SubFile;
|
|
|
|
|
|
|
|
QFile *_file;
|
|
|
|
QByteArray _data;
|
|
|
|
int _blockNum;
|
|
|
|
int _blockPos;
|
|
|
|
int _pos;
|
2019-05-10 18:56:19 +02:00
|
|
|
};
|
|
|
|
|
2020-01-19 13:23:20 +01:00
|
|
|
SubFile(IMG *img)
|
2020-02-09 23:24:48 +01:00
|
|
|
: _gmpOffset(0), _img(img), _blocks(new QVector<quint16>()), _path(0),
|
|
|
|
_id(0) {}
|
2019-09-05 22:31:13 +02:00
|
|
|
SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img),
|
2020-02-09 23:24:48 +01:00
|
|
|
_blocks(gmp->_blocks), _path(gmp->_path), _id(gmp->id()) {}
|
|
|
|
SubFile(const QString &path)
|
|
|
|
: _gmpOffset(0), _img(0), _blocks(0), _path(new QString(path)), _id(0) {}
|
2020-01-19 13:23:20 +01:00
|
|
|
~SubFile()
|
|
|
|
{
|
2020-02-09 23:24:48 +01:00
|
|
|
if (!_gmpOffset) {
|
2020-01-19 13:23:20 +01:00
|
|
|
delete _blocks;
|
2020-02-09 23:24:48 +01:00
|
|
|
delete _path;
|
|
|
|
}
|
2020-01-19 13:23:20 +01:00
|
|
|
}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2019-09-05 22:31:13 +02:00
|
|
|
void addBlock(quint16 block) {_blocks->append(block);}
|
2020-02-09 23:24:48 +01:00
|
|
|
void setId(quint16 id) {_id = id;}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
|
|
|
bool seek(Handle &handle, quint32 pos) const;
|
|
|
|
|
2020-01-21 21:50:13 +01:00
|
|
|
template<typename T>
|
|
|
|
bool readUInt8(Handle &handle, T &val) const
|
|
|
|
{
|
|
|
|
quint8 b;
|
|
|
|
if (!readByte(handle, b))
|
|
|
|
return false;
|
|
|
|
val = b;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool readUInt16(Handle &handle, T &val) const
|
2019-05-10 18:56:19 +02:00
|
|
|
{
|
|
|
|
quint8 b0, b1;
|
|
|
|
if (!(readByte(handle, b0) && readByte(handle, b1)))
|
|
|
|
return false;
|
|
|
|
val = b0 | ((quint16)b1) << 8;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readInt16(Handle &handle, qint16 &val) const
|
|
|
|
{
|
|
|
|
if (!readUInt16(handle, (quint16&)val))
|
|
|
|
return false;
|
|
|
|
if((quint16)val > 0x7FFF)
|
|
|
|
val = (val & 0x7FFF) - 0x8000;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readUInt24(Handle &handle, quint32 &val) const
|
|
|
|
{
|
|
|
|
quint8 b0, b1, b2;
|
|
|
|
if (!(readByte(handle, b0) && readByte(handle, b1)
|
|
|
|
&& readByte(handle, b2)))
|
|
|
|
return false;
|
|
|
|
val = b0 | ((quint32)b1) << 8 | ((quint32)b2) << 16;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readInt24(Handle &handle, qint32 &val) const
|
|
|
|
{
|
|
|
|
if (!readUInt24(handle, (quint32&)val))
|
|
|
|
return false;
|
|
|
|
if (val > 0x7FFFFF)
|
|
|
|
val = (val & 0x7FFFFF) - 0x800000;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readUInt32(Handle &handle, quint32 &val) const
|
|
|
|
{
|
|
|
|
quint8 b0, b1, b2, b3;
|
|
|
|
if (!(readByte(handle, b0) && readByte(handle, b1)
|
|
|
|
&& readByte(handle, b2) && readByte(handle, b3)))
|
|
|
|
return false;
|
|
|
|
val = b0 | ((quint32)b1) << 8 | ((quint32)b2) << 16
|
|
|
|
| ((quint32)b3) << 24;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-02-04 21:47:31 +01:00
|
|
|
bool readVUInt32SW(Handle &hdl, quint32 bytes, quint32 &val) const
|
|
|
|
{
|
|
|
|
quint8 b;
|
|
|
|
|
|
|
|
val = 0;
|
|
|
|
for (quint32 i = bytes; i; i--) {
|
|
|
|
if (!readByte(hdl, b))
|
|
|
|
return false;
|
|
|
|
val |= ((quint32)b) << ((i-1) * 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-09-18 08:37:33 +02:00
|
|
|
bool readVUInt32(Handle &hdl, quint32 &val) const;
|
2020-01-21 21:50:13 +01:00
|
|
|
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
|
2019-09-18 08:37:33 +02:00
|
|
|
|
2020-02-09 23:24:48 +01:00
|
|
|
quint16 id() const {return _blocks ? _blocks->first() : _id;}
|
|
|
|
QString fileName() const {return _path ? *_path : _img->fileName();}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2019-09-05 22:31:13 +02:00
|
|
|
protected:
|
|
|
|
quint32 _gmpOffset;
|
|
|
|
|
2019-05-10 18:56:19 +02:00
|
|
|
private:
|
2020-02-10 09:10:09 +01:00
|
|
|
bool readByte(Handle &handle, quint8 &val) const
|
|
|
|
{
|
2020-02-10 19:40:04 +01:00
|
|
|
int blockSize = _img ? _img->blockSize() : BLOCK_SIZE;
|
2020-02-10 09:10:09 +01:00
|
|
|
val = handle._data.at(handle._blockPos++);
|
|
|
|
handle._pos++;
|
|
|
|
return (handle._blockPos >= blockSize)
|
|
|
|
? seek(handle, handle._pos) : true;
|
|
|
|
}
|
2020-01-21 21:50:13 +01:00
|
|
|
|
2019-05-10 18:56:19 +02:00
|
|
|
IMG *_img;
|
2019-09-05 22:31:13 +02:00
|
|
|
QVector<quint16> *_blocks;
|
2020-02-09 23:24:48 +01:00
|
|
|
QString *_path;
|
|
|
|
quint16 _id;
|
2019-05-10 18:56:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif // SUBFILE_H
|