2019-05-16 20:23:37 +02:00
|
|
|
#include <QFile>
|
2019-05-10 18:56:19 +02:00
|
|
|
#include "img.h"
|
|
|
|
#include "subfile.h"
|
|
|
|
|
2019-05-16 20:23:37 +02:00
|
|
|
|
2020-06-27 22:46:26 +02:00
|
|
|
#define mod2n(x, m) ((x) & ((m) - 1));
|
|
|
|
|
2019-05-10 18:56:19 +02:00
|
|
|
bool SubFile::seek(Handle &handle, quint32 pos) const
|
|
|
|
{
|
2021-01-27 21:18:06 +01:00
|
|
|
if (_img) {
|
|
|
|
quint32 blockBits = _img->blockBits();
|
|
|
|
int blockNum = pos >> blockBits;
|
2020-02-09 23:24:48 +01:00
|
|
|
|
|
|
|
if (handle._blockNum != blockNum) {
|
2021-01-27 21:18:06 +01:00
|
|
|
if (blockNum >= _blocks->size())
|
2020-02-09 23:24:48 +01:00
|
|
|
return false;
|
2021-01-27 21:18:06 +01:00
|
|
|
if (!_img->readBlock(handle._file, _blocks->at(blockNum),
|
|
|
|
handle._data.data()))
|
2020-02-09 23:24:48 +01:00
|
|
|
return false;
|
|
|
|
handle._blockNum = blockNum;
|
|
|
|
}
|
|
|
|
|
2021-01-27 21:18:06 +01:00
|
|
|
handle._blockPos = mod2n(pos, 1U<<blockBits);
|
2020-02-09 23:24:48 +01:00
|
|
|
handle._pos = pos;
|
|
|
|
} else {
|
2021-01-27 21:18:06 +01:00
|
|
|
int blockNum = pos >> BLOCK_BITS;
|
2019-05-16 20:23:37 +02:00
|
|
|
|
2020-02-09 23:24:48 +01:00
|
|
|
if (handle._blockNum != blockNum) {
|
2021-01-27 21:18:06 +01:00
|
|
|
if (!handle._file.seek((quint64)blockNum << BLOCK_BITS))
|
2019-05-16 20:23:37 +02:00
|
|
|
return false;
|
2021-01-27 21:18:06 +01:00
|
|
|
if (handle._file.read(handle._data.data(), (1<<BLOCK_BITS)) < 0)
|
2019-05-16 20:23:37 +02:00
|
|
|
return false;
|
2020-02-09 23:24:48 +01:00
|
|
|
handle._blockNum = blockNum;
|
2019-05-16 20:23:37 +02:00
|
|
|
}
|
2019-05-10 18:56:19 +02:00
|
|
|
|
2021-01-27 21:18:06 +01:00
|
|
|
handle._blockPos = mod2n(pos, 1U<<BLOCK_BITS);
|
2020-02-09 23:24:48 +01:00
|
|
|
handle._pos = pos;
|
2019-05-16 20:23:37 +02:00
|
|
|
}
|
2021-01-27 21:18:06 +01:00
|
|
|
|
|
|
|
return true;
|
2019-05-10 18:56:19 +02:00
|
|
|
}
|
|
|
|
|
2019-09-18 08:37:33 +02:00
|
|
|
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
|
|
|
|
{
|
|
|
|
quint8 bytes, shift, b;
|
|
|
|
|
|
|
|
if (!readByte(hdl, b))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((b & 1) == 0) {
|
|
|
|
if ((b & 2) == 0) {
|
|
|
|
bytes = ((b >> 2) & 1) ^ 3;
|
|
|
|
shift = 5;
|
|
|
|
} else {
|
|
|
|
shift = 6;
|
|
|
|
bytes = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shift = 7;
|
|
|
|
bytes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
val = b >> (8 - shift);
|
|
|
|
|
|
|
|
for (int i = 1; i <= bytes; i++) {
|
|
|
|
if (!readByte(hdl, b))
|
|
|
|
return false;
|
|
|
|
val |= (((quint32)b) << (i * 8)) >> (8 - shift);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-06-27 22:46:26 +02:00
|
|
|
bool SubFile::readVUInt32(Handle &hdl, quint32 bytes, quint32 &val) const
|
|
|
|
{
|
|
|
|
switch (bytes) {
|
|
|
|
case 1:
|
|
|
|
return readUInt8(hdl, val);
|
|
|
|
case 2:
|
|
|
|
return readUInt16(hdl, val);
|
|
|
|
case 3:
|
|
|
|
return readUInt24(hdl, val);
|
|
|
|
case 4:
|
|
|
|
return readUInt32(hdl, val);
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-21 21:50:13 +01:00
|
|
|
bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
|
|
|
|
{
|
|
|
|
quint8 bits;
|
|
|
|
|
|
|
|
if (!readUInt8(hdl, bits))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!(bits & 1)) {
|
2020-02-09 23:24:48 +01:00
|
|
|
seek(hdl, hdl._pos - 1);
|
2020-01-21 21:50:13 +01:00
|
|
|
if (!((bits>>1) & 1)) {
|
|
|
|
if (!((bits>>2) & 1)) {
|
|
|
|
if (!readUInt32(hdl, bitfield))
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if (!readUInt24(hdl, bitfield))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bitfield >>= 3;
|
|
|
|
} else {
|
|
|
|
if (!readUInt16(hdl, bitfield))
|
|
|
|
return false;
|
|
|
|
bitfield >>= 2;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
bitfield = bits>>1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|