Ottifants portable
Пока мы исследуем разные приставки да копаемся в их внутренностях, обсуждаем их особенности да способы реализации железа, его использования… Возможно стоит посмотреть — как провернуть дельце.
Дельце, которое позволит нам использовать их код для нашего интереса и нашего удовольствия.
Итак, речь пойдёт снова о приставке :) О Сеге Мастер Систем.
SMS интересна.
Не самая крутая приставка, но – довольно крупная компания девелоперов с очень насыщенными проектами. Много данных, много уровней, разнообразные игры, пусть и платформеры в большинстве.
Для меня СМС оказалась открытием, так как качество игр впечатляет обьёмом и проработкой геймплея.
Не так давно, на волне Соника, я занялся портированием следующей игры. Задача была седующая – беру произвольную игру, переношу на ZX Enhanced, под. TS Config.
Итак, в данном случае задача — работать чисто с бинарём. Без любой другой помощи.
Итак, бинарь на диске. Дизайн видеочипа – известен по докам. Рассматриваю, оказывается что детали по спеке, как ни странно — отличаются, но основные позиции по железу – те же.
Выбирать игру для порта оказалось сложно. Много всего, много жанров, но при этом – не такая уж у приставки и обширная база игр, всего-то около 300 примерно. Со спектрумом не сравнить :)
Смотрели игры мы всем чатом, я перебирал то что мне было интересно, а ребята подбрасывали свои варианты. Некоторые игры не проходили первоначальный отбор из-за слабой графики, слабого геймплея; некоторые – например, Фантастик Диззи – я отбраковал из-за дичайшего обилия работы в видеопроцом. Мне до сих пор кажется сложным: отрабатывать и тестировать в 4 раза больше обращений к vdp (видеопроцессору), чем у соника. Для сравнения: ~300 обращений (out (c),a) у Соник;
Диззи же ~1200. Код Мастерс, блин.
Отложим.
Выбор пал на Оттифанс. Это было предложение от ts labs. Смотрю – неплохо! Оказалось – отличная игра, со своим характером по управлению, но – обширная, навёрнутая в части графики, в обьёме уровней, с кучей боссов, и – даже с выбором языков! Пусть в игре они и не используются, только в меню :)
Исследование
Разбор движка приносит интересные вещи. ROM файл содержит не только игру, он содержит и минимальный отладочный движок. Начиная с области #0066 есть отдельная, не используемая в игре процедура, которая использует особенности явно не стандартного маппера памяти картриджа. Похоже – оставлена отладочная процедура, которая вызывается по определённому событию, которое может произойти только на отладочной приставке.Происходит переключение банков, которые не могут быть на картридже – похоже, отрабатывают старшие биты порта маппера; сохраняются абсолютно все значения регистров, что-то перемещается в RAM приставки и отрабатывает.
Что именно перемещается? Увы, эта часть картриджа отсутствует :)
Отладочные дела, ок.
Хорошо, но — что делать на этот раз? Исходников — нет, данных нет, бинарь есть. :)
Будем патчить! (Привет Деня Грачёв!) ;)
И будем патчить оригинальный бинарь.
Есть офигенный Ville, есть его компилер z80 для такого рода систем, который позволяет «подложить» бинарь под компиляцию, и оверврайтить его сверху своим кодом. Кстати, других таких вещей для оверврайта бинаря своим кодом я пока у нас не видел. Ville, ты – реально крут. Добавлю, что его wladx – стандарт для ребят, пишущих под SMS, SNES и т.д., читайте его доки.
Отличная вещь, в общем. Привыкаешь быстро, работает как должно :) И – по происшествию десятка лет – он не останавливается в разработке компилятора. Я, честно – впечатлён.
Итак, подкладываем бинарь с помощью директивы
.background "_spg/Ottifants.sms" ;Ottifants.sms
Определяем где у нас чо будет:
.DEF Tile_page $3f
.DEF decode_pix $e404
.DEF tileram_adr $e408
.DEF tilemap_adr $e40a ;tilemap ram adress
.DEF update_tilemem $e416
.DEF view_tilemem $e41c
… и прочее – тут важна для меня связка кернеля, и определение паг памяти.
Сейчас разработка ведётся с помощью wladx & sjasmplus, пока ещё.
Оказывается, удобнее таки использовать один компилятор, основной. Да, тот, не привычный :) у которого $ вместо #, вместо equ — .DEF, прочее. Но, по сути, это – не так важно.
Организовываем две области.
Одна – это патч оригинального бинаря, вторая – это процедуры для нашей системы.
Одна – это вызовы, вторая – обработчики.
Опять же – располагаемся в верхней памяти, с #e000. Здесь много памяти, 8кб — это отлично.
Устанавливаю стандартный набор паг в окнах для работы игры – это, обычно, 0ая, 1ая пага для окон 0 и 1 – здесь реально весь код, и эти паги они почти не меняют в играх. Стандарт своего рода.
Провожу поиск по обращению к мапперу памяти – ld ($ffff), a, и заменяю их 3 байта смены банка памяти через обращение к ячейке — на смену банка через колл на процедуру:
pokeys ld hl,0
pokeys1 ld a,#32
cp (hl)
jr nz,1f
inc hl
ld a,#ff
cp (hl)
jr nz,1f
inc hl
ld a,#ff
cp (hl)
jr nz,1f
dec hl
dec hl
ld (hl),#cd
inc hl
ld (hl),low set_page2
inc hl
ld (hl),high set_page2
1 inc hl
ld a,h
cp #51
jr nz,pokeys1
ret
set_page2 push bc
ld bc,PAGE2
out (c),a
ld (#FFFF), a
pop bc
ret
Вы можете отметить, что в цикле патча обращений к мапперу я ограничиваюсь адресом #5100. Это – проверено эмпирически, и работает сугубо только с этой игрой. Все замены я перемотрел, но и вероятность замены ТРЁХ байтов довольно низка. Но – перестраховываемся, это – код, который отрабатывает процессор. Шуток – нет.
Грузим образ в spg, добавляем свой загрузочный инит – игруха должна лежать по своим банкам, и игруха должна быть пропатчена по обращению к памяти. Всё нормально?
Давай смотреть.
Итак, что сейчас имеем. Оригинальный код должен обращаться к своей памяти, соответственно – если нигде не накосячил – оно не должно вешаться.
Ок, спг собрался, ставлю точку запуска на старт с инитом и патчем.
Чёрный экран.
Изредка мигают цветные полосы на экране.
Смотришь, наблюдаешь. Мигают.
ОНО НЕ ВЕШАЕТСЯ.
Отлично! Шаг сделан. Игра работает на самом базовом уровне.
Да, она не видит нажатия кнопок;
да, она не отображает в наш экран;
да – она не звучит.
Дык – это нормально. Это отлично.
Игра – работает.
Я вижу цветные полоски на бордере при обращении к порту видеочипа. Что-то – происходит.
Оно – живое на заставке.
ОТЛИЧНО.
Работаем дальше ©
У Emulicious – отличный дебаггер. Да, со своими проблемами. Не умеет сохранять недекомпиленное, не всегда понимает что нужно декомпилить а что нет, не проставляет меток в новых декомпиленных областях… Но – очень впечатляющ.
Отображение видеопамяти вплоть до моментов записи в чип, при их дурацком способе побитного сохранения цвета — 4 бита на 4 байта в одну точку, и каждый бит – составляющая; отображение тайловой памяти, спрайтовой памяти. Реально, радует. Удобный. Спасибо! Это помогает при отладке НЕВЕРОЯТНО.
Такое вот окошко для дебага:
<em>Итак, Деня, начинаем ПАТЧИТЬ :)
Тут уж всё просто.Вы понимаете насколько.
Для начала – всё что сложно обернуть в вызов процедуры, и что постоянно используется – лучше использовать rst. Ребят, как часто вы используете rst #xx?
Я – никогда.
Но – это находка.
Один байт. И – вызов. Вместо трёх, на которые НЕТ памяти. Народ юзает Out (#be),a, как пример. Два байта.
Жаль, не так много rst. И, опять-же — вызовы часто заняты!
Отладка
…
Отладка
…
Отладка
Хожу дебаггером, смотрю — как всё работает. Где вызовы к видеопроцу. Как отрабатывают прерывания, что вызывается.
Потом – ищем обращения к адресам видеопамяти видеопроца. Принцип у работы с ним простой: сначала – указываем адрес для записи в видеопамять. Потом – чип будет принимать данные по этому адресу при записи в этот же порт.
Чип – простой, я расписывал ранее, как можно определить обращение на чтение, как – на запись. Используем.
Трансляция данных
Я транслирую их видеочип. Я записываю их данные в свой блок памяти, который как бы уже подготовленные для нас данные их vdp, и из которого позже всё и отображается.Blade нашёл свой, интересный мне способ, который уменьшает загрузку процессора на отображение этого блока памяти путём прямой записи в память тайлов с учётом особенностей отображения. Мне – это ОЧЕНЬ нравится, это – крутое развитие системы отображения тайловой памяти sms.
Ну, потом уже рутина. Палитра, нереально один в один с 2бита Евы. Конвертим, определяем вызовы по её отправке в видеопроц, направляем на свою процедуру.
Далее – ребята отправляют в видеопамять спрайты, начиная с #3f00; всё довольно неплохо – х, у, тайл – но увы, немного с адресами сложность.
Для звука – запись в порты чипа sn, с одной стороны — хорошо похожего на ау, но имеющего 4 канала. Три тона, один шум. Без огибающей. Делаю простую, но не очень хорошую вещь – разделяю всё на 2 ау. Ок, на моей Еве только музыка, но так и должно быть :)
И вот.
Игра – завелась.
зы: если Вам интересна тема портирования игр — пишите на имейл waybester@gmail.com, возможно — найдём о чём поговорить :)
8 комментариев
WLA DX конечно стандарт, и в общем-то хорош, но очень уж глючный, особенно в части редких процессоров. Так что его использования стараются избегать, и именно по причине проблем с WLA наделали немало альтернатив. Он с тех пор вроде как исправился, но осадочек-то остался. Сам до сих пор использую его для SNES (только для 65816), но это вынужденная мера, tcc-816 завязан на него (адски глючная связка).
До сих пор грызёт любопытство как же в 80-х эти игры создавались, даже после прочтения пары статей на эту тему.
Такое ощущение, что шансы войти в этот рынок тогда не являясь разрабом под игровые автоматы был минимальным.
www.genny4ever.net/g4e_modules2/download.php?file=genesis_technical_overview
tv-games.narod.ru/hard/Sega_Tech_Rus_1_5b.rar
До кучи:
segaretro.org/Mega_Drive_official_documentation
Дока для SNES более редкая, долгое время её передавали из под полы, вероятно боясь гнева Nintendo. Состоит из двух книг, циркулирующих под названиями snes_book1.pdf и snes_book2.pdf. В одной описана сама SNES, в другой сопроцессоры:
archive.org/details/SNESDevManual
Касательно вхождения на рынок, ну, 99% всех европейских разработчиков не являлись разработчиками под игровые автоматы, да и вообще опытными разработчиками. В интернете множество интервью с ними, тем более сейчас, и узнать, как создавались игры, несложно. Не знаю, например самое известное:
games.greggman.com/game/programming_m_c__kids/
dutycyclegenerator.com/