ZX-Ревю 1993 №7-8 1992 г.

Применение ассемблера для создания быстроработающих программ - продолжение. (начало см. с. 9-12, 48-61, 97-103) ДВИЖЕНИЕ.


ПРИМЕНЕНИЕ АССЕМБЛЕРА ДЛЯ СОЗДАНИЯ БЫСТРОРАБОТАЮЩИХ ПРОГРАММ

Перевод с английского Пашорина В.И.

Продолжение. Начало см. с. 9-12, 48-61, 97-103

7. ДВИЖЕНИЕ

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

Для организации движения изображения по экрану большинство программистов используют знакоместа, что позволяет ускорить выполнение программы и оперировать с любым из возможных цветов. Весь экран представляет собой прямоугольную матрицу 24x32, т.е. всего 768 знакомест и поэтому перемещение символа из одного знакоместа в другое, соседнее с ним, выглядит не совсем плавным. При этом, если необходимо показать перемещение только одного пиксела, приходится переписывать весь символ из одного знакоместа в другое. Однако при этом, в отличие от BASIC-команды PLOT, нет ограничений на выбор цвета.

Перемещение знакоместа переднего плана экрана

Для начала необходимо определить стартовую позицию шаблона и затем, используя способы, рассмотренные в главе 5, установить шаблон в это знакоместо. Обычно начальное положение дублируется, поскольку полностью задать положение шаблона - это значит установить его текущее и последующее положения на экране дисплея. Для исключения мигания при перемещении шаблона необходимо сразу же выводить его в новой позиции целиком. Такой способ используется для задания режима OVER 1, при котором перемещение шаблона осуществляется на фоне заднего плана без изменения последнего.

Программа 7.1 демонстрирует этот способ. Здесь шаблон в виде космического корабля перемещается по экрану вверх/вниз при нажатии клавиш 1/Q и вправо /влево при нажатии клавиш 9/0. Клавиша "SPACE" используется для возврата в БЕЙСИК.

Листинг 7. 1.

КОММЕНТАРИЙ

;Отключение прерываний. ;Переход на начало работы. ;Шаблон символа CHR$ 144. ;Шаблон символа CHR$ 145. ;Шаблон символа CHR$ 145. ;Начало области UDG.

23760

23761

23763 DATA_1

23771

23779

23787 START 23791 23794 23797

135 7

LD DE, (23675)

LD HL,DATA_1

LD BC,24

23799

23801 DATA_2

18 0A JR BEGIN

22 0 0 16 8 17 8 144 145 146

23811 BEGIN 23815

FD 36 0E 28 FD 36 53 0F

LD (IY+14),40 LD (IY+83),15

Задание трех первых символов графики UDG.

Переход на начало работы. Эта последовательность кодов является символьной строкой, которую можно трактовать как AT 0,0;PAPER 8;INK 8; CHR$ 144;CHR$ 145;CHR$ 146. Выставляем цвет бордюра. Выставляем INK и PAPER.

АДРЕС МЕТКА

МАШ. КОД

АССЕМБЛЕР

ORG 23760 F3 DI

18 18 JR START

0 0 15 24 49 226 225 224 24 60 255 255 153 255 231 60

0 0 240 24 140 71 ED 5B 7B 5C 21 D3 5C

01 18 00

ED B0 LDIR

23819

3E

02

LD A,02

23821

CD

01

16

CALL 5633

Открыли канал печати на экран

23824

CD

6B

0D

CALL 3435

Очистка экрана.

23827

3E

02

LD A,02

23829

CD

01

16

CALL 5633

23832

11

F9

5C

LD DE,DATA 2

Начало символьной строки.

23835

01

0A

00

LD BC,10

Длина символьной строки.

23838

CD

3C

20

CALL 8252

Печать символьной строки.

23841

L7

11

00

5B

LD DE,23296

Начало буфера принтера.

23844

21

F9

5C

LD HL,DATA 2

Начало символьной строки.

23847

01

0A

00

LD BC,10

Длина символьной строки.

23850

ED

B0

LDIR

Переброска символьной строки DATA_2 в начало буфера принтера.

23852

2A

01

5B

LD HL,(23297)

Координаты текущей позиции печати.

23855

01

FE

EF

LD BC,61438

23858

ED

78

IN A,(C)

Ввод данных с порта клавиатуры. Согласно тому числу, которое установлено в ВС,здесь принимается сигнал с правой половины верхнего ряда клавиш (клавиши 6...0).

23860

CB

47

BIT 0,A

Проверка клавиши "0".

23862

20

01

JR NZ,L1

Переход, если не нажата.

23864

24

INC H

Если нажата.

23865

L1

CB

4F

BIT 1,A

Проверка клавиши "9".

23867

20

02

JR NZ,L2

Переход, если не нажата.

23869

25

DEC H

Если нажата.

23870

L2

01

FE

F7

LD BC,63486

23873

ED

78

IN A,(C)

Опрос полуряда (1...5).

23875

CB

47

BIT 0,A

Проверка клавиши " 1 " .

23877

20

01

JR NZ,L3

Переход, если не нажата.

23879

2D

DEC L

Если нажата.

23880

L3

01

FE

FB

LD BC,64510

23883

ED

78

IN A,(C)

Опрос полуряда (Q...T).

23885

CB

47

BIT 0,A

Проверка клавиши "Q".

23887

20

01

JR NZ,L4

Переход, если не нажата.

23889

2C

INC L

Если нажата.

23890

L4

7D

LD A,L

Координата по вертикали.

23891

FE

16

CP 22

Проверка на выход за пределы экрана снизу.

23893

20

03

JR NZ,L5

Переход, если все в порядке.

23895

2D

DEC L

Иначе уменьшаем L

23896

18

05

JR L6

и переходим на метку L6.

23898

L5

FE

FF

CP 255

Проверка на выход за пределы экрана сверху.

23900

20

01

JR NZ,L6

Переход, если все в порядке.

23902

2C

INC L

Иначе увеличиваем L.

23903

L6

7C

LD A,H

23904

FE

1E

CP 30

Проверка на выход за пределы экрана справа.

23906

20

03

JR NZ,L8

Переход, если все в порядке.

23908

25

DEC H

Иначе уменьшаем Н.

23909

18

05

JR L9

и переходим на метку L9.

23911

L8

FE

FF

CP 255

Проверка на выход за пределы экрана слева.

23913

20

01

JR NZ,L9

Переход, если все в порядке.

23915

24

INC H

Иначе увеличиваем Н.

23916

L9

ED

5B

01 5B

LD DE,(23297)

Координаты старой позиции печати.

23920

AF

XOR A

Обнуление флага переноса (это важный момент при подготовке к исполнению команды SBC).

23921

E5

PUSH HL

Запомнили координаты новой

позиции печати на стеке.

23922

ED

52

SBC HL,DE

Проверяем изменилась ли позиция печати.

23924

E1

POP HL

Восстановили новую позицию.

23925

28

2C

JR Z,L12

Если позиция печати не не-нялась, делаем обход на L12

23927

22

01

5B

LD (23297)

HL

Запомнили координаты новой позиции печати в буфере принтера.

23930

FD

36

57 03

LD (IY+87)

3

Включение OVER 1.

23934

11

F9

5C

LD DE,DATA

2

23937

01

0A

00

LD BC,10

23940

CD

3C

20

CALL 8252

Печать в старых координатах

а поскольку включен режим OVER 1, то это на самом деле не печать, а стирание.

23943

11

00

5B

LD DE,23296

23946

01

0A

00

LD BC,10

23949

CD

3C

20

CALL 8252

;Печать в новой позиции.

23952

11

F9

5C

LD DE,DATA 2

23955

21

00

5B

LD HL,23296

23958

01

0A

00

LD BC,10

23961

LD

B0

LDIR

;Копирование новой позиции ;в старую.

23963

21

88

13

LD HL,5000

I

23966

L11

2B

DEC HL

I

23967

7C

LD A,H

|Цикл задержки.

23968

B5

OR L

I

23969

20

FB

JR NZ,L11

I

23971

L12

01

FE

7F

LD BC,32766

|Опрос нажатия

23974

ED

78

IN A,(C)

|клавиши

23976

CB

47

BIT 0,A

|"ПРОБЕЛ".

23978

C2

21

5D

JP NZ,L7

;Если не нажата, переход на

23981

FD

36

57

00 LD (IY+87),0

;Восстановление режима OVER

23985

FB

EI

;Разрешение прерываний.

23986

C9

RET

;Возврат в БЕЙСИК.

Космический корабль может перемещаться одновременно в двух направлениях без изменения изображения заднего плана. Корабль выводится в цветах PAPER 8 и INK 8, чтобы оставаться контрастный на любом фоне заднего плана изображения. Скорость перемещения корабля регулируется с помощью цикла задержки. Если же корабль остается неподвижным, то процедура стирающая старое изображение и печатающая новое обходится, чтобы избежать мерцания.

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

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

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

Перемещение изображения заднего плана экрана

Для задания перемещения заднего плана необходимо организовать перемещение не одного знакоместа, а всего экрана или его части. Это перемещение обычно выполняется в одном из 4 направлений: вверх, вниз, вправо, влево; причем перемещаются одновременно и символы и их атрибуты. Если смещение всего экрана происходит на одну символьную позицию, то необходимо решить, как поступить с символами, вышедшими за пределы экрана. Мы можем либо потерять их и выводить на противоположной стороне экрана пустые знакоместа, либо запомнить их вместе с атрибутами и затем выводить на экран в соответствующем месте на противоположной стороне. Такой эффект зацикливания изображения весьма полезен для игровых программ.

Программы с 7.2 по 7.5 демонстрируют смещение атрибутов без возврата с противоположной стороны для всех четырех направлений (такое движение принято называть "протяжкой" - SCROLL). Программы с 7.6 по 7.9 демонстрируют смещение атрибутов по всем четырем направлениям с возвратом (назовем это движение "прокруткой" - ROLL).

"Прокрутку" и "протяжку" символов для всех четырех направлений демонстрируют программы 7.10 ... 7.18.

Листинг 7.2

SCROLL вверх для атрибутов.

АДРЕС

МЕТКА

МАШ

. КОД

АССЕМБЛЕР КОММЕНТАРИЙ

ORG 23760

23760

11

00

58

LD DE,22528

Начало области экранных атрибутов.

23763

21

20

58

LD HL,22560

Начало области атрибутов для второго ряда знакомест.

23766

01

E0

02

LD BC,736

Длина перебрасываемого блока (23 нижних строки по 32 знакоместа).

23769

ED

B0

LDIR

Перенос атрибутов на одну строку вверх.

23771

06

20

LD B,32

Заполнение нижней строки

23773

3A

8D

5C

LD A,(23693)

экрана постоянными атрибута-

23776

L2

12

LD (DE),A

ми, взятыми из системной пе

23777

13

INC DE

ременной ATTR P(23693)

23778

10

F2

DJNZ L2

23780

C9

RET

Возврат.

Эти программы легко усовершенствовать для организации ROLL и SCROLL только части экрана. Весь экран условно разбит на 3 сегмента, по 8 рядов в каждом. Каждый ряд, в свою очередь, состоит из 8 линий. Каждая линия в дисплейной области памяти занимает 32 байта. Причем записывается в эту область памяти сначала первая линия первого ряда, затем первая линия второго ряда и т.д. последовательно до первой линии восьмого ряда, включительно.

Затем записываются вторые линии первых восьми рядов, затем третьи и так последовательно весь сегмент, после чего записывается второй и за ним последовательно третий сегмент экрана. Каждый сегмент занимает 2046 байтов в дисплейной области памяти.

Обратите внимание, что в процедурах 7.3...7.18 используются команды передачи блока байтов - LDIR и LDDR. После выполнения этих команд в регистровых парах HL и DE остается записанный конечный адрес блока +1 (для LDIR) и конечный адрес - 1 (для LDDR), Это можно использовать для задания адреса продолжения выполнения программ процедуры, а не перезаписывать адреса в HL и DE.

Программы 7.2...7.18 написаны так, чтобы не вносить в них изменения при смене адреса загрузки. Программа 7.19 является усовершенствованной версией программы SCREEN UP SCROLL. Если Вам все понятно в ней, попробуйте сами усовершенствовать программу SCREEN DOWN SCROLL.

Сравнивая программы 7.15 и 7.19 Вы заметите что вторая занимает уже не 99, а только 87 байтов, хотя и это не абсолютно компактная программа. Весьма полезные детали искусства программирования, а также способы уменьшения объема памяти и времени работы показаны в программе 7.15. Эта программа перемещает вверх каждый символ ряда, линия за линией.

SCROLL вниз для атрибутов

LD DE,23295 LD HL,23253 LD BC,736 LDDR LD B,32 LD A,(23593) L7 LD (BE),A INC DE DJNZ L7 RET

Листинг 7.4

SCROLL влево для атрибутов

LD B,24 LD HL,22528 L12 PUSH HL POP DE PUSH BC INC HL LD BC,31 LDIR

LD A,(23693) LD (DE),A POP BC DJNZ L12 RET

Листинг 7.5

SCROLL вправо для атрибутов

LD B,24 LD HL,23295 L14 PUSH HL POP DE PUSH BC DEC HL LD BC,31 LDDR

LD A,(23693) LD (DE),A POP BC DJNZ,L14 RET

Листинг 7.6

ROLL вверх для атрибутов.

L24

L25

L32

L16

L17

LD HL,22528

Начало ат

рибутов.

PUSH HL

Копирование

POP DE

через стек.

LD B,32

32 знако-

места ряда.

LD A,(HL)

Запомнили

PUSH AF

атрибуты на

стеке.

INC HL

Знакомес-

то справа.

DJNZ L16

Повтор для

всего ряда.

LD BC,736

Протяжка для

LDIR

23-х нижних

рядов.

LD B,32

Восстанавли-

POP AF

ваем атрибуты

DEC HL

верхнего ряда

LD (HL),A

в нижнем ряду

DJNZ L17

экрана.

RET

Возврат.

Листинг 7.7

ROLL вниз для атрибутов

LD HL,23295 PUSH HL POP DE LD B,32 LD A,(HL) PUSH AF DEC HL DJNZ L24 LD BC,736 LDDR LD B,32 POP AF INC HL LD (HL),A DJNZ L25 RET

Листинг 7.8

ROLL влево для атрибутов

LD B,24 LD HL,22528 PUSH HL POP DE PUSH BC LD A,(HL) INC HL LD BC,31 LDIR

LD (DE),A POP BC DJNZ L32 RET

Листинг 7.10 ROLL влево для

LD B,192 LD HL,16384

PUSH HL POP DE PUSH ВС LD A,(HL)

L1

INC HL LD ВС,31 LDIR

LD (DE,A)

L1

POP BC DJNZ L1

RET

L33

символов.

Высота экрана. Начало экранной области. Копирование через стек. Запомнили BC. Запомнили текущую линию самого левого знакоместа. Адрес линии справа.

31 знакоместо в ряду. Копирование. Копирование линии самого левого знакоместа в самое правое.

Восстановление счетчика линий Если не все линии скопированы, то возврат на L1. Выход.

Листинг 7.9

ROLL вправо для атрибутов

LD B,24 LD HL,23295 PUSH HL POP DE PUSH BC LD A,(HL) DEC HL LD BC,31 LDDR

LD (DE),A POP BC DJNZ L33 RET

Листинг 7.11

ROLL вправо для символов

LD B,192 LD HL,22527 PUSH HL POP DE PUSH BC LD A,(HL) DEC HL LD BC,31 LDDR

LD (DE),A POP BC DJNZ,L1 RET

Листинг 7.12

SCROLL влево для символов.

LD HL,16384 XOR A LD B,192 L13 PUSH BC PUSH HL POP DE INC HL LD BC,31 LDIR

LD (DE),A POP BC DJNZ L13 RET

Листинг 7.13

SCROLL влево для символов. (второй вариант)

LD HL,16384 LD DE,32 LD B,192 L1 LD (HL),0 ADD HL,DE DJNZ L1 LD HL,16385 LD DE,16384 LD BC,6143 LDIR

EX DE,HL LD (HL),0 RET

Листинг 7.14

SCROLL вправо для символов.

LD HL,22527 XOR A LD B,192 L14 PUSH BC PUSH HL POP DE DEC HL LD BC,31 LDDR

LD (DE),A POP BC DJNZ L14 RET

SCROLL вверх для символов.

LD DE,16384 LD HL,16416 LD BC,2016 LDIR LD B,8 LD HL,18432 LD DE,16608 L3 PUSH BC PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L3 LD DE,18432 LD HL,18464 LD BC,2016 LDIR LD B,8 LD HL,20460 LD DE,18656 L4 PUSH BC PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L4 LD DE,20480 LD HL,20512 LD BC,2016 LDIR LD B,8 LD HL,20704 L5 PUSH BC PUSH HL LD B,32 L6 LD(HL),0 INC HL DJNZ L6 POP HL POP BC INC H DJNZ L5 RET

Листинг 7.16

ROLL вверх для символов.

LD HL,16384 LD B,32 LD A,(HL) PUSH AF INC HL DJNZ L19 XOR A LD L,A INC H LD A,H CP 72 JR NZ,L18 LD DE,16384 LD HL,16415 LD BC,2016 LDIR LD B,8 LD HL,18342 LD DE,16608 PUSH BC PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L20 LD DE,18432 LD HL,18464 LD BC,2016 LDIR LD B,8 LD HL,20480 LD DE 18656 PUSH BC PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L21 LD DE,20480 LD HL,20512 LD BC,2016 LDIR

LD HL,22527 LD B,32 POP AF LD (HL),A DEC HL DJNZ L23 LD A,255 LD L,A DEC H LD A,H CP 79 JR NZ,L22 RET

L18 L19

L20

L21

L22 L23

SCROLL вниз для символов.

LD DE,22527 LD HL,22495 LD BC,2016 LDDR LD B,8 LD HL,18656 LD DE,20480 L8 PUSH BC PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L6 LD DE,20479 LD HL,20447 LD BC,2016 LDDR LD B,8 LD HL,16608 LD DE,18432

L9 PUSH BC PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L9 LD DE,18431 LD HL,18399 LD BC,2016 LDDR

LD HL,16384 L10 LD B,32 L11 LD(HL),0 INC HL DJNZ L11 XOR A LD L,A INC H LD A,H CP 72 JR NZ,L10 RET

Листинг 7.18

ROLL вниз для символов

LD HL,22527 L26 LD B,32

Конец дисплейной области.

32 знакоместа в строке, Запомнили нижнюю линию текущего знакоместа. Знакоместо слева.

И так 8 раз. Возврат к предыдущей линии последнего знако -места ряда. Проверка на выход в 23-ю строку экрана Если нет, то возврат назад Копирование информации в третьем сегменте на ряд вниз.

Восемь линий. Адрес начала первой линии последнего ряда второго

L27 LD A,(HL)

PUSH AF

DEC HL

DJNZ L27 LD A,255

LD L,A DEC H LD A,H

CP 79

JR NZ,L26

LD DE,22527 LD HL,22495 LD BC,2016 LDDR

LD B,8 LD HL,18656

сегмента

LD DE,20480

L28 PUSH BC

PUSH HL PUSH DE

LD BC,32 LDIR

POP DE

POP HL

POP BC

INC D

INC H

DJNZ L28

LD DE,20479 LD HL,20447

LD BC,2016 LDDR

Адрес начала первой линии первого ряда третьего сег мента.

Сохранили РР-гистры от порчи командой LDIR. 32 байта в каждой линии. Перенос одной линии через границу сегментов. восстановление регистров

Переход к очередной линии ряда.

Возврат для переноса 8-ми линий через границу сегмента.

Движение информации во втором сегменте на ряд вниз.

LD B,8 LD HL,16608 LD DE,18432 L29 PUSH BC

PUSH HL PUSH DE LD BC,32 LDIR POP DE POP HL POP BC INC D INC H DJNZ L29 LD DE,18431 LD HL,18399 LD BC,2016 LDDR

L30 L31

LD HL,16384 LD B,32 POP AF LD (HL),A INC HL DJNZ L31 XOR A LD L,A INC H LD A,H CP 72

|Перенос

|информации

|через

|границу

|между

|первым

|и вторым

|сегментами.

;Движение ин-;формации в ;первом сег-;менте на ряд ;вниз.

;Начало экрана I

|Восстановле-|ние со стека |информации |для восьми |линий первого |ряда (на стек |она поступила |из восьми |нижних линий

JR NZ,L30 RET

|экрана) ;Выход.

Листинг 7.19

SCROLL вверх для символов (2-ой вариант)

LD HL,16384

;Начало дис-;плейной об: ласти памяти. ;Движение пер-;вого сегмента | Перенос |ряда через |границу

|сегментов. |

;Движение вто-;рого сегмента |Перенос ряда |через границу |сегментов.

CALL SEGM

EX DE,HL LD HL,18438 PUSH HL CALL UP POP HL CALL SEGM

EX DE,HL LD HL,20480 PUSH HL CALL UP POP HL CALL SEGM

Движение третьего сегмента.

Обнуление (стирание) информации в последнем ряду

третьего сегмента.

LD HL,20704 PUSH HL LD 8,32 LD (HL),0 INC HL DJNZ L3 POP HL INC H LD A,H CP 88 JR NZ,L4 RET

L4 L3

Выход

Продолжение Л. 7.19.

Нижеследующая процедура копирует все ряды (кроме верхнего) в текущем сегменте на один ряд выше.

SEGM

LD B,7 PUSH BC LD BC,32

Первый ряд сегмента не переносим, потому 7

Сохранили от "порчи".

Соответствующая линия следующего ряда отстоит на 32 байта от текущей. Копирование адреса через стек HL указывает на ряд ниже

Сохранили HL и DE от "порчи" командой LDIR Копирование ря-

L1

PUSH HL POP DE ADD HL,BC

PUSH HL

PUSH DE CALL UP

;да вверх.

POP DE

POP HL POP BC DJNZ L1

Восстановление регистров.

Если не все 7 рядов скопированы, возврат. Выход.

I

RET

Нижеследующая процедура копирует содержимое экранного ряда на один ряд выше.

UP L2

LD B,8

8 линий в ряду.

PUSH BC

Сохранили регис

PUSH HL

тры от "порчи"

PUSH DE

командой LDIR.

LD BC,32

32 байта в линии

LDIR

Перенос на один

ряд вверх.

POP DE

POP HL

;Восстановление

POP BC

;регистров.

INC D

Переход к оче-

редной линии

INC H

текущего ряда.

DJNZ L2

Если не все 8

линий скопирова-

ны, возврат.

RET

Выход.

Вместо программы, выполняющей перемещение сразу же целого ряда, можно написать программу, выполняющую перемещение только одного столбца. Чтобы переместить весь ряд, эта программа должна повториться 32 раза. В то же время, такое решение позволит перемещать не весь ряд, а только заданное количество столбцов и, более того, при таком решении нет необходимости хранить в памяти все 256 байтов верхнего ряда экрана (как, например, в программе 7.18), а только 8 байтов одного столбца ряда. Программа 7.20 показывает, как достигается такое уменьшение объема памяти. Здесь адрес первого байта смещаемого столбца записывается в регистровую пару DE, а общее число смещаемых столбцов записывается в регистр B. Эта программа может быть размещена в любом участке памяти.

Листинг 7.20.

SCROLL вверх по столбцам.

L5

L6

L4

XOR A

Сброс ак-ра.

LD DE,16388

Адрес верхней

линии 4-го

столбца.

LD B,10

Двигаем вверх

10 столбцов.

PUSH DE

Сохранение ре-

гистров

PUSH BC

от коррупции.

PUSH DE

Копирование из

POP HL

DE в HL.

LD B,8

8 линий ряда.

LD A,(HL)

Запоминаем на

PUSH AF

стеке восемь

INC H

линий верхнего

DJNZ L6

ряда.

LD B,7

7 рядов сег

мента.

L2

PUSH BC LD HL,32 ADD HL,DE

PUSH HL LD B,8

LD A,(HL) LD (DE),A INC H INC D DJNZ L1 POP DE POP BC DJNZ L2

Указание на следующую линию ряда.

Восемь линий в ряду. Копирование через акк-р для одного ряда

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

Перенос восьми линий через границу сегмента.

LS

LD HL,1824 ADD HL,DE LD A,H CP 88 JR Z,END PUSH HL LD B,8 LD A,(HL) LD (DE),A INC H INC D DJNZ L3 POP DE JR L4

L3

Возврат для работы со следующий сегм. Восстановление со стека в нижнем ряду столбца того, что запомнили в самом верхнем ряду. Восстановление регистров. Переход к очередному столбцу экрана. Если не все 10 столбцов обслужены, возврат на L5. Выход.

LD DE,32 SBC HL,DE LD B,8 POP AF LD (HL),A DEC HL DJNZ L7 POP BC POP DE INC DE

END

L7

DJNZ L5

RET

Дальнейшее уменьшение объема памяти, занимаемого программой, может быть достигнуто, если выполнять перемещение одновременно не всех рядов, а только заданного их количества. При этом можно реализовать смещение на экране определенного окна с заданными размерами. Программа 7.31, занимающая всего 58 байтов, демонстрирует это решение. Для проверки выхода на границу сегмента экрана здесь используется команда BIT 0,H. Если нулевой бит регистра H не равен 0, то мы находимся на границе сегмента экрана и вместо добавления числа 32 к числу, записанному в регистровой паре DE, необходимо добавить число 1824 для перевода "первого" ряда в следующий сегмент. Число смещаемых рядов определяется числом шагов цикла L4. Адрес ячейки верхнего левого угла смещаемого окна может быть определен по формуле:

16384+(1824*INT (ROW/8)) + ((ROW - INT(ROW/8))*32 + COLUMN

Здесь ROW - номер экранной строки (в знакоместах). COLUMN - номер экранного столбца (в знакоместах).

Для смещения всего экрана в регистровой паре DE должно быть записано число 16384, в регистре B перед циклом L6 число 32 и здесь же, но перед циклом L4 -число 23. Эту программу можно переделать для организации смещения вверх/вниз.

Листинг 7.21.

XOR A

LD DE,16515

Левый верхний угол прокручиваемого "окна" имеет координаты X=3; Y=4.

Ширина "окна" - 7 знакомест.

L5

L1

Высота "окна" - 13 знакомест

L4

L2 L3

L5

LD B,7

PUSH DE PUSH BC PUSH DE POP HL LD B,8 LD A,(HL) PUSH AF INC H DJNZ L1 LD B,13

PUSH BC LD HL, 32 ADD HL,DE BIT 0,H JR Z,L2 LD HL,1824 ADD HL,DE PUSH HL LD B,8 LD A,(HL) LD (DE),A INC D INC H DJNZ L3 POP DE POP BC DJNZ L4 LD B,8 DEC H POP AF LD (HL),A DJNZ L5 POP BC POP DE POP DE INC DE DJNZ L6 RET

В ПЗУ компьютера ZX Spectrum имеется одна из наиболее полезных процедур -SCROLL n, позволяющая смещать n строк вместе с их атрибутами. Число n должно быть больше или равным 2 (но, конечно, не больше, чем 24).

Программа 7.22 показывает, как можно использовать эту процедуру для очистки строк с 16-ой по 24-ю включительно. Число строк отсчитывается от 24-й, при этом в регистр B записывается число строк-1 и девять раз вызывается процедура SCROLL n, находящаяся по

адресу 3584.

Листинг 7.22

LD B,9 L1 PUSH BC LD B,8 CALL 3584 POP BC DJNZ L1 RET

Ну, и в конце этой главы разберем процедуру, позволяющую одновременно смещать влево (или вправо) сразу же половину символа. Эта процедура хоть и короткая, но довольно сложная, т.к. здесь используются новые команды. Например, команда RLD перемещает биты с 0-го по 3-й в биты с 7-го по 4-й в ячейке, адрес которой находится в регистровой паре HL. Биты же с 7-го по 4-й из этой ячейки переписываются в биты с 0-го по 3-й в регистр А. А данные, которые были в этом регистре в битах с 0-го по 3-й переписываются в ячейку, адрес которой находится в регистровой паре HL, и занимают здесь соответственно 0...3 биты. Эта команда не влияет на флаги состояния процессора.

Листинг 7.23

DI

LD HL,22527 LD B,196 L1 PUSH BC XOR A LD B,32 PUSH HL L2 RLD

DEC HL DJNZ L2 POP DE EX DE,HL ADD A,(HL) LD (HL),A EX DE,HL POP BC DJNZ L1 EI RET

В программе 7.23 для каждой строки экрана используется команда RLD для перемещения правой половины каждого символа в левую часть. Левая половина первого символа при этом остается пустой, т.к. для каждой строки изначально в регистре A записан 0. Чтобы организовать циркулярное смещение, необходимо временно запоминать значение левой половины первого символа, а затем выводить ее, как правую половину последнего символа.




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Почта - Почта MSF.
Раскрутка - Как играть в игру Encyclopedia of WAR.
Письмо №317 - Вологда
Литература - О новом журнале для Амиги - AmiExp.
События 1 - добровольно покинул ряды lsg и oca наш кодер ex-mr. pi, ныне morphy.

В этот день...   16 апреля