Spectrum-совместимые компьютеры «Байт»,«Байт-01» и прочие раритеты

5 / 128

Сборка образа картриджа приставки «Эльф»

Адаптация игры

Для каждой игры процесс адаптации строго индивидуальный (творческий), не может быть описан конкретными правилами, и для него не может быть строго заданного алгоритма действий. Я лишь кратко коснусь сути адаптации.

Очень упрощённо, приставка «Эльф» - это по сути ZX-Spectrum, из которого убрали клавиатуру и оставили Kempston-джойстик. Абсолютное большинство игр для ZX-Spectrum рассчитаны на работу с клавиатурой. Наша цель - сделать так, чтобы игра сразу опрашивала Kempston джойстик и позволяла при запуске при его помощи выбирать нужные опции и играть.

Для этого надо переделать управление самой игрой для Kempston джойстика, затем изменить управление в меню игры на Kempston джойстик, при необходимости изменить текст меню игры, выкинув из него ненужные опции типа выбора управления. Да, всё это описано одним предложением, однако потребует много времени.

В качестве примера я приведу процесс переделки игры Star Raiders II под управление приставки «Эльф». Конечно же, вы видите финальный результат, когда всё понятно что надо менять. Но процесс анализа и поиска занял примерно один вечер.

Пример адаптации кодового блока игры Star Raiders II

Раскрыв загрузчик игры мы «достаём» из него кодовый блок игры длиной #765C байт и со стартовым адресом #7514. Старт игры производится по тому же адресу - #7514.

Ищем, где в игре производится опрос клавиатуры и Kempston джойстика. Находим следующий кусок кода:

#7ED3 LD A,(#FF02)
      OR A
      JP NZ,#98BF
      LD A,1
      LD (#FF2A),A
      LD A,%10111111 ;опрос полуряда клавиатуры HJKL Enter
      IN A,(#FE)
      AND 8          ;состояние кнопки "J" - смена управления
      CP 8
      JR Z,#7F19     ;кнопка не нажата
      LD (#7EE6),A

Далее опытным путём устанавливаем, что при старте игры сразу выбрано управление Kempston джойстик. Значит приведенный код неактуален - нам не надо менять управление. Убираем из него смену управления, и меняем код на:

#7ED3 LD A,(#FF02)
      OR A
      JP NZ,#98BF
      LD A,1
      LD (#FF2A),A
      JP #7F19

Далее ищем, где отображается текст "KEMPSTON". Для начала находим таблицы управления в игре и адреса текстовых сообщений для выбранного управления:

#B24E DEFW #99D0 ;Адрес обработчика Kempston Joystick
      DEFW #B1F8 ;Адрес текстового сообщения "KEMPSTON"

      DEFW #99D6 ;Адрес обработчика Interface II Joystick
      DEFW #B203 ;Адрес текстового сообщения "INTERFACE 2"

      DEFW #99F1 ;Адрес обработкичка клавиш
      DEFW #B20E ;Адрес текстового сообщения "KEYBOARD"

Отсюда нам надо текстовое сообщение по адресу #B1F8:

#B1F8 DEFM "KEMPSTON@@@" ;Пробелы отображаются символом "@"

Меняем этот текст на:

#B1F8 DEFM "JOYSTICK 1@"

В игре кроме Kempston ещё есть множество других кнопок управления. Ищем, где бы они могли опрашиваться. Находим следующий кусок кода:

#7F7A LD HL,#7FA6 ;Таблица обработчика дополнительных клавиш
      LD C,7      ;Опрашиваем 7 клавиш
#7F7F LD A,(HL)   ;Первый байт таблицы - старший байт адреса порта клавиатуры
      INC HL
      IN A,(#FE)  ;Считываем состояние клавиш нужного полуряда клавиатуры
      AND (HL)    ;Маскируем бит нужной клавиши
      JR Z,#7F8D  ;Если клавиша нажата, переходим
      DEC C       ;Клавиша не нажата, уменьшаем счётчик опрашиваемых клавиш
      JR NZ,#7F7F ;Считываем состояние следующей клавиши
      LD A,C 
      JR #7F95

#7F8D LD A,C
      CP 0
#7F8F EQU $-1
      JR Z,#7F98
      LD (#63EC),A
#7F95 LD (#7F8F),A


;Таблица для 7 дополнительных клавиш.
;Первый байт - старший байт порта клавиатуры для опроса клавиши.
;Второй байт - маска для выделения нажатия нужной клавиши.
#7FA6 DEFB #FD,#02 ;Клавиша S - вкл/выкл защитного поля
      DEFB #FB,#02 ;Клавиша W - смена оружия
      DEFB #BF,#01 ;Клавиша Enter - вызов карты
      DEFB #FB,#10 ;Клавиша T - радар
      DEFB #DF,#04 ;Клавиша I - пауза
      DEFB #BF,#02 ;Клавиша L - выбор сложности игры
      DEFB #FE,#01 ;Клавиша Caps Shift - старт игры/выход в главное меню

Все эти 7 клавиш надо переопределить на имеющие 7 сводобных кнопок в приставке. Плюс дополнительная сложность - если в игре опрашивается только клавиатура, где нажатая кнопка даёт 0 в нужном бите, у нас смесь кнопок, которые в нажатом состоянии могут быть как в 0, так и в 1, поэтому таблицу кнопок придётся расширить, введя ещё один байт, который будет указывать надо ли инвертировать считанное значение из порта, чтобы привести бит нажатой кнопки к 0.

Так как таблица при этом увеличится в размере, мы не сможем использовать её нынешнее место в памяти. Смотрим, куда бы можно было поместить и таблицу и ноывй обработчик этих семи дополнительных кнопок игры. У нас есть ненужное место, где находятся обработчики Interface II и клавиатуры для игры. Это область памяти с адреса #99D6 и длиной #42 байта.

Пишем в эту область памяти свой обработчик и таблицу:

;Опрос дополнительных кнопок

       ORG #99D6

       LD HL,TABLE
       LD C,7
A1     LD A,(HL)   ;номер порта
       LD (A2),A
       INC HL
       LD A,(HL)   ;признак инверсии значения
       LD (A3),A
       INC HL
       XOR A
       IN A,(0)
A2     EQU $-1
       XOR 0
A3     EQU $-1
       AND (HL)    ;AND с маской нужного бита
       INC HL
       JP Z,#7F8D  ;было нажатие кнопки

       DEC C
       JR NZ,A1
       LD A,C
       JP #7F95

;7 записей в таблице
;порт, биты для инверсии (0-не надо, FF-инвертируем), маска для выделения значащего бита
;Кнопка считается нажатой, если AND с маской даст 0
;Для битов, активных в 1 надо делать инверсию по XOR
TABLE DEFB #1F,#00,%00100000  ;FIRE A - защитное поле вкл/выкл
      DEFB #1F,#00,%10000000  ;SELECT - смена оружия
      DEFB #1F,#FF,%01000000  ;START - карта/битва

      ;Джойстик 2
      DEFB #FE,#00,%00000010  ;DOWN - радар корабля/состояние систем
      DEFB #FE,#00,%00000100  ;RIGHT - пауза
      DEFB #FE,#00,%00010000  ;LEFT - выбор уровня сложности
      DEFB #FE,#00,%00000001  ;FIRE B - выход в меню/старт игры

Дальше надо поменять вызов обработчика дополнительных кнопок на новый адрес #99D6:

#7F7A JP #99D6

Сохраняем изменённый кодовый блок игры. А дальше надо из него получить файл, который можно прошить в ПЗУ картриджа и запустить на приставке.

Конечно же, для этого можно воспользоваться информацией по программированию приставки, однако вам быстро надоест для каждой игры высчитывать адреса для размещения в ПЗУ, перекодировать описание игры в формат приставки, писать каждый раз меню, собирать всё это в один готовый файл для прошивки в ПЗУ. На самом деле, это приличный объём работы. И в отличие от процесса адаптации игры, эта часть работы может быть автоматизирована.

Мне удалось решить проблему автоматизации размещения игр на картридже. Для этого пришлось написать несколько утилит, которые позволят всё сделать быстро. Все утилиты написаны для системы iS-DOS. Во-первых, это какая-никакая, а операционная система, позволяющая упорядоченно хранить файлы большого объёма (это важно!), а также под эту систему есть неплохой ассемблер. Поэтому всё нижеследущее описание будет дано применительно к работе в системе iS-DOS. Важно, чтобы у вас был хотя бы небольшой опыт работы с этой системой, её утилитами и текстовым редактором. В текстовом редакторе будет писаться загрузчик игры и конфигурационные файлы.

Системные требования

Мои утилиты будут работать в любой системе iS-DOS: Classic, Chic или TASiS. Учитывая, что образ картриджа может занимать вплоть до 1МБ, крайне желательно иметь систему с винчестером. Во-первых, для HDD объём одного устройства iS-DOS может достигать 16МБ, чего с лихвой хватит для работы. Во-вторых, система, запущенная с винчестера, работает намного быстрее, чем загруженная просто с дискеты. Однако для адаптации нескольких игр вполне хватит и дискеты.

Ничто не мешает делать всё в эмуляторе. Процесс конфигурации эмулятора я опущу ввиду того, что не пользуюсь оным.

Сборка одной игры

Процесс получения образа картриджа можно разделить на два этапа: сборка одной игры и сборка образа картриджа из уже собранных игр.

Вернёмся к нашей игре. После адаптации у нас есть кодовый блок игры (или несколько кодовых блоков), который нужно поместить в определённое место ОЗУ и запустить на выполнение переходом на определённый адрес в памяти. Помимо кодовых блоков у нас может быть заставка, которую тоже можно вывести на экран в процессе загрузки.

Все эти блоки можно поместить в один большой файл, добавить к нему загрузчик игры, и мы получим готовый файл игры, из которого впоследствии можно компоновать образ картриджа. Для удобства я дал таким файлам игр расширение *.alf.

Чтобы не забивать себе голову расчётом где и в каком банке ПЗУ должен располагаться конкретный блок игры, как его загружать, как считать все смещения адресов внутри образа ПЗУ, написана программа, которая всё это делает за вас. От вас лишь потребуется написать загрузчик и указать программе какие файлы должны быть включены в игру.

Для примера возьмём игру Bruce Lee из образа диска в конце этой страницы. Переходим в папку ALF\GAMES\BRUCELEE.

Игра состоит из заставки (scr.pak) и главного блока игры (main.pak). Расширение *.pak - это если блок запакован при помощи HRUST 1.3. Для экономии места все блоки игры пакуются. Сам паковщик HRUST1.3 не работает в системе iS-DOS, поэтому я предварительно пакую блоки отдельно и переношу их потом в папку с игрой. Распаковщик уже будет встроен в ПЗУ с картриджем, и при загрузке игры блоки распаковываются. Однако ничто не мешает не паковать данные и собирать игру из непакованных блоков. Кроме увеличения места в ПЗУ это ничего не поменяет.

_files.txt - текстовый файл, где указывается перечень файлов, которые должны быть включены в игру, а также выходной файл с собранной игрой. О загрузчике будет немного ниже по тексту статьи.

loader.asm - это загрузчик игры.

opis.txt - описание игры. Это тот текст, который будет выведен на экран при загрузке игры на приставке. Текст пишется обычной кириллицей (в iS-DOS применяется 866-я кодировка) и в процессе сборки игры конвертируется в формат, который поддерживается приставкой. Регистр символов значения не имеет. Текст должен быть выровнен в строки длиной 28 символов (текстовый редактор iS-DOS позволяет форматировать текст в любую длину строки). Из описания берётся ровно #02F4 байт текста. Символы перевод строки игнорируютс, лишнее обрезается, а недостающее дополняется пробелами. Так что можно спокойно писать короткие описания, не боясь, что они будут отображены неправильно.

Для сборки игры надо запустить файл _build.bat. При этом все блоки игры соберутся в один файл *.alf, который указан как выходной файл игры (в файле _files.txt)

Описание файла _build.bat

Пройдёмся по структуре файла _build.bat. Менять этот файл надо только для того, чтобы включить или отключить компиляцию нужного модуля.

;Описание игры
;Вызов утилиты, которая преобразует описание игры из файла opis.txt
;в формат Эльф. Результат помещается в файл opis.cod
Q:\ALF\BUILDER\con_opis opis.txt opis.cod

;Компиляция загрузчика в файл loader.cod
;Тут не надо ничего менять!
Q:AS\as /auto loader.asm
Q:AS\as /auto /.key%1 C:LOADER\ldblk.asm
Q:RES\calc ldblk.obj
Q:AS\as /auto C:BUILDER\vars.asm
Q:AS\link loader ldblk vars /out loader.cod
Q:RES\calc loader.cod
Q:RES\calc vars.obj
Q:RES\calc loader.obj

;Сборка игры в файл *.alf
;Игра собирается из файлов, указанных в _files.txt
Q:ALF\BUILDER\builder2 _files.txt 

Загрузчик игры

Исходный код загрузчика находится в файле loader.txt. Сам загрузчик представляет собой небольшую (порядка 400-500 байт) программу, которая при выполнении возьмёт из ПЗУ картриджа нужные кодовые блоки игры, разместит их в памяти и запустит на выполнение.

В загрузчик входит подпрограмма, которая по номеру кодового блока игры сама загружает его из ПЗУ в память. Напомню, что порядок блоков игр задаётся в файле _files.txt, при этом блоки нумеруются по порядку, начиная с 1.

В нашем случае файл _files.txt содержит текст:

;Выходной файл
brucele.alf

;Описание
opis.cod

;Файлы игры
main.pak
scr.pak

В этом файле содержится перечень всех файлов, из которых собирается игра. В файле допускаются строки с комментариями, начинающиеся с символа ";".

Первый по счёту файл всегда будет считаться выходным файлом, куда будет записываться собранная игра. В нашем случае это brucele.alf.

Второй по счёту файл - описание игры. В нашем случае это opis.cod. Этот файл получается при компиляции игры из файла opis.txt.

Эти первые два файла должны быть заданы именно в указанном порядке. Сначала - выходной файл, потом файл с описанием игры!

Далее идут сами файлы игры. Эти файлы условно нумеруются по порядку, начиная с 1. По этим номерам они будут доступны в загрузчике игры.

main.pak - упакованный главный кодовый блок игры. Это будет блок №1.

scr.pak - упакованная заставка игры. Это будет блок №2.

Так как загрузчик занимает какое-то место в памяти, нужно предусмотреть его размещение и стартовый адрес таким образом, чтобы он не "пересёкся" с загружаемыми файлами игры. То есть для загрузчика должно быть отдельное место в памяти. В случае, когда для загрузчика просто нет места (такое случается, когда игра занимает всю доступную память от #5B00 до #FFFF, загрузчик можно разместить в экранной области ОЗУ (но нельзя занимать место с #4000 по #4004 включительно - это ограничение ПЗУ приставки!). Для различных случаев нужен индивидуальный подход.

Из загрузчика могут быть вызваны дополнительные модули. На данный момент написаны 3 модуля - меню читов, модуль проверки наличия 128К RAM и модуль проверки приставки на «новодельность». Модули представляют собой автономные программы, которые после завершения своей работы отдают управление обратно в загрузчик. На этапе сборки образа картриджа все модули помещаются в 0-й банк ПЗУ и могут быть оттуда вызваны загрузчиком.

Пример загрузчика loader.asm

Далее разберу по порядку загрузчик игры Bruce Lee (он находится в файле loader.asm):

;Загрузчик должен иметь длину 256 байт или более!!!
;Адрес загрузчика выбирается так, чтобы он не пересёкся с кодовыми блоками игры.
    ORG #5F00

    JR BEGIN

    DEFW #5F00 ;адрес компиляции загрузчика - должен совпадать с ORG!!!
;Этот адрес используется в дальнейшем сборщиком программ в картридж. К сожалению
;особенности ассемблера iS-DOS не позволяют указать адрес компиляции через переменную,
;поэтому тут приходится дублировать адрес числом.

;--- РЕЗЕРВИРОВАНИЕ МЕСТА ДЛЯ ОПИСАТЕЛЯ ФАЙЛОВ, ВХОДЯЩИХ В ИГРУ ---
;В начале загрузчика при сборке файла с игрой создаётся таблица смещений
;каждого из файлов игры. На этапе написания загрузчика мы просто
;тут резервируем место под нужное количество файлов.
$TABLE
    DEFS 3    ;сюда пишется адрес игры в ПЗУ

;Сюда надо записать количество файлов, из которых будет состоять игра.
;Сам загрузчик не включается в этот список.
;Файлы меню читов и проверки на 128К, если они есть, должны быть
;включены в общий список файлов.
;Сам список файлов задаётся в файле _files.txt
FILES  EQU 2    ;Сколько файлов будем подгружать (без учёта загрузчика)

     DEFS 6+FILES*6+1   ;Резервируем место для таблицы файлов
;---- КОНЕЦ ОПИСАТЕЛЯ ФАЙЛОВ ------


;--- НАЧАЛО КОДА ЗАГРУЗЧИКА -----
BEGIN
       LD SP,#5DF7 ;Задаём стек, обычно он располагается до начала загрузчика

       LD A,#80    ;Включаем 0-й банк ПЗУ картриджа
       OUT (#5F),A ;В нём на этапе сборки образа картриджа, помещается
                   ;распаковщик HRUST длиной 256 байт.

;Берём рапаковщик из ПЗУ картриджа и переносим в память.
;По умолчанию распаковщик переносится в адрес #5B00 (он задан в переменной $DEPACK)
;Если нужен другой адрес для распаковщика, то в регистр DE вписываем нужный адрес.
       LD HL,$HRUST  ;адрес распаковщика в ПЗУ картриджа
       LD DE,$DEPACK
       LD BC,#0100
       LDIR          ;переносим в ОЗУ

       LD HL,$MENU   ;Адрес модуля меню с читами в ПЗУ
       LD DE,$MODADR ;Адрес компиляции модуля (на данный момент это #7000)
       LD BC,#0200   ;Максимальная длина модуля
       LDIR          ;Переносим модуль из в ПЗУ в ОЗУ
;Задание параметров вызова меню с читами
       LD HL,MENU    ;Адрес массива строк меню.
       LD DE,OPTIONS ;Адрес массива, куда будут помещены результаты выбора опций меню
       CALL $MODADR  ;Вызов меню с читами

;Загрузка заставки игры
       LD A,2       ;Заставка (scr.pak) является 2-м файлом в _files.txt
       LD DE,#61A8  ;Адрес для загрузки упакованной заставки.
                    ;Может быть любым, лишь бы не испортил загрузчик
                    ;и распаковщик
       CALL $LDBLK  ;Загрузка файла заставки

;Распаковка заставки
       LD HL,#61A8  ;Адрес загруженной заставки
       LD DE,#4000  ;Адрес, куда распаковываем заставку
       CALL $DEPACK ;Вызов распаковщика, расположенного в #5B00

;Заставку, равно как и другие файлы, можно не паковать. Это необязательное
;требование. В этом случае кодовые блоки с вызовом распаковщика можно убрать.

;Загрузка основного блока игры
;В нашем случае игры состоит из одного файла.
       LD A,1       ;Главный кодовый блок (main.pak) записан как файл №1
                    ;в файле _files.txt (файл main.pak)
       LD DE,#61A8  ;В нашем случае кодовый блок располагается с адреса #61A8
       CALL $LDBLK  ;Загрузка файла

       LD A,1       ;Выключаем ПЗУ картриджа и включаем вместо него ПЗУ Basic-48
       OUT (#5F),A

       LD HL,#61A8  ;распаковка основного блока игры
       LD DE,#61A8  ;с адреса #61A8 в тот же адрес.
       CALL $DEPACK


;Пауза перед запуском игры, чтобы полюбоваться заставкой, иначе заставка
;быстро исчезнет
OTP    IN A,(#1F)     ;Ждём отпускания кнопок джойстика 1
       AND %00011111
       JR NZ,OTP

       CALL PAUSE     ;Пауза на дребезг кнопок

       LD B,2         ;Большая пауза после вывода заставки
OTP2   LD DE,#FFFF
OTP3   IN A,(#1F)
       AND %00011111  ;Но по нажатию любой кнопки джойстика 1
       JR NZ,OTP4     ;выходим из паузы
       DEC DE
       LD A,D
       OR E
       JR NZ,OTP3
       DJNZ OTP2
OTP4


;--------- ЭТОТ БЛОК ИСПОЛЬЗУЕТСЯ ТОЛЬКО ЕСЛИ У НАС ЕСТЬ МЕНЮ С ЧИТАМИ --------

;В процессе своей работы меню с читами помещает результат выбора опций
;в память в массив OPTIONS.
       LD IX,OPTIONS ;Адрес опций меню
       LD A,(IX+0)   ;Первая опция
       OR A
       JR Z,OPT2     ;Первая опция в меню не была выбрана, пропускаем её обработку.

;Действия для первой опции - бесконечные жизни в игре
       XOR A
       LD (51795),A

;Проверка второй опции. В данном случае в меню только одна опция, поэтому данный
;блок просто закомментирован.
OPT2  ; LD A,(IX+1)  ;Вторая опция
      ; OR A
      ; JR Z,START

;Действия для второй опции - тут тоже пусто.
;------ КОНЕЦ БЛОКА ДЛЯ МЕНЮ С ЧИТАМИ -------------


;Старт игры
START  JP #E4DE


;Пауза, чтобы убрать дребезг кнопок джойстика.
PAUSE  LD BC,#2000
PAUSE1 DEC BC
       LD A,B
       OR C
       JR NZ,PAUSE1
       RET

;Массив, куда помещаются результаты выбора опций меню.
;Число после DEFS - количество опций.
OPTIONS DEFS 1

;Массив строк меню с читами. У нас тут одна строка.
MENU   DEFM "BESKONE^NYE VIZNI"
       DEFB 0     ;0 - признак конца строки.
       DEFB #FF   ;#FF - признак конца массива строк

Модуль для меню с читами

Этот модуль представляет собой отдельно работающую автономную программу, которая выводит на экран меню, обеспечивает выбор нужного пункта меню (или нескольких пунктов) и выход обратно. Данные о выбранных пунктах меню сохраняются в указанный при вызове меню адрес.

Модуль размещается в ПЗУ картриджа. При необходимости его можно скопировать из ПЗУ в память и запустить. Пример запуска меню:

;Перед этим надо убедиться, что включен 0-й банк ПЗУ картриджа.
;Модуль хранится в 0-м банке ПЗУ картриджа по адресу $MENU
;Включить 0-й банк ПЗУ можно командами LD A,#80: OUT (#5F),A

       LD HL,$MENU   ;Адрес модуля меню с читами в ПЗУ
       LD DE,$MODADR ;Адрес компиляции модуля (на данный момент это #7000)
       LD BC,#0200   ;Максимальная длина модуля
       LDIR          ;Переносим модуль из в ПЗУ в ОЗУ

;Задание параметров вызова меню с читами
       LD HL,MENU    ;Адрес массива строк меню.
       LD DE,OPTIONS ;Адрес массива, куда будут помещены результаты выбора опций меню
       CALL $MODADR  ;Вызов меню с читами

При запуске меню проверяется - нажата ли хотя бы одна клавиша джойстика 1 (кроме Огонь). Если нет, то меню не запускается, управление отдаётся обратно в загрузчик.

Если нажата какая-нибудь клавиша, запускается меню и на экран выводятся строки из массива строк в регистре HL. Пример массива строк:

MENU   DEFM "BESKONE^NYE VIZNI"
       DEFB 0     ;0 - признак конца строки.
       DEFB #FF   ;#FF - признак конца массива строк

У нас тут одна строка - выбор бесконечных жизней. Если выбрать эту строку, то в массив OPTIONS по смещению +0 запишется значение #FF. Если опция не будет выбрана, то в массив запишется значение 0. Если в меню будут заданы несколько строк, то для второй строки смещение в массиве OPTIONS будет +1, для третьей - +2 и так далее. Соответственно массив OPTIONS должен быть задан такого размера, сколько у нас планируется опций в меню. Кодировка символов строк - такая же, как кодировка сообщений в ПЗУ приставки:

Знакогенератор в меню приставки «Эльф»

Пример задания OPTIONS для одной строки:

OPTIONS  DEFS 1  ;резервируем 1 байт.

Модуль проверки ОЗУ на 128К

Располагается в 0-м банке ПЗУ картриджа по адресу $CH128. Длина модуля - не более #0100 байт.

Можно использовать при запуске игр, которые требуют наличия 128К ОЗУ. Если всё нормально, то после запуска модуля он сразу же отдаст управление обратно. Если же память 128К не будет найдена, модуль выведет на экран соответствующее сообщение и остановит работу.

Модуль компилируется в адрес #7000, и по этому же адресу выпускается на выполнение.

Пример вызова блока проверки ОЗУ на объём 128К:

;Перед этим надо убедиться, что включен 0-й банк ПЗУ картриджа.
;Модуль хранится в 0-м банке ПЗУ картриджа по адресу $CH128
;Включить 0-й банк ПЗУ можно командами LD A,#80: OUT (#5F),A

       LD HL,$CH128  ;Адрес модуля в ПЗУ
       LD DE,$MODADR ;Адрес компиляции модуля (на данный момент это #7000)
       LD BC,#0100   ;Максимальная длина модуля
       LDIR          ;Переносим модуль из в ПЗУ в ОЗУ
       CALL $MODADR  ;Запускаем модуль

       ....          ;Продолжение работы загрузчика

Модуль проверки приставки на «новодельность»

Располагается в 0-м банке ПЗУ картриджа по адресу $CHNOV. Длина модуля - не более #0100 байт.

Можно использовать при запуске игр, которые будут работать только на «новодельных» приставках. Если всё нормально, то после запуска модуля он сразу же отдаст управление обратно. В противном случае модуль выведет на экран соответствующее сообщение и остановит работу.

Модуль компилируется в адрес #7000, и по этому же адресу выпускается на выполнение.

Пример вызова блока проверки ОЗУ на «новодельность»:

;Перед этим надо убедиться, что включен 0-й банк ПЗУ картриджа.
;Модуль хранится в 0-м банке ПЗУ картриджа по адресу $CHNOV
;Включить 0-й банк ПЗУ можно командами LD A,#80: OUT (#5F),A

       LD HL,$CHNOV  ;Адрес модуля в ПЗУ
       LD DE,$MODADR ;Адрес компиляции модуля (на данный момент это #7000)
       LD BC,#0100   ;Максимальная длина модуля
       LDIR          ;Переносим модуль из в ПЗУ в ОЗУ
       CALL $MODADR  ;Запускаем модуль

       ....          ;Продолжение работы загрузчика

Сборка образа картриджа

Имея один или несколько файлов *.alf из них можно собрать образ картриджа. Для этого нужно перейти в папку ALF\ и изменить файл spisok.txt. В этом файле перечисляются игры в том порядке, в котором они должны отображаться в меню картриджа. Для каждой игры указывается название (это название будет отображаться в меню картриджа) и путь к файлу *.alf с игрой.

Формат имени игры такой же самый, как и описания игры - используется только кириллица, регистр значения не имеет. Используется только 12 байт имени. Лишнее обрезается, а недостающее до 12 байт дополняется пробелами при сборке картриджа. Поэтому пишем имя как есть, не добивая его пробелами.

Запускаем файл makebin.bat. После его выполнения в текущей папке мы получим *.bin файл с прошивкой. Имя этого файла задаётся в makebin.bat. Вы можете отредактировать файл для получения другого имени выходного файла.

Однако это не всё. Полученный файл не имеет длину, кратную 128К, поэтому его надо дополнить до такого размера, чтобы он был ровно по объёму ПЗУ (128К, 256К, 512К либо 1024К). Это делается запуском файла makerom.bat. После его выполнения у нас будет уже окончательный файл для прошивки в ПЗУ. Копируем этот файл из iS-DOS, скажем, на MS-DOS диск, а уже оттуда на компьютер с программатором ПЗУ, прошиваем ПЗУ, вставляем картридж с прошитыми ПЗУ в приставку и играем.

Утилиты и игры

Утилиты для сборки образа картриджа приставки «Эльф» (дата сборки 4.12.2024)В архиве содержится FDI-образ диска iS-DOS с утилитами для сборки образа картриджа. В качестве примера приведён загрузчик игры Bruce Lee.
Игры с оригинальных картриджей приставки (дата сборки 25.11.2024)В архиве содержится часть игр с оригинальных картриджей приставки, переделанных в формат *.alf и готовых к сборке в образ картриджа.
Адаптированные игры (дата сборки 9.12.2024)В архиве содержатся все адаптированные на данный момент игры в формате *.alf, готовые к сборке в образ картриджа.