Ссылка на редактор последней версии: http://fight.pp.ua/zxpk/bdash/
Привет, друзья.
Так сложилось что Boulder Dash стал игрой-спутником моей жизни.
Время от времени играю в нее, либо делаю ее с нуля на одном или другом языке, даже на Юнити.
Недавно решил разобраться именно с той старой спектрумовской версией игры, с которой собственно все началось.
Подумал я - а что если залезть в код, найти где хранятся данные уровней, поменять их на что-то новое, и получить таким образом новую версию(и) игры. Ну интересно же!
Первое что пришло в голову - ну наверное объекты хранятся в игре в форме таблички(массива) объектов, где они прописаны строчками один за другим в виде байтов.
Написал программу которая ищет паттерны. Ну там например знаю что на первом уровне есть какой-то участок (dirt, space, space, boulder, dirt) Ну и пишу паттерн 10021, и ищу своей программой. Никак ничего не находит!!! Программа сама по себе рабочая, она действительно находит последовательности байт соответствующие моему образцу.
Блин, думаю, что-то здесь не чисто.
Копал рыл гугл и нарыл очень интересную информацию, которая помогла мне сделать для себя массу интересных открытий. Если Вы любите эту игру и не знали о том, что я скажу, то Вам будет тоже интересно.
Оказывается уровни игры создаются очень хитрым образом. Все уровни 100 штук(20*5) записаны всего в 1657 байтах.
Гениально!
Посчитайте сколько реально понадобилось бы если хранить так, как я хотел по байту на объект:
40*22*20*5 = 88000 байт! И это только на хранение объектов, а там есть еще информации немного помимо этого (сколько нужно собрать алмазов, время и т.д.)
Нету в Спектруме столько памяти (говорим про классику 48 кб)
А записываются все построения из объектов в виде неких "макросов" типа:
прямоугольник из кирпичей залитый пустотой с началом в (4,7) и размером (10,10)
и на это добро уходит 6 байт вместо например 100 байт. Неплохой выигрыш!
И это еще не все.
Ну это еще можно было бы может догадаться - в игре же часто объекты располагаются рядами либо прямоугольниками, либо по диагонали.
Но кто бы мог подумать что рассыпанные камни по уровню тоже не хранятся "по одному"!!!
Для этого игра использует свой собственной псевдогенератор случайных чисел, при чем четко предсказуемый и аппаратно-независимый, что позволяет иметь те же результаты (уровни игры) при каждом запуске игры и даже на разных платформах
Это меня убило полностью.
Я все время в детстве думал: ну какая же умная голова так интересно разместила препятствия на уровне.
А никто сильно и не парился - максимум подобрал нужных два параметра: seed(измеряется числом от 0 до 255) и probabiliy (измеряется числом от 0 до 255) Первое меняет уникальное расположение (как бы меняет точку отсчета для алгоритма генерации случайных чисел) а второе число меняет интенсивность, при нуле - ничего не попадет на экран, при 255 - максимум.
Теперь понимаете как легко создать новые сложности для существующих уникальных уровней!?
Уменьшаем время на прохождение и настраиваем генератор!
Копаясь дальше с Boulder Dash I
я точно определил где все это находится и меняя эти параметры я могу видеть изменения при запуске игры (в любом эмуляторе)
То есть если еще поменять спрайты (попроще задача) - то можно выдать новые версии игры, ну хотя бы даже просто по приколу.
Однако все же я столкнулся с одной маленькой, но ключевой проблемой, которую я пока решить не могу.
Может кто-то опытный из вас может подсказать или помочь.
Дело в том, что сразу после этого участка данных сразу располагается другой хоть и не большой но какой-то конечно же используемый кусок, то ли кода то ли данных.
Это значит что все мои изменения не должны "вылазить" за размеры уже "определенного" блока. Он может быть таким же или меньшим по размеру, что в принципе тоже решение!!
Просто в идеале хотелось бы снять это ограничение если это возможно.
Сразу после того маленького куска непонятного кода идет куча свободного места (сплошные 0x00) где есть место развернуться фантазии.
Я подумал, а можно как-то перенести мои данные туда!? и где-то в игре переназначить адрес, чтобы брало данные из нового места. Хотя звучит вполне логично, я даже вроде нашел где фигурирует адрес начало моего блока, который встретился мне один раз во всей игре.
Я поменял его на новый, там в новом месте разместил данные, правда только первый уровень. И это не заработало, игра сбросилась при запуске первого уровня..
Что-то я недосмотрел. Еще есть вариант запулить туда все уровни сразу, но не уверен, что это поможет. По крайней мере пока что я не могу это сделать "автоматически", так как первый уровень я занес в ручную по байту в дизассемблере.
Пока остается вариант нарисовать уровни в пределах выделенного фрагмента 1657 байт, при чем в середине блока все достаточно гибко, там просто разделители (0xFF) между уровнями, а в середин уровней - все тоже очень гибко.. То есть размеры уровней в байтах можно уменьшать и увеличивать как хочешь, главное чтобы общая сумма не залезла за 1657
Вот такие дела..
Есть мысли?
Спасибо за внимание
Оригинал:
Программно восоздано мною по тем же данным (Javascript)