Программирование для приставок Заключительная глава данной книги посвящена вопросам разработки программного обеспечения, связанного с приставками. Глава разделена на две части. В первой части рассматривается процесс создания программ для игровых приставок. Кратко описывается типичная структура игровой программы и необходимые инструментальные средства, приводятся сведения об отладке программ. Во второй части рассказывается об эмуляции игровых приставок с помощью персонального компьютера. Здесь разбирается структура программы-эмулятора и анализируются имеющиеся в ней функции. Весь материал представлен применительно к игровой приставке DENDY, однако его можно использовать и для других приставок. 5.1. Создание программ для игровых приставок В целом создание программ для игровых приставок аналогично разработке программ для обычных компьютеров, но существуют и некоторые особенности. В основном они связаны с использованием кросс-средств, поскольку программа составляется не на том компьютере, на котором будет выполняться. Также широко применяются специализированные графические редакторы, которые ускоряют процесс получения фоновых изображений и спрайтов в формате, требующемся для конкретной приставки. 5.1.1. Использование инструментальных средств Ниже представлен перечень инструментальных средств, необходимых для разработки программ: * текстовый редактор, в котором набираются исходные тексты программы; * кросс-ассемблер (если вы создаете программу на ассемблере) или кросс-компилятор (если вы пишете программу на языке высокого уровня), которые генерируют код для процессора, установленного в игровой приставке; * специализированный графический редактор, с помощью которого будет создаваться игровая графика (его тип зависит от того, для какой игровой приставки предназначается программа); * эмулятор игровой приставки для предварительной отладки программы; * программатор и перепрограммируемый картридж для завершающей отладки и создания ПЗУ картриджа. Для каждой игровой системы фирма-производитель выпускает комплект разработчика, включающий все названные компоненты и необходимую документацию. Однако, поскольку цена такого комплекта колеблется от 2000 до 10000 долларов, его приобретение для домашнего использования не представляется возможным. Как правило, вместо него применяют бесплатные и условно бесплатные программы аналогичного назначения, доступные через Internet. Часто весь набор программ (за исключением программатора) объединяют в комплект, называемый интегрированной средой разработки (IDE). Перечислим этапы создания программы: 1. Написание первой версии программы, определение ее размера и типа ПЗУ, создание графики. 2.Отладка базовой версии программы с помощью эмулятора. 3.Запись отлаженной программы в перепрограммируемое ПЗУ картриджа и ее проверка на игровой приставке. Не следует пропускать этот этап, поскольку функционирование эмулятора и приставки не идентично, особенно при формировании звукового сопровождения и при использовании жесткой синхронизации по времени выполнения. 4.Добавление в базовый вариант звукового сопровождения, дополнительной графики, специальных аппаратно-зависимых функций, после чего программа снова проверяется на реальной приставке. 5.Запись готовой программы в ПЗУ картриджа и передача на окончательное тестирование. 5.1.2. Структура игровой программы На рис. 5.1 приведена блок-схема типичной программы для игровой приставки. В данном разделе мы рассмотрим ее структуру и назначение отдельных блоков, а в следующем покажем, как указанные концепции реализуются при программировании для конкретной модели. Рис. 5.1. Блок-схема программы для игровой приставки ИТАК, ПЕРВЫМ ДЕЙСТВИЕМ, КОТОРОЕ ДОЛЖНА ВЫПОЛНИТЬ ПРОГРАММА, ЯВЛЯЕТСЯ ИНИЦИАЛИЗАЦИЯ АППАРАТУРЫ ПРИСТАВКИ. ФАКТИЧЕСКИ ПРИ ЭТОМ В РЕГИСТРЫ ВИДЕОПРОЦЕССОРА, КОНТРОЛЛЕРА ВВОДА/ВЫВОДА, ЗВУКОВОГО ПРОЦЕССОРА И ДРУГИХ МИКРОСХЕМ ЗАПИСЫВАЮТСЯ ЗНАЧЕНИЯ, ОПРЕДЕЛЯЮЩИЕ РЕЖИМ РАБОТЫ. ЧТОБЫ ДОБИТЬСЯ СТАБИЛЬНОГО ФУНКЦИОНИРОВАНИЯ ПРОГРАММЫ, НЕОБХОДИМО ЯВНО ЗАДАВАТЬ ВСЕ ЗНАЧЕНИЯ, А НЕ ПОЛАГАТЬСЯ НА ТЕ, КОТОРЫЕ УСТАНАВЛИВАЮТСЯ В ПРИСТАВКЕ ПРИ НАЖАТИИ КНОПКИ RESET. ЗАТЕМ ПРОИСХОДИТ ИНИЦИАЛИЗАЦИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ ИГРОВОЙ ПРОГРАММЫ. В ПАМЯТЬ ВИДЕОПРОЦЕССОРА ЗАГРУЖАЮТСЯ НЕОБХОДИМЫЕ ЗНАКОГЕНЕРАТОРЫ И УКАЗЫВАЮТСЯ НАЧАЛЬНЫЕ ЗНАЧЕНИЯ ПЕРЕМЕННЫХ, КОТОРЫЕ ЯВЛЯЮТСЯ ОБЩИМИ ДЛЯ ВСЕЙ ПРОГРАММЫ. ОБЫЧНО ЭТО АДРЕСА РАЗЛИЧНЫХ ТАБЛИЦ, ПОДПРОГРАММ ОБРАБОТКИ ЗАПРОСОВ НА ПРЕРЫВАНИЕ И ССЫЛКИ НА РАЗЛИЧНЫЕ СТРУКТУРЫ ДАННЫХ. ПОСЛЕ ЗАВЕРШЕНИЯ ИНИЦИАЛИЗАЦИИ НА ЭКРАН ВЫВОДИТСЯ ГЛАВНОЕ МЕНЮ ИГРЫ, ПРОГРАММА ПЕРЕХОДИТ В СОСТОЯНИЕ ОЖИДАНИЯ ВВОДА ДАННЫХ. В ЭТОМ БЛОКЕ В ПРОСТЕЙШЕМ СЛУЧАЕ СЛЕДУЕТ ПОСТОЯННО ОПРАШИВАТЬ СОСТОЯНИЕ КНОПКИ START НА ИГРОВОМ ПУЛЬТЕ, А КОГДА ОНА БУДЕТ НАЖАТА, ПЕРЕЙТИ К СЛЕДУЮЩЕМУ БЛОКУ. БОЛЕЕ СЛОЖНЫЕ МЕНЮ МОГУТ ВКЛЮЧАТЬ В СЕБЯ НЕСКОЛЬКО ПУНКТОВ, ПОЗВОЛЯЮЩИХ ВЫБРАТЬ ЧИСЛО ИГРОКОВ, ИЗМЕНИТЬ УРОВЕНЬ СЛОЖНОСТИ, ЗАГРУЗИТЬ ЗАПИСАННУЮ РАНЕЕ ИГРОВУЮ СИТУАЦИЮ И Т.Д. КРОМЕ ТОГО, МЕНЮ ДОПУСТИМО ОФОРМИТЬ С ПОМОЩЬЮ РАЗЛИЧНЫХ АНИМИРОВАННЫХ СПРАЙТОВ, ДОБАВИТЬ МУЗЫКАЛЬНОЕ СОПРОВОЖДЕНИЕ - ТОГДА СТРУКТУРА МЕНЮ УПОДОБИТСЯ СТРУКТУРЕ ЦЕЛОЙ ПРОГРАММЫ С БЛОКАМИ, ОБРАБАТЫВАЮЩИМИ РАЗЛИЧНЫЕ ВАРИАНТЫ ВЫБОРА ПОЛЬЗОВАТЕЛЯ, ОТВЕЧАЮЩИМИ ЗА ВЫВОД ИЗОБРАЖЕНИЙ И ЗВУКА, ПЕРЕМЕЩАЮЩИМИ ГРАФИЧЕСКИЕ ОБЪЕКТЫ. КОГДА ПОЛЬЗОВАТЕЛЬ ВВЕЛ ТРЕБУЕМЫЕ ДАННЫЕ И НАЖАЛ НА КНОПКУ START, ЗАПУСКАЕТСЯ СОБСТВЕННО ИГРОВАЯ ПРОГРАММА, КОТОРАЯ НАЧИНАЕТСЯ С ИНИЦИАЛИЗАЦИИ ПЕРЕМЕННЫХ. В ЭТОМ БЛОКЕ УКАЗЫВАЕТСЯ ЧИСЛО ИГРОВЫХ ОБЪЕКТОВ И ИХ НАЧАЛЬНЫЕ ПОЗИЦИИ, СЧЕТ ИГРЫ СТАНОВИТСЯ РАВНЫМ 0, ЗАДАЕТСЯ СТАРТОВАЯ ПОЗИЦИЯ ИГРОКА, А В ВИДЕОПАМЯТЬ ПРИ НЕОБХОДИМОСТИ ЗАГРУЖАЕТСЯ НОВЫЙ ЗНАКОГЕНЕРАТОР. ОСНОВНОЙ ЦИКЛ ИГРЫ НАЧИНАЕТСЯ ВВОДОМ ИНФОРМАЦИИ С ИГРОВОГО ПУЛЬТА. ЗАТЕМ ЦЕНТРАЛЬНЫЙ ПРОЦЕССОР РАССЧИТЫВАЕТ НОВЫЕ ПОЛОЖЕНИЯ ВСЕХ ИГРОВЫХ ОБЪЕКТОВ И ПРОВЕРЯЕТ, НЕ ЗАКОНЧИЛАСЬ ЛИ ИГРА. ЕСЛИ ИГРА ДЕЙСТВИТЕЛЬНО ЗАКОНЧИЛАСЬ, ПРОГРАММА ВЫВЕДЕТ ФИНАЛЬНУЮ КАРТИНКУ И ВЕРНЕТСЯ К НАЧАЛЬНОМУ МЕНЮ. В ПРОТИВНОМ СЛУЧАЕ ПОСЛЕ ОЧЕРЕДНОГО КАДРОВОГО СИНХРОИМПУЛЬСА ПРОЦЕССОР ОБНОВИТ ИЗОБРАЖЕНИЕ НА ЭКРАНЕ, А ПРОГРАММА БУДЕТ ВВОДИТЬ ДАННЫЕ С ПУЛЬТА, И ОСНОВНОЙ ЦИКЛ ПОВТОРИТСЯ. ОТМЕТИМ, ЧТО ПРОЦЕДУРА ОБНОВЛЕНИЯ ИЗОБРАЖЕНИЯ ЧАСТО ВЫЗЫВАЕТСЯ ПРИ ПОСТУПЛЕНИИ ЗАПРОСА НА ПРЕРЫВАНИЕ ПО КАДРОВОМУ СИНХРОИМПУЛЬСУ. В ЭТОМ СЛУЧАЕ ПРОЦЕССОР НЕ ТРАТИТ ВРЕМЯ НА ОЖИДАНИЕ СИНХРОИМПУЛЬСА, А СРАЗУ ПЕРЕХОДИТ К НОВОМУ ВВОДУ ДАННЫХ С ПУЛЬТА. КОНЕЧНО, БЛОКИ ОПИСАННОЙ СХЕМЫ МОГУТ МЕНЯТЬСЯ МЕСТАМИ. ДЛЯ УПРОЩЕНИЯ МАТЕРИАЛА В ПРЕДСТАВЛЕННУЮ БЛОК-СХЕМУ НЕ ВКЛЮЧЕНЫ МОДУЛИ, КОТОРЫЕ ОТВЕЧАЮТ ЗА ВЫВОД ЗВУКОВОГО СОПРОВОЖДЕНИЯ. 5.1.3. Пример разработки программы ДЛЯ ИЗУЧЕНИЯ ОСНОВ ПРОГРАММИРОВАНИЯ МЫ ВЫБРАЛИ ЛОГИЧЕСКУЮ ИГРУ SOKOBAN, НА ПРИМЕРЕ КОТОРОЙ МОЖНО ОЗНАКОМИТЬСЯ С ОСОБЕННОСТЯМИ РАБОТЫ С ПУЛЬТАМИ И ГРАФИКОЙ, А ПОТОМ ПЕРЕЙТИ К СОЗДАНИЮ СОБСТВЕННЫХ ПРОЕКТОВ. ПОПРОБУЕМ НАПИСАТЬ ПРОСТЕЙШУЮ ИГРУ ДЛЯ ПРИСТАВКИ DENDY, ВОСПОЛЬЗОВАВШИСЬ БЛОК-СХЕМОЙ, ПРИВЕДЕННОЙ НА РИС. 5.1. ПОЛНЫЙ ТЕКСТ ПРОГРАММЫ ПРИВЕДЕН В ПРИЛОЖЕНИИ 2. НАЧНЕМ С РАСПРЕДЕЛЕНИЯ ПАМЯТИ И ОПРЕДЕЛЕНИЯ ОСНОВНЫХ СТРУКТУР ДАННЫХ. ИГРА SOKOBAN СОСТОИТ ИЗ НЕСКОЛЬКИХ УРОВНЕЙ, КАЖДЫЙ ИЗ КОТОРЫХ ПРЕДСТАВЛЯЕТ СОБОЙ НЕБОЛЬШОЙ ЛАБИРИНТ. В РАЗНЫХ МЕСТАХ РАССТАВЛЕНЫ КОНТЕЙНЕРЫ, КОТОРЫЕ ИГРОК ДОЛЖЕН ПЕРЕМЕСТИТЬ НА ВЫДЕЛЕННОЕ ДЛЯ НИХ МЕСТО. ПРИ ЭТОМ ИГРОК МОЖЕТ ПЕРЕДВИГАТЬСЯ САМ ИЛИ ТОЛКАТЬ ОДИН КОНТЕЙНЕР. ТЯНУТЬ КОНТЕЙНЕР ЗА СОБОЙ ИЛИ ТОЛКАТЬ НЕСКОЛЬКО КОНТЕЙНЕРОВ ЗАПРЕЩЕНО. ТИПИЧНЫЙ ВИД ИГРОВОГО ЭКРАНА ПРЕДСТАВЛЕН НА РИС. 5.2. Рис. 5.2. Вид игрового экрана программы Sokoban НАМЕТИМ ОСНОВНЫЕ БЛОКИ ДАННЫХ, СОСТАВЛЯЮЩИЕ ИГРУ. ВО-ПЕРВЫХ, НЕОБХОДИМ ЗНАКОГЕНЕРАТОР, ИЗ КОТОРОГО БУДУТ СОЗДАВАТЬСЯ ИЗОБРАЖЕНИЯ НА ЭКРАНЕ. ЧТОБЫ СДЕЛАТЬ ИГРУ ПРИВЛЕКАТЕЛЬНЕЕ, МЫ БУДЕМ ПРИМЕНЯТЬ ДЛЯ КАЖДОГО УРОВНЯ РАЗНЫЕ НАБОРЫ СИМВОЛОВ. ВСЕГО ПОТРЕБУЕТСЯ ПЯТЬ ГРУПП СИМВОЛОВ ДЛЯ ОТОБРАЖЕНИЯ СЛЕДУЮЩИХ ОБЪЕКТОВ: СТЕНА, ПОЛ, МЕСТО ДЛЯ КОНТЕЙНЕРА, КОНТЕЙНЕР И ИГРОК, А ТАКЖЕ ОТДЕЛЬНЫЙ СИМВОЛ ПРОБЕЛА ДЛЯ ЗАПОЛНЕНИЯ НЕИСПОЛЬЗУЕМЫХ ФРАГМЕНТОВ ЭКРАНА. НЕПОДВИЖНЫЕ ОБЪЕКТЫ, к которым относятся пол, стены и места для контейнеров, выводятся как фоновое изображение, игрок и контейнеры реализуются в виде спрайтов. Сам знакогенератор помещается в ПЗУ, подключаемое к видеопроцессору. Итак, произведем распределение памяти знакогенератора: * символы с кодами 00h - 3Fh применяются для стен; * символы с кодами 50h - 8Fh - для пола; * символы с кодами A0h - DFh - обозначение мест для контейнеров; * спрайты с кодами 00h - 3Fh - для игрока; * спрайты с кодами 40h - 7Fh - для контейнеров. Кроме перечисленных, в знакогенераторе располагаются символы для создания титульного экрана с кодами от F0h до FFh (символы для титульной картинки) и от 9Ah до 9Fh (символы для надписи «PRESS STARTV). Первый знакогенератор с базовым адресом 0000h используется для спрайтов, а второй, начинающийся с адреса l000h, - для элементов фонового изображения. Выбранное в данном случае распределение памяти знакогенератора приведено на рис. 5.3. Рис. 5.3. Распределение памяти в знакогенераторе игры Sokoban Вы можете нарисовать свой знакогенератор, руководствуясь приведенными в описании игровой приставки сведениями, или воспользоваться готовым знакогенератором из файла sokoban.chr. Помимо знакогенератора нам потребуется ПЗУ для хранения карт уровней, титульного экрана и самой программы. Разработаем структуры уровня игры. Для каждого уровня нужна карта и палитра. Карты уровней начинаются с адреса 8000h, каждая занимает 256 байт и состоит соответственно из 16 строк по 16 байт. Первый байт в каждой строке используется для хранения цвета из палитры данного уровня. Таким образом, в 16 строках заданы все 16 цветов палитры уровня. Оставшиеся 15 байт строки применяются для изображения карты уровня. Каждый байт определяет две клетки карты, при этом принята следующая кодировка: 0 - пустая клетка? 1 - стена; 2 - пол; 3 - место для контейнера; 4 - контейнер; 5 - игрок. Закодированные данные для карты уровня, изображенного на рис. 5.2, при этом будут выглядеть так: 8000: 00 00 00 00 00 00 00 00 8008: 00 00 00 00 00 00 00 00 8010: 0Е 00 00 00 00 00 00 00 8018: 00 00 00 00 00 00 00 00 8020: 02 00 00 00 00 00 00 00 8028: 00 00 00 00 00 00 00 00 8030: 11 00 00 00 00 01 11 11 8038: 00 00 00 00 00 00 00 00 8040: 21 00 00 00 00 01 22 21 8048: 00 00 00 00 00 00 00 00 8050: 0F 00 00 00 00 01 42 21 8058: 00 00 00 00 00 00 00 00 8060: 02 00 00 00 01 11 22 41 8068: 10 00 00 00 00 00 00 00 8070: 05 00 00 00 01 22 42 42 8078: 10 00 00 00 00 00 00 00 8080: 36 00 00 01 11 21 21 12 8088: 10 00 11 11 11 00 00 00 8090: OF 00 00 01 22 21 21 12 8098: 11 11 12 23 31 00 00 00 80А0: 05 00 00 01 24 22 42 22 80А8: 22 22 22 23 31 00 00 00 80В0: 15 00 00 01 11 11 21 11 80В8: 21 51 12 23 31 00 00 00 80С0: 14 00 00 00 00 01 22 22 80С8: 21 11 11 11 11 00 00 00 80D0: 00 00 00 00 00 01 11 11 80D8: 11 00 00 00 00 00 00 00 80Е0: 00 00 00 00 00 00 00 00 80Е8: 00 00 00 00 00 00 00 00 80F0: 00 00 00 00 00 00 00 00 80F8: 00 00 00 00 00 00 00 00 Следуя приведенному образцу, можно создавать уровни вручную или написать программу для рисования уровней и знакогенераторов к ним. Кроме карт уровней, в выделенной области памяти находится титульный экран и палитра для него. Эти данные занимают диапазон адресов B200h - B30Fh. Начиная с адреса C000h располагается сама программа, а в ячейках FFFAh - FFFFh записаны три адреса, по которым осуществляется переход при сбросе процессора и поступлении запросов на маскируемое и немаскируемое прерывание. Распределение памяти в нашей программе можно увидеть на рис. 5.4. Рис. 5.4. Распределение памяти в игре Sokoban Теперь перейдем к написанию программы. Сначала в блок-схеме идет инициализация аппаратуры, создание таблиц, распределение памяти и другие действия, выполняющиеся только один раз при первом запуске программы с помощью следующего фрагмента: org $С000 ; Адрес начала программы, reset: sei cld ldx #$0 stx $2000 ; Выключение ; видеопроцессора. stx ppuconl stx $2001 ldx #$FF txs ; Установка указателя ; стека. lda #7 ; Подготовка к очистке sta $1 ; ОЗУ по адресам ; 0 - $7FF. lda #0 ldy #0 clrram: sta (0),y ; Цикл очистки ОЗУ. dey bne clrram dec $1 bpl clrram lda #$20 ; Подготовка к очистке ; видеопамяти, sta $2006 ; Запись адреса для ; доступа к видеопамяти lda #0 ; в регистры ; видеопроцессора. sta $2006 ldy #$10 ldx #0 clrvram: sta $2007 ; Цикл очистки ; видеопамяти. dex bne clrvram dey bne clrvram lda #$3F ; Установка адреса ldx #$0 ; для копирования sta $2006 ; палитры в память ; видеопроцессора. stx $2006 ldy #$20 setpal: lda bgpal,x ; Цикл ; копирования ; данных sta $2007 ; в ОЗУ палитры. inx dey bne setpal lda #$0 ; Задание ; используемых ; символов sta bgwall ; для стен, lda #$50 sta bgground ; для пола, lda #$A0 sta bggoal ; для мест ; контейнеров, lda #$0 sta spchar ; для игрока, lda #$40 sta spbox ; для контейнера. lda #1 sta boxleft lda #$90 ; Включение ; видеопроцессора, ; задание sta $2000 ; экранной страницы ; и разрешение sta ppucon1 ; на формирование ; запроса NMI. После выполнения приведенного фрагмента приставка полностью инициализирована и готова к работе. Обратите внимание: в этой части программы явно производится очистка всех областей памяти. Никогда не стоит рассчитывать, что при запуске программы во всех ячейках памяти и регистрах будут записаны нули. Следующим фрагментом блок-схемы является отображение титульного экрана и работа с меню. Стартовое меню в нашей игре отсутствует, и после вывода заставки программа просто ждет, пока на игровом пульте будет нажата кнопка START. Весь блок удобно оформить в виде подпрограммы и добавить в основную программу следующий фрагмент: lda #0 sta startkey jsr title ; Вывод титульного экрана. После того как пользователь нажал требуемую кнопку, программа переходит к следующему блоку - началу основного цикла игры: lda #$80 ; Установка ; указателя ; данных уровня sta lvlptr+1 ; на адрес $8000 ; (уровень 1). loop: jsr loadlevel ; Загрузка ; уровня. waitnmi: jmp waitnmi ; Ожидание ; кадрового ; импульса. Все действия очень просты: сначала указатель текущего уровня устанавливается на адрес 8000h -адрес блока данных для первого уровня. Затем подпрограмма loadlevel загружает карту уровня и отображает ее на экране. Когда уровень загружен, программа входит в бесконечный цикл и ожидает поступления запроса на прерывание по кадровому синхроимпульсу от видеопроцессора. После поступления запроса на немаскируемое прерывание, который формируется видеопроцессором в начале кадрового синхроимпульса, центральный процессор прекращает цикл ожидания и переходит на метку vblank. Если текущий уровень выполнен, программа начнет загрузку в память следующего уровня; если же задача, стоящая перед игроком, еще не решена, будет произведена инициализация рабочих переменных. vblank: pha ; Сохранение ; регистров А, X и Y txa ; в стеке. pha tya pha lda boxleft ; Если boxleft = 0, ; то уровень bne play ; завершен. inc lvlptr+1 ; Изменение указателя ; на данные jsr loadlevel ; и загрузка нового ; уровня. play: lda #0 ; Отключение ; скроллинга ; изображения. sta $2005 sta $2005 sta dirx ; Обнуление ; переменных, sta diry ; задающих ; направление ; движения. lda #2 sta $4014 ; Программирование ; звукового ; процессора. После опроса игрового пульта можно изменить положение всех объектов на игровом поле. Сначала фиксируется состояние пульта в его регистре и считывается состояние кнопок А, В и SELECT. Поскольку в игре эти кнопки не используются, то полученные данные игнорируются. ldx #1 ; Фиксация состояния ; пульта. stx $4016 dex stx $4016 lda $4016 ; Считывание состояния ; кнопок А, В и SELECT. lda $4016 ; Эти КНОПКИ lda $4016 ; не используются. Затем проверяется состояние КНОПКИ START. Если игрок нажимает эту кнопку, происходит перезагрузка текущего уровня. lda $4016 ; Нажата клавиша START? and #1 beq notstart pla ; Да, стек очищается. pla pla dec bgwall ; Установка ; знакогенератора. dec bgground dec bggoal dec spchar dec spbox jmp bigloop ; Повторная загрузка ; уровня. Затем следует проверка состояния клавиш управления движением игрока. Если какая-либо из них нажата, то программа соответствующим образом инициализирует переменные dirx и diry, после чего управление передается фрагменту, начинающемуся с метки trymove, который проверяет допустимость данного перемещения. Если же ни одна из клавиш не задействована, то процедура обработки прерывания прекращается, и программа продолжает исполнение бесконечного цикла, ожидая нового запроса на прерывание. notstart: lda #0 sta startkey. lda $4016 ; Вверх. and #1 beq notup lda #$FF sta diry jmp trymove notup: lda $4016 ; Вниз. and #1 beq notdown lda #1 sta diry jmp trymove notdown: lda $4016 ; Влево. and #1 beq notleft lda #255 sta dirx jmp trytomove notleft: lda $4016 ; Вправо. and #1 beq notmove lda #1 sta dirx jmp trytomove notmove: pla ; Восстановление ; регистров. tay pla tax pla rti Фрагмент программы, расположенный начиная с метки trymove, контролирует перемещение игрока в указанном направлении. Если движение невозможно, программа переходит на метку notmove и возвращается в цикл ожидания кадрового синхроимпульса. Если же игрок передвигается, будет вызвана подпрограмма move, меняющая положение спрайта игрока. Однако если при этом необходимо перетащить еще и контейнер, то вызывается подпрограмма movebox, перемещающая спрайты контейнера и игрока. Прежде чем осваивать написание программ для конкретной приставки, следует научиться адаптировать имеющиеся программы. Однако у каждой из рассмотренных приставок существуют свои правила оформления программ, фиксированные области данных и т.д. Часть этих особенностей уже рассматривалась при описании конкретных приставок и сопровождалась фрагментами программ. Кроме того, в приложении 2 приведено несколько законченных программ. Их изучение и модификация позволят лучше понять приемы программирования игровых приставок различных моделей. |