Как написать игру для ZX Spectrum на ассемблере


         

БЫСТРЫЙ ВЫВОД СПРАЙТОВ - часть 3


Прежде чем привести ее текст, объясним смысл вновь встретившейся здесь команды. Это инструкция EX (SP),HL, которая обменивает содержимое регистровой пары HL со значением, находящимся на вершине машинного стека: то, что было в HL, помещается на вершину стека, а два байта со стека перемещаются в HL. Значение регистра SP при этом не изменяется. Обратите внимание на то, как в подпрограмме WRITE2 осуществляется переход по выбранному адресу: число заносится в стек командой EX (SP),HL, а затем выполняется команда RET.

Другой момент, требующий пояснения, это процедура, расположенная в ПЗУ по адресу 8, благодаря чему ее можно вызывать командой RST. Она используется интерпретатором для выдачи различных сообщений и с ее помощью можно в любой момент остановить практически любую программу в кодах при возникновении критической ошибки. Код сообщения, уменьшенный на единицу (например, -1 для 0 OK), записывается в директиве DEFB непосредственно за командой RST 8.

WRITE LD A,(HL) ;берем очередной символ из строки INC HL AND A RET Z ;вывод символов до кода 0 CP " " JR C,WRITE2 ;если управляющий код (< 32) WRITE1 CALL PRSYM JR WRITE ; Выбор из таблицы адреса перехода в зависимости от кода WRITE2 PUSH HL PUSH BC LD HL,TABLE ;адрес таблицы LD C,A ;сохраняем код в C WRITE3 LD A,(HL) ;читаем код из таблицы INC HL AND A JR Z,WRITE5 ;если встречен маркер конца таблицы CP C JR Z,WRITE4 ;если код найден INC HL ;пропускаем 2 байта адреса INC HL JR WRITE3 ;проверяем следующий код WRITE4 POP BC LD A,(HL) ;берем из таблицы адрес перехода INC HL LD H,(HL) ;помещаем его в HL LD L,A EX (SP),HL ;восстанавливаем HL, а адрес записываем ; на вершину стека RET ;переходим по адресу с вершины стека WRITE5 POP BC ;если код отсутствует в таблице, POP HL ; то восстанавливаем регистры LD A,"?" ; и печатаем символ ?

JR WRITE1 ; Перевод строки PR_13 PUSH HL LD HL,(23684) ;адрес текущей позиции печати LD A,L AND %11100000 ;возвращаемся к началу строки ADD A,#20 ;переходим к следующей строке LD L,A JR NZ,PR13_1 ;если не перешли в следующую треть LD A,H ADD A,8 ;старший байт адреса увеличиваем на 8 LD H,A CP #58 ;проверяем, был ли выход за пределы экрана JR C,PR13_1 LD H,#40 ;переводим позицию печати в верхнюю ; строку экрана PR13_1 LD (23684),HL ;возвращаем рассчитанный адрес ; позиции печати POP HL JR WRITE ; Цвет «чернил» INK PR_16 LD A,(HL) ;читаем следующий байт из строки AND %111 ;выделяем 3 младших бита (значения 0...7) PUSH BC LD B,%11111000 ;в регистре B - маска битов для INK PR16_1 LD C,A LD A,(IY+85) ;23695 AND B ;освобождаем биты предыдущего атрибута OR C ; и записываем на их место новое значение LD (IY+85),A ;возвращаем байт атрибутов PR16_2 POP BC INC HL JR WRITE ; Цвет «бумаги» PAPER PR_17 LD A,(HL) ;с цветом PAPER аналогично INK AND %111 RLCA ; только предварительно сдвигаем RLCA ; биты на свое место RLCA PUSH BC LD B,%11000111 JR PR16_1 ; Мерцание FLASH PR_18 LD A,(HL) AND 1 PUSH BC LD B,%01111111 PR18_1 RRCA JR PR16_1 ; Яркость BRIGHT PR_19 LD A,(HL) AND 1 PUSH BC LD B,%10111111 RRCA JR PR18_1 ; Инверсия INVERSE (3-й бит в системной переменной P_FLAG) PR_20 LD A,(HL) AND 1 PUSH BC LD B,%11110111 RLCA RLCA PR20_1 RLCA LD C,A LD A,(IY+87) AND B OR C LD (IY+87),A JR PR16_2 ; Режим наложения OVER (1-й бит в системной переменной P_FLAG) PR_21 LD A,(HL) AND 1 PUSH BC LD B,%11111101 JR PR20_1 ; Позиционирование курсора AT PR_22 LD A,(HL) ;берем номер строки CP 24 ;если больше 24, то выход позиции JR NC,OUTSCR ; печати за пределы экрана INC HL PUSH DE PUSH HL CALL 3742 ;вычисляем адрес начала строки POP DE LD A,(DE) ;берем номер столбца CP 32 ;если больше 32, то выход позиции JR NC,OUTSCR ; печати за пределы экрана INC DE ADD A,L LD L,A LD (23684),HL ;запоминаем адрес новой позиции POP HL EX DE,HL JP WRITE OUTSCR RST 8 ;сообщение Бейсика DEFB 4 ; «Out of screen»




Содержание  Назад  Вперед