Просмотр полной версии : Дизассемблирование игры Batty
CityAceE
09.06.2020, 18:05
Если я ничего не путаю, то Batty тоже без прерываний работает. Хотя градации яркости, конечно, очень умело использует...
Эх, надо, наверное, предпринять очередную попытку дизассемблировать игру и добиться, чтобы полученный исходник потом компилировался обратно в запускаемый код.
===
Готовый полностью разобранный и откомментированный дизассемблер игры положил сюда: https://github.com/CityAceE/Batty
В batty и arkanoid 2 используются прерывания, в arkanoid - чтение порта FF
NEO SPECTRUMAN
09.06.2020, 18:31
в arkanoid - чтение порта FF
а для чего оно там?
умя на дельте все прекрасно работало
может конечно пофикшенная\ не та версия
Синхронизация с разверткой, как я понимаю. Например в emu версия с wos не работает, а если убрать проверку порта FF, то шарик носится как угорелый. Вроде где-то была тема про это, но я видел только название, саму ее не читал.
- - - Добавлено - - -
Кстати, еще неудобный для специалиста (не MX) момент в batty и арканоидах. Там есть цветные кирпичи с белой границей, и по ним может идти белый блик. На специалисте так не сделаешь, разве что менять на черную границу и черные блики.
Если я ничего не путаю, то Batty тоже без прерываний работает.
на IM1. для чего-то там берутся значения из системных переменных (таймер)
глянул фирменную версию https://www.worldofspectrum.org/pub/sinclair/games/b/Batty.tzx.zip
BreakPoint=26624, кодовый блок получается 26624,23156
CityAceE
10.06.2020, 04:11
кодовый блок получается 26624,23156
Игра после запуска раскодируется для начала, а может быть даже и разжимается. Я этот момент проходил и добирался до чистого кода, но потом забросил.
Если бряк на 6800h не устраивает, то наверно можно считать более-менее приемлемым компромиссом бряк на адрес 93F8h в меню. При современном развитии эмуляторов кракнуть не проблема, вопрос в том - что дальше? Кстати, есть еще версия для ориона с z80 card II, вывод графики там уже можно сказать почти переделан под специалист. Насколько помню основной код и адреса там как в спековской версии.
CityAceE
10.06.2020, 13:32
При современном развитии эмуляторов кракнуть не проблема, вопрос в том - что дальше?
Да, безусловно, получить чистый кодовый блок проблем нет. Проблема в дальнейшем дизассемблировании. Я пытался получить дизассемблер с помощью IDA, но мне показалось, что это не самый удачный вариант, либо же я просто плохо могу понимать чужой код. Сложно отделять код от графики и таблиц. Наверняка существуют какие-то более удобные инструменты под подобную задачу, но мне они неизвестны.
Кстати, есть еще версия для ориона с z80 card II, вывод графики там уже можно сказать почти переделан под специалист. Насколько помню основной код и адреса там как в спековской версии.
Тогда, наверное, можно было бы для начала адаптировать эту версию под Специалист с Z80 и пытаться дизассемблировать уже её, чтобы перевести код с Z80 на i8080.
Есть такая штука - skoolkit (https://github.com/skoolkid/skoolkit). Сам я ей не пользовался, но результаты работы смотрел, конкретно дизассм пзу спектрума (https://github.com/skoolkid/rom). Ну и там кое-какие игрушки досконально разобраны, правда не batty.
CityAceE
11.06.2020, 02:53
Есть такая штука - skoolkit.
Спасибо, что напомнил! Я тоже его видел уже, как раз, когда Batty ковырял. Но в итоге так и не попробовал. С тех пор, я вижу, он ещё больше продвинулся. Нужно будет обязательно попробовать. Судя по описанию и результатам, это именно то, что нужно!
shurik-ua
11.06.2020, 04:43
почему бы не попробовать решать эту задачу с железной стороны - а именно заменить i8080 на z80 - работы значительно поубавится
вроде специалист есть на z80 от хардыча.
Самый удобный вариант специалиста для переноса спековских (и не только) игр - Эрик с доработками SYR-ALEX. Хотя и с ним есть пара проблем
1. Даже с доработкой цвет всего "8с", не 16+16.
2. В emu не поддерживаются прерывания, это очень серьезная проблема. Тормоза проца тоже не поддерживаются, но это скажется только на критичных по времени процедурах, типа биперной музыки или обмена с магнитофоном.
В MX2 или Сябр можно, как я понимаю, установить z80, но простой адаптации туда спековских игрушек мешает отсутствие удобного менеджера памяти и прерываний.
CityAceE
11.06.2020, 06:16
skoolkit - вполне себе вещь! Работает именно так, как я себе представлял работу правильного дизассемблера. Для начала я прошёл Batty до конца, запустил все режимы и постарался смоделировать все возможные игровые ситуации. В это время эмулятор создавал мне профайл игры - помечал участки памяти как исполняемый код, данные и т.д. Благодаря этой информации, дизассемблер будет точно знать абсолютно все участки с исполняемым кодом и не будет пытаться дизассемблирвоать спрайты, таблицы и другие данные, а также не пропустит никакой код. Далее, на основе этого профайла я получил удобоваримый дизассемблер игры, который можно анализировать, комментировать и, наверное, даже в итоге попытаться скомпилировать обратно.
Так как анализу подвергался снепшот игры, то дизассемблер захватил в том числе и экран, а также неиспользуемую область памяти. Но я умышленно не стал ничего вырезать и оставил всё, как есть. Так как дизассемблер всё-таки не слишком интеллектуальный, то, например, адреса в экранной области он преобразовал в метки. Также он не смог разрезать блоки данных и вставить метки в середину блока, поэтому в некоторых местах вместо меток он оставил абсолютные адреса. Благо, что при дизассемблировании он записал в лог все такие места, который я сохранил и приложил к ассемблерному тексту.
Так, появилась мысль... Сейчас доработаю текст и выложу.
В общем, вырезал экран из исходного файла и дизассемблер подставил, как и положено, адреса вместо меток. Также вручную подставил метки в середину блоков данных и дизассемблер смог их переварить, но при этом выдал предупреждения типа:
WARNING: Address $9D3A replaced with L9D3A in unsubbed LD operation:
9D0D LD HL,$9D3A
Потому что число $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/sinclair/games-maps/w/WipeOut.png
но эта игра у нас была неизвестна.
по (большим) объёмам занимаемой памяти получается
55040,768 ; аттрибуты экрана
55808,6144; пиксели экрана
61952,3584 ; строится таблица
CityAceE
11.06.2020, 13:16
Ещё посидел над дизассемблером. Сразу после загрузки кода с TZX происходит переброс кодового блока на другой адрес и управление передаётся на адрес #6800. Всё что ниже этого адреса, на первый взгляд никак не используется, поэтому я исключил эти данные. С адреса #6800 начинается процедура декодирования или распаковывания (я не анализировал) кода. И после окончания декодирования управление передаётся на адрес #B9B1. Собственно это и является адресом запуска игры. На входе должны быть установлены SP #6000 и IY 5C3A. Остальные регистры вроде бы не важны.
Я отгрузил кодовый блок сразу после процедуры декодирования. Далее, согласно полученному профайлу дизассемблировал его. В процессе дизассемблирования я получал предупреждения о метках. Те из них, которые явно являются метками (в эти ячейки памяти что-то пишется или читается оттуда) я заменил в карте. Остальные не стал трогать - все они есть в файле warn.txt. Тут уже нужно руками смотреть где что, и анализировать.
Ещё все стринги принудительно перевёл в данные, так как осмысленного текста там всё равно нигде не было.
Полученный дизассемблер прилагаю для ознакомления.
есть хитрые моменты в коде
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 !!
это самомодификация ;jp ?, #XXXX
ну и например ; Data block at 9A27; там на самом деле исполняемый код
CityAceE
11.06.2020, 14:25
ну и например ; Data block at 9A27; там на самом деле исполняемый код
Возможно это и исполняемый код, но он в процессе полного прохождения игры ни разу не исполнялся. Ещё может быть, конечно, что я профайл снял с запущенной игры, а дизассемблировал ещё не запущенную (но раскодированную!). Возможно там где-то по коду после запуска ещё какая-нибудь перетасовка данных происходит, но я так навскидку не увидел. И из-за этого могло произойти расхождение профайла с кодом. На всякий случай прилагаю дизассемблер того снепшота, с которого снимал профайл. Однако там отличия минимальны - в основном в блоках данных. Но также видны и следы самомодификации кода!
в процессе полного прохождения игры ни разу не исполнялся.
похоже так и есть. я запустил rzx поставив прерывание (на весь этот код) - игра дошла до повтора уровней - оно не сработало
CityAceE
14.06.2020, 11:27
В общем, засел я конкретно за дизассемблер Batty. Вначале думал, что вот сейчас объединю кодовые блоки и выложу очередной вариант дизассемблера игры, потом ещё что-то, а потом ещё что-то и т.д. А в итоге продвинулся довольно серьёзно, просидев все выходные с утра до вечера. До анализа самого кода я пока ещё не добрался, но структура игры сейчас чётка видна. Графика и данные практически полностью разобраны. Для примера прикладываю все спрайты, которые есть в игре. Чтобы их получить, пришлось написать программу на Python. Это облегчило анализ таблиц графики. Есть ещё небольшой участок (его границы известны) с графикой, которая отвечает за отрисовку поля: обрамления и текстуры раунда.
В процессе разбора программы выяснилось, что в игре есть пустые спрайты. Судя по всему должна была быть анимация увеличения шарика после получения соответствующего бонуса, а также должен был быть ещё один какой-то бонус.
Встречается и мёртвый код - небольшие подпрограммы, которые нигде не вызываются.
В начале игры то, что я изначально принял за декодирование блока, оказалось инверсией спрайтов (плюс ещё какие-то манипуляции с данными). Почему автор сразу не положил графику в нужном виде, а непосредственно перед запуском инвертирует её, совсем непонятно.
Сейчас у меня есть листинг, который компилируется обратно в код на 100% совпадающий с исходным. Однако нельзя сказать, что дизассемблер полноценный, так как если изменить адрес компиляции, то игра перестаёт работать. Где-то есть таблицы и данные, которые пока не учтены.
После каждой правки исходного текста я компилирую программу и обязательно сравниваю с эталонным кодом, чтобы убедиться, что я ничего не сломал и что получаемый код полностью соответствует оригиналу. Как только я достигну момента, что больше не буду знать, что делать дальше, я обязательно выложу результат.
если изменить адрес компиляции, то игра перестаёт работать.
если я правильно понял то основной блок плотно окружён создаваемыми буферами/таблицами, куда его двигать-то ?
кроме того вполне возможны выборки со строгим учётом того что данные начинаются с #XX00
хотя как вариант можно попробовать сдвинуть вниз на 256байт, с учётом коррекции стека (сейчас он 24576) вроде должно заработать.
CityAceE
14.06.2020, 15:20
если я правильно понял то основной блок плотно окружён создаваемыми буферами/таблицами
Да, нет, буферы, конечно, есть, но не так уж там и плотно - свободного места там ещё полно.
кроме того вполне возможны выборки со строгим учётом того что данные начинаются с #XX00
Все такие места вынесены в буферы, на сколько я увидел.
В моём случае всё проще. Я по мере того, как вникаю в код, вижу, что не все переменные ещё учитываю. Пока слишком много мест где, например, в HL записывается число, а потом вызывается подпрограмма. А та в свою очередь вызывает другу, в которой данные читаются из таблицы адресуемой HL. Я когда совсем устану, выложу всё, чтобы кто-то ещё свежим взглядом посмотрел.
вот например странный момент
#C084 LD A,(#5CDD) ; 23773 ???
AND A
CALL NZ,
после старта эта переменная не инициализируется (теоретически там может быть что угодно)
NEO SPECTRUMAN
14.06.2020, 15:42
после старта эта переменная не инициализируется (теоретически там может быть что угодно)
например отладочный режим с god mode
только такую конструкцию я видел дето на геймбое
на спеке такое тоже встречается, но конкретно в нашем случае эта задумка испорчена (там после загрузки точно не ноль)
игра грузится 23296,23156 и потом блок пересылается выше
CityAceE
14.06.2020, 16:32
после старта эта переменная не инициализируется (теоретически там может быть что угодно)
Я там вот столько их нашёл:
; Переменные BASIC'а?
L5C78 EQU $5C78
L5CD8 EQU $5CD8
L5CD9 EQU $5CD9
L5CDB EQU $5CDB
L5CDC EQU $5CDC
L5CDD EQU $5CDD
Что это и для чего они, ещё предстоит разобраться. Очевидно это нужно для корректной работы IM1. Этот режим задаётся в игре в явном виде:
LC077:
LD IY,(LB793)
LD A,(L5C78)
LD (LB7E7),A
EI
IM 1
LD A,(L5CDD)
AND A
CALL NZ,L974A
LD IX,LC0B8
LD B,$05
LC077_0:
PUSH BC
LD A,(IX+$00)
AND A
CALL NZ,LC0AB
LD BC,$0007
ADD IX,BC
POP BC
DJNZ LC077_0
LD A,(L5C78)
LD B,A
LD A,(LB7E7)
CP B
DI
RET
Игра запускается и без проблем работает даже если загрузить кодовый блок в полностью чистую память.
Нашёл в игре вот такое. Откуда оно и для чего пока не знаю:
https://pic.maxiol.com/images2/1592140503.90460257.scr.png
Надпись появляется перед игрой, если в ячейку #B973 записать 0. Эта ячейка нигде не записывается. Возможно, это некий Easter Egg.
Ячейка 5CDD похожа на признак необходимости оперативно (не дожидаясь потери жизни) обновить цифры счета на экране. При обычной загрузке там не 0, но даже если будет 0, то проблем это на первый взгляд не вызывает.
то, что я изначально принял за декодирование блока, оказалось инверсией спрайтов (плюс ещё какие-то манипуляции с данными). Почему автор сразу не положил графику в нужном виде, а непосредственно перед запуском инвертирует её, совсем непонятно.
возможно данные рисовались на `старшем` компе (Amiga/AtariST), и формат подразумевал (пусть и примитивное) сжатие
...............
кажется нашёл автора https://twitter.com/mrmbee
попробуйте, может удастся его разговорить
послужной список у него приличный
https://www.mobygames.com/developer/sheet/view/developerId,51899/
5CD9 - количество активных шариков/мячиков
CityAceE
15.06.2020, 03:49
Нашёл в игре вот такое.
Оказалось, что это уже известная (https://www.the-tipshop.co.uk/cgi-bin/info.pl?wosid=0000472)информация.
Нил Киннок (https://ru.wikipedia.org/wiki/%D0%9A%D0%B8%D0%BD%D0%BD%D0%BE%D0%BA,_%D0%9D%D0%B8 %D0%BB) - это британский политик, который в год выхода Batty (1987) баллотировался (https://en.wikipedia.org/wiki/1987_United_Kingdom_general_election) на выборах.
Добился того, что скомпилированная по новому адресу игра запускается и работает в главном меню и таблице рекордов. Но стоит только запустить саму игру, как она сбрасывается. Копаем дальше :)
Встретил интересную конструкцию:
L9F37:
LD BC,$0016
LD B,C
DB $C3 ; JP L8EDA
L9F3C:
DEFW L8EDA
DEFW L9F63
DEFW LA27E
DEFW LA27E
DEFW LA55A
DEFW LA5A3
DEFW LA89A
DEFW LA8D2
DEFW LA902
DEFW LA9BC
DEFW LAA30
DEFW LA58D
; Routine at 9F54
L9F54:
LD HL,L9F3C
LD A,(IX+$00)
ADD A,A
CALL hl_add_a
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
JP (HL)
L9F37 - это подпрограмма, которая вызывается из других мест. Адрес L8EDA одновременно используется и в этой подпрограмме, и в таблице ниже. Для чего такая экономия непонятно... Конечно, возможно, А не может иметь нулевое значение, но тем не менее...
возможно, А не может иметь нулевое значение
На мой взгляд это более вероятный вариант. В (извините) эксолоне несколько раз встречаются таблицы, в которых 0й индекс никогда не бывает, поэтому адрес как бы начала такой таблицы приходится на завершение предыдущего кода или данных.
CityAceE
15.06.2020, 09:49
Мне тоже так кажется, но я пока перестраховался. Потом нужно будет вернуться в этому месту и изучить его. Хочется получить листинг, который можно будет максимально дербанить, переставляя части программы как душе угодно. И вдруг всё-таки адрес используется и там, и сям? Тогда, если перенести таблицу в другое место, всё сломается. Тем более подпрограмма выше таблицы вообще выглядит как-то глупо: зачем грузить регистровую пару, если можно было загрузить только один регистр?
Команды по адресам 8EBB и 8EC5 читают сначала 9F38, потом 9F39 (периодически срабатывает в меню). Возможно еще есть фрагменты, где пишут или читают 9F38-9F39
посмотри с #999C там из таблицы берутся абсолютные адреса и подставляются в четыре команды JP #XXXX,
потом ещё пара команд изменяется (через А) ; похоже на изменение процедуры печати (в зависимости от ширины спрайта)
CityAceE
15.06.2020, 17:36
посмотри с #999C там из таблицы берутся абсолютные адреса и подставляются в четыре команды JP #XXXX,
Не знаю как на счёт JP, но я там нашёл таблицу с указателями на инструкции POP DE в одной процедуре и на POP BC в другой. Дальше пока не раскручивал. Видимо, они потом меняются местами.
LD (#9A20),HL
LD (#9AB4),HL
LD (#9AB9),HL
LD (#99E3),HL
L9A1F: JP NZ,L9A1F
L9AB3: JP NC,L9AB3
L9AB8: JP L9AB8
L99E2: JP L99E2
DA00-F1FF - теневой буфер с построчной организацией, туда рисуют вышеупомянутые процедуры. Потом на экран перекидывают по LDI.
DA00-F1FF - теневой буфер с построчной организацией, туда рисуют вышеупомянутые процедуры. Потом на экран перекидывают по LDI.
я это выше сообщил
по (большим) объёмам занимаемой памяти получается
55040,768 ; аттрибуты экрана
55808,6144; пиксели экрана
61952,3584 ; строится таблица
...........
блин, оказывается SpecEmu проигрывает RZX в каком-то отдельном цикле - (отладчик и BreakPoint`ы не учитываются)
а я уж губы раскатал, думал расставлю прерывания и на примере полного прохождения пойму некоторые моменты
я это выше сообщил
Где (я не нашел)?
Где (я не нашел)?
пост #15
...............
процедура по адресу 38774 вычисляет адрес карты уровня. A=№(00-14)
27837,15*2 ; адреса карт размещения кирпичиков
27867,15*15*12 ; карты уровней
30567 код игры
почему адреса карт хранятся в таблице, а не вычисляются сложением (карты уровней фиксированной длины) мне непонятно
........
38221,199 ; текст меню
38420 XXXX; какая-то переменная
.........
я сначала не понял как игра `помечает` выбитые кирпичи
(для построения экрана после потери мячика используется тажа карта что и для начала уровня)
оказывается кроме цвета у кирпичика есть свойства (биты 4-7).
перед началом уровня они сбрасываются, а например при попадании в него устанавливаются.
- - - Добавлено - - -
Судя по всему должна была быть анимация увеличения шарика после получения соответствующего бонуса
так она вроде есть. бонус smash - большой мяч который пробивает всё
goodboy,
ZX Spectrum, Amstrad CPC, Commodore 64
нада смотреть на какой машине было сделано раньше.
я завтра уеду на пару недель из города - помочь с разбором не смогу
- - - Добавлено - - -
нада смотреть на какой машине было сделано раньше.
кстати, да - здравая мысль. на CPC графика кирпичиками
CityAceE
16.06.2020, 02:43
так она вроде есть. бонус smash - большой мяч который пробивает всё
Там есть вот такое место:
; Data block at 77BE
anim_ball_resize:
DEFW spr_ball_normal
DEFW spr_empty_1
DEFW spr_empty_2
DEFW spr_empty_3
DEFW spr_empty_4
DEFW spr_empty_5
DEFW spr_empty_6
DEFW spr_empty_7
DEFW spr_big_ball
И сравни, например, с анимацией птицы:
; Анимация птицы
anim_bird:
DEFW spr_bird_1
DEFW spr_bird_2
DEFW spr_bird_3
DEFW spr_bird_4
DEFW spr_bird_3
DEFW spr_bird_2
DEFW spr_bird_1
DEFW spr_bird_5
DEFW spr_bird_1
DEFW spr_bird_2
DEFW spr_bird_3
я завтра уеду на пару недель из города - помочь с разбором не смогу
Я думаю, что мы сейчас делаем двойную работу. Многое из того, что вы написали с ivagor, мне уже было известно из кода. Давайте я закончу с дизассемблированием, выложу то, что получилось и мы потом вместе приступим к анализу кода. Это будет гораздо удобнее и быстрее. Я сейчас по ходу разбора переименовываю некоторые безликие цифровые метки, присваивая им осмысленные названия. И уже дальше, опираясь на эти названия, из контекста становится примерно понятно что значат соседние процедуры. Например:
; Used by the routines at L927F and LB9E8.
L93F8:
LD HL,$0000
LD (L938A),HL
CALL draw_frame
LD HL,$BF00 ; Координаты окна (весь экран нижняя строка)
LD DE,win_full_screen_purple_ink
CALL fill_attrib
LD HL,$B708 ; Координаты окна
LD DE,win_1e_16_white_ink
CALL fill_attrib
LD HL,$4718 ; Адрес на экране
LD DE,spr_press_a
CALL print_sprite ; Press A
LD HL,$47C8 ; Адрес на экране
LD DE,spr_press_b
CALL print_sprite ; Press B
LD HL,hi_score_1up
LD DE,txt_score_1up+4
CALL copy_score
LD HL,hi_score_2up
LD DE,txt_score_2up+4
CALL copy_score
LD DE,txt_main_menu
LD B,$0F ; Количество строк в сообщении
CALL print_message
LD HL,(coord_ctrl_1up)
LD DE,spr_pointer_1
CALL print_sprite
LD HL,(coord_ctrl_2up)
LD DE,spr_pointer_2
CALL print_sprite
38420 XXXX; какая-то переменная
; Data block at 9614
L9614:
DEFW txt_1_player
DEFW txt_controls
CityAceE
16.06.2020, 09:36
Ну что ж, теперь все компилируется и играет по адресу отличному от стандартного. Пробовал компилировать на 100 байт больше и на 100 байт меньше. Если на 100 байт меньше, то в таблице когда ввожу имя портится верхняя часть экрана. Скорее всего какой-то нижний буфер перехлестнул кодом. Потому что такого эффекта нет, если скомпилировать на +100 байт от стандартного адреса. Глубоко не тестировал - может там ещё что есть. Но сейчас анализировать код уже стало гораздо проще, так как я могу что-то менять, закомментировать какие-то участки кода, добавить своё и т.д.
Нашёл в игре неиспользуемый цветной спрайт. Кусок левой боковины. Мне показалось, что это дверь, как а Арканойде, для перехода на следующий раунд. Скорее всего это должно было выглядеть вот так:
https://pic.maxiol.com/thumbs2/1592289186.90460257.battydoor.png (https://pic.maxiol.com/?v=1592289186.90460257.battydoor.png&dp=2)
Причём сейчас я эту "дверь" поместил не в графическом редакторе, а путём добавления нескольких строчек кода к исходнику :) Отладка в действии!
Bedazzle
16.06.2020, 14:04
Пробовал компилировать на 100 байт больше и на 100 байт меньше. Если на 100 байт меньше
Лучше покрыть минимум 257 байт, тогда есть гарантия, что оба байта адресов поменялись.
CityAceE
16.06.2020, 14:33
Лучше покрыть минимум 257 байт, тогда есть гарантия, что оба байта адресов поменялись.
Да, правильная мысль! Сдвинул на 257 байт и эффект проявился в обоих сторонах. Не думаю, что это серьёзная проблема, равно или поздно найду в чём проблема, потому что сейчас в игре практически не осталось белых пятен :)
По мере разбора кода наталкиваюсь на интересные вещи. Например, игровое поле окружено бордюром. И бордюр шириной не 8 пикселей, а 9! Вначале рисуются спрайты толщиной 8 пикселей, а потом ещё отдельно по внутреннему краю дорисовывается несплошная линия толщиной в пиксель. Вот автор заморочился, чтобы всё было идеально!
Нашёл причину порчи таблицы! Почему-то я этот абсолютный адрес в тексте программы пропустил, хотя смотрел её вдоль и поперёк многократно.
Прикладываю версию Batty, скомпилированную по другом адресу (+257 байт от стандартного). Кому не лень потестируйте, пожалуйста, чтобы убедиться, что ничего не сломалось.
CityAceE
17.06.2020, 08:45
Нашёл в игре очень интересный звук, который автор в итоге так и не использовал нигде.
Сделал специальный снепшот, чтобы можно было его услышать. Для воспроизведения этого таинственного звука, в главном меню нужно нажать кнопку В - выбор управления для второго игрока. И вместо стандартного звука (как на кнопке А) вы услышите нечто другое :)
Barmaley_m
28.06.2020, 16:47
Ничего себе проект!!! Очень интересно. А какая конечная цель? Портирование на другой комп?
CityAceE
28.06.2020, 17:08
А какая конечная цель? Портирование на другой комп?
Да, конечная цель - портирование на ПК Специалист.
CityAceE
02.07.2020, 10:30
На всякий случай сообщаю, что дизассемблирование не бросил, а продолжаю копаться в программе. То, чтобы было сходу понятно давно уже разобрал. Сейчас работа замедлилась, потому что теперь в силу неочевидности и моего малого опыта работы с чужим кодом, приходится подолгу сидеть над каждой новой процедурой и переменной. Но дело потихоньку движется!
Ну, и так, для затравки могу немного рассказать про какие-то части игры.
То, что я в самом начале принял за декодирование и распаковку кода на самом деле оказалось подготовкой графики. Во-первых, в конце памяти строится таблица сдвигов. К этой таблице обращается процедура печати спрайтов для их вывода со сдвигом по горизонтали. Это относится к перемещению врагов, искр от взорвавшейся каретки, выпадающей цифры 400 и т.д. После этого идёт создание некоторых готовых спрайтов со сдвигом. В игре, сразу после её загрузки, есть пустые спрайты и эта процедура заполняет эти пустые спрайты сдвинутыми. Прежде всего это касается шарика - к стандартному спрайту добавляется ещё 7 сдвинутых спрайтов. И также ещё по одному сдвинутому спрайту добавляется к спрайтам каретки: стандартной, расширенной и к каретке с пулемётом. То есть подготавливаются самые используемые спрайты, а остальные сдвигаются по таблице в процессе их вывода на экран. И на последнем этапе подготовки графики часть спрайтов инвертируется. После этого управление передаётся игре по адресу #B9B1.
Странно автор подошёл к формированию уровней. Все свойства уровней раскиданы по коду, а некоторые свойства выбираются программно.
1. Кирпичи: их расположение и прочность практически единственная вещь, которую можно редактировать. Собственно, это и было обнаружено хакерами, которые выпускали Batty 2, Batty 3 и т.д. При этом в этих "продолжениях" всё остальное оставалось от оригинальной игры.
2. Магниты: их наличие на уровне, количество и расположение также можно редактировать. Однако без доступа к коду сделать это не очень просто и к тому же есть ограничения. Дело в том, что под описание магнитов на уровнях отведено разное место. В описании вначале идёт байт, указывающий сколько магнитов есть на уровне, и далее, если в первом байте не ноль, по два байта координат каждого магнита. Таким образом для описания магнитов первого уровня используется только один один байт (#00), а для второго уже три (#01, #XX, #YY). На уровнях 9, 13 и 14 используется по 4 магнита и, соответственно описание для каждого из них занимает по 9 байт. И так как описание каждого уровня имеет разный размер, в игре есть таблица расположения этих описаний. Как видите, не так-то просто это отредактировать по живому коду, особенно если захочется поместить магнитов больше, чем есть в игре..
; Data block at 8E06
; Таблица магнитов для уровней
magnets:
DEFW magnet_level_03 ; Данные для первого уровня берутся из 3-го
DEFW magnet_level_02
DEFW magnet_level_03
DEFW magnet_level_04
DEFW magnet_level_05
DEFW magnet_level_06
DEFW magnet_level_07
DEFW magnet_level_08
DEFW magnet_level_09
DEFW magnet_level_10
DEFW magnet_level_11
DEFW magnet_level_12
DEFW magnet_level_13
DEFW magnet_level_14
DEFW magnet_level_15
DEFW magnet_level_15 ; Для чего-то продублирован 15-й уровень
; Data block at 8E26
; Первый байт - количество магнитов на уровне, далее по два байта их координаты
magnet_level_15:
DEFB $02,$4C,$82,$9C,$82
magnet_level_14:
DEFB $04,$8C,$24,$C4,$24,$8C,$64,$C4,$64
magnet_level_13:
DEFB $04,$10,$20,$D8,$20,$18,$6C,$D0,$6C
magnet_level_12:
DEFB $03,$74,$08,$20,$44,$C8,$44
magnet_level_11:
DEFB $02,$5C,$84,$8C,$84
magnet_level_10:
DEFB $01,$74,$44
magnet_level_09:
DEFB $04,$40,$3C,$A8,$3C,$54,$6C,$94,$6C
magnet_level_08:
DEFB $03,$74,$18,$4C,$74,$9C,$74
magnet_level_07:
DEFB $02,$30,$5C,$D8,$5C
magnet_level_06:
DEFB $03,$74,$10,$48,$73,$A0,$73
magnet_level_05:
DEFB $00
magnet_level_04:
DEFB $01,$74,$7C
magnet_level_03:
DEFB $00
magnet_level_02:
DEFB $01,$74,$2C
3. Текстуры: всего есть 4 вида текстур и они последовательно чередуются по кругу от уровня к уровню. Таким образом назначить какую-то определённую текстуру уровню не представляется возможным. Причём, что интересно, текстура первого уровня находится в одном месте программы, а текстуры трёх других совсем в другом месте.
; Routine at BE8B
;
; Used by the routine at LB9E8.
; Рисуем полный игровой экран со всеми элементами в буфере
game_screen_draw_to_buffer:
LD HL,spr_level_textures
LD A,(current_level_number_1up)
AND $03
ADD A,A
CALL hl_add_a
LD E,(HL)
INC HL
LD D,(HL)
LD (current_texture+1),DE ; Помещаем указатель на текстуру уровня
4. Враги: всего есть два вида врагов и они, также как и текстуры, просто чередуются от уровня к уровню.
CityAceE
25.07.2020, 18:26
Всё ещё не бросил разбор Batty, как может показаться из-за отсутствия активности в этой теме. Но это процесс небыстрый, на который я сейчас трачу львиную долю своего свободного времени. Всё, чтобы было очевидного я давно разобрал. Теперь разбираю то, во что необходимо вникать подольше. Бывает, что за весь вечер после работы удаётся разобрать только одну небольшую процедуру. Но с каждым разом белых пятен становится всё меньше и меньше. Листинг приобретает читабельный вид. Например:
CALL rnd_update
LD HL,handling_object
CALL call_hl_for_all_obj
CALL fill_briks_data
LD HL,ix_buf_addr_calc
CALL call_hl_for_all_obj
CALL obj_to_buff_transfer
LD HL,print_spr_with_mask_buff
LD A,(object_ball_2)
RLA
CALL NC,call_hl_for_all_obj
CALL play_sounds_queue
LD HL,print_spr_from_buf_to_scr
CALL call_hl_for_all_obj
LD A,(wins_counter)
AND A
CALL NZ,wins_recovery
CALL L987A_0
CALL pause_game
LD A,(object_ball_2)
AND A
JP NZ,LBC10_5
LD B,$03
CALL pause_long
LD A,(lives_1up)
DEC A ; Отнимаем жизнь
LD (lives_1up),A
JR Z,LBC10_6
LD A,(game_mode)
DEC A
CALL Z,current_level_2up_copier
JP LB9E8_1
Как в судоку, в японских кроссвордах или других подобных головоломках, каждая разобранная процедура, переменная или таблица, помогают понять суть происходящего там, где ещё вчера было ничего не понятно.
Вообще ощущаю себя так, как будто я тайком проник на огромный работающий завод, где все работники ушли в отпуск. И я втихаря могу заходить во все кабинеты и помещения, дёргать и крутить все ручки на станках, и наблюдать за происходящим.
Ну и на закуску. Batty могла бы выглядеть примерно так, как на скринштах. В игре постоянно обнаруживаю какие-то ошмётки от экспериментов автора. И это один из них, который автор, видимо, просто забыл удалить из игры.
https://pic.maxiol.com/images2/1595689395.1531823518.screen1.png https://pic.maxiol.com/images2/1595689419.1531823518.screen2.png
CityAceE
26.07.2020, 14:47
Я, безусловно, знал, что бонусы в игре выпадают неравномерно. Но оказалось, что автор сделал ещё и разную вероятность для разных раундов.
Вероятность выпадения бонусов на первых 6-ти уровнях:
Увеличение биты: 3
Пулемёт: 2
Размножение шариков: 2
Липучка: 2
Slow: 2
Дополнительная жизнь: 1
Ракета: 1
Smash: 1
5000 очков: 1
Kill Aliens: 1
А вот вероятность выпадения бонусов на остальных уровнях:
Увеличение биты: 4
Пулемёт: 2
Размножение шариков: 3
Липучка: 3
Slow: 0
Дополнительная жизнь: 0
Ракета: 1
Smash: 1
5000 очков: 1
Kill Aliens: 1
Вообще в игре помимо этих двух таблиц вероятностей выпадения призов, есть ещё три, но, как и многое другое, автор решил их не использовать.
При этом на всех уровнях вероятность выпадения ракеты принудительно занижается ещё больше. А если на каком-то раунде была поймана дополнительная жизнь, то больше на этом раунде же можно не ждать такого же приза - его совершенно точно не будет :)
И ещё, врагов на раунде не стоит ждать, если количество невыбитых кирпичей 44 и больше. А также враги вообще не пояалются на 5-м уровне.
Вообще, автор конкретно заморочился с геймдизайном и балансом игры. Это отчётливо видно по коду. Всего 15 раундов, но какая реиграбельность у игры! Видно, что он продумывал каждый раунд и подкручивал баланс, а не просто нарисовал сотню разных раундов и в таком виде выкатил игру. На самом деле памяти хватило бы не на один десяток раундов, но автор ограничился лишь 15-ю...
Barmaley_m
26.07.2020, 23:40
Batty - чрезвычайно трудная игра. Первые три уровня ещё ничего, с ракетой можно на халяву их посмотреть, а вот дальше идёт тяжело. Много проблем доставляет повышение скорости шарика через время или когда враги начинают наглеть и летать низко. После двух повышений шанс выжить практически нулевой. Наверное, единицы прошли всю игру до конца без "бессмертия".
Вот интересно - влияет ли на повышение скорости шарика столкновение его с врагами?
CityAceE
27.07.2020, 09:34
Наверное, единицы прошли всю игру до конца без "бессмертия".
Мы с другом проходили ;) И не раз! И в одиночной игре, и совместно. При этом своё мастерство оттачивали на игровом автомате, платя по 15 коп. за каждую попытку. Тогда мы даже не догадывались, что это игра с домашнего компьютера - думали, что это просто игровой автомат такой специальный. Денег тогда на Batty было потрачено немерено! Когда мы играли в неё, вокруг нас собиралась толпа зрителей. Вот с тех самых пор для меня Batty является особенной игрой. Именно поэтому я и занялся её ковырянием. Причем это уже который мой подход, но все предыдущие закончились неудачей.
Вот интересно - влияет ли на повышение скорости шарика столкновение его с врагами?
Я такой проверки не встречал. Вот конкретно процедуру сбивания врагов шариком я ещё детально не разбирал, но совершенно точно сбивание врага кареткой на скорость никак не влияет.
А вот POKE, чтобы скорость не увеличивалась: 0xA48C - 0
Скорость шарика можно замедлить ещё на один шаг и тогда она будет минимальной и такой же как у врагов, но играть тогда станет вообще неинтересно. Вообще скорость шарика регулируется переменной со значениями от 2 до 6. В игре стоит ограничение, чтобы скорость не поднималась выше 6-ти. А когда ловим приз Slow, то скорость опускается до 2-х, как и при старте. И ещё, если скорость шарика 2, то приз Slow не выпадет - всё автором продумано :)
Bedazzle
27.07.2020, 15:41
Вот с тех самых пор для меня Batty является особенной игрой. Именно поэтому я и занялся её ковырянием. Причем это уже который мой подход, но все предыдущие закончились неудачей.
Дорогу осилит идущий.
А вот POKE, чтобы скорость не увеличивалась: 0xA48C - 0
Лучше указывать что на что меняется, тогда в случае если есть разные версии игрушки, сразу это дело можно опознать.
Нашёл в игре очень интересный звук, который автор в итоге так и не использовал нигде.
я уже `несколько` раз рассказывал что Batty `выросла` из игры WipeOut
https://zx-pk.ru/threads/11127-rannyaya-versiya-batty.html
CityAceE
27.07.2020, 17:32
я уже `несколько` раз рассказывал что Batty `выросла` из игры WipeOut
Только сегодня посмотрел видеопрохождение WipeOut, чтобы сравнить с Batty. Конечно, общие корни видны во всём. Тот самый таинственный звук, найденный в Batty, звучит при старте WipeOut. Также, например, в WipeOut активная надпись в меню мерцает, переливаясь цветами, а в Batty она просто мигает. Но на самом деле в Batty процедура тоже перебирает цвета для перелива из таблице, но в таблице жёстко задан в первой половине белый цвет, а по второй - чёрный. Ну и по другим мелочам видно, что большая часть кода у этих игр одинакова.
CityAceE
19.09.2020, 19:12
Кстати, есть еще версия для ориона с z80 card II, вывод графики там уже можно сказать почти переделан под специалист. ivagor Не смог найти откуда скачать этот вариант. Не мог бы ты поделиться? Мне удалось только выяснить, что игру адаптировал Сергей Коровкин (Crystal Grafic). Но самой игры нет нигде. Есть только вот такое:
https://www.youtube.com/watch?v=HvzVdQMtcDI
Не смог найти откуда скачать этот вариант.
???
ссылка там практически в описании
http://zvzd3d.ru/Orion128/Orion128Main.html
CityAceE
19.09.2020, 19:24
???
Наверное, я неправильно выразился. Я ищу Batty, адаптированную со Спектрума - её нет нигде. Везде попадается только тот вариант, видео которого я привёл.
Временно выложил тут
Большое спасибо!
Непонятно для чего автору Орионовской конверсии понадобилось вносить "улучшения" в раскраску, если, как я понимаю, была возможность перенести игру 1:1.
https://pic.maxiol.com/images2/1600533298.1531953296.battyorion0.png https://pic.maxiol.com/images2/1600533351.1531953296.battyorion1.png
CityAceE
29.12.2020, 09:51
Я собирался всё причесать, подправить, окультурить и т.д., но понял, что вряд ли буду этим заниматься в обозримом будущем (если вообще буду), и решил выложить то, что имею на текущий момент:
https://github.com/CityAceE/Batty
Просто запускаете батник и на выходе получите sna с игрой - в комплекте есть всё необходимое.
Игра разобрана полностью. Любые части кода можно переносить куда угодно, менять переменные, компилировать с любого доступного адреса и т.д. - в итоге всё скомпилируется и будет работать, если внесённые изменения адекватны, то есть, например, буферы не налазят друг на друга, или стек не оказывается в области кода. Проверено целенаправленно и многократно, в том числе и адаптацией данной игры на ПК Специалист (https://zx-pk.ru/threads/32119-batty-dlya-pk-spetsialist.html).
Когда я разбирал игру, я комментировал многие строчки кода и переименовывал процедуры, чтобы в дальнейшем можно было понять, что они делают. И чем больше становилось таких описанных и переименованных процедур, тем проще потом становилось разбираться с остальным кодом. Однако на ранних этапах анализа я мог ошибочно расценить назначение тех или иных вещей. На поздних этапах я почти всё это поправил, но, конечно, что-то да осталось. Так что имейте ввиду, что где-то там могут встретиться какие-то ошибочные описания. Но это не значит, что они там есть!
Буду благодарен, если кто-то разберётся с оставшимися неописанными переменными и процедурами, поправит мои ошибки и сделает pull request.
NEO SPECTRUMAN
29.12.2020, 10:21
а 8080 версия? :)
CityAceE
29.12.2020, 10:41
а 8080 версия?
Я такую в итоге так и не сделал.
NEO SPECTRUMAN
29.12.2020, 10:44
а там много кода используещего стек не по назначению?
пробежался глазами
увидел только одну процедуру
после С300 известно точное расположении всех буферов?
вижу одна дырка 3К вторая 1К
CityAceE
29.12.2020, 10:48
а там много кода используещего стек не по назначению?
Их там почти нет.
после С300 известно точное расположении всех буферов?
Там всё в самом начале в комментариях расписано.
NEO SPECTRUMAN
29.12.2020, 10:51
мдо там только 425 JR
плачевная ситуация...
CityAceE
29.12.2020, 11:01
мдо там только 425 JR
плачевная ситуация...
Если вдруг у тебя возникла мысль перевести игру на i8080, то давай я тебе лучше дам исходник для Специалиста. От этого перевода хотя бы прок будет. Но заранее предупреждаю, что в обычной памяти Специалиста места не осталось совсем - всё занято кодом и буферами. Если только использовать место по бокам экрана - а это целых 4 Кб (2+2)!
NEO SPECTRUMAN
29.12.2020, 11:16
Если вдруг у тебя возникла мысль перевести игру на i8080, то давай я тебе лучше дам исходник для Специалиста.
я думал быстренько сделать порт для zx8080
чтоб хоть что нибудь было
тк ПЗУ-шка задерживается (пойдет адаптироватьсо по второму кругу : )
но я смотрю тут быстренько не получитсо...
еще и рисуется с исползованием стека
я думал пройтись автозаменой и наделать макросов
чтоб особо не думать :)
а в условиях специалиста так вообще
вангую что для него это возможно только если избавиться от экранного буфера и рисовать напрямую в экран со всем миганием...
- - - Добавлено - - -
Если только использовать место по бокам экрана - а это целых 4 Кб (2+2)!
только оно блоками по 16 байт
в принципе с ADP это не проблема
оно само туда положит если будет вмещатся
но нужно иметь такие блоки (тем более в больших количествах)
или же нарезать малоиспользуемый код на 16 байтные блокии при помощи jp
но такой код станет еще на 19% жирнее и медленее
CityAceE
29.12.2020, 11:26
только оно блоками по 16 байт
Нет же. Два непрерывных куска по 2 Кб.
Границы экрана Спектрума на экране Специалиста:
981F B71F
=============
9720|9820 ... B720|B820
|.... ....|
98DF|98DF ... B7DF|B8DF
=============
98E0 B7E0
Экранная область Специалиста с #9000 по #BFFF
NEO SPECTRUMAN
29.12.2020, 11:31
ахда у него же экран повернут
и все 256 байт "страницы" идут в высоту
- - - Добавлено - - -
Нет же.
тогда там еще 32*64 сверху и снизу :)
и достаточно крупными блоками для возможности их использовать
MEGAMONSTER
29.12.2020, 11:37
CityAceE, может немного шлифанешь игру? В том смысле, чтоб из главного меню можно выбрать макс. скорость шарика к-во жизней, типа как в кракаут?
CityAceE
29.12.2020, 11:46
может немного шлифанешь игру?
Исходники выложены, любой желающий сможет это сделать. Но я авторский код "улучшать" не хочу.
Единственное, я бы только баг поправил, когда ворона иногда портит фон. Но я так и не смог понять из-за чего это происходит. Как это получается я знаю, а за-за чего - нет.
NEO SPECTRUMAN
29.12.2020, 12:04
Любые части кода можно переносить куда угодно, менять переменные, компилировать с любого доступного адреса
при этом после замены всех jr на jp работоспособность помножилась на 0 :)
так что я наверно в этом участвовать не буду
CityAceE
29.12.2020, 12:16
при этом после замены всех jr на jp работоспособность помножилась на 0
Скорее всего просто код вылез за допустимые пределы. Там же сразу после кода всякие нужные буферы идут, которые будут код затирать, если код попадёт в эту область.
---
Нет. Это процедура print_message валит игру. Если вместо неё поставить заглушку (ret), то игра, как минимум, запустится.
---
Ах, да... Я же совсем забыл! В Batty постоянно используется самомодификация кода. В том числе и переходы по JR вычисляются и подставляются. Просто так слепо JR на JP заменить не удастся.
Круто. Весь топик от начала до конца как детектив прочитал! :)
Уважаемые как удлинить доску и/или замедлить полет шара/мяча.
CityAceE
29.12.2022, 10:47
замедлить полет шара/мяча.
Я приводил POKE в этой теме.
https://www.the-tipshop.co.uk/cgi-bin/info.pl?name=Batty&publisher=Hit%2dPak&alias_string=
Кстати, хотел бы заиметь эффект блика на кирпичах в начале каждого раунда. Есть процедурка? Вернее - по каким адресам/меткам искать?
; Routine at AD8F
;
; Used by the routine at all_metal_briks_animation_snd.
Вроде оно?
CityAceE
29.12.2022, 13:30
Вроде оно?
Я уже, к сожалению, не смогу подсказать, потому что ничего не помню. Но, думаю, что по комментариям и названием процедур эту подпрограмму реально отыскать. Ещё для облегчения поиска можно с исходниками поэкспериментировать - ставить точки останова, закомментировать некоторые процедуры и т.д.
+ ещё один дизасм https://github.com/pobtastic/batty
+ ещё один дизасм https://github.com/pobtastic/batty
какая то сырая дичь.
оу, нифига вы что тут мутите
Наверняка существуют какие-то более удобные инструменты под подобную задачу, но мне они неизвестны.
Есть проект Ghidra от АНБ, там вроде поддерживается Z80. Он анализирует исполнение кода и позволяет отдекомпилить его в условный си. Для перекомпиляции не пойдет - много ошибок, но чтобы понять как работает код достаточно. Правда проект громоздкий, чтото около полутора гига прийдется скачать и жабу установить.
А в чем суть декомпиляции, что хотите с этим сделать?
Кстати, еще когда в школе учился, пририсовал ради прикола в batty значёк МС на скрине в Art Studio. Во всех релизах доступных в инете есть этот значёк, правда я не уверен что это именно я его пририсовал, а не в оригинале так было... Т.к. судя по описанию автор скрина Mark Crane. Но хорошо помню как рисовал его именно в том месте... :D Правда сам уже толком не помню как именно он выглядел... Теперь смотрю на скрин и мучает меня вопрос - не моя ли это проделка :D Никто случаем не встречал версию со скрином без этого значка?
Bedazzle
04.11.2024, 11:01
Правда проект громоздкий, чтото около полутора гига прийдется скачать и жабу установить.
Крайняя версия - 400мб зип архив + 200 мб опенждк.
логотип M.C. - авторский.
но это псевдоним. Mark Crane = Mark Betteridge
в более ранней версии (известной под названием WipeOut) KB.RAM = Mark B
https://nintendo.fandom.com/wiki/Mark_Betteridge
https://www.pressreader.com/uk/crash-9YY2/20210625/282059100101812?srsltid=AfmBOorYYYEauk6rQELdWyZfQx eZHJ6g8GbucRJvCulQZFiytDXIPvuY
CityAceE
05.11.2024, 09:01
А в чем суть декомпиляции, что хотите с этим сделать?
Да всё уже, по сути, сделано: получен полный дизассемблер игры, код разобран, стали известны все нюансы игры, ну и, как итог, игра перенесена на платформу Специалист + Z80. Перенести код за i8080 терпения уже на хватило, да и не только у меня одного.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot