Там дубликаты всего и вся. Есть сжатые текстуры, и несжатые сразу в одном архиве. Этот несжатый тоже используется, но сжатый используется чаще
Почему сразу нельзя было написать? Код на разжатие кусков NSF я указал. Он не подходит и там отдельное сжатие? Тогда, зная формат NSF, можно получить сжатый кусок (если это не NSF сжатие) и несжатый кусок уже есть, остаётся сравнить и попытаться выяснить код декомпрессии или разобрать код игры.
Вы просите помощи, но не говорите что выяснили сами, это плохо.
UPD: По началу несжатой текстуры (34 12 01 00 6F E0 C2 52 05 00 00 00 DD DC AF 72) находится несжатый кусок - 0x230800- (
paul_met его показал, в начале 34 12, что говорит о несжатии) и сжатый - 0xA000- (35 12 говорит о сжатии). Я проверил начало вручную и сжатие совпадает с указанным ранее (
https://github.com/cbhacks/CrashEdit/blob/5662fce6c0694b855b40ca99c6b2da8718e54fcf/Crash/Formats/Crash Formats/NSF.cs). Простое сжатие. Вот файлы, сжатый (я взял с запасом) и несжатый, можно быстро отделить код и проверить наверняка.
UPD2: Переписал на Python декомпрессию и подтвердил, что с 0xA000 сжатый по алгоритму NSF кусок совпадает с несжатым 0x230800. Вот код:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from pathlib import Path
from struct import unpack
data = Path("font_comp.bin").read_bytes()
dataLength = len(data)
ChunkLength = 65536
result = bytearray(ChunkLength)
length, = unpack("<i", data[4:8])
offset = 12
pos = 0
while pos < length:
if dataLength < offset + 1:
print("NSF.ReadChunk: Data is too short")
prefix = data[offset]
offset += 1
if (prefix & 0x80) != 0:
prefix &= 0x7F
if dataLength < offset + 1:
print("NSF.ReadChunk: Data is too short")
seek = data[offset]
offset += 1
span = seek & 7
seek >>= 3
seek |= prefix << 5
if span == 7:
span = 64
else:
span += 3
if pos - seek < 0:
print("NSF.ReadChunk: Repeat begins out of bounds")
if pos + span > ChunkLength:
print("NSF.ReadChunk: Repeat ends out of bounds")
# Do NOT use Array.Copy as
# overlap is possible i.e. span
# may be greater than seek
for i in range(span):
result[pos + i] = result[pos - seek + i]
pos += span
else:
if dataLength < offset + prefix:
print("NSF.ReadChunk: Data is too short")
result[pos:pos+prefix] = data[offset:offset+prefix]
offset += prefix
pos += prefix
#if dataLength < offset + skip:
# print("NSF.ReadChunk: Data is too short")
#offset += skip
#if dataLength < offset + (ChunkLength - length):
# print("NSF.ReadChunk: Data is too short")
prefix = ChunkLength - length
result[pos:pos+prefix] = data[offset:offset+prefix]
#offset += (ChunkLength - length)
Path("font_uncomp.bin").write_bytes(result)
Тайна разгадана, остаётся просто разобрать формат NSF и написать элементарное сжатие.