? Я могу весь дамп вывода этой фразы выложить, если надо, конечно.
Очень занимательный алгоритм.
Blue Marline(Nes)
Сообщений 21 страница 40 из 45
Поделиться212006-09-04 20:53:30
Поделиться222006-09-04 21:17:03
Вот, пожалуйста:
ROM:8106 LDA ($E),Y ROM:8108 BNE loc_8112 ROM:810A INY ROM:810B LDA ($E),Y ROM:810D STA byte_3 ROM:810F INY ROM:8110 LDA ($E),Y ROM:8112 ROM:8112 loc_8112: ; CODE XREF: sub_80FE+Aj ROM:8112 STA byte_8 ROM:8114 INY ROM:8115 BNE loc_811F ROM:8117 ROM:8117 loc_8117: ; CODE XREF: sub_80FE+6j ROM:8117 AND #7 ROM:8119 BNE locret_8127 ROM:811B ASL byte_8 ROM:811D LDA byte_8 ROM:811F ROM:811F loc_811F: ; CODE XREF: sub_80FE+17j ROM:811F ASL A ROM:8120 BCC locret_8127 ROM:8122 LDA ($E),Y ; загрузка контрольного байта(в ней вся проблема - она происходит как-то ; нерегулярно!) Скорее, почему она происходит - вот проблема. ROM:8124 STA byte_9 ROM:8126 INY ROM:8127 ROM:8127 locret_8127: ; CODE XREF: sub_80FE+1Bj ROM:8127 ; sub_80FE+22j ROM:8127 RTS ROM:8127; End of function sub_80FE
Может, я что-то недопонял, но процедура копирования предыдущего символа выглядит так:
ROM:80ED ASL byte_9 ;(кидаем следующий бит контрольного байта во флаг) ROM:80EF BCS loc_80F6; если бит установлен в 1, то.... ROM:80F1 ROM:80F1 loc_80F1: ; CODE XREF: sub_80E8+3j ROM:80F1 LDA ($E),Y ; обходим загрузку следующего знака из РОМа! ROM:80F3 INY ROM:80F4 BNE loc_80F8 ROM:80F6 ROM:80F6 loc_80F6: ; CODE XREF: sub_80E8+7j ROM:80F6 LDA byte_3 ;.....загружаем ноль(в тройке ВСЕГДА ноль) ROM:80F8 ROM:80F8 loc_80F8: ; CODE XREF: sub_80E8+Cj ROM:80F8 PHA (в стек) ROM:80F9 JSR sub_80FE ROM:80FC PLA ROM:80FD RTS ; вытаскиваем и переходим к подпрограмме вывода, но теперь у нас XOR'ится с нулём, а ; значит следующий знак будет таким же как и предыдущий и из рома не скопировано ни ;одного байта.
Поделиться232006-09-05 10:23:22
Блин, забыл дома ром взять, а так:
загрузка контрольного байта(в ней вся проблема - она происходит как-то нерегулярно!) Скорее, почему она происходит - вот проблема.
А происходит оно потому, что срабатывает условие для BCC (правда я не помню какое именно), а срабатывает оно в зависимости от значения аккумулятора, изменённого командой ASL и загружаемого из byte_8 (я не понял что это), в который записывается заранее.
Отредактировано Alex_231 (2006-09-05 10:24:07)
Поделиться242006-09-05 18:38:31
Да, там всё понятно - там байт девятка - тоже шифтуется несколько раз, а он загружается вообще непонятно откуда. Надо сказать, что пока ты не возьмешься за дело по-нормальному, т.е. возьмешь ром - ничего определенного ты не скажешь.
Поделиться252006-09-06 08:45:31
Эт верно.
Всё, надоело, сейчас скачаю ром и гляну (склероз проклятый)
Поделиться262006-09-06 10:47:32
В общем так:
и восьмой, и девятый байты берутся из этой же цепочки, девятый показывает, какие байты повторяются, а какие нет, а восьмой показывает какие байты грузятся в девятый.
Таким образом данная цепочка есть не что иное, как своеобразный способ сжатия (эффективен на идущих подряд пробелах).
Сие же есть пожатая тайловая карта, но чтобы написать для нее декомпрессор, нужно рассмотреть весь алгоритм (а точнее - работу с ячейкой $000E), мы же рассмотрели только подпрограмму, которая непосредственно производит распаковку.
P.S.: Как красиво на главной смотрится 2299 сообщений, 99 зарегестрированных пользователей и 11 пользователей в рекорде
Отредактировано Alex_231 (2006-09-06 10:54:33)
Поделиться272006-09-06 17:39:38
умм... Рассмотри =)
Поделиться282006-09-07 08:41:43
А нужно ли всю тайловую карту менять?
Проще вжать в найденный отрезок нужную надпись вручную, без лишнего гемора.
Поделиться292006-09-08 03:59:10
Хотя нет, вжать то мы вожмём (это я про "PRESS START BUTTON"), а что с копирайтами и с названием делать? Жать руками такой объём - не очень-то удобно.
Придётся всё-таки писать декомпрессор
P.S.: А "PRESS START BUTTON" я, кстати, вжал (в виде "НАЖМИ СТАРТ"), нормально смотрится.
P.P.S.: Блин, когда декомпрессор писать, FFAD идет муравьиными шагами, да ещё и учеба началась ((
Отредактировано Alex_231 (2006-09-08 04:06:09)
Поделиться302006-09-08 11:57:47
Наброски декомпрессора готовы: правильно разжимает пока только %-ов 30 пакета, так как еще не все условия учтены, но начало положено, думаю, завтра допишу.
Отредактировано Alex_231 (2006-09-08 11:58:28)
Поделиться312006-09-08 17:24:23
Что-то не понимаю: как ты вжал, если не разобрался с самой процедурой?
ну напишешь ты Нажми старт - контрольные байты ты поменял на нули, конечно. В итоге в тайловой карте стало меньше тайлов. По всем признакам в таком случае - картинка просто порется.
Или ты не до конца рассказал процедуру?
И к тому же, возможно таким же алгоритмом пожаты и карты на других экранах.
Поделиться322006-09-09 08:56:51
Почему не до конца?
Я просто не совсем верно описал принцип распаковки.
Но в этом я уже разобрался, а вот как программа переходит от одного контрольного байта к другому (те, которые в восьмом байте хранятся) мне ясно не до конца:
там два цикла, один вложен в другой, каждый цикл идёт от 1 до 8, переход организуется при сравнении с $07 и с $3F, первое для внутреннего цикла, второе - для внешнего.
Таким образом, один внешний цикл заполняет две строки в тайловой карте.
После его окончания в восьмой байт записывается новый контрольный байт и все повторяется. Вот как раз тот момент, когда читается новый контрольный байт, мне не до конца понятен, чтение может происходить по-разному и я пока не понял как это описать в программе (потому как не понял как это происходит в игре).
Внутренний же цикл очень прост: если из восьмого контрольного байта в флаг перемещается ноль, а из девятого - единица, или из восьмого - единица, а из девятого - ноль, то происходит вычисление нового кода, в противном случае происходит происходит копирование предыдущего.
Когда внутренний цикл заканчивается происходит сдвиг контрольного байта в восьмёрке, и он (цикл) запускается снова.
При вжатии я сместил копируемые байты в сторны (так, чтобы копировались пробелы: переместил контрольные биты, а не заменил их на нули), тем самым количество тайлов в карте осталось прежним, а некопируемый диапазон расширился до нужного размера.
Правда пришлось сдвинуть и сам контрольный байт влево, тот, который второй - $47, предварительно изменив его на $07, а первый - $C2 - на $F0.
То есть из цепочки 1100 0010 0100 0111
я сделал цепочку 1111 0000 0000 0111
Отредактировано Alex_231 (2006-09-09 10:42:36)
Поделиться332006-09-09 11:55:40
И еще одно: похоже, если в флаг из восьмого байта переносится ноль, то внутренний цикл проводится дважды (пока не проверенные, но интуитивно почувствованные данные)
Отредактировано Alex_231 (2006-09-09 11:58:16)
Поделиться342006-09-09 12:18:23
последнее утверждение подтвердилось экспериментально: прописав в программе это повторение, я получил увеличение правилной распаковки пакета, но всё ещё не полностью.
Отредактировано Alex_231 (2006-09-11 11:25:11)
Поделиться352006-09-09 20:07:42
Боже мой, на каком языке вы говорите??? На земном??? <;о)
Поделиться362006-09-10 15:24:29
ОК, ты меня навёл на правильную мысль. Теперь я имею право сказать: "ЗНАЧИТ ТАК:" =Р
Есть такой байт 5, ты, наверное, уже о нём думал =) Это счётчик уже выведенных на экран тайлов из карты. Так вот те два сравнения относятся только к пятерке и вообще никакого отношения не имеют не к внутреннему ни к внешнему циклам. В самом начале в два контрольных байта(8 и 9) загружаются значения. выводится первый символ, который был считан ранее. Проверяется старший бит девятки. Ну, как уже говорилось, если единичка, то знак повторяется, если ноль - читается следующий. и так далее, пока у нас не "исшифтуется" девятка. А шифтуется она в любом случае, даже если выводятся два одинаковых тайла. Это значит, что к моменту, когда девятка кончится в пятерке станет $#08. На этот случай есть команда по адресу $8117, которая проверяет кратность счётчика(пятерки) числу восемь. И если у нас девятка исшифтовалась, то мы один разик шифтуем восьмёрку и если в восьмёрке ноль, то девятку мы не читаем, а оставляем такой же какой она стала (а осталась она с нулями), а уже в подпрограмме
вывода индекса тайла девятку мы не шифтуем, а просто постоянно считываем по одному индексу тайла из РОМа. Одним словом, если восьмерочный бит ноль, то следующие восемь тайлов будут без повторов.
Таким образом, мы в конце концов исшифтуем и восьмерку. К тому времени в счётчике тайлов будет $#40, тут уже сработает команда $8102 - которая позволит нам считать из рома новое значение восьмёрки, если порядковый номер следующего тайла будет кратен #$40. И всё повторится сначала.
Вот и всё. Остается писать пакер/анпакер, что представляет большую проблему по сравнению с другими алгоритмами: приходится учитывать счетчик тайлов ВСЕЙ карты, а значит распаковка обязательна
целиком - по частям нельзя. Как и запаковка.
И вот ещё:
Внутренний же цикл очень прост: если из восьмого контрольного байта в флаг перемещается ноль, а из девятого - единица, или из восьмого - единица, а из девятого - ноль, то происходит вычисление нового кода, в противном случае происходит происходит копирование предыдущего.
На самом деле, если из восьмерки перемещается ноль, то что в девятке уже неважно(см. выше) - байты пойдут без повторов.
Ещё, если посмотреть внимательнее, то надписи на экранах типа "Where shall we go today?" тоже пережаты этим алгоритмом.
Гайверу виднее: может где ещё. Так что с этой игрой ещё кувыркаться и кувыркаться =Р
PS: хотел написать распаковщик, но у самого переводы стоят =)
Поделиться372006-09-11 05:42:58
Есть такой байт 5, ты, наверное, уже о нём думал =) Это счётчик уже выведенных на экран тайлов из карты. Так вот те два сравнения относятся только к пятерке и вообще никакого отношения не имеют не к внутреннему ни к внешнему циклам.
Ты меня не так понял.
Я сделал вывод о циклах как раз по пятому байту, но циклы эти организуются в высокоуровневом языке, а в ассемблере вычисления производятся аналогично циклу, но самого цикла как такового там нет.
Остается писать пакер/анпакер, что представляет большую проблему по сравнению с другими алгоритмами: приходится учитывать счетчик тайлов ВСЕЙ карты, а значит распаковка обязательна
целиком - по частям нельзя. Как и запаковка.
Не согласен, я писал без учета количества разжатых тайлов (если только циклы не считать средством учета), да и пак/анпак по частям тоже возможен, но только вручную.
А вообще - верно, с повтором я намудрил
Декомпрессор готов.
Щас за пакер возьмусь.
Отредактировано Alex_231 (2006-09-11 06:21:50)
Поделиться382006-09-11 09:40:10
Griever, а может пока я пакер пишу ты разберёшься, как программа определяет когда пора заканчивать распаковку, а то я сделал по адресам, но это не совсем правильно, так как в роме есть указатель только на начало пакета, а конец как-то вычисляется.
Поделиться392006-09-11 11:12:40
Эх, ну я и размахнулся, готов пакер, проверил - работает, правда иногда подглючивает, но как-то странно:
нижеуказанные комбинации после разжатия в игре (позже: хотя и декомпрессор так же разжимает, значит это глюк пакера ) выглядят так:
D8 40 D4 --> D8 D8 D4
E8 40 E4 --> E8 E8 E4
F8 40 F4 --> F8 F8 F4
но если заменить 40 на 00 то всё проходит как должное.
Интересно, в чём же его проблема?
А вот что получилось в результате (это я так, шутя):
Отредактировано Alex_231 (2006-09-11 11:50:25)
Поделиться402006-09-11 15:05:09
Круто! Там в игре как минимум штук 6 таких экранов - этот, 3 экрана когда выбираешь в какой порт плыть, когда поймаешь огромную рыбу типа марлина (любого вида) или акулы и взвесишь её в порту и ещё...
Игра здоровская, будет просто замечательно, если удастся её перевести на русский язык...