почему бы не попробовать решать эту задачу с железной стороны - а именно заменить i8080 на z80 - работы значительно поубавится
вроде специалист есть на z80 от хардыча.
Вид для печати
почему бы не попробовать решать эту задачу с железной стороны - а именно заменить i8080 на z80 - работы значительно поубавится
вроде специалист есть на z80 от хардыча.
Самый удобный вариант специалиста для переноса спековских (и не только) игр - Эрик с доработками SYR-ALEX. Хотя и с ним есть пара проблем
1. Даже с доработкой цвет всего "8с", не 16+16.
2. В emu не поддерживаются прерывания, это очень серьезная проблема. Тормоза проца тоже не поддерживаются, но это скажется только на критичных по времени процедурах, типа биперной музыки или обмена с магнитофоном.
В MX2 или Сябр можно, как я понимаю, установить z80, но простой адаптации туда спековских игрушек мешает отсутствие удобного менеджера памяти и прерываний.
skoolkit - вполне себе вещь! Работает именно так, как я себе представлял работу правильного дизассемблера. Для начала я прошёл Batty до конца, запустил все режимы и постарался смоделировать все возможные игровые ситуации. В это время эмулятор создавал мне профайл игры - помечал участки памяти как исполняемый код, данные и т.д. Благодаря этой информации, дизассемблер будет точно знать абсолютно все участки с исполняемым кодом и не будет пытаться дизассемблирвоать спрайты, таблицы и другие данные, а также не пропустит никакой код. Далее, на основе этого профайла я получил удобоваримый дизассемблер игры, который можно анализировать, комментировать и, наверное, даже в итоге попытаться скомпилировать обратно.
Так как анализу подвергался снепшот игры, то дизассемблер захватил в том числе и экран, а также неиспользуемую область памяти. Но я умышленно не стал ничего вырезать и оставил всё, как есть. Так как дизассемблер всё-таки не слишком интеллектуальный, то, например, адреса в экранной области он преобразовал в метки. Также он не смог разрезать блоки данных и вставить метки в середину блока, поэтому в некоторых местах вместо меток он оставил абсолютные адреса. Благо, что при дизассемблировании он записал в лог все такие места, который я сохранил и приложил к ассемблерному тексту.
Так, появилась мысль... Сейчас доработаю текст и выложу.
В общем, вырезал экран из исходного файла и дизассемблер подставил, как и положено, адреса вместо меток. Также вручную подставил метки в середину блоков данных и дизассемблер смог их переварить, но при этом выдал предупреждения типа:
Потому что число $9D3A можно двояко интерпретировать: и как адрес, и как какие-то данные, которые нужно поместить в регистровую пару. Но навскидку кажется, что все эти числа именно адреса, которые нужно преобразовать в метки.Код:WARNING: Address $9D3A replaced with L9D3A in unsubbed LD operation:
9D0D LD HL,$9D3A
Однако осталось два адреса, которые привели дизассемблер в ступор:
Эти числа больше похожи на данные, а не на метки, так как эти адреса в коде приходятся на середину процедур. Я пытался поставить туда метки, но после этого получал более серьёзные ошибки. Так что оставил так.Код:WARNING: No label for address ($BF00):
926E LD HL,$BF00
WARNING: No label for address ($AEEB):
AEE0 LD HL,$AEEB
Вот сейчас код уже можно пытаться анализировать.
И ещё мне показалось, что он данные и текст интерпретирует по алгоритму: если в блоке все байты лежат в области ASCII, значит это текстовое сообщение. Но ни одного осмысленного сообщения я там так и не нашёл. Видимо, нужно принудительно все текстовые сообщения привести к данным.
Точно можно. Pasmo, например, компилирует на ура.
Не увидел в архиве, поэтому на всякий случай, там можно создавать файл управляющий *.ctl, в котором указывать, как интерпретировать конкретный участок памяти (код, данные, текст и т.д.). Он по сути и является рабочим файлом, который и нужно доводить до ума, а дизасемблер каждый раз перегенерировать.
в первом случае это координаты (для рисования рамки вокруг таблицы счёта)
во втором случае это адрес таблицы аттрибутов для кирпичиков, A=№, но 0 не бывает.
поэтому начало таблицы приходится на RET (конец другой подпрограммы)
понятней будет #AEE0 ld hl,44780-1 ; ld hl,BrickAttrTable-1
да, есть такое. я сначала даже не обратил внимание (думал построение каких-то таблиц).
похоже автор таким макаром частично скрыл спрайты врагов/ракетки
и кстати перед Batty он сделал WipeOut https://www.worldofspectrum.org/pub/.../w/WipeOut.png
но эта игра у нас была неизвестна.
по (большим) объёмам занимаемой памяти получается
55040,768 ; аттрибуты экрана
55808,6144; пиксели экрана
61952,3584 ; строится таблица
Ещё посидел над дизассемблером. Сразу после загрузки кода с TZX происходит переброс кодового блока на другой адрес и управление передаётся на адрес #6800. Всё что ниже этого адреса, на первый взгляд никак не используется, поэтому я исключил эти данные. С адреса #6800 начинается процедура декодирования или распаковывания (я не анализировал) кода. И после окончания декодирования управление передаётся на адрес #B9B1. Собственно это и является адресом запуска игры. На входе должны быть установлены SP #6000 и IY 5C3A. Остальные регистры вроде бы не важны.
Я отгрузил кодовый блок сразу после процедуры декодирования. Далее, согласно полученному профайлу дизассемблировал его. В процессе дизассемблирования я получал предупреждения о метках. Те из них, которые явно являются метками (в эти ячейки памяти что-то пишется или читается оттуда) я заменил в карте. Остальные не стал трогать - все они есть в файле warn.txt. Тут уже нужно руками смотреть где что, и анализировать.
Ещё все стринги принудительно перевёл в данные, так как осмысленного текста там всё равно нигде не было.
Полученный дизассемблер прилагаю для ознакомления.
есть хитрые моменты в коде
это самомодификация ;jp ?, #XXXXКод:L9910_6:
ADD A,A
CALL LB5BB
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
LD ($9A20),HL !!
LD ($9AB4),HL !!
LD ($9AB9),HL !!
LD ($99E3),HL !!
ну и например ; Data block at 9A27; там на самом деле исполняемый код
Возможно это и исполняемый код, но он в процессе полного прохождения игры ни разу не исполнялся. Ещё может быть, конечно, что я профайл снял с запущенной игры, а дизассемблировал ещё не запущенную (но раскодированную!). Возможно там где-то по коду после запуска ещё какая-нибудь перетасовка данных происходит, но я так навскидку не увидел. И из-за этого могло произойти расхождение профайла с кодом. На всякий случай прилагаю дизассемблер того снепшота, с которого снимал профайл. Однако там отличия минимальны - в основном в блоках данных. Но также видны и следы самомодификации кода!
В общем, засел я конкретно за дизассемблер Batty. Вначале думал, что вот сейчас объединю кодовые блоки и выложу очередной вариант дизассемблера игры, потом ещё что-то, а потом ещё что-то и т.д. А в итоге продвинулся довольно серьёзно, просидев все выходные с утра до вечера. До анализа самого кода я пока ещё не добрался, но структура игры сейчас чётка видна. Графика и данные практически полностью разобраны. Для примера прикладываю все спрайты, которые есть в игре. Чтобы их получить, пришлось написать программу на Python. Это облегчило анализ таблиц графики. Есть ещё небольшой участок (его границы известны) с графикой, которая отвечает за отрисовку поля: обрамления и текстуры раунда.
В процессе разбора программы выяснилось, что в игре есть пустые спрайты. Судя по всему должна была быть анимация увеличения шарика после получения соответствующего бонуса, а также должен был быть ещё один какой-то бонус.
Встречается и мёртвый код - небольшие подпрограммы, которые нигде не вызываются.
В начале игры то, что я изначально принял за декодирование блока, оказалось инверсией спрайтов (плюс ещё какие-то манипуляции с данными). Почему автор сразу не положил графику в нужном виде, а непосредственно перед запуском инвертирует её, совсем непонятно.
Сейчас у меня есть листинг, который компилируется обратно в код на 100% совпадающий с исходным. Однако нельзя сказать, что дизассемблер полноценный, так как если изменить адрес компиляции, то игра перестаёт работать. Где-то есть таблицы и данные, которые пока не учтены.
После каждой правки исходного текста я компилирую программу и обязательно сравниваю с эталонным кодом, чтобы убедиться, что я ничего не сломал и что получаемый код полностью соответствует оригиналу. Как только я достигну момента, что больше не буду знать, что делать дальше, я обязательно выложу результат.