1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 15:23:22 +02:00
GPXSee/src/map/IMG/nodfile.cpp

149 lines
3.6 KiB
C++
Raw Normal View History

#include "bitstream.h"
#include "nodfile.h"
bool NODFile::init(Handle &hdl)
{
quint16 hdrLen;
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)))
return false;
if (hdrLen >= 0x7b) {
if (!(seek(hdl, _gmpOffset + 0x21) && readUInt8(hdl, _blockShift)
&& readUInt8(hdl, _nodeShift)))
return false;
if (!(seek(hdl, _gmpOffset + 0x67) && readUInt32(hdl, _blockOffset)
&& readUInt32(hdl, _blockSize) && readUInt16(hdl, _blockRecordSize)
&& readUInt32(hdl, _indexOffset) && readUInt32(hdl, _indexSize)
&& readUInt16(hdl, _indexRecordSize) && readUInt32(hdl, _indexFlags)))
return false;
}
return true;
}
quint32 NODFile::indexIdSize(Handle &hdl)
{
if (!_indexRecordSize && !init(hdl))
return 0;
quint32 indexCount = _indexSize / _indexRecordSize;
if (indexCount <= 0x100)
return 1;
else if (indexCount <= 0x1000)
return 2;
else if (indexCount <= 0x1000000)
return 3;
else
return 0;
}
bool NODFile::blockInfo(Handle &hdl, quint32 blockIndexId,
BlockInfo &blockInfo) const
{
quint32 blockOffset;
quint32 offset = _indexRecordSize * blockIndexId + _indexOffset;
quint32 offsetSize = (_indexFlags & 3) + 1;
Q_ASSERT(offset <= _indexOffset + _indexSize);
if (!(seek(hdl, offset) && readVUInt32(hdl, offsetSize, blockOffset)))
return false;
blockInfo.offset = (blockOffset << _blockShift) + _blockOffset;
if (!(seek(hdl, blockInfo.offset) && readUInt16(hdl, blockInfo.h0)
&& readUInt32(hdl, blockInfo.h2) && readUInt32(hdl, blockInfo.h6)
&& readUInt32(hdl, blockInfo.ha) && readUInt16(hdl, blockInfo.he)
&& readUInt8(hdl, blockInfo.h10) && readUInt8(hdl, blockInfo.h11)
&& readUInt8(hdl, blockInfo.h12)))
return false;
return true;
}
bool NODFile::linkInfo(Handle &hdl, const BlockInfo &blockInfo, quint32 linkId,
LinkInfo &linkInfo) const
{
Q_ASSERT(linkId < blockInfo.h10);
quint32 infoOffset = ((blockInfo.he * linkId) >> 3) + 0x13
+ ((blockInfo.h0 >> 0xb) & 1) + blockInfo.offset;
quint32 s1 = ((blockInfo.h0 >> 2) & 0x1f) + 8;
quint32 s2 = (blockInfo.h0 >> 7) & 0xf;
quint32 skip = (blockInfo.he * linkId) & 7;
Q_ASSERT(infoOffset <= _blockOffset + _blockSize);
if (!seek(hdl, infoOffset))
return false;
quint32 unused, flags;
BitStream1 bs(*this, hdl, _blockOffset + _blockSize - infoOffset);
if (!(bs.read(skip, unused) && bs.read(0xc, flags)))
return false;
linkInfo.flags = ((flags << 8) & 0xf0000) | (flags & 0xff);
if (!(flags << 8 & 0x10000)) {
if (!bs.read(s1, linkInfo.linkOffset))
return false;
} else {
if (!bs.read(s1 - s2, linkInfo.linkOffset))
return false;
linkInfo.linkOffset += blockInfo.ha;
}
return true;
}
bool NODFile::linkType(Handle &hdl, const BlockInfo &blockInfo, quint8 linkId,
quint32 &type) const
{
quint32 offset = ((blockInfo.h10 * blockInfo.he + 7) >> 3) + 0x13 +
blockInfo.offset + ((blockInfo.h0 >> 0xb) & 1) + (quint32)blockInfo.h11
* 3;
quint32 low = 0;
quint32 high = blockInfo.h12 - 1;
quint32 pos;
quint16 val;
if (high > 1) {
do {
pos = (low + high) / 2;
if (!seek(hdl, offset + _blockRecordSize * pos))
return false;
if (!readUInt16(hdl, val))
return false;
quint32 tmp = pos;
if ((val >> 8) <= linkId) {
low = pos;
tmp = high;
}
high = tmp;
} while (low + 1 < high);
}
if (!seek(hdl, offset + _blockRecordSize * low))
return false;
if (!readUInt16(hdl, val))
return false;
type = val & 0x3f;
if ((low < high) && (pos != high)) {
if (!seek(hdl, offset + _blockRecordSize * high))
return false;
if (!readUInt16(hdl, val))
return false;
if ((val >> 8) <= linkId) {
type = (val & 0x3f);
}
}
type *= 256;
return true;
}