Адаптация программ с кодовым загрузчиком и небольшой артефакт +3.
Развивая начатую тему, привожу еще один характерный пример адаптации к системе +3DOS.
Многое в нашей жизни делается обычно, когда нужда заставит. Так и в этом случае, адаптировав с десяток ходовых игр преимущественно с простым загрузчиком на бейсике, настал момент, когда понадобилось адаптировать игру с загрузчиком в машинном коде. У меня две самые любимые игры это ELITE и ADVANCED SOCCER SIMULATOR. В эти игры я могу играть часами и годами. И, наверное, из-за них пришла идея приобрести реальный Спектрум.
Если с первой игрой ELITE мне повезло, удалось найти вариант на ленте с простым загрузчиком, то со второй дела обстояли гораздо хуже. Простых вариантов не было, были либо полные дисковые версии для TR_DOS с монозагрузчиком, либо ленточные версии с загрузчиком в коде. В коллекции Волгодонска встретилась неполная дисковая версия с бейсик загрузчиком. Как я писал выше, лучше идти по простому пути, взять самый простой вариант, то есть в нашем случае это будет вариант из коллекции Волгодонска с загрузчиком на бейсике. Однако удачно работающая версия в TR_DOS при переносе в +3DOS отказалась работать, зависая перед инициализацией игры, которая происходит по нажатию пробела после стартовой заставки.
Забегая вперед, скажу, что дело оказалось вовсе не в +3DOS, а в самом Спектруме +3, как таковом. На том этапе я этого еще не знал и думал, что возможно зависание происходит из-за исходной корявой адаптации к TR_DOS, внешне это подтверждалось отсутствием подпрограммы загрузки отложенной игры, которая инициализируется перед стартом, предлагая либо начать новую игру либо загрузить старую. В самой игре автором было предусмотрено только сохранение, а загрузка делалась исключительно вначале игры. Из-за этого получалось, что версия игры была настолько убогая, что как-то вернуться к сохраненному (даже на ленту) состоянию игры, в ней было невозможно.
Кроме этого казуса в загрузчике фигурировали непонятные мне pokes, кроме того, в экранную область по мимо картинки грузилась какая-то гадость и запускалась по адресу 16384… Короче говоря, я решил не возится с этой убогой версией и обратится к оригинальной на образе tzx WOS.
Загрузчик у оригинальной версии был классический, то есть сначала бейсик загрузчик грузил кодовый загрузчик, а потом кодовый грузил все остальное.
Есть мнение, что самой эффективной защитой от среднестатистического ламера является применение кодового загрузчика. Не знаю, этим ли руководствовался автор игры, но первичный бейсик загрузчик у оригинальной версии выглядел так:
0 CLEAR 24783: LOAD “” СODE: RANDOMIZE USR 64307
Как видно из листинга, вся необходимая для работы информация в нем присутствует. А защита в виде 0-й строки вызывает всего лишь улыбку и вопрос – А что автор думал, что кто-то захочет править эту единственную строку???
Дальше дело сложнее. На образе ленты размещены 5-ть кодовых файлов без заголовка, и все, что он них можно узнать – это их длину. Однако перед ними расположен один кодовый файл с заголовком, который очевидно грузится по команде LOAD “” СODE в бейсик загрузчике.
Параметры файла просты: адрес загрузки 64000, длина 1536, точка входа 64307. Используя эту информацию и монитор ADM 7.08 можно определить, что это загрузчик в машинном коде, который грузит 4-ре из выше упомянутых 5-ти кодовых блоков.
1 блок 16384, 6912 – очевидно заставка
2 блок 25600, 4608 – по всей видимости, просто часть самой игры
3 блок 43856, 3968 – программа загрузки с ленты отложенной игры та, которая отсутствовала в корявой версии под TR-DOS.
4 блок 50000, 14000 – основной кодовый блок игры.
Определить эту информацию несложно, можно обратится к книге Родионова там, в разделе «Загрузчик в машинных кодах все подробно описано».
В этом случае по точке входа 64307 после некоторых заготовительных операций осуществлялась загрузка блоков следующим образом:
LD IX,START
LD DE,LENGTH
LD A,FF
SCF
CALL FA84
Слова START и LENGTH, которые предварительно загружаются в регистры IX и DE перед вызовом подпрограммы загрузки с ленты CALL FA84 дают информацию о параметрах загружаемых блоков, которые я указал ранее. А что же с 5-м кодовым блоком? Этот блок оказался исходным состоянием игры, то есть содержащим все параметры, переменные игры, которые сохраняются при отгрузке. На ленте присутствовал файл с исходным состоянием игры, который грузился подпрограммой загрузки расположенной в 3-ем блоке при выборе опции новая игра. В случае выбора опции отложенная игра грузился аналогичный файл с параметрами отложенной игры. Параметры 5 блока 30208, 13648.
Таким образом, выудя всю необходимую информацию о файлах игры, пишется загрузчик, и записываются на диск файлы. Точку входа можно использовать аналогичную 64307, предварительно подредактировав код блоков 1 и 2, обойдя в них процедуры загрузки с ленты при помощи команд JR или JP. Конечно, блок 1 вообще можно было бы выбросить и отправит процессор сразу по адресу в блок 2 на подпрограмму загрузки отложенной игры, однако блоки организованы непросто и те функции, которые я за ними закрепил, весьма условны и справедливы только для рассматриваемой нами задачи. В целом в них встречаются куски (подпрограммы), используемые в процессе самой игры, а не только при загрузке.
Проделав все операции, игра удачно стартовала в TR_DOS, при этом в отличие от корявой версии в этом случае можно было использовать отгрузку состояния игры на ленту. Однако при переносе игры в +3DOS игра зависала после выбора футбольной команды. Я установил, что зависание в корявой версии в + 3DOS было вызвано той же причиной, кроме того, как оказалось, игра аналогично висла и при загрузке с ленты, если грузить ее на Спектруме +3. Причем, даже в режиме замка 48к, что сильно удивляло и ставило в тупик. Одно стало понятно, что сама +3DOS к этому отношения не имела, дело в самом Спектруме +3.
Пошаговое исследование при помощи дебаггера эмулятора RealSpectrum позволило локализовать дефект, установить адрес подпрограммы после которой происходит зависание.
53546 CALL 51823
Как я понял, происходило это при формировании звукового сигнала, когда я вводил номер футбольной команды, нажимал ввод, и программа переходила на подпрограмму синтеза отзвука нажатия клавиши. При этом заблаговременно для нее разрешался режим прерывания IM2. Вот в нем-то и оказалась проблема! Дело в том, что дебаггер показывал различный вектор прерывания в системе 128 Пентагон и в системе Спектрум+3. Для Пентагона вектор был равен FFFF, а для Спектрум+3 – 2100. На скору руку в системе Спектрум +3 при помощи дебаггера я принудительно изменил вектор с 2100 на FFFF. Игра заработала без проблем! Таким образом, причина была точно установлена. Осталось только определить: из-за чего меняется вектор прерывания в системе +3 и как исправить его на FFFF.
Всем известно, что вектор прерывания находится по адресу I+255, где I – регистр прерываний процессора. В регистр I сразу по точке входа 64307 загружался быйт 39H, 255 (FFH) – это байт на шине данных. Исходя из этого, вектор прерываний для этой программы хранился по адресу 39FFH или 14847, то есть в ПЗУ. Я установил, что в обычной прошивке в этом месте располагается большой блок байтов со значением FF, а в +3 вместо FF – 00, причем в банке 48к у +3 была такая же ситуация из-за чего при переходе даже в режим замка программа тоже висла.
В одной из книг я вычитал, что есть некая таблица векторов прерываний, расположенных в ПЗУ, то есть, грубо говоря, приведены вектора прерываний, которые хранятся в XXFF адресах ПЗУ. Очевидно, что одной из проблем при адаптации программ к системе +3 может быть проблема с вектором прерываний, так как ПЗУ у +3 неидентично оригинальному.
Ясно, что проблему можно решить путем изменения содержимого регистра I, но для этого сначала необходимо найти где-то расположенные рядом два байта FF FF причем так, чтобы первый располагался в XXFF. Перерыв все возможные адреса ПЗУ и самой программы я понял, что такого варианта просто нет, его надо создать.
Где создать? Конечно в блоке загрузчика, тем более мне там встретился пустой кусок с нулевыми байтам. Сделал, изменил регистр I. Игра пошла! Однако при отображении счета во время демонстрации матча на цифрах появились характерные горизонтальные полоски… Да, это те самые FF FF которые я записал, казалось бы в свободное место в загрузчике. Тогда я пошел другим путем, воспользовался тем, что RAMTOP установлен намного ниже, чем грузится первый кодовый файл и в самый низкий подходящий адрес записал необходимые ффки. Запустил игру, когда одна из команд забила гол, сформировался звук сигнализирующий об этом, бордюр моргнул синим цветом и игра повисла. И там занято!!! Да что же делать. Весь код игры же не раскрутишь, чтобы определить, где там есть свободный кусок, да тем более еще, и не каждый подойдет.
Но выход все-таки есть! У Спектрума+3 бейсик программа начинается с такого же адреса, как и у любого магнитофонного Спека 23755, то есть без смещения на 112 байт, как у дисковых вариантов с TR-DOS. Поэтому то и не возникает проблем с RAMTOP, хотя исходный бейсик файл загрузчика при адаптации, как правило, увеличивается.
Воспользовавшись этой уже положительной чертой +3, я опустил RAMTOP до нужного адреса, чтобы появилось место для создания байтов FF FF в нужном адресе XXFF.
Исходный RAMTOP 24783 или 60CFH ближайший подходящий адрес вниз от этого 5FFFH, тогда RAMTOP буде 5FFEH или 24574, а проблема будет лечится введением трех poke:
POKE 24575,255: POKE 24576,255 для создания FF FF
и
POKE 64308,96 – для настройки регистра I на адрес 24575.
Таким образом, была достигнута еще одна победа над Спеком +3! Для меня эта победа вдвойне приятна, так как я хоть и умею читать машинный код, но как таковой продолжительной практики программирования у меня не было!
Продолжение следует…




Ответить с цитированием