Описание: Разбор алгоритма сжатия (2006 год) |
Поиск в теме | Версия для печати |
Griever |
Отправлено: 11 Февраля, 2016 - 08:25:37
|
VIP
Покинул форум
Сообщений всего: 457
Дата рег-ции: Июнь 2015
|
Griever
ОК, ты меня навёл на правильную мысль. Теперь я имею право сказать: "ЗНАЧИТ ТАК:" =Р
Есть такой байт 5, ты, наверное, уже о нём думал =) Это счётчик уже выведенных на экран тайлов из карты. Так вот те два сравнения относятся только к пятерке и вообще никакого отношения не имеют не к внутреннему ни к внешнему циклам. В самом начале в два контрольных байта(8 и 9) загружаются значения. выводится первый символ, который был считан ранее. Проверяется старший бит девятки. Ну, как уже говорилось, если единичка, то знак повторяется, если ноль - читается следующий. и так далее, пока у нас не "исшифтуется" девятка. А шифтуется она в любом случае, даже если выводятся два одинаковых тайла. Это значит, что к моменту, когда девятка кончится в пятерке станет $#08. На этот случай есть команда по адресу $8117, которая проверяет кратность счётчика(пятерки) числу восемь. И если у нас девятка исшифтовалась, то мы один разик шифтуем восьмёрку и если в восьмёрке ноль, то девятку мы не читаем, а оставляем такой же какой она стала (а осталась она с нулями), а уже в подпрограмме
вывода индекса тайла девятку мы не шифтуем, а просто постоянно считываем по одному индексу тайла из РОМа. Одним словом, если восьмерочный бит ноль, то следующие восемь тайлов будут без повторов.
Таким образом, мы в конце концов исшифтуем и восьмерку. К тому времени в счётчике тайлов будет $#40, тут уже сработает команда $8102 - которая позволит нам считать из рома новое значение восьмёрки, если порядковый номер следующего тайла будет кратен #$40. И всё повторится сначала.
Вот и всё. Остается писать пакер/анпакер, что представляет большую проблему по сравнению с другими алгоритмами: приходится учитывать счетчик тайлов ВСЕЙ карты, а значит распаковка обязательна
целиком - по частям нельзя. Как и запаковка.
И вот ещё:
Цитата:Внутренний же цикл очень прост: если из восьмого контрольного байта в флаг перемещается ноль, а из девятого - единица, или из восьмого - единица, а из девятого - ноль, то происходит вычисление нового кода, в противном случае происходит происходит копирование предыдущего.
На самом деле, если из восьмерки перемещается ноль, то что в девятке уже неважно(см. выше) - байты пойдут без повторов.
Ещё, если посмотреть внимательнее, то надписи на экранах типа "Where shall we go today?" тоже пережаты этим алгоритмом.
Гайверу виднее: может где ещё. Так что с этой игрой ещё кувыркаться и кувыркаться =Р
PS: хотел написать распаковщик, но у самого переводы стоят =)
|
|
|
alex_231 |
Отправлено: 11 Февраля, 2016 - 08:26:00
|
Chief-Net
Покинул форум
Сообщений всего: 4688
Дата рег-ции: Окт. 2014
|
alex_231
Цитата: Есть такой байт 5, ты, наверное, уже о нём думал =) Это счётчик уже выведенных на экран тайлов из карты. Так вот те два сравнения относятся только к пятерке и вообще никакого отношения не имеют не к внутреннему ни к внешнему циклам.
Ты меня не так понял.
Я сделал вывод о циклах как раз по пятому байту, но циклы эти организуются в высокоуровневом языке, а в ассемблере вычисления производятся аналогично циклу, но самого цикла как такового там нет.
Цитата:Остается писать пакер/анпакер, что представляет большую проблему по сравнению с другими алгоритмами: приходится учитывать счетчик тайлов ВСЕЙ карты, а значит распаковка обязательна
целиком - по частям нельзя. Как и запаковка.
Не согласен, я писал без учета количества разжатых тайлов (если только циклы не считать средством учета), да и пак/анпак по частям тоже возможен, но только вручную.
А вообще - верно, с повтором я намудрил
Декомпрессор готов.
Щас за пакер возьмусь.
----- Делая выбор, отбрось простое решение и выбери правильное...
|
|
|
alex_231 |
Отправлено: 11 Февраля, 2016 - 08:27:01
|
Chief-Net
Покинул форум
Сообщений всего: 4688
Дата рег-ции: Окт. 2014
|
alex_231
Эх, ну я и размахнулся, готов пакер, проверил - работает, правда иногда подглючивает, но как-то странно:
нижеуказанные комбинации после разжатия в игре (позже: хотя и декомпрессор так же разжимает, значит это глюк пакера ) выглядят так:
D8 40 D4 --> D8 D8 D4
E8 40 E4 --> E8 E8 E4
F8 40 F4 --> F8 F8 F4
но если заменить 40 на 00 то всё проходит как должное.
Интересно, в чём же его проблема?
А вот что получилось в результате (это я так, шутя): Прикреплено изображение
----- Делая выбор, отбрось простое решение и выбери правильное...
|
|
|
Griever |
Отправлено: 11 Февраля, 2016 - 08:28:58
|
VIP
Покинул форум
Сообщений всего: 457
Дата рег-ции: Июнь 2015
|
Griever
Цитата:Griever, а может пока я пакер пишу ты разберёшься, как программа определяет когда пора заканчивать распаковку, а то я сделал по адресам, но это не совсем правильно, так как в роме есть указатель только на начало пакета, а конец как-то вычисляется.
Хорошо, если тебе всё ещё это интересно, то пожалуйста:
По адресу $a2d5 (если ты помнишь, это перед самым началом нашей тайловой карты) есть два байта: $1E и $3E. Они XOR'ятся и получается $20 - объём извлекаемых данных, характерный для этой карты(не знаю, почему именно двадцать и почему нельзя распаковать сразу весь экран). Он сохраняется в ячейку $02 и $304. Первая используется при копировании уже распакованных данных в PPU, а вторая - при первичной распаковке в RAM. И потом командой по адресу 8037 в первом случае и С338 во втором постоянно сравнивается с нулём после декремента. Казалось бы: почему $20, ведь экран
на NES состоит из 32*20 тайлов? На самом деле после распаковки 32-х тайлов в RAM, их сразу сбрасывают в PPU. Поэтому распаковка осуществляется этакими "блоками" по 32 тайла. Значит экран будет заполнен после тридцати таких "итераций" (учёба в вузе пополнила мой лексикон =)) Так вот, в принципе, можно поставить счётчик на блоки, и закончить распаковку на тридцатом блоке. Ну ещё можно поставить условие, что если в 304 будет записано не $20, а $08, то распаковка должна закончиться. В отношении нашей карты я встретил такую ситуацию, когда производилось чтение из рома по адресу $A461.
Не знаю точно - сработает ли, но конец карты должен быть именно там. Эта ситуация объясняется тем что после распаковки тайловых карт сразу начинается распаковка таблиц аттрибутов(23с0-2400), которая в свою очередь
скидывается в PPU в блоках по 8 (восемь итераций). Поэтому, как только начинается распаковка аттрибутов - прекращаем распаковку.
Примечательно что в ячейках $301 и $302 содержится адрес PPU, относящийся к области тайловых карт, с которого следует возобновить
распаковку индексов. Причём они не загружаются из рома, а к ним прибавляется постоянно число $20, которое предварительно
берётся из рома по адресу $a29d |
|
|
|
Поиск в теме | Версия для печати |
Страниц (2): « 1 [2] |
Сейчас эту тему просматривают: 1 (гостей: 1, зарегистрированных: 0) |
« Экстрим хакинг » |
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
|
|
|