ZX-Ревю 1995 №4 1995 г.

Этюды - Сегодня этот раздел мы хотим начать с критического письма в адрес ЭТЮДОВ, поступившего от Сергея Колотова из г. Шадринск Курганской обл.


Сегодня этот раздел мы хотим начать с критического письма в адрес ЭТЮДОВ, поступившего от Сергея Колотова из г. Шадринск Курганской обл. Он пишет:

Раздел ЭТЮДЫ является одним из любимейших для меня в вашем журнале. Хотя я и не беру из него все программы целиком, но некоторые из них привлекают к себе хорошей идеей, и я пишу свои аналогичные, но более эффективные процедурки.

Все, вроде, в ЭТЮДАХ хорошо, но где же главная цель этого раздела? Вспомним, о чем писал в 3 номере РЕВЮ за прошлый год основоположник раздела А.А.Иванов. Цель рубрики должна состоять не в публикации кучи различных процедур, а в совершенствовании техники программирования, создании "алмазов". Конкурсы, задачи и их элегантные решения - вот чему должно уделяться внимание на страницах ЭТЮДОВ. Тот раздел, который существует сейчас, можно назвать не "ЭТЮДЫ", а "НА СВАЛКЕ".

Ну это, пожалуй уже через край. Хотя мы и согласны с началом письма, но уверены, что с последним замечанием не согласятся и наши читатели. Мы бы назвали не НА СВАЛКЕ, а В МАГАЗИНЕ. На свалку выбрасывают никому не нужные вещи, а в магазин идут, когда хотят приобрести что-то полезное. Именно так считает большинство наших читателей, судя по их письмам. Что до отсутствия конкурсов, так это дело времени. Выдумывать, "высасывая из пальца"различные задания для читателей, мы считаем малополезным занятием. Задачи должна ставить жизнь. Ну а пока идеи не сформулировались в четкую задачу, публикуются готовые процедуры. Ведь что происходит, когда читатель посылает нам свою (или не свою, а вытащенную из другой программы) процедуру? Он делится с нами тем, что его заинтересовало, или тем, с чем ему пришлось столкнуться, будь то эффект с экраном или что-то другое. И пусть даже его способ не оптимален. Публикуя его вариант, мы надеемся, что кто-нибудь тоже решил эту задачу, и сделал это иначе. На самом деле так и есть, читатели пишут нам и делятся более эффективными вариантами. Пробегитесь внимательно по предыдущим выпускам ЭТЮДОВ - Вы найдете не одно подтверждение этому. Разве не в этом смысл раздела ЭТЮДЫ? Да и сегодняшний выпуск не будет исключением. Сейчас к нам поступают письма с идеями, касающимися именно техники программирования.

Однако возвращаемся к письму Сергея Колотова:

Предлагаю читателям подумать над некоторыми задачками. Победителем будет считаться тот, чьи решения будут наиболее компактными и короткими. И еще одно замечание. Все решения должны быть оформлены как подпрограммы и не должны использовать процедуры ПЗУ. Итак, вот конкретные задачи:

1. Вычислить HL=B*C

2. Отсортировать по возрастанию массив, начинающийся в памяти с адреса, указываемого HL, длина массива задана в BC.

3. Календарь. В регистре DE год. В регистре С - месяц. Надо получить в регистре А число дней в месяце.

4. Увеличить изображение в центральной части экрана в два раза так, чтобы оно занимало весь экран (графика + атрибуты).

5. Закрасить экран атрибутом, заданным в А, закручивающейся по часовой стрелке спиралью, с задержкой, величина которой может быть регулируемой и задана в ВС или одном из регистров этой регистровой пары (манипуляция только с файлом атрибутов).

6. Напечатать символ, код которого задан в аккумуляторе, размером во весь экран, атрибутом, заданным в С (манипуляция только с файлом атрибутов).

А теперь я вношу свой вклад в раздел ЭТЮДЫ. Речь пойдет все о той же "гасилке" экрана. Предлагаю такую процедуру, написанную специально для побития рекорда. Она занимает 23 (!) байта и при этом имеет возможность полноценной регулировки скорости.

1

; © SerzhSoft'95

10

DEC

HL

2

PAUSE

EQU

5

11

BIT

3,H

3

ORG

50000

12

JR

NZ, L2

4

ENT

$

13

LD

B,PAUSE

5

CLRSCR

LD

C,127

14

L3

HALT

6

L1

LD

HL,23295

15

DJNZ

L3

7

L2

LD

A,(HL)

16

RRC

C

8

AND

C

17

JR

C, L1

9

LD

(HL),A

18

RET

C350

0E 7F

21

FF

5A

7E

A1

77

B0

C358

2B CB

5C

20

F8

06

05

76

06

C360

10 FD

CB

09

38

EC

C9

00

F1

Присмотримся внимательнее к его процедуре. Начало - традиционное. А вот и оригинальная идея. Адреса в файле атрибутов изменяются не от начала, используя инкремент, а от конца, используя декремент. Что это дает? Число 23295 в двоичном представлении выглядит так: 01011010 11111111 а 22528 так: 01011000 00000000 а 22527 так: 01010111 11111111

Вы уже поняли: третий бит старшего регистра (он подчеркнут) равен единице при уменьшении адреса в файле атрибутов, и становится равным нулю при переходе в дисплейный файл. Его-то и контролирует команда в строке 10. Благодаря этому приему удалось выгадать "победный" байт.

Логично выглядит и использование регистра В и команды DJNZ в цикле задержки вместо JR NZ.

И еще о строке 16. Совсем не важно, используется ли в ней команда сдвига или ротации - в последнем случае единственный "ноль" в маске, перемещаясь от старших разрядов к младшим, поочередно гасит их. Так как старшие разряды атрибутов уже обнулены, то при сравнении по ИЛИ в строке 8, там нули и останутся.

Да, друзья, всего два месяца продержался предыдущий рекорд, и вот новый рекордсмен - Сергей Колотов из Шадринска! Скажет ли кто-нибудь следующее слово?

К другим работам Сергея мы вернемся чуть ниже. А пока поговорим о конкурсе. Со своей стороны можем добавить к вышеперечисленным еще одну конкурсную задачу, которая, как мы уже говорили, подсказана самой жизнью.

Речь идет о дистрибуции программного обеспечения. Дело в том, что мы получаем сейчас очень много программ, в которых управление (опрос клавиатуры, джойстиков) выполнено, мягко говоря, некорректно. Из-за этого многие из них не хотят работать на других моделях Спектрум-совместимых компьютерах несмотря на то, что благополучно работают на компьютере автора. В других программах никак не удается "попасть" в нужный пункт меню из-за отсутствия задержки перед автоповтором (это, наверняка замечали все). Иные "виснут" на компьютерах без порта KEMPSTON-джойстика. В других не предусмотрено элементарное REDEFINE KEYS. В общем, для многих программистов это стало настоящей проблемой из-за того, что они не знают всех особенностей компьютерного парка нашей страны. В то же время существует множество программ, которые имеют удобное управление и прекрасно работают на любых компьютерах.

Сдвиги в решении этой проблемы можно получить только благодаря коллективным усилиям. Идея такая. Вы присылаете нам процедуры опроса (условно назовем их KEY-INPUT), которые считаете наиболее удачными. Мы публикуем их после собственного тестирования и предлагаем читателям сделать то же самое. Вы опробуете их, и у кого эти процедуры не захотят себя хорошо вести, сообщают нам (вместе с подробностями о Вашем компьютере и ПЗУ) или добиваются от них "примерного поведения" и тоже сообщают нам. Мы же, по результатам такого "всеобщего" тестирования сможем предложить всем наиболее удачные варианты и рекомендовать их для использования в своих авторских программах. Кстати, это очень хорошо согласуется и с мнением о создании рынка процедур, высказываемым во многих письмах.

Второй момент. Мы не собираемся оговаривать заранее какие-то условия, связанные с работой процедур KEY-INPUT. Пусть условия будут свободными. Это может быть процедура, гоняющая стрелку по экрану в четырех направлениях, или выбирающая пункт в меню на экране (вверх-вниз), или выдающая результат в системной ячейке, или что-то еще. Ценными остаются общие требования: минимальная длина, максимальная эффективность.

В качестве примера, приводим одно письмо.

© Алексей Артамонов, г. Москва, 1995.

Перед тем, как вам написать, я долго мучился с программами (прикладными, игровыми и системными) в которых программистом не предусмотрен выбор управления. Жестко заданное управление не всегда для всех приемлемо. У меня в таких случаях очень быстро пропадает интерес к программе. Чтобы этого не случалось с программами, которые создают читатели, я предлагаю дать возможность пользователю выбрать удобное ему управление. Обычно используют следующие виды управления: KEMPSTON, SINCLAIR (левый и правый), CURSOR, KEYBOARD. С джойстиками, то есть с программой, которая их будет опрашивать, у Вас вряд ли будет какая-нибудь проблема (практика показывает, что проблемы есть и с этим вопросом - прим. ИФК), а вот при написании программы для обслуживания клавиатуры желательно предоставить пользователю возможность переназначить клавиши по его желанию. Для этого неплохо бы написать универсальную программу, которая подходила бы к любым заданным клавишам. Кстати, если Вы дадите в своей программе выбирать и джойстики, то SINCLAIR 1 и 2 и CURSOR тоже может обслуживать эта программа, так как все эти джойстики "являются" клавишами клавиатуры. Исходя из всего вышесказанного, давайте напишем программу, которая бы обслуживала одновременно и KEMPSTON-джойстик и любые выбранные Вами клавиши:

LOOP

LD

D, 0

;Процедура, ко

IN

A,(31)

;торая обслужи

AND

31

;вает KEMPSTON

LD

D, A

;джойстик.

RET

NZ

;

LD

B, 5

; Процедура,

LD

HL,TABL;

LD

A, (HL)

; которая

IN

A, (254) ;

INC

HL

; обслуживает

AND

(HL)

;

CPL

;клавиши,

CP

255

;

RL

D

;заданные

INC

HL

;

DJNZ

LOOP

;в таблице

LD

A, 31

;

XOR

D

;TABL.

LD

D, A

;

RET

;

Теперь о таблице TABL. Ее формат должен быть следующий: 1-й байт - старший байт порта, который отвечает за полуряд на клавиатуре, 2-й байт - установленный бит соответствует нажатой клавише. Например, эти два байта указывают на клавишу SPACE: 127, 1. На выходе из программы в регистре D будут установлены те биты, которые соответствуют нажатым клавишам. То есть, если Вы в таблице поместили два байта, указывающие на клавишу "S", и если в регистре D установлен 0-й бит, то эта клавиша нажата. Команда XOR нужна для того, чтобы нажатая клавиша соответствовала установленному биту, а не сброшенному.

И еще. В данной процедуре большим приоритетом обладает KEMPSTON-джойстик. Так что если он находится не в нейтральном положении или нажата кнопка "огонь", то программа будет игнорировать клавиатуру.

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

сама идея интересна. Ну что же, будем ждать, что скажете Вы, уважаемые читатели.

* * *

Пара "классических" этюдов поступила практически одновременно из разных мест. Оба они содержались в письме Павла Старкова из Красноярска и в письме Эдуарда К. и Андрея Власова из Ростова-на-Дону.

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

DOWN INC H

LD A, H

AND 7

RET NZ

LD A, L

ADD A,32

LD L, A

RET C

LD A, H

SUB 8

LD H, A RET

Длина процедуры: 15 байтов.

Вторая процедура с тем же параметром на входе, выдает в регистре HL адрес ячейки, соответствующий соседней сверху пиксельной линии:

DEC

H

LD

A, H

AND

7

CP

7

RET

NZ

LD

A, L

SUB

32

LD

L, A

RET

C

LD

A, H

ADD

A, 8

LD

H, A

RET

Длина процедуры: 17 байтов.

А вот "маленькая хитрость ", которой поделился Максим Локтюхин из Саратова.

Что сделает обыкновенный начинающий программист, если ему понадобится удвоить содержимое регистровой пары BC?

PUSH

HL

PUSH

HL

LD

H, B

PUSH

HL

LD

L, C

POP

BC

ADD

HL, BC

или:

ADD

HL, HL

LD

B, H

PUSH

HL

LD

C, L

POP

BC

POP

HL

POP

HL

Но если бы он был охотником, то мог бы считать, что у него убежало сразу три зайца: быстрота, размер, простота конструкции (использование дополнительного регистра HL). А убить их можно всего двумя "выстрелами" -командами SLA и RL:

SLA C (4 байта,

RL B 16 тактов)

Поясняю: SLA сдвигает младший байт влево, то есть увеличивает его вдвое, а если 7-й бит был включен, то выставится флаг С. RL - абсолютно то же самое, но если в предыдущей команде включился флаг С, то сейчас он запишется в младший бит старшего разряда регистровой пары. В общем получается то же, что и в приведенных выше программках, даже флаг С выставится, если значение регистровой пары было больше 32768.

Если дело касается регистра DE, то заслуживает внимания традиционный вариант. Он более короткий, однако менее быстрый:

EX DE,HL

ADD HL,HL (3 байта, EX DE,HL 19 тактов) Здесь нет необходимости сохранять на стеке содержимое регистровой пары HL (оно и так сохраняется в регистре DE), а вот для регистра BC или для ячейки памяти, адресуемой регистром HL, такой прием действительно пригодится:

SLA (HL) (4 байта, RL (HL) 30 тактов)

* * *

Пару "загадок" прислал Дмитрий Крапивин из Арзамаса:

1. DI

LD SP,767 (адрес в ПЗУ значения

M1 JR M1 не имеет).

Если запустить эту программу и нажать кнопку "MAGIC", то Speccy сбросится. Почему?

2. LD HL,PROG

LD (32767),HL

DI

LD A,127

LD I,A

IM 2

EI

L1 JR L1

PROG RET

А эта программа вообще "не умеет себя вести". Почему?

Начинающие программисты могут подумать над этими "загадками", но ответы посылать нам не надо

(кто не сумеет отгадать - узнает ответы в следующем номере).

* * *

И опять в нашей почте много писем, посвященных уменьшению длины процедуры гашения экрана. Но практически все - повторения уже придуманных ранее вариантов. Упомянем только письмо Дмитрия Блохина (BIT & BEAT) из Новомосковска, в котором использовался прием, похожий на предложенный Сергеем Колотовым:

6 L1

LD

HL,23552

7 L2

LD

A,(HL)

8

AND

C

9

LD

(HL),A

10

I NC

HL

11

LD

A, H

12

AND

4

13

JR

Z, L2

Как видим, здесь следует инкремент регистра HL, и контроль 2-го бита регистра H: 22528 = #5800 = 01011000 00000000 23296 = #5B00 = 01011011 00000000

23551 = #5BFF = 01011011 11111111

23552 = #5C00 = 01011111 00000000

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

Кстати, раз уж разговор коснулся процедуры гашения экрана, то можем сообщить еще один интересный факт. Несмотря на обилие писем и вариантов с решением проблемы, только один (!) человек (Вячеслав © SBM из Владивостока) заметил, что сравнивать процедуру из TERMINATOR с процедурой Шишкина и другими, алгоритм которых приводился в прошлом номере, - некорректно, так как в TERMINATOR'е гашение происходит одновременным гашением PAPER и INK, а в приводимых более простых вариантах - сначала гашение битов PAPER, затем - INK.

Как сказал один из наших корреспондентов: "Читая - думайте"! К чему приводит упрощение алгоритма, мы уже знаем из прошлого выпуска ЭТЮДОВ (вспомните хотя бы ну очень короткую процедуру).

Посмотрите, что произойдет, скажем с белым цветом в процедуре из TERMINATOR'а? Сначала он станет желтым, потом голубым, зеленым... и т.д. до черного. Вне зависимости от того, PAPER это или INK плюс полноценные 8 градаций вот что придает процедуре из TERMINATOR'а такое приятное на взгляд ощущение. Все-таки западных программистов "голыми руками не возьмешь " - у них есть, чему поучиться! Но резервы по упрощению процедуры все-же есть. Для этого надо вспомнить все оригинальные идеи, предложенные нашими корреспондентами во время "мозгового штурма".

Вячеслав предлагает процедуру зажигания экрана, для работы в паре с "гасилкой" (работающую, однако, все-таки по упрощенному алгоритму, а не как в TERMINATOR'е). Примечательность её в том, что она является полным "антиподом" процедуры гашения. В "гасилке" маска сдвигалась вправо, заполняя старшие разряды нулями. В "зажигалке" - маска сдвигается влево, а младшие разряды заполняются "единицами".

"Стоп! Разве есть команда такого сдвига?" - спросит читатель, внимательно изучив наш ТРЕХТОМНИК по машинным кодам.

Такая команда существует, хотя и является недокументированной. Это SLI Сравните:

7

6

5

4

3

2

1

0

7

6

5

4

3

2

1

0

Коды команд SLI:

SLI B - CB 30 SLI C - CB 31

SLI D - CB 32 SLI E - CB 33

SLI H - CB 34 SLI L - CB 35

SLI (HL) - CB 36 SLI A - CB 37

Набирать же эти команды в ассемблере придется не иначе, как при помощи пары DEFB. Для корректной работы процедуру пришлось дополнить очисткой экрана, включая 2 нижних строки (обнулением атрибутов) перед переброской дисплейного файла из буфера. Кроме того, мы немного "оптимизировали" процедуру Вячеслава, используя "последние достижения" технической мысли Сергея Колотова, и в таком виде предлагаем её читателям:

1 BUFF

EQU

51000

18

LD

DE,BUFF+6911

2 PAUSE

EQU

5

19

L2

LD

A, (DE)

3

ORG

50000

20

AND

C

4

ENT

$

21

LD

(HL),A

5

LD

HL,#5800

22

DEC

HL

6

LD

(HL),L

23

DEC

DE

7

LD

D, H

24

BIT

3,H

8

LD

E, L

25

JR

NZ, L2

9

INC

DE

26

LD

B,PAUSE

10

LD

BC, #02FF

27

L3

HALT

11

LDIR

28

DJNZ

L3

12

LD

HL,BUFF

29

DEFB

#CB

13

LD

DE,#4000

30

DEFB

#31

14

LD

BC,#1800

31

JR

NC, L1

15

LDIR

32

POP

HL

16

LD

C, 0

33

RET

17 L1

LD

HL,23295

Длина процедуры = 51 байт:

C350

21

00

58

75

54

5D

13

01

C6

C358

FF

02

ED

B0

21

38

C7

11

EA

C360

00

40

01

00

18

ED

B0

0E

27

C368

00

21

FF

5A

11

37

E2

1A

E9

C370

A1

77

2B

1B

CB

5C

20

F7

CF

C378

06

05

76

10

FD

CB

31

30

F5

C380

E8

E1

C9

00

00

00

00

00

D5

Кстати, в процедуре можно было обойтись и документированными командами:

29 CCF

30 RL C однако такая конструкция имеет длину три байта, так что использование SLI оправдано тем, что экономит один байт.

* * *

А теперь возвращаемся к письму, с которого мы начали сегодняшний раздел ЭТЮДЫ.

BEGIN LOOP

;или CALL RND

RES

5,(IY+1)

LD

HL,#4000

PUSH

HL

CALL

RND 2

POP

HL

LD

A,(SEED)

OR

(HL)

LD

(HL),A

INC

HL

BIT

5,(IY+1)

RET

NZ

LD

A, H

CP

#58

JR

NZ,LOOP

JR

BEGIN

Измерялось время полного заполнения экрана цветом INK. В приведенной Сергеем процедуре оно составило 12 секунд против 18 секунд у прототипа. Увеличение быстродействия в полтора раза при сокращении длины почти вдвое (с 85 до 45 байт) - это очень неплохой результат!

Но и на этом не заканчивается письмо Сергея.

И, напоследок, предлагаю довольно-таки интересную процедуру прорисовки предварительно загруженной в буфер картинки с возрастающим шумовым эффектом. Она называется SHOWER. Ручаюсь - такой Вы ещё не встречали.

© Сергей Колотов, г. Шадринск, 1995.

В ZX-РЕВЮ^, № 6, на стр.5 был опубликован генератор случайных чисел. Мне удалось существенно сократить программу, причем и время выполнения уменьшилось. Вот в этом-то и состоит смысл раздела ЭТЮДЫ (да кто же с этим спорит-то - прим. ИФК), ведь программистам нужны самые эффективные и быстроработающие процедуры. А в конечном итоге пользователям программ станет удобнее работать с ними и меньше времени тратить на ожидание, например, пока компьютер перетасует колоду карт. Пожалуйста, опубликуйте эту процедуру.

Охотно делаем это:

1 ; © SerzhSoft'95

20

SBC

HL, BC

2

ORG

50000

21

SBC

A, E

3

ENT

$

22

LD

B, H

4 RND 2

LD

HL,(SEED)

23

LD

C, L

5

LD

DE, 1

24

LD

E, A

6

XOR

A

25

ADD

HL, HL

7

ADD

HL, DE

26

RLA

8

ADC

A, D

27

ADD

HL, HL

9

LD

B, H

28

RLA

10

LD

C, L

29

ADD

HL, BC

11

LD

E, A

30

ADC

A, E

12

ADD

HL, HL

31

LD

E, A

13

RLA

32

SBC

HL, DE

14

ADD

HL, HL

33

LD

E, D

15

RLA

34

CCF

16

ADD

HL, HL

35

SBC

HL, DE

17

RLA

36

LD

(SEED),HL

18

ADD

HL, HL

37

RET

19

RLA

38 SEED

DEFW

0

Длина процедуры = 45 байтов:

C350

2A

7B

C3

11

01

00

AF

19

55

C358

8A

44

4D

5F

29

17

29

17

15

C360

29

17

29

17

ED

42

9B

44

B1

C368

4D

5F

29

17

29

17

09

8B

EB

C370

5F

ED

52

5A

3F

ED

52

22

CB

C378

7B

C3

C9

00

00

00

00

00

42

Проверку сравнительного быстродействия процедуры мы провели следующим образом:

1 ; © SerzhSoft'95

24

OR

BORDER

2

ORG

50000

25

OUT

(254),A

3

ENT

$

26

LD

A, C

4 BUFF

EQU

51000

27

RRCA

5 TYPE

EQU

24

28

RRCA

6 PAUSE

EQU

3

29

RRCA

7 BORDER

EQU

0

30

DEC

HL

8 SHOWER

LD

HL,BUFF+6911

31

DEC

DE

9

LD

DE,23295

32

DJNZ

LP3

10

LD

BC,768

33

RRCA

11

LDDR

34

BIT

6,H

12

EX

DE, HL

35

JR

NZ,LP2

13

LD

A, 128

36

POP

HL

14 LP1

PUSH

DE

37

POP

DE

15

PUSH

HL

38

LD

B,PAUSE

16 LP2

LD

B,TYPE

39 LP4

HALT

17 LP3

LD

C,A

40

DJNZ

LP4

18

EX

DE, HL

41

RRCA

19

AND

(HL)

42

RRCA

20

EX

DE, HL

43

RRCA

21

OR

(HL)

44

JR

NC,LP1

22

LD

(HL),A

45

RET

23

AND

248

Длина процедуры = 56 байтов:

C350

21

87

DE

11

FF

5A

01

00

04

C358

03

ED

B8

EB

3E

80

D5

E5

26

C360

06

18

4F

EB

A6

EB

B6

77

39

C368

E6

F8

F6

00

D3

FE

79

0F

58

C370

0F

0F

2B

1B

10

EC

0F

CB

6D

C378

74

20

E5

E1

D1

06

03

76

E5

C380

10

FD

0F

0F

0F

30

D7

C9

4D

Интересен параметр TYPE. От него зависит режим вывода картинки на экран. Допустимо большинство значений от 0 до 255, за исключением некоторых.

Во время вызова процедуры прерывания должны быть разрешены.

Прошу опубликовать мой адрес. Читатели, желающие написать мне, найдут единомышленника в следующих вопросах: ЭТЮДЫ, вирусы на ZX-Spectrum, адаптация программ под TR-DOS, Adventure games:

641812, Курганская обл.,

г. Шадринск, ул. Либкнехта,

д. 27, кв. 1. Колотову Сергею.

* * *

© Николай Губин, г. Новгород, 1995.

Предлагаю процедуру, выполняющую красивый эффект при помощи манипуляции с атрибутами. Цветовая волна как-бы расходится от центра к краям.

1

ORG

50000

20

LD

A, B

2

ENT

$

21

LD

(POKE2+1),A

3 START

EI

22

ADD

A, A

4

HALT

23

LD

(POKE3+1),A

5

LD

IX,TABL

24

LOOP

LD

B,#10

6

LD

HL,#5800

25

LOOP1

INC

E

7

LD

BC,#0105

26

LD

A, E

8

CALL

ATR

27

AND

#1F

9

CALL

I NTAB

28

LD

(NUM+2),A

10

LD

A, #7F

29

NUM

LD

A,(IX+0)

11

IN

A,(#FE)

30

LD

(HL),A

12

RRA

31

INC

HL

13

JR

C,START

32

DJNZ

LOOP1

14

RET

33

LD

B,#10

15 ATR

LD

E,0

34

LOOP2

DEC

E

16

LD

A, C

35

LD

A, E

17

SRL

A

36

AND

#1F

18

INC

A

37

LD

(NUM1+2),A

19

LD

(POKE1+1),A

38

NUM1

LD

A,(IX+0)

39

LD

(HL),A

56

RET

40

INC

HL

57

INTAB

LD

HL,TABL+1

41

DJNZ

LOOP2

58

LD

DE,TABL

42

LD

A, C

59

LD

BC,#20

43

POKE1

CP

4

60

LD

A, (DE)

44

JR

Z,CONT

61

LDIR

45

PUSH

AF

62

LD

(DE) , A

46

LD

A, E

63

RET

47

POKE2

ADD

A,4

64

TABL

DEFB

0,#40,1,#41

48

LD

E, A

65

DEFB

2,#42,3,#43

49

POP

AF

66

DEFB

4,#44,5,#45

50

JR

NC,CONT

67

DEFB

6,#46,7,#47

51

LD

A, E

68

DEFB

#47,#47,7

52

POKE3

SUB

4

69

DEFB

#46,6,#45,5

53

LD

E, A

70

DEFB

#44,4,#43,3

54

CONT

DEC

C

71

DEFB

#42,2,#41,1

55

JR

NZ,LOOP

72

DEFB

#40,0

Длина процедуры = 143 байта:

C350

FB

76

DD

21

BE

C3

21

00

24

C358

58

01

05

01

CD

6A

C3

CD

41

C360

B0

C3

3E

7F

DB

FE

1F

38

83

C368

E7

C9

1E

00

79

CB

3F

3C

B8

C370

32

9D

C3

78

32

A3

C3

87

5C

C378

32

AA

C3

06

10

1C

7B

E6

6D

C380

1F

32

86

C3

DD

7E

00

77

AF

C388

23

10

F2

06

10

1D

7B

E6

04

C390

1F

32

96

C3

DD

7E

00

77

CF

C398

23

10

F2

79

FE

04

28

0C

2F

C3A0

F5

7B

C6

04

5F

F1

30

04

21

C3A8

7B

D6

04

5F

0D

20

CC

C9

E1

C3B0

21

BF

C3

11

BE

C3

01

20

C9

C3B8

00

1A

ED

B0

12

C9

00

40

4D

C3C0

01

41

02

42

03

43

04

44

97

C3C8

05

45

06

46

07

47

47

47

FD

C3D0

07

46

06

45

05

44

04

43

BB

C3D8

03

42

02

41

01

40

00

00

64

Для большей видимости эффекта можно набрать программу на Бейсике типа:

1 BORDER 0: PAPER 0: CLS

2 FOR F=0 TO 5: PRINT AT F,0;"3 2 л ю б ы х с и м в о л а ": NEXT F

3 RANDOMIZE USR 5E4

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

7 LD BC,#0118

тогда эффект будет распространяться на весь экран (для видимости эффекта можете перед стартом процедуры загрузить на экран какую-нибудь картинку).

Интересен параметр, задаваемый в 7 строке в регистре В. Попробуйте задавать значения 0, 1, 2, 4, 10, 30 и увидите, как будет видоизменяться эффект.

© Евгений Любимов, Виталий Сердюк, г. Новокузнецк, 1995. Эту процедуру мы "вытащили" из Ьой'а, который называется "ZYX". Она дополнена предварительной установкой атрибутов для завершенности эффекта:

1

ORG

50000

13

LD

HL,16384

2

ENT

$

14

L3

LD

B, C

3

LD

HL,#5800

15

L1

XOR

A

4

LD

D, H

16

RR

(HL)

5

LD

E, L

17

INC

HL

6

INC

DE

18

XOR

A

7

LD

(HL),7

19

RL

(HL)

8

LD

BC,#02FF

20

INC

HL

9

LDIR

21

DJNZ

L1

10 ;

22

LD

B, C

11

LD

D, 8

23

L2

XOR

A

12 L4

LD

C,16

24

RL

(HL)

25 INC HL 31 CP 88

26 XOR A 32 JR NZ, L3

27 RR (HL) 33 DEC D

28 INC HL 34 JR NZ,L4 2 9 DJNZ L2 35 RET

30 LD A, H

Длина процедуры = 51 байт:

C350

21

00

58

54

5D

13

36

07

8D

C358

01

FF

02

ED

B0

16

08

0E

E6

C360

10

21

00

40

41

AF

CB

1E

6D

C368

23

AF

CB

16

23

10

F6

41

48

C370

AF

CB

16

23

AF

CB

1E

23

A1

C378

10

F6

7C

FE

58

20

E5

15

2D

C380

20

DD

C9

00

00

00

00

00

09

Следующая программа включает в себя две процедуры. Первая плавно "заливает" бордюр экрана, а вторая -так же плавно очищает его. Процедуры для удобства объединены в один блок.

1 ORG

50000

24

OR

L

2

ENT

$

25

JR

NZ, L4

3 PROG1

LD

HL,1

26

LD

A,(L10)

4

LD

B, 160

27

OUT

(254),A

5 L2

PUSH

BC

28

RET

6

PUSH

HL

29

L9

DEFB

0

7

CALL

L1

30

L10

DEFB

1

8

POP

HL

31

;

9

LD

DE,10

32

PROG2

LD

HL,1600

10

ADD

HL, DE

33

LD

B, 160

11

POP

BC

34

L5

PUSH

BC

12

DJNZ

L2

35

PUSH

HL

13

LD

A, (L9)

36

CALL

L1

14

AND

7

37

POP

HL

15

OUT

(254),A

38

LD

DE,10

16

RET

39

AND

A

17 L1

HALT

40

SBC

HL, DE

18

LD

A, (L9)

41

POP

BC

19

OUT

(254),A

42

DJNZ

L5

20 L4

DEC

HL

43

LD

A,(L10)

21

LD

B,1

44

AND

7

22 L3

DJNZ

L3

45

OUT

(254),A

23

LD

A, H

46

RET

Если первая процедура будет расположена с адреса 50000, то вторая окажется в 50049. Суммарная длина = 77 байтов:

C350

21

01

00

06

A0

C5

E5

CD

52

C358

6A

C3

E1

11

0A

00

19

C1

1E

C360

10

F3

3A

7F

C3

E6

07

D3

62

C368

FE

C9

76

3A

7F

C3

D3

FE

B5

C370

2B

06

01

10

FE

7C

B5

20

C4

C378

F7

3A

80

C3

D3

FE

C9

00

49

C380

01

21

40

06

06

A0

C5

E5

FB

C388

CD

6A

C3

E1

11

0A

00

A7

E8

C390

ED

52

C1

10

F1

3A

80

C3

D1

C398

E6

07

D3

FE

C9

00

00

00

E2

Использование программы:

10 RANDOMIZE USR 50049: RANDOMIZE USR 50000: GO TO 10

* * *

Мы рады сообщить, что читатели не забывают и про музыкальный процессор: начали поступать программки и по нему.

(C) Рустам Гайнутдинов, г. Зеленодольск, 1995.

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

1 ORG 50000 5 LD (NN+1),A

2 ENT $ 6 LD A, 8

3 LD IX,22855 7 CALL ANAL

4 LD A,32 8 LD IX,22887

9

LD

A, 16

25

DEL1

LD

A,(BUF)

10

LD

(NN+1),A

26

AND

A

11

LD

A, 9

27

JR

Z, LEB

12

CALL

ANAL

28

PUSH

IX

13

LD

IX,22919

29

POP

HL

14

LD

A,24

30

NN

LD

(HL),0

15

LD

(NN+1),A

31

LD

HL,BUF

16

LD

A, 10

32

DEC

(HL)

17

CALL

ANAL

33

JR

NEXT

18

RET

34

LEB

PUSH

IX

19 ANAL

LD

BC,65533

35

POP

HL

20

OUT

(C) , A

36

LD

(HL),00

21

IN

A, (C)

37

NEXT

INC

IX

22

AND

15

38

DJNZ

DEL1

23

LD

(BUF),A

39

RET

24

LD

B, 15

40

BUF

DEFB

0

Длина процедуры = 85 байтов:

C350

DD

21

47

59

3E

20

32

93

D4

C358

C3

3E

08

CD

7B

C3

DD

21

2D

C360

67

59

3E

10

32

93

C3

3E

F7

C368

09

CD

7B

C3

DD

21

87

59

1D

C370

3E

18

32

93

C3

3E

0A

CD

26

C378

7B

C3

C9

01

FD

FF

ED

79

A5

C380

ED

78

E6

0F

32

A4

C3

06

3C

C388

0F

3A

A4

C3

A7

28

0B

DD

B2

C390

E5

E1

36

00

21

A4

C3

35

0C

C398

18

05

DD

E5

E1

36

00

DD

2E

C3A0

23

10

E6

C9

00

00

00

00

45

Теперь о применении полученного блока кодов "mus"CODE 50000,85.

Предположим, у Вас имеется подготовленный и скомпилированный в адрес 51000 пакетом SOUND TRACKER, музыкальный фрагмент "SONG".

Тогда для проигрывания музыки и индикации потребуется Бейсик-программа (с автостартом со 2-й строки):

1 GO TO 100

2 BORDER 0: PAPER 0: INK 7: CLEAR 49999: RANDOMIZE USR 15619: REM : LOAD "SONG"

CODE

3 RANDOMIZE USR 15619: REM : LOAD "mus" CODE

4 FOR a=USR "a" TO USR "a"+7: READ b: POKE a,b: NEXT a: RUN : DATA 0,119,119,119,119,119,119,0

10 RANDOMIZE USR 51000: FOR i=10 TO 12: PRINT INVERSE 1;AT i,6;CHR$ (55+i); INK 0;"AAAAAAAAAAAAAAAA": NEXT i: RETURN: REM UDG 100 GO SUB 10

110 RANDOMIZE USR 51006: RANDOMIZE USR 50000: PAUSE 1: IF INKEY$="" THEN GO TO

110

120 GO SUB 10

Строка 4 формирует UDG-символ "А ", при помощи которого изображаются очень симпатичные сегменты

индикатора. В строке 10 происходит инициализация звукового модуля и печать сегментов индикатора цветом

PAPER. А наложение атрибутов выполняет предложенная программа в кодах. Это происходит в строке 110 после

проигрывания очередного такта.

Строка 120 прекращает музыку при нажатии на любую клавишу.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
О нас - газета для интеллектуалов и параноиков.
Железо - Что делать, если мыша не правильного типа.
Мнение - несколько слов в адрес журнала "Fаultless".
Предисловие - Вот и вышел наконец-то первый номер нашей газетки.
Scene 0fF! - Win32 vs DOS.

В этот день...   24 ноября