Chief-NET

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Chief-NET » Экстрим хакинг » Blue Marline(Nes)


Blue Marline(Nes)

Сообщений 21 страница 40 из 45

21

? Я могу весь дамп вывода этой фразы выложить, если надо, конечно.
Очень занимательный алгоритм.

22

Вот, пожалуйста:

Код:
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'ится с нулём, а
                              ; значит следующий знак будет таким же как и предыдущий и из рома не скопировано ни
                              ;одного байта.

23

Блин, забыл дома ром взять, а так:
загрузка контрольного байта(в ней вся проблема - она происходит как-то нерегулярно!) Скорее, почему она происходит - вот проблема.
А происходит оно потому, что срабатывает условие для BCC (правда я не помню какое именно), а срабатывает оно в зависимости от значения аккумулятора, изменённого командой ASL и загружаемого из byte_8 (я не понял что это), в который записывается заранее.

Отредактировано Alex_231 (2006-09-05 10:24:07)

24

Да, там всё понятно - там байт девятка - тоже шифтуется несколько раз, а он загружается вообще непонятно откуда. Надо сказать, что пока ты не возьмешься за дело по-нормальному, т.е. возьмешь ром - ничего определенного ты не скажешь.

25

Эт верно.
Всё, надоело, сейчас скачаю ром и гляну (склероз проклятый)

26

В общем так:
и восьмой, и девятый байты берутся из этой же цепочки, девятый показывает, какие байты повторяются, а какие нет, а восьмой показывает какие байты грузятся в девятый.
Таким образом данная цепочка есть не что иное, как своеобразный способ сжатия (эффективен на идущих подряд пробелах).
Сие же есть пожатая тайловая карта, но чтобы написать для нее декомпрессор, нужно рассмотреть весь алгоритм (а точнее - работу с ячейкой $000E), мы же рассмотрели только подпрограмму, которая непосредственно производит распаковку.

P.S.: Как красиво на главной смотрится 2299 сообщений, 99 зарегестрированных пользователей и 11 пользователей в рекорде :)

Отредактировано Alex_231 (2006-09-06 10:54:33)

27

умм... Рассмотри =)

28

А нужно ли всю тайловую карту менять?
Проще вжать в найденный отрезок нужную надпись вручную, без лишнего гемора.

29

Хотя нет, вжать то мы вожмём (это я про "PRESS START BUTTON"), а что с копирайтами и с названием делать? Жать руками такой объём - не очень-то удобно.
Придётся всё-таки писать декомпрессор :-)

P.S.: А "PRESS START BUTTON" я, кстати, вжал (в виде "НАЖМИ СТАРТ"), нормально смотрится.
P.P.S.: Блин, когда декомпрессор писать, FFAD идет муравьиными шагами, да ещё и учеба началась :-(((

Отредактировано Alex_231 (2006-09-08 04:06:09)

30

Наброски декомпрессора готовы: правильно разжимает пока только %-ов 30 пакета, так как еще не все условия учтены, но начало положено, думаю, завтра допишу.

Отредактировано Alex_231 (2006-09-08 11:58:28)

31

:(  Что-то не понимаю: как ты вжал, если не разобрался с самой процедурой?
ну напишешь ты Нажми старт - контрольные байты ты поменял на нули, конечно. В итоге в тайловой карте стало меньше тайлов. По всем признакам в таком случае - картинка просто порется.
Или ты не до конца рассказал процедуру?
И к тому же, возможно таким же алгоритмом пожаты и карты на других экранах.

32

Почему не до конца?

Я просто не совсем верно описал принцип распаковки.
Но в этом я уже разобрался, а вот как программа переходит от одного контрольного байта к другому (те, которые в восьмом байте хранятся) мне ясно не до конца:
там два цикла, один вложен в другой, каждый цикл идёт от 1 до 8, переход организуется при сравнении с $07 и с $3F, первое для внутреннего цикла, второе - для внешнего.
Таким образом, один внешний цикл заполняет две строки в тайловой карте.
После его окончания в восьмой байт записывается новый контрольный байт и все повторяется. Вот как раз тот момент, когда читается новый контрольный байт, мне не до конца понятен, чтение может происходить по-разному и я пока не понял как это описать в программе (потому как не понял как это происходит в игре).

Внутренний же цикл очень прост: если из восьмого контрольного байта в флаг перемещается ноль, а из девятого - единица, или из восьмого - единица, а из девятого - ноль, то происходит вычисление нового кода, в противном случае происходит происходит копирование предыдущего.
Когда внутренний цикл заканчивается происходит сдвиг контрольного байта в восьмёрке, и он (цикл) запускается снова.

При вжатии я сместил копируемые байты в сторны (так, чтобы копировались пробелы: переместил контрольные биты, а не заменил их на нули), тем самым количество тайлов в карте осталось прежним, а некопируемый диапазон расширился до нужного размера.
Правда пришлось сдвинуть и сам контрольный байт влево, тот, который второй - $47, предварительно изменив его на $07, а первый - $C2 - на $F0.
То есть из цепочки 1100 0010 0100 0111
я сделал цепочку 1111 0000 0000 0111

Отредактировано Alex_231 (2006-09-09 10:42:36)

33

И еще одно: похоже, если в флаг из восьмого байта переносится ноль, то внутренний цикл проводится дважды (пока не проверенные, но интуитивно почувствованные данные)

Отредактировано Alex_231 (2006-09-09 11:58:16)

34

последнее утверждение подтвердилось экспериментально: прописав в программе это повторение, я получил увеличение правилной распаковки пакета, но всё ещё не полностью.

Отредактировано Alex_231 (2006-09-11 11:25:11)

35

Боже мой, на каком языке вы говорите??? На земном??? <;о)

36

ОК, ты меня навёл на правильную мысль. Теперь я имею право сказать: "ЗНАЧИТ ТАК:" =Р
Есть такой байт 5, ты, наверное, уже о нём думал =) Это счётчик уже выведенных на экран тайлов из карты. Так вот те два сравнения относятся только к пятерке и вообще никакого отношения не имеют не к внутреннему ни к внешнему циклам. В самом начале в два контрольных байта(8 и 9) загружаются значения. выводится первый символ, который был считан ранее. Проверяется старший бит девятки. Ну, как уже говорилось, если единичка, то знак повторяется, если ноль - читается следующий. и так далее, пока у нас не "исшифтуется" девятка. А шифтуется она в любом случае, даже если выводятся два одинаковых тайла. Это значит, что к моменту, когда девятка кончится в пятерке станет $#08. На этот случай есть команда по адресу $8117, которая проверяет кратность счётчика(пятерки) числу восемь. И если у нас девятка исшифтовалась, то мы один разик шифтуем восьмёрку и если в восьмёрке ноль, то девятку мы не читаем, а оставляем такой же какой она стала (а осталась она с нулями), а уже в подпрограмме
вывода индекса тайла девятку мы не шифтуем, а просто постоянно считываем по одному индексу тайла из РОМа. Одним словом, если восьмерочный бит ноль, то следующие восемь тайлов будут без повторов.
Таким образом, мы в конце концов исшифтуем и восьмерку. К тому времени в счётчике тайлов будет $#40, тут уже сработает команда $8102 - которая позволит нам считать из рома новое значение восьмёрки, если порядковый номер следующего тайла будет кратен #$40. И всё повторится сначала.
Вот и всё. Остается писать пакер/анпакер, что представляет большую проблему по сравнению с другими алгоритмами: приходится учитывать счетчик тайлов ВСЕЙ карты, а значит распаковка обязательна
целиком - по частям нельзя. Как и запаковка.
И вот ещё:

Внутренний же цикл очень прост: если из восьмого контрольного байта в флаг перемещается ноль, а из девятого - единица, или из восьмого - единица, а из девятого - ноль, то происходит вычисление нового кода, в противном случае происходит происходит копирование предыдущего.

На самом деле, если из восьмерки перемещается ноль, то что в девятке уже неважно(см. выше) - байты пойдут без повторов.

Ещё, если посмотреть внимательнее, то надписи на экранах типа "Where shall we go today?" тоже пережаты этим алгоритмом.
Гайверу виднее: может где ещё. ;) Так что с этой игрой ещё кувыркаться и кувыркаться =Р
PS: хотел написать распаковщик, но у самого переводы стоят =)

37

Есть такой байт 5, ты, наверное, уже о нём думал =) Это счётчик уже выведенных на экран тайлов из карты. Так вот те два сравнения относятся только к пятерке и вообще никакого отношения не имеют не к внутреннему ни к внешнему циклам.

Ты меня не так понял.
Я сделал вывод о циклах как раз по пятому байту, но циклы эти организуются в высокоуровневом языке, а в ассемблере вычисления производятся аналогично циклу, но самого цикла как такового там нет.

Остается писать пакер/анпакер, что представляет большую проблему по сравнению с другими алгоритмами: приходится учитывать счетчик тайлов ВСЕЙ карты, а значит распаковка обязательна
целиком - по частям нельзя. Как и запаковка.

Не согласен, я писал без учета количества разжатых тайлов (если только циклы не считать средством учета), да и пак/анпак по частям тоже возможен, но только вручную.

А вообще - верно, с повтором я намудрил :)

Декомпрессор готов.

Щас за пакер возьмусь.

Отредактировано Alex_231 (2006-09-11 06:21:50)

38

Griever, а может пока я пакер пишу ты разберёшься, как программа определяет когда пора заканчивать распаковку, а то я сделал по адресам, но это не совсем правильно, так как в роме есть указатель только на начало пакета, а конец как-то вычисляется.

39

Эх, ну я и размахнулся, готов пакер, проверил - работает, правда иногда подглючивает, но как-то странно:
нижеуказанные комбинации после разжатия в игре (позже: хотя и декомпрессор так же разжимает, значит это глюк пакера :-( ) выглядят так:
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)

40

Круто! Там в игре как минимум штук 6 таких экранов - этот, 3 экрана когда выбираешь в какой порт плыть, когда поймаешь огромную рыбу типа марлина (любого вида)  или акулы и взвесишь её в порту и ещё...

Игра здоровская, будет просто замечательно, если удастся её перевести на русский язык...


Вы здесь » Chief-NET » Экстрим хакинг » Blue Marline(Nes)