ZX-Ревю 1991 №7-8 1990 г.

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


Маленькие хитрости

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

Вы можете таким же образом использовать символ CHR$6 в начале строки, в конце, можете давать их подряд, чтобы в тексте сообщения образовались пустые строки (хотя для этого есть и другие "хитрости").

Аналогичным же образом в текстовые строки вставляют и цветовые атрибуты. Возьмем строку: 10 PRINT INK 1;PAPER 6; BRIGHT 1; FLASH 1; "TEST".

Она занимает 48 байтов, из которых 31 можно сэкономить (в нашем справочнике по программированию в машинных кодах, т.3 трехтомника, мы приводим таблицу всех символов "Спектрума", в том числе и управляющих кодов). Действуйте так: 10 PRINT

перейти в режим E нажать CAPS SHIFT нажать 1

перейти в режим E нажать 6

перейти в режим E нажать 9

перейти в режим E нажать CAPS SHIFT нажать 9 набрать "TEST" нажать ENTER

Когда Вы все это проделаете, ярко-синее слово TEST будет изображено на желтом фоне и будет при этом мигать.

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

перейти в режим E нажать 8

перейти в режим E нажать CAPS SHIFT нажать 8

перейти в режим E нажать 7

перейти в режим E нажать CAPS SHIFT нажать 0

Но это будет стоить Вам еще 8 байтов. С другой стороны, эти цветовые проблемы не возникли бы, если бы Вы строку держали бы только в области VARS. И, напоследок, еще один прием. Вы можете напечатать один символ поверх другого. Часто это бывает полезно, если Вы хотите сделать текст на экране подчеркнутый.

Для этого могут применяться управляющие коды CHR$8 - BACKSPACE и CHR$21 -OVER. Попробуйте:

LET a$="A"+CHR$8*CHR$21+"_"

Дайте команду PRINT a$ и Вы увидите на экране подчеркнутую букву "a". Поэкспериментируйте с компьютером, посмотрите как в оператор PRINT входят цветовые коды после перехода в режим к и нажатия цифровой клавиши (по разному с CAPS

SHIFT и без).

Еще один путь экономии памяти состоит в использовании токенов ключевых слов, правда это нельзя сделать с русскоязычными текстами, поскольку все токены - это английские слова. Тем не менее, интересен сам прием.

Например, в Вашей программе есть такое сообщение:

20 PRINT "NEW DATA"

Оно может использоваться, например, в Вашей базе данных. Занимает такая запись 16 байтов, но если вместо слов NEW и DATA использовать токены NEW и DATA, то расход можно уменьшить до 10 байтов, поскольку всякий токен, даже такой длинный как RANDOMIZE занимает только один байт.

Однако, если Вы попробуете набрать такую строку с помощью токенов, то у Вас ничего не получится. Как только Вы откроете первую кавычку, на экране возникнет курсор L и машина будет ждать от Вас ввода букв. Это ведь и естественно. Внутри кавычек ведь пишется текст, набираемый по буквам, а никак не операторы БЕЙСИКа. Вам надо обхитрить компьютер, чтобы он все-таки выдал Вам курсор K. Это можно сделать так: 20 PRINT "THEN NEW THEN DATA"

- а теперь удалите операторы THEN стиранием.

Если Вам хочется отдохнуть после напряженной работы с компьютером, попробуйте поэкспериментировать, какой длины Вы сможете составить предложение, используя только токены и знаки пунктуации. Вот удивительно глупый пример: RUN VAL, COS LEN FLASH!

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

Вам надо сделать 6 различных сообщений. Можно задать эти сообщения так: LET а$="Вы находитесь в коридоре, ведущем ", а затем: 10 PRINT а$; "на север"

Не забудьте только в а$ после слова "ведущем" оставить один пробел. Тексты значительно проще читаются, если между строками на экране оставить пустые строки. Это можно сделать, если применять CHR$6 (запятую оператора PRINT), о чем мы писали в прошлом выпуске, но можно вставить и символ CHR$13 (ENTER). Попробуйте, например: LET a$=CHR$13+"ZX Spectrum" + CHR$13 PRINT "Test 1";a$;"Test 2"

Вы увидите, что фразы отделены пробельными строками.

Очень часто в своих программах Вы под главным окном программы делаете небольшое окно для коммуникации с пользователем. Это означает, что Вам приходится использовать строки типа:

10 PRINT AT 20,4;"Подумайте и ответьте:"

Конечно, если эта фраза используется очень часто, то ее можно присвоить переменной, что даст определенную экономию, но еще больше можно сэкономить с помощью CHR$22.

CHR$22 - управляющий код AT (управляет позицией печати) тоже можно вставить в программных переменных VARS, как и любой другой управляющий символ. Вот пример такой строки:

LET a$=CHR$22+CHR$20+CHR$4+"Подумайте и ответьте:"

Если теперь дать PRINT a$, то это сообщение появится в двадцатой строке, начиная с четвертого столбца.

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

LET p$=CHR$22+CHR$20+CHR$4,

а затем применять например так: 10 PRINT p$;"Ваше сообщение..."

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

Напечатав сообщение в заданном месте, Вы может быть захотите его стереть. Обычно это делают так:

10 PRINT AT 20,0;" (32 пробела)"

Эти пробелы - расточительный расход памяти. Можно было бы сделать так: 10 PRINT AT 20,0,,

В конце здесь стоит не кавычка - это две запятые (CHR$6). Еще лучше этот пример запишется: LET d$=CHR$22+CHR$20+CHR$0 + '' (2 запятые оператора PRINT)", а затем давать PRINT d$, когда надо стереть сообщение.

О том, как вставить "запятые PRINT" (CHR$6) внутрь текстовых кавычек, мы с Вами говорили ранее.

Используя серию символов "запятая PRINT" Вы можете стирать несколько строк, но для этого можно использовать также оператор INPUT AT.

Количество строк, подлежащих очистке, отсчитывается снизу вверх, а текущая позиция печати должна быть над областью, подлежащей очистке, иначе экран начнет скроллировать. Например, чтобы очистить четыре нижние строки. Попробуйте: 10 PRINT AT 17,0;:INPUT AT 4,0;

Кстати, если Вы применяли печать сообщения оператором PRINT #0;"сообщение..."

и теперь имеете трудности с его очисткой, это можно сделать просто: INPUT;!

Все то, что мы говорили о символах управления позицией печати CHR$22, применимо и к управляющему символу CHR$23 (TAB). Он управляет величиной табуляции. Но надо помнить, что TAB влияет на весь ряд, в том числе и на атрибуты, и результат может быть очень странным.

Теперь перейдем к "хитростям", связанным с элементарной графикой. Кое-что интересное при очень малом расходе памяти можно получить, если использовать самые обычные символы в сочетании с управляющими кодами. Вот небольшой пример: 10 LET h$=" Режим E CAPS SHIFT 2

$" (ENTER) 20 LET b$=

"Режим E CAPS SHIFT E Режим E CAPS SHIFT 7 Режим E 1

Режим E 6

Режим E CAPS SHIFT 3

режим E CAPS SHIFT 9

@

Режим E CAPS SHIFT 7 Режим E 1

Режим E CAPS SHIFT 8 Режим E CAPS SHIFT 2 Режим E 7 0"(ENTER) ^рока 30 вводится обычным порядком:

30 LET s$=CHR$22+CHR$17+CHR$22+b$+CHR$22+CHR$18+CHR$8+b$+CHR$22+CHR$19*CHR$22+h$

Если Вы внимательно следите за нашими выпусками и читаете этот раздел, то Вы

должны знать, что обозначают странные записи в строках 10 и 20.

Запустите эту программу (RUN). Сначала Вы получите только сообщение O.K., а теперь дайте команду

CLS:PRINT s$

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

PRINT s$.

Печатая символы, заложенные в ПЗУ "Спектрума" конечно можно достичь каких-то элементарных результатов, но почему бы не попробовать воспользоваться еще и командой OVER.

Эта команда позволяет напечатать один символ поверх другого и получить что-то

новое.

Работает она несколько необычно.

INK поверх INK дает PAPER

PAPER поверх PAPER тоже дает PAPER, но

INK поверх PAPER дает INK.

Благодаря этому, если напечатать один символ поверх другого, можно получить совершенно неожиданные новые символы (нечто вроде псевдо-графики пользователя). Попробуйте напечатать * поверх > (получится нечто вроде аэроплана). Буква "C" поверх буквы "O" даст изображение пули, а * поверх восклицательного знака - пламя ракетного двигателя. Попробуйте поэкспериментировать сами, поле исследований большое, ведь возможны десятки тысяч комбинаций.

Теперь посмотрим, что можно сделать с графикой пользователя UDG. Если с ней заняться серьезно, то можно внутри Вашего компьютера найти совсем новый "Спектрум".

Поскольку каждый из символов UDG имеет довольно малые размеры, то для получения чего-то существенного их надо использовать группами. Тогда можно получать картинку любого размера.

В Вашем распоряжении 21 символ UDG, закрепленные за клавишами A - U. Даже если не заниматься манипуляциями с памятью машины, которые позволят сильно расширить этот набор, все равно это не так мало, как кажется. Крепко подумав, можно некоторые символы UDG использовать не для одной цели.

В книге Виккерса (официальная инструкция по работе со "Спектрумом", широко распространенная на наших "рынках") в главе, посвященной UDG-графике, есть пример построения шахматных фигур. Правда они получаются такими маленькими, что к реальному делу их трудно приспособить, а вот если бы увеличить их размер хотя бы в два раза было бы совсем другое дело. Итак, существуют 6 различных шахматных фигур. Если на каждую использовать по 4 символа UDG, то потребуется 24 символа, а у нас есть только 21. Решение очень простое - сделаем основание каждой фигуры стандартным (нижние два символа), а варьировать будем только верх. Тогда нам необходимо:

6x2+2=14 (символов).

Остался еще запас, можно даже для пешек сделать основание другим способом (поменьше размером).

Но на самом деле Вы вовсе и не ограничены 21 символом. Можете иметь их столько, сколько пожелаете, надо только сообщить об этом Вашем желании компьютеру и расплатиться по 8 байтов за каждый новый символ. Среди многочисленных системных переменных "Спектрума" есть одна, которая называется UDG и располагается в адресах 23675 и 23676.

В этих ячейках можно найти информацию об адресе первого байта, с которого начинается графика символов UDG.

Если Вы дадите команду:

PRINT USR "A",

то получите число 65368, поскольку "A" - первый символ графики UDG, то это число есть адрес первого символа.

Если Вы дадите команды:

PRINT PEEK 23675

и

PRINT PEEK 23676,

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

Умножьте 255 на 256 и прибавьте 88. Вы получите тот же адрес - 65368.

Если в системную переменную UDG заслать оператором POKE другие числа, то компьютер будет искать конструкцию символов UDG в других областях памяти. Можете выполнять это так часто, как пожелаете. Наберите программу, приведенную ниже. Обратите при этом внимание на то, что символы с чертой наверху - это графические символы и набирать их надо в графическом режиме (курсор G).

10 FOR f=60000 TO 60007 READ a: POKE f,a: NEXT f:

DATA 1,3,7,15,31,63,127,255

20 POKE 23675,96:

POKE 33676,234: PRINT "AAAAA"

Вы создали символ UDG в форме треугольника и разместили его в новом адресе - 60 000 (строка 10)

В строке 20 Вы переадресовали системную переменную UDG на новый набор (на адрес 60 000).

Вы по-прежнему не можете иметь в одном наборе символов UDG более 21, но зато можете теперь иметь в памяти компьютера столько наборов, сколько хотите, переключая системную переменную UDG на адреса, с которых начинаются эти наборы.

Попробуем теперь, используя самодельные наборы UDG оживить Ваши программы небольшими цветными картинками. Используем для каждой картинки набор из 20 символов UDG, тогда картинка будет иметь вид:

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

Это вполне приемлемый размер, способный порадовать глаз будущему пользователю Вашей программы.

Теперь нарисуйте на миллиметровке или на бумаге в клетку саму Вашу картинку размером 40x32 точки. Продумайте, какие цвета INK и PAPER Вы будете использовать для каждого знакоместа. Можете использовать и FLASH и BRIGHT.

Теперь рисунок, полученный для символов "A", "B" ... "T" надо занести в память компьютера (мы работаем с 20 символами, о 21-ом мы как бы "забыли", он нам не нужен).

Как это делается, Вы можете прочитать в предыдущем номере "ZX-РЕВЮ" в разделе "Для начинающих". Написано об этом и в нашей разработке "Большие возможности Вашего Спектрума", правда мы сейчас ее снимаем с распространения в связи с тем, что готовим новое издание, исправленное и дополненное.

Конечно, формировать наборы UDG вручную - дело крайне утомительное. Лучше воспользоваться какой-либо специально предназначенной для этой цели программой, а их немало.

Например, есть пакет HORIZONS, который поставляется вместе с фирменным "Спектрумом". В нем есть программа CHARACTER GENERATOR, служащая для этой цели. Конечно, фирменной машины у Вас может и не быть, но этот пакет программ был самым первым, попавшим к нам в страну и распространен более широко, чем что-либо еще.

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

Войдите в режим "FONT". Вы увидите 96 символов "Спектрума". Это не UDG-символы, а символы основного набора, тем не менее и они нам подойдут. Нарисуйте первые 20 символов из набора, как Вам надо. Теперь дайте команду "SAVE FONT". Присвойте набору имя, например "MYFONT1". Он выгрузится на ленту под этим именем и займет 768 байтов (96 символов по 8 байтов). Но Вам-то ведь нужны только первые 20 символов, т.е. 160 байтов. Поэтому лишние 608 байтов надо "отрезать".

Сделаем, например, так:

- выйдите из "ARTSTUDIO"

- загрузите сформированный блок "MYFONT1" в адрес, в котором хотели бы хранить свой набор UDG, например, в адрес 60 000:

LOAD "MYFONT1" CODE 60000,768

А теперь выгрузите на ленту его первые 160 байтов, обрезав тем самым остальные: SAVE "MYFONT1" CODE 60000,160

Теперь у Вас на ленте есть первый набор, загружать его очень просто. LOAD "" CODE

Он всегда будет загружаться в адрес 60 000.

Аналогично можете себе наделать еще сколько хотите разных наборов, меняя их имя.

Предположим, что Вы наделали таких наборов штук 30, т.е. заготовили 30 картинок. Теперь их можно "сшить" в один сплошной блок машинного кода, начинающийся, скажем с адреса 60 000. Для этого может пригодиться следующая программа:

10 LET g$=CHR$22+CHR$10+CHR$0+ "ABCDE"+CHR$13+"FGHIJ"*CHR$13+ "KLMNO"+CHR$13+"PQRST"

11 REM *буквы, надчеркнутые сверху, вводятся в графическом режиме 15 LET a=60000:LET c=1

20 INPUT "name of font"; t$

30 IF t$="0" THEN GO TO 200

31 IF LEN t$>10 THEN GO TO 20

32 LET c=c+1

35 LOAD t$ CODE a,168

4O RANDOMIZE a: POKE 23675,PEEK 23670: POKE 23676,PEEK 23671: PRINT g$

50 LET k=0: FOR f=22848 TO 22944 STEP 32

60 FOR n=0 TO 4: LET k=k+1: POKE f+n,7

70 INPUT "Attribute value?",V

75 IF V<1 OR V>255 THEN GO TO 70

80 POKE f+n,V: POKE a+160+k,V

90 NEXT n:NEXT f: LET a=a+180

100 PAUSE 100:CLS: GO TO 20

200 INPUT "name for your picture?", t$: IF t$="" OR LEN t$>10 THEN GO TO 200 210 SAVE t$ CODE 60000,c*180 220 VERIFY t$ CODE

Программа работает следующим образом. Сначала она просит Вас ввести имя первого набора символов UDG и загружает его. После этого программа запрашивает от Вас ввода цветовых атрибутов для каждого из 20 символов, из которых сделана картинка (программная переменная "V"). Если Вы не знаете, как кодируются цветовые атрибуты, воспользуйтесь таблицей 1.

Например, если Вы хотите иметь желтое изображение (INK=6) на синем фоне (PAPER=1), то должны в ответ на запрос дать число 14.

Если хотите, чтобы символ был ярким (BRIGHT), добавьте к полученному числу еще 64, а если хотите чтобы он еще и мигал (FLASH), то прибавьте еще 128. Но пожалуйста, не забывайте, что в пределах одного знакоместа (8x8 пикселей) можно иметь только один цвет INK и один цвет PAPER.

Табл. 1

PAPER

0

1

2

3

4

5

6

7

0

-

8

16

24

32

40

48

56

1

1

-

17

25

33

41

49

57

2

2

10

-

26

34

42

50

58

3

3

11

19

-

35

43

51

59

INK

4

4

12

20

28

-

44

52

60

5

5

13

21

29

37

-

53

61

6

6

14

22

30

38

46

-

62

7

7

15

23

31

39

47

55

63

Закончив работу с первым набором, можете приступить ко второму и т.д. Когда закончите, в ответ на вопрос об имени вашего набора нажмите 0 и Вам предложат выгрузить весь блок целиком, начиная с адреса 60000.

Каждый из наборов при выгрузке займет по 180 байтов, из них 160 - черно-белая информация (20 символов x 8 байтов) и еще 20 байтов займут цветовые атрибуты - по одному байту на каждый символ (на одно знакоместо).

Нам осталось только научиться использовать сформированный графический файл в своих программах. Для этого может пригодиться следующая программа. Наберите ее и запустите командой RUN 9999.

100 LET f$="001 START": GO SUB 1000: STOP

1000 LET c = VAL f$ (TO 3)*180+59820: RANDOMIZE c: POKE 23675,PEEK 23670: POKE 23676,PEEK 23671: PRINT g$'f$(4 TO): LET c=c+160:

FOR f=22848 TO 22944 STEP 32:

FOR n=0 TO 4:

POKE f+n, PEEK c:

LET c=c+1:

NEXT n:

NEXT f:

RETURN

9998 REM *Символы от A до T в следующей строке являются графическими и набираются в

графическом режиме

9999 LET g$=CHR$22+CHR$10+CHR$0+"ABCDE"+CHR$13+"FGHIJ"+CHR$13+"KLMNO"+CHR13+"PQRST"

B строке 9999 формируется строковая переменная g$, содержащая в виде 20-ти символов UDG Вашу картинку. Картинка будет печататься в строке 10, начиная с нулевой колонки на экране Вашего телевизора. Место печати задается в строке 9999 кодами

CHR$22 (AT)

CHR$10 (номер строки)

CHR$0 (номер колонки).

Конечно, Вы можете изменить место печати, изменив номер строки, но номер колонки пусть останется равным нулю. Дело в том, что Ваша картинка имеет ведь 4 строки, а переход к печати следующей выполняется кодом CHR$13 (ENTER), после которого позиция печати выставляется всегда в нулевой колонке. Если захотите печатать не с нулевой колонки, то придется в строке 9999 убрать все CHR$ 13 и заменить их на соответствующие последовательности CHR$ 22 + CHR$ R + CHR$ C, где R - номер строки, а C - номер колонки.

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

Когда после запуска программы получите сообщение O.K, можете стереть строку 9999. Теперь картинка содержится в переменной g$, которая хранится в области переменных VARS и строку 9999 можно удалить для экономии места в программной области PROG.

Переменная f$ содержит сразу и номер Вашей картинки (сначала это 001) и название

(START).

Всю работу выполняет подпрограмма, начинавшаяся в строке 1000. Во-первых, берется номер картинки и умножается на 180. Когда к результату прибавили 59820, получается, что первая картинка находятся по адресу 60000, вторая - 60180 и т.д. Оператором RANDOMIZE по этому значению выставляется другая системная переменная -SEED, поэтому когда Вы будете командой PEEK "вытаскивать" графику UDG, Вы найдете нужные адреса в этой системной переменной.

Так программа печатает Вашу картинку в текущих цветовых атрибутах экрана (как они были установлены до того). Раскрашивание же картинки производится в той же строке 1000. Файл экранных атрибутов начинается с 22528 и занимает 768 байтов (24 ряда по 32 байта).

Поскольку Ваша картинка печатается в экранной строке 10, то атрибуты начинаются с 22528+10*32=22848, что Вы и видите в программной строке 1000. Закрашиванием Вашей картинки занимаются в строке 1000 два цикла - по f и по n.

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




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Глюки! - о различных глюках ассемблера XAS'a. "железные" глюки: порта клавиатуры, kempston joystick'а, музыкального процессора, кэша на пентагоне, дисководов.
Ferrum! - Как добиться хорошей связи с BBS.
BBS - список станций BBS ZXNet.
Вступление - об авторах, содержание номера.
Программирование - Загрузчик для рабочей дискеты.

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