PDA

Просмотр полной версии : Дизассемблирование River Raid



morozov
16.07.2021, 08:47
Привет!

С полгода назад поначитался форма и других интернетов, и на ностальгической новогодней волне решил попробовать дизассемблировать River Raid (https://github.com/morozov/river-raid-disasm). В отличие от автора подобного проекта о The Great Escape (https://github.com/dpt/The-Great-Escape), полную документацию со всеми картинками я вряд ли когда-то осилю. И в отличие от Batty (https://zx-pk.ru/threads/31932-dizassemblirovanie-igry-batty) ни на какую другую ретро-платформу портировать тоже не планирую, т.к. не умею.

Хотел довести проект до такого состояния, когда достаточно подробно смогу понимать логику движка, и переписать игру на чём-нибудь типа Ebiten (https://ebiten.org/). С одной стороны, можно было бы играть без эмулятора на всём, что движется; с другой, можно было бы устранить клешинг. Уж больно он противный в этой игре.

Пытаясь описывать логику отрисовки уровней, понял, что описанине словами будет недостаточно понятно, и стал прототипировать отрисовку на PHP (https://github.com/morozov/river-raid-php). Сравнивал с картами с maps.speccy.cz (https://maps.speccy.cz/map.php?id=RiverRaid&sort=4&part=18&ath=): не считая мостов (руки не дошли), вроде похоже и без клешинга!

Что сделано:

Файл ассемблера, который собирается с любого стартового адреса (значит Skookit всё расставил правильно).
Описаны все спрайты.
Описаны данные и логика построения уровней.
Описана логика выбора управления и начального уровня, переключения между игроками, некоторые структуры данных.
Мелкие исправления в инструкциях. Без нех некоторые переходы и метки указывали на один байт раньше, код работал на удачу и не переносился.
Мелкие исправления в спрайтах. У самолёта в одной из позиций по-прежнему отгрызен кусок левого крыла.


Более-менее интересное из того, что узнал по коду:

Логику второго игрока явно дописывали в последнюю очередь задней левой ногой. Куча дублирования кода, который по-хорошему нужно было бы обобщить.
Логика отрисовки островов и берегов сильно продублирована, хотя она абсолютно одинаковая. Может писали на каком-то высокоуровневом языке, и это компилятор так скомпилировал?
Данные об уровнях хранятся крайне неэкономно. Подробностей сейчас не вспомню.
Цвет корабля и цвет второго игрока (голубой) задаётся в одном и том же месте.
В коде есть несколько указателей, которые нигде не используются
Все спрайты продублированы в четырёх позициях со смещением в два пикселя, чтобы проще было отрисовывать, но истребители летят с такой скоростью, что используются только один или два спрайта.
За 10.000 очков дают бонусную жизнь. Сколько ни играл, не замечал (или не набирал столько).
Определение столкновения с объектом происходит прямо по данным на экране. Т.е. если поставить игру на паузу, нарисовать что-нибудь на экране с помощью POKE, в это что-то можно врезаться. Это приводит к багу, что если заправляться и стрельнуть в заправку, иногда можно себя взорвать (а точнее, врезаться во взрыв), хотя в основном такого не происходит.
По адресу #8561 есть экран с выбором управления, который нигде не выводится (см. ниже).
Счёт хранится прямо в виде ASCII-символов, и вся арифметика (например, добавление очков) выполняется вручную над символами, прямо как в школе столбиком.
Когда танк подъезжает к берегу, то на каждом шаге его координату нужно увеличить или уменьшить в зависимости от того, на каком он берегу. Так вот сначала она всегда увеличивается, а потом, если танк на правом берегу, уменьшается на вдвое большее значение. Может на низком уровне оно так и принято, но выглядит диковато.


По ходу работы предложил улучшение (https://github.com/skoolkid/skoolkit/issues/112) в Skoolkit, чтобы в снапшоте, который он делает из образа ленты, можно было инициализировать системные переменные. Наверное в этом плане River Raid – исключение, раз никому до меня такое раньше не требовалось.

Что не сделано? Куча всего. Более-менее подробно описана логика полёта снаряда танка на берегу, но поведение всех других объектов не описано. У многих меток временные названия типа "something", а добрая треть так и не названы.

В последние несколько попыток продолжить разбор натыкался на то, что не понимаю, что дальше делать. От этого весь запал иссяк. Решил оставить наработки здесь – вдруг кто-то захочет продолжить или хотя бы подскажет, куда дальше копать.

Спасибо за внимание.

Ссылки:

Репозиторий с разбором: https://github.com/morozov/river-raid-disasm
Репозиторий с отрисованными уровнями: https://github.com/morozov/river-raid-php


Неиспользуемый экран выбора управления:
75829

Lethargeek
16.07.2021, 09:13
Счёт хранится прямо в виде ASCII-символов, и вся арифметика (например, добавление очков) выполняется вручную над символами, прямо как в школе столбиком.
так это для старых восьмибиток дело обычное, получается быстрее вместе с отображением, чем считать в двоичной, а потом каждый раз переводить для вывода в десятичную

Bedazzle
16.07.2021, 10:43
В последние несколько попыток продолжить разбор натыкался на то, что не понимаю, что дальше делать. От этого весь запал иссяк.

Что дальше делать в том смысле, что застрял перед непонятной стеной, или что не знаешь, куда улучшать?

morozov
16.07.2021, 18:57
Что дальше делать в том смысле, что застрял перед непонятной стеной, или что не знаешь, куда улучшать?

Застрял. В коде осталось порядка 150 меток с автосгенерированными названиями типа L1234 и неописанным назначением. Ну и куча логики не описана. Но всякий раз, когда берусь за какую-то неописанную процедуру, начинаю разбираться, перехожу по вызовам, а картина не вырисовывается. Какая-то каша вызывает какую-то другую кашу.

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

Bedazzle
17.07.2021, 01:08
берусь за какую-то неописанную процедуру, начинаю разбираться, перехожу по вызовам, а картина не вырисовывается. Какая-то каша вызывает какую-то другую кашу.

Мне пока везло: всё, за что брался оказалось достаточно неплохо структурировано внутри.
Я отказался от скулкита, режу на кучу мелких исходников, где по возможности одна функция. Заодно что-то и в макросы засовываю. Компилю бинарник, который сверяется с эталоном. Если что-то поломал, сразу вылезает. Ну и в отладчик метки подсосать полезно.

morozov
17.07.2021, 02:57
Я отказался от скулкита, режу на кучу мелких исходников, где по возможности одна функция.

Почему отказался? Чтобы резать? Мне сама идея управления файлом с аннтотациями очень нравится. Хотя, гигантский исходник на выходе слегка напрягает. Вполне возможно, что Скулкит и резать умеет, ну или можно попросить сделать. Я как-то подумывал.


Заодно что-то и в макросы засовываю.

Я бы это ближе к финалу делал, на стадии наведения порядка.


Компилю бинарник, который сверяется с эталоном. Если что-то поломал, сразу вылезает.

Это я тоже делаю. Бывает, не понятно, за что какое-то значение отвечает, меняю, собираю, смотрю, что поменялось.


Ну и в отладчик метки подсосать полезно.

Это как? Я пользуюсь Fuse, там никаких меток нету. Каким отладчиком стоит попробовать попользоваться?


Heavy on the disasm
Eric and the disasm
Mask 3: Venom strikes disasm
Bard's disasm


Можно где-то на все эти проекты посмотреть? Я как-то пытался искать, но вроде не нашёл.

morozov
17.07.2021, 07:10
Ещё интересную штуку вспомнил: значение счёта в игре всегда кратно десяти, причём в коде все значения очков прописаны сразу десятками, и в счёте ноль в первой позиции приписан по сути просто для красоты. Наверняка, так во многих играх делается. Интересно, есть ли у этого феномена какое-то название. Что-нибудь из области экономики или психологии (инфляция счёта?).

Bedazzle
17.07.2021, 21:10
Почему отказался? Чтобы резать?

Да, чтобы удобно работать над маленьким кусочком, который при желании можно инклудить в другой проект.
Скулкит для документации планировал делать на финальном этапе, но до него пока не осилил. :)


Это как? Я пользуюсь Fuse, там никаких меток нету. Каким отладчиком стоит попробовать попользоваться?

В основном делаю в EmuzWin, если нужен трейс, то в SpecEmu.
Народ я так понял, делает в Unreal, но мне он не зашёл по многим причинам. Сейчас пробую перелезть в Xpeccy.


Можно где-то на все эти проекты посмотреть?

Из выложенного только Эрик (https://github.com/Bedazzle/EATF).
HOTM разобран до потрохов, Mask 3 пока на половине (перекинулся на Bards tale - первый уровень где-то на 3/4 разобран), и Lode runner на 3/4.

Black Cat / Era CG
17.07.2021, 22:05
Наверняка, так во многих играх делаетсяВ контре на НЕС дописывают 00, максимум очков 6553500.