mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-02-16 07:40:49 +01:00
Added support for OZF3 map files
This commit is contained in:
parent
1a66ed0a36
commit
1e4bcd0ac1
@ -348,12 +348,12 @@ bool OfflineMap::getImageInfo(const QString &path)
|
||||
}
|
||||
|
||||
QString suffix = ii.suffix().toLower();
|
||||
if (suffix == "ozf3" || suffix == "ozfx3" || suffix == "ozf4"
|
||||
|| suffix == "ozfx4") {
|
||||
_errorString = QString("%1: Obfuscated image files not supported")
|
||||
if (suffix == "ozf4" || suffix == "ozfx4") {
|
||||
_errorString = QString("%1: OZF4 image files not supported")
|
||||
.arg(QFileInfo(_imgPath).fileName());
|
||||
return false;
|
||||
} else if (suffix == "ozf2" || suffix == "ozfx2") {
|
||||
} else if (suffix == "ozf2" || suffix == "ozfx2" || suffix == "ozf3"
|
||||
|| suffix == "ozfx3") {
|
||||
_ozf.load(_imgPath);
|
||||
_size = _ozf.size();
|
||||
} else {
|
||||
|
110
src/ozf.cpp
110
src/ozf.cpp
@ -3,8 +3,23 @@
|
||||
#include "ozf.h"
|
||||
|
||||
|
||||
#define OZF2_MAGIC 0x7778
|
||||
#define OZF2_SEPARATOR 0x77777777
|
||||
#define OZF2_MAGIC 0x7778
|
||||
#define OZF3_MAGIC 0x7780
|
||||
#define SEPARATOR 0x77777777
|
||||
|
||||
static const quint8 XKEY[] =
|
||||
{
|
||||
0x2D, 0x4A, 0x43, 0xF1, 0x27, 0x9B, 0x69, 0x4F,
|
||||
0x36, 0x52, 0x87, 0xEC, 0x5F, 0x42, 0x53, 0x22,
|
||||
0x9E, 0x8B, 0x2D, 0x83, 0x3D, 0xD2, 0x84, 0xBA,
|
||||
0xD8, 0x5B
|
||||
};
|
||||
|
||||
static void decrypt(void *data, size_t size, quint8 init)
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
reinterpret_cast<quint8*>(data)[i] ^= XKEY[i % sizeof(XKEY)] + init;
|
||||
}
|
||||
|
||||
template<class T> bool OZF::readValue(T &val)
|
||||
{
|
||||
@ -13,6 +28,9 @@ template<class T> bool OZF::readValue(T &val)
|
||||
if (_file.read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
|
||||
return false;
|
||||
|
||||
if (_decrypt)
|
||||
decrypt(&data, sizeof(T), _key);
|
||||
|
||||
if (sizeof(T) > 1)
|
||||
val = qFromLittleEndian(data);
|
||||
else
|
||||
@ -21,17 +39,88 @@ template<class T> bool OZF::readValue(T &val)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OZF::read(void *data, size_t size)
|
||||
{
|
||||
if (_file.read((char*)data, size) < (qint64)size)
|
||||
return false;
|
||||
|
||||
if (_decrypt)
|
||||
decrypt(data, size, _key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OZF::readKey()
|
||||
{
|
||||
quint8 randomNumber, initial;
|
||||
quint32 keyblock;
|
||||
|
||||
|
||||
if (!_file.seek(14))
|
||||
return false;
|
||||
if (!readValue(randomNumber))
|
||||
return false;
|
||||
|
||||
if (!_file.seek(162))
|
||||
return false;
|
||||
if (!readValue(initial))
|
||||
return false;
|
||||
|
||||
_decrypt = true; _key = initial;
|
||||
if (!_file.seek(15 + randomNumber))
|
||||
return false;
|
||||
if (!readValue(keyblock))
|
||||
return false;
|
||||
|
||||
switch (keyblock & 0xFF) {
|
||||
case 0xf1:
|
||||
initial += 0x8a;
|
||||
break;
|
||||
case 0x18:
|
||||
case 0x54:
|
||||
initial += 0xa0;
|
||||
break;
|
||||
case 0x56:
|
||||
initial += 0xb9;
|
||||
break;
|
||||
case 0x43:
|
||||
initial += 0x6a;
|
||||
break;
|
||||
case 0x83:
|
||||
initial += 0xa4;
|
||||
break;
|
||||
case 0xc5:
|
||||
initial += 0x7e;
|
||||
break;
|
||||
case 0x38:
|
||||
initial += 0xc1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_key = initial;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OZF::readHeaders()
|
||||
{
|
||||
quint16 magic;
|
||||
quint32 separator;
|
||||
|
||||
if (!readValue(magic) || magic != OZF2_MAGIC)
|
||||
if (!readValue(magic))
|
||||
return false;
|
||||
|
||||
if (!_file.seek(_file.pos() + 52))
|
||||
return false;
|
||||
if (!readValue(separator) || separator != OZF2_SEPARATOR)
|
||||
if (magic == OZF2_MAGIC) {
|
||||
if (!_file.seek(_file.pos() + 52))
|
||||
return false;
|
||||
if (!readValue(separator) || separator != SEPARATOR)
|
||||
return false;
|
||||
} else if (magic == OZF3_MAGIC) {
|
||||
if (!readKey())
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -69,9 +158,10 @@ bool OZF::readTileTable()
|
||||
_dim = QSize(x, y);
|
||||
|
||||
_palette = QVector<quint32>(256);
|
||||
if (!read(&(_palette[0]), sizeof(quint32) * 256))
|
||||
return false;
|
||||
for (int i = 0; i < _palette.size(); i++) {
|
||||
if (!readValue(bgr0))
|
||||
return false;
|
||||
bgr0 = qFromLittleEndian(_palette.at(i));
|
||||
|
||||
quint32 b = (bgr0 & 0x000000FF);
|
||||
quint32 g = (bgr0 & 0x0000FF00) >> 8;
|
||||
@ -98,7 +188,7 @@ bool OZF::load(const QString &path)
|
||||
return false;
|
||||
|
||||
if (!readHeaders()) {
|
||||
qWarning("%s: not a OZF2 file", qPrintable(_file.fileName()));
|
||||
qWarning("%s: not a OZF2/OZF3 file", qPrintable(_file.fileName()));
|
||||
_file.close();
|
||||
return false;
|
||||
}
|
||||
@ -128,6 +218,8 @@ QPixmap OZF::tile(int x, int y)
|
||||
QByteArray ba = _file.read(size);
|
||||
if (ba.size() != size)
|
||||
return QPixmap();
|
||||
if (_decrypt)
|
||||
decrypt(ba.data(), qMin(16, ba.size()), _key);
|
||||
quint32 bes = qToBigEndian(tileSize().width() * tileSize().height());
|
||||
ba.prepend(QByteArray((char*)&bes, sizeof(bes)));
|
||||
QByteArray uba = qUncompress(ba);
|
||||
|
@ -11,6 +11,8 @@
|
||||
class OZF
|
||||
{
|
||||
public:
|
||||
OZF() : _decrypt(false), _key(0) {}
|
||||
|
||||
bool load(const QString &path);
|
||||
|
||||
QString fileName() const {return _file.fileName();}
|
||||
@ -22,9 +24,14 @@ public:
|
||||
|
||||
private:
|
||||
template<class T> bool readValue(T &val);
|
||||
bool read(void *data, size_t size);
|
||||
bool readKey();
|
||||
bool readHeaders();
|
||||
bool readTileTable();
|
||||
|
||||
bool _decrypt;
|
||||
quint8 _key;
|
||||
|
||||
QSize _size;
|
||||
QSize _dim;
|
||||
QVector<QRgb> _palette;
|
||||
|
Loading…
x
Reference in New Issue
Block a user