IPB

Добро пожаловать, гость ( Вход | Регистрация )

> Сжатие LZX / LZSS, старые игры от Blizzard
-=CHE@TER=-
Jun 20 2010, 13:46
Сообщение #1


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,355
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 311 раз(а)



Тут интересную тему подняли на Extractor.ru:
_ttp://www.extractor.ru/ipb/index.php?showtopic=2111

Нашёл описание Microsoft LZX - он ближе всех походит:
_ttp://www.nf-team.org/drmad/zf/zf5/zf5_025.htm

Занятный алгоритм. Я практически разобрал формат архивов и сжатия. Там используется какая-то модификация LZX - см. ссылку, которую я дал. Всё бы хорошо, но вот отчего-то у меня после распаковки в 64 байтах файл расходится с тем, что должно быть (там человек выкладывал файл сграбленный из памяти). А расходится из-за того, что окно (window) при распаковке ездит взад и вперёд.
В общем, за 2 дня интенсивного mindfuck'а я уже совсем отупел, хотя 90% разобрал как работает...

Формат сжатых данных:

BYTE - байт-маска, указывающие какие идут данные за ним (обрабатывать нужно задом наперёд!). Если в байте бит зажжён - значит нужно прочитать из входного файла 1 байт и переместить его в выходной поток. Если бит не зажжён, то нужно прочитать из входного файла 2 байта (WORD), которые потом интерпретируются как отсылка к уже распакованным данным (см. ниже).
Пусть наш байт будет такой: 10010111 - это значит из файл мы должны прочитать (обрабатывать нужно задом наперёд!):
BYTE BYTE BYTE WORD BYTE WORD WORD BYTE
Причём, все прочитанные байты мы сразу складываем в выходной файл, а когда читаем WORD, то делаем следующее:

Предположим мы прочитали значение типа WORD и оно равно $0FFD - первые 4 бита - количество байт, которые нужно переслать минус 3 (т.е. нужно всегда добавлять 3, чтобы получить количество для пересылки!). Оставшиеся 12 бит (вот тут засада) это адрес в уже распакованном потоке, откуда эти данные нужно читать в выходной.
Дело в том, что при распаковке выходной поток используется и как входной тоже.
В общем, для $0FFD количество байт для чтения равно 3 (0 + 3), а смещение 0xFFD от начала (?) потока.

Но, т.к. поток делится на окна по 4096 ($1000) байт, то тут возникает проблема. Дело в том, что окно смещается вместе с распакованным потоком, но как получить его точное расположение, я не понял. Пока размер распакованного потока менее 4096 - всё ок, как только стал больше, так начинаю брать смещение уже не оттуда. Что самое смешное, так это то что, похоже, экно ездит то вперёд, то назад, потому что я что только не делал и как только его сдвиг не считал - в зависимости от кувырканий, то одни, то другие байты не совпадают.

Вот исходные коды распаковщика LZX:
lzxfiles.zip (~37 Kb)

Что там внутри:
1.zlx - упакованная музыка
1.xmi - дамп распакованной
unlzx.c - исходные коды
unlzx.exe - программа
BTHORNE.EXE - исполняемый файл игры Black Thorne, в исходных кодах я оставил адреса процедуры распаковки
z.bat - после его запуска будет произведена попытка распаковать файл и появятся ещё 3 файла:
dump - распакованный поток
l - сравнение распакованного потока с оригиналом
list - это я делал вывод программы для удобства отладки

Уф...
Кто-нибудь хочет / может помочь? Я просто где-то долблюсь в стенку лбом и не вижу двери.
Наставьте, пожалуйста, на путь истинный! (*улыбается*)
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
 
Reply to this topicStart new topic
Ответов
Axsis
Mar 14 2011, 16:28
Сообщение #2


Advanced Member
***

Группа: CTPAX-X
Сообщений: 121
Регистрация: 6-February 08
Пользователь №: 374
Спасибо сказали: 149 раз(а)



по идее в этом блоке
CODE

        While l > 0 Do
        Begin
          buff[p] := buff[o];
          p:=p + 1;
          loop[lidx] := buff[o];
          lidx:=(lidx + 1) And $fff;
          o := ((o + 1) And $fff);
          l:=l - 1;
        End;

вместо buff[o] надо брать байт loop[o] (в обоих местах)
CODE

        While l > 0 Do
        Begin
          buff[p] := loop[o];
          p:=p + 1;
          loop[lidx] := loop[o];
          lidx:=(lidx + 1) And $fff;
          o := (o + 1) And $fff;
          l:=l - 1;
        End;

по идее так дожно быть.
для того этот второй буфер и нужен был, потому что смещение 'o' отсчитывается от его начала, а данные в буфере "плавают" - lidx (указатель на байт в который мы сейчас запишем новые распакованные данные) циклически увеличивается. unsure.gif


Спасибо сказали:
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Сообщения в этой теме


Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 19th April 2024 - 16:16