Перейти к содержимому


Внимание!

Это форум по извлечению ресурсов из игр: музыки, звуков, текстур, 3D-моделей...
Перед поиском ответов на форуме, рекомендуется ознакомиться с основным сайтом EXTRACTOR.ru!
[ Прочтите внимательно - правила создания тем и ответа в них ]
Все вопросы по запуску игр задавайте в другом месте: Установка и запуск игр.


Фотография

KGB (DOS, 1992) [.SQX]

SQX HERAD KGB DOS распаковка

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 4

#1 binarymaster

binarymaster

    Младший сержант

  • Пользователи
  • 19 сообщений
  • Пол:Мужчина

Отправлено 28 February 2017 - 09:15

Доброго времени суток!

 

Пытаюсь разобраться в формате сжатия SQX, который используется в игре KGB / Conspiracy. Всего их 3 подтипа - SQX-0, 1 и 2 - конкретно интересуют первые два, так как они используются для сжатия игровой музыки.

 

Распаковку файлов первого типа удалось реализовать, на базе алгоритма HSQ (он используется в игре Dune). С алгоритмом SQX-1 пока не понятно, каким образом работают битовые флаги.

 

Прикрепляю распаковщик с исходным кодом на Delphi - в нём реализовано автоматическое определение алгоритма упаковки (HSQ / SQX-0 / SQX-1 / SQX-2) с попыткой реализации SQX-1 распаковщика (который работает неправильно), а также тестовые файлы - упакованные и корректно распакованные (вытащил из памяти игры в DOSBox):

 

http://rgho.st/8yhSmdx6R

 

Заранее спасибо за любую помощь.



#2 -=CHE@TER=-

-=CHE@TER=-

    Полковник

  • Администраторы
  • 971 сообщений
  • Пол:Мужчина

Отправлено 01 March 2017 - 18:22

KGB (Conspiracy) .SQX unpacker
По-моему алгоритм сжатия там один. Я только не понял где музыка - вроде, MIDI иснтрукции видно, но заголовка MTrk нет. Видимо, там сырые данные.
Ах, да, программа под DOS, ибо это тупо вырванная из игры функция распаковки, потому что там, ох вау, самоизменяющийся код.
И, если всё работает как надо, то можно пожертвовать любую приемлемую сумму на копилку CTPAX-X (реквизиты на сайте слева под меню).

#3 binarymaster

binarymaster

    Младший сержант

  • Пользователи
  • 19 сообщений
  • Пол:Мужчина

Отправлено 01 March 2017 - 23:42

На самом деле алгоритмы немного разные, и видимо самоизменяющийся код распаковки с этим связан. В этой игре, как и в Dune, музыка хранится в формате HERAD - это MIDI-подобный формат, в реверсинге которого я принимал участие. Если интересно, вот ссылка на обсуждение на англоязычном форуме:

http://www.vogons.or...php?f=7&t=49813

 

Большое спасибо, распаковщик работает корректно с SQX-0 и SQX-1! Отправил небольшую сумму пожертвования. :)

 

Осталось лишь понять, как он работает :D



#4 -=CHE@TER=-

-=CHE@TER=-

    Полковник

  • Администраторы
  • 971 сообщений
  • Пол:Мужчина

Отправлено 04 March 2017 - 08:50

Пожертвование пришло - большое спасибо за поддержку проекта!
Кстати, обновил распаковщик - ничего серьёзного, опечатка в сообщении об ошибке.
Насчёт распаковщика - уж очень там муторное сжатие, так что в попытке его расковырять я в какой-то момент понял, что проще будет выдернуть сам алгоритм.
Оставлю небольшие комментарии из того, что я успел разобрать, до того как махнул рукой на всё. Само сжатие напоминает LZSS/LZX от Blizzard / Microsoft, только тут не фиксированный битовый флаг (0 или 1), а он может быть плавающей длинны - до первого 0-го бита (см. ниже объяснение).
sub_16993 - это функция распаковки. На вход она принимает два параметра: входной и выходной буфер, причём в выходном буфере первые два байта должны быть теми, которые прочитаны из файла (не знаю, нужно это или нет, но на всякий случай повторил то, как оригинальный распаковщик работал). Весь остальной файл, кроме упомянутых первых двух байт, передаётся как входной буфер.
Перед началом работы функция сама себя модифицирует. Подозреваю, что это сделано потому что алгоритмы распаковки очень похожи и чтобы не копипастить код разработчики решили таким оригинальным образом "на лету" сами себя пропатчить.
_698B - это массив из трёх смещений, которые функция патчит.
Три вызова call @sub_16A3E - это три патча в памяти. Там я в комментариях указал шестнадцатеричный код что было и стало - мне это нужно было для проверки корректности выдернутого кода. Проверял я только на файле "KGBSDB.SQX", т.к. он был первым, который игра распаковывала будучи запущенной под отладчиком (в SETUP настроил включить звук, т.к. этот файл - это драйвер, как я понял, от Sound Blaster).
Так вот, на этом файле алгоритм распаковки работал (под отладчиком) как-то так:
- читается слово (WORD, 2 байта) из выходного потока, т.к. там какие-то ещё служебные поля в начале были, то первое слово было, кажется, 0x2100;
- далее это слово сдвигается вправо, до тех пор, пока не ноль (т.е. пока там есть хотя бы 1 не нулевой бит);
- если при сдвиге сдвинутый (самый правый) бит был 0 - то тупо копируется байт из входного буфера в выходной;
- если бит 1, то сдвигается опять и смотрится следующий бит - если он 1, то снова сдвигается и так несколько раз; т.е. как только появился 0 - то сдвиг прекращается и, в зависимости от сдвинутых битов, что-то делается. И, это важно, проверяется, что после каждого такого сдвига слово не превратилось в ноль - иначе, как я понял, читается следующее(?), вроде бы.
После того как до меня дошло, что в коде это будет куча if..., if..., if..., то осознал, что нафиг не хочу с этим алгоритмом возиться (а если ещё учесть самоизменяющийся код...) и тупо его выдрал.

#5 binarymaster

binarymaster

    Младший сержант

  • Пользователи
  • 19 сообщений
  • Пол:Мужчина

Отправлено 05 April 2017 - 20:47

В общем, наконец-то полностью перевёл ассемблер в привычный код на Делфи.

 

Всё работает, и всё распаковывает. :D

 

http://rgho.st/7nfjCDW9R

 

Действительно, оказалось, что алгоритм распаковки единый. Первым 2-байтовым словом инициализируется вывод, далее 3 байта в заголовке (могут варьироваться от 0 до 2) управляют алгоритмом. Четвёртый байт влияет на маску, модифицирующую смещение и количество копируемых байтов (собственно меняет кол-во бит, выделенных на то и другое). В остальном, алгоритм основан на HSQ, и является его улучшенной версией.

 

-=CHE@TER=-, ещё раз большое спасибо! Полагаю, тему можно закрыть. :)