Инструменты пользователя

Инструменты сайта


msx:basic_programming_guide:11

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

msx:basic_programming_guide:11 [2020-03-21 22:45]
msx:basic_programming_guide:11 [2022-09-09 23:28] (текущий)
Строка 1: Строка 1:
-[<>​] +~~HIDEPAGE:​search;​sitemap~~ 
-~~TOC wide~~ +~~REDIRECT>msx:basic_dialogue_programming_language:011~~
- +
-====== Глава XI. Работа с видеопамятью и видеопроцессором ====== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Надо понять тот минимум,​ на котором покоится мир, и всё избыточное безжалостно отсекать (бритва Оккама).<​WRAP rightalign>​ +
-—//​У.Оккам//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-===== XI.1. Видеопамять ===== +
- +
-//​Процессор//​ (англ. "​processor",​ от "​process"​ — "​обрабатывать"​) — совокупность устройств ЭВМ, выполняющих функции по преобразованию информации. В зависимости от назначения различают центральные,​ функционально–ориентированные и проблемно–ориентированные процессоры. +
- +
-Графические возможности ПЭВМ "​YAMAHA"​ поддерживаются функционально–ориентированным процессором — //​видеопроцессором//​. Видеопроцессор (VDP) постоянно "​общается"​ с //​видеопамятью//​ (VRAM), которая доступна центральному процессору через порты ввода–вывода,​ отвечает за изображение на экране и интерпретирует находящиеся в ней данные в соответствии с заданным режимом ''​SCREEN''​. Видеопроцессор обеспечивает отображение информации,​ хранящейся в видеопамяти,​ на экран дисплея. +
- +
-//​Видеопамять//​ ("​Video RAM") — доступная устройству сопряжения дисплея и компьютера область оперативной памяти ЭВМ, в которой расположены данные,​ соответствующие изображению на экране. В текстовом режиме видеопамять содержит коды и атрибуты символов,​в графических режимах каждой точке экрана соответствует одна или несколько ячеек видеопамяти,​ указывающие её цвет и яркость. Видеопамять разделена на несколько областей,​ называемых //​Таблицами//,​ имена которых,​ размеры и назначение зависят от установленного режима ''​SCREEN''​. +
- +
-<WRAP centeralign>​Это деление памяти автоматически выполняется оператором ''​SCREEN'',​ который инициализирует Таблицы видеопамяти.</​WRAP>​ +
- +
-Прежде чем Вы попытаетесь непосредственно воздействовать на "​содержимое"​ экрана дисплея,​ хорошо разберитесь в назначении Таблиц VRAM! +
- +
- ​Далее в тексте Вам часто будут встречаются следующие аббревиатуры:​ +
-^  Аббревиатура ​ ^  Что Вам необходимо //​запомнить//​! ​ ^^ +
-|  PNT  |"​Pattern Name Table"​|"​Таблица имён образов"​| +
-|  PGT  |"​Pattern Generation Table"​|"​Таблица шаблонов образов"​ ("​Таблица изображений"​)| +
-|  CT  |"​Color Table"​|"​Таблица цветов"​| +
-|  SGT  |"​Sprite Generation Table"​|"​Таблица шаблонов спрайтов"​| +
-|  SAT  |"​Sprite Attribute Table"​|"​Таблица атрибутов спрайтов"​| +
-|  SCT  |"​Sprite Color Table"​|"​Таблица цветов спрайтов"​| +
-|  PT  |"​Palette Table"​|"​Таблица палитры"​| +
- +
-{{anchor:​base}} +
-==== XI.1.1. Псевдопеременная BASE ==== +
- +
-Псевдопеременная ''​BASE''​ используется для чтения начальных адресов Таблиц VRAM, а также для их "​перемещения"​ в видеопамяти. +
- +
-  * <​WRAP>​ Вначале о синтаксисе псевдопеременной ''​BASE'',​ используемой как функция:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-BASE(N) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​BASE''​ ("​base"​ — "​база",​ "​значение или адрес, относительно которого представляются другие значения и адреса"​) — служебное слово;​ +
-  * N — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,19] для компьютеров [[msx:msx_1]] и отрезку [0,44] для компьютеров [[msx:​msx_2]]. По значению N можно определить номер Таблицы видеопамяти (VRAM). +
- +
-<WRAP centeralign>​Функция ''​BASE(N)'',​ где N=M*5+T, возвращает //​начальный адрес//​ Таблицы с номером Т в режиме ''​SCREEN M''​. Ясно, что M=N\5 и T=N MOD 5</​WRAP>​ +
- +
-Номер Таблицы T принадлежит интервалу [0,4]; режим экрана M может принимать значения 0, 1, 2, 3, 4, 5, 6, 7, 8 для компьютеров [[msx:​msx_2]] (0, 1, 2, 3 для компьютеров [[msx:​msx_1]]). Таким образом,​ с помощью функции ''​BASE()''​ можно иметь доступ не более, чем к //​пяти//​ Таблицам для каждого из режимов экрана. +
- +
-Ниже приведены имена Таблиц,​ соответствующих различным значениям T: +
- +
-^T^  //Имя// Таблицы ​ ^ +
-|0|PNT| +
-|1|CT  (кроме режимов ''​SCREEN 3, 5, 6, 7, 8''​ и 40–символьного режима ''​SCREEN 0''​)| +
-|2|PGT (кроме режимов ''​SCREEN 5, 6, 7, 8''​)| +
-|3|SAT (кроме режима ''​SCREEN 0''​)| +
-|4|SGT (кроме режима ''​SCREEN 0''​)| +
- +
-Например,​ найдём начальный адрес Таблицы CT в режиме ''​SCREEN 2''​. Для этого выполним команду:​ +
-<​code>​ +
-PRINT HEX$(BASE(5*2+1)) +
- ​2000 ​            ▲ ▲ +
-Ok  Режим экрана──┘ └── Номер Таблицы +
-</​code>​ +
- +
-Следующая табличка позволяет найти начальный адрес //​Таблицы//​ VRAM с номером T для режима ''​SCREEN M'':​ +
- +
-^  М \ Т  ^  0(PNT) ​ ^  1(CT)  ^  2(PGT) ​ ^  3(SAT) ​ ^  4(SGT) ​ ^ +
-|0 (40)|  0  |  —— ​ |  &​H800 ​ |  —— ​ |  —— ​ | +
-|0 (80)|  0  |  &​H800 ​ |  &​H1000 ​ |  —— ​ |  —— ​ | +
-|1|  &​H1800 ​ |  &​H2000 ​ |  0  |  &​H1B00 ​ |  &​H3800 ​ | +
-|2|  &​H1800 ​ |  &​H2000 ​ |  0  |  &​H1B00 ​ |  &​H3800 ​ | +
-|3|  &​H800 ​ |  —— ​ |  0  |  &​H1B00 ​ |  &​H3800 ​ | +
-|4|  &​H1800 ​ |  &​H2000 ​ |  0  |  &​H1E00 ​ |  &​H3800 ​ | +
-|5|  0  |  —— ​ |  —— ​ |  &​H7600 ​ |  &​H7800 ​ | +
-|6|  0  |  —— ​ |  —— ​ |  &​H7600 ​ |  &​H7800 ​ | +
-|7|  0  |  —— ​ |  —— ​ |  &​HFA00 ​ |  &​HF000 ​ | +
-|8|  0  |  —— ​ |  —— ​ |  &​HFA00 ​ |  &​HF000 ​ | +
- +
-Прочерками здесь помечены адреса Таблиц,​ отсутствующих в видеопамяти для данных M и T. Числа 40 и 80, стоящие в круглых скобках,​ указывают на ширину экрана в режиме ''​SCREEN 0''​. +
- +
-А в этой табличке показано количество байтов в каждой из Таблиц VRAM. +
- +
-^  М \ Т  ^  0(PNT) ​ ^  1(CT)  ^  2(PGT) ​ ^  3(SAT) ​ ^  4(SGT) ​ ^ +
-|0 (40)|  960  |  —— ​ |  2048  |  —— ​ |  —— ​ | +
-|0 (80)|  1920  |  270  |  2048  |  —— ​ |  —— ​ | +
-|1|  768  |  32  |  2048  |  128  |  2048  | +
-|2|  768  |  6144  |  6144  |  128  |  2048  | +
-|3|  768  |  —— ​ |  1536  |  128  |  2048  | +
-|4|  768  |  6144  |  6144  |  128  |  2048  | +
-|5|  27136  |  —— ​ |  —— ​ |  128  |  2048  | +
-|6|  27136  |  —— ​ |  —— ​ |  128  |  2048  | +
-|7|  54272  |  —— ​ |  —— ​ |  128  |  2048  | +
-|8|  54272  |  —— ​ |  —— ​ |  128  |  2048  | +
- +
-<WRAP centeralign>​Внимание! Функция ''​BASE''​ не позволяет найти начальные адреса Таблиц PT и SCT</​WRAP>​ +
- +
-Но Вы не волнуйтесь:​ в следующей табличке мы приводим начальные адреса и этих Таблиц:​ +
-^  Режим ​ ^  PT  ^  SCT  ^ +
-|0 (40)|  &​H0400 ​ |  —— ​ | +
-|0 (80)|  &​H0800 ​ |  —— ​ | +
-|1|  &​H2020 ​ |  —— ​ | +
-|2|  &​H1B80 ​ |  —— ​ | +
-|3|  &​H2020 ​ |  —— ​ | +
-|4|  &​H1E80 ​ |  &​H1C00 ​ | +
-|5|  &​H7680 ​ |  &​H7400 ​ | +
-|6|  &​H7680 ​ |  &​H7400 ​ | +
-|7|  &​HFA80 ​ |  &​HF800 ​ | +
-|8|  &​HFA80 ​ |  &​HF800 ​ | +
-Таблица ​ PT  для всех режимов ''​SCREEN''​ занимает в видеопамяти 32 байта. Таблица SCT для всех режимов ''​SCREEN''​ занимает в видеопамяти 512 байт. </​WRAP>​ +
-  * <​WRAP>​ А теперь — синтаксис псевдопеременной BASE,​используемой в //​левой//​ части оператора присваивания:​ +
-  BASE(N)= 1024*A +
-или +
-  BASE(N)=&​H400*A +
-где: +
-  * N — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,19]. Значение N — это номер //​Таблицы//​ VRAM; +
-  * A — арифметическое выражение,​целая часть значения которого,​ умноженная на число 1024, определяет новый начальный адрес таблицы VRAM с номером N (1Кбайт = 1024 байтам). Значение A должно принадлежать отрезку [0,15] для компьютеров серий [[msx:​msx_1]] и [[msx:​msx_2]]. +
- +
-^  Значение A  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  | +
-^  &​H400·A ​ |  0  |  &​H400 ​ |  &​H0800 ​ |  &​H0C00 ​ |  &​H1000 ​ |  &​H1400 ​ |  &​H1800 ​ |  &​H1C00 ​ |  &​H2000 ​ | +
- +
-^  Значение A  |  9  |  10  |  11  |  12  |  13  |  14  |  15  | +
-^  &​H400·A ​ |  &​H2400 ​ |  &​H2800 ​ |  &​H2C00 ​ |  &​H3000 ​ |  &​H3400 ​ |  &​H3800 ​ |  &​H3C00 ​ | +
- +
-Если значения N или A не будут принадлежать указанным отрезкам,​ то компьютер выдаст сообщение об ошибке:​ <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Псевдопеременная ''​BASE'',​ расположенная в правой части оператора присваивания,​ позволяет "​перемещать"​ Таблицы. Она используется только в режимах ''​SCREEN 0''​ ÷ ''​SCREEN 3'',​ и поэтому значение N должно принадлежать отрезку [0,19]. +
- +
-Вспомним,​ что в режимах ''​SCREEN 5÷8''​ можно переключаться с одной экранной //​страницы//​ на другую при помощи оператора ''​SET PAGE''​. Этот оператор,​ однако,​ не применим в режимах ''​SCREEN 0÷4''​. Используя же псевдопеременную ''​BASE'',​ можно "​работать"​ с экранными страницами в режимах ''​SCREEN 0÷3''​. В режиме ''​SCREEN 4''​ работа с экранными страницами запрещена. Приведём следующую табличку:​ +
- +
-^  //​Режим//​ экрана ​ |  0(40)  |  0(80)  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  | +
-^  Число разрешённых \\ экранных страниц ​ |  4  |  2  |  1  |  1  |  1  |  1  |  4  |  4  |  2  |  2  | +
-|:::|  Используется ''​BASE'' ​ ||||| |  Используется ''​SET PAGE'' ​ |||| +
-</​WRAP>​ +
- +
-__//​Пример//​__. Запись нескольких экранных //​страниц//​ в режиме ''​SCREEN 0''​ и их переключение. +
- +
-Стандартный начальный адрес для Таблицы PNT в режиме ''​SCREEN 0''​ равен 0. "​Передвинем"​ эту таблицу вначале к адресу &H2000, а затем к адресу &H2400. Идентифицируем экранные страницы ("​что–нибудь"​ на них напишем!),​ а затем будем переключаться с одной страницы на другую путём переопределения начала Таблицы PNT в строках 100 и 110. +
- +
-<WRAP centeralign>​Заметим,​ что начальные адреса Таблиц PNT, PGT, SGT и SAT для текущего режима ''​SCREEN''​ хранятся в рабочей области,​ начиная с адресов &HF922, &HF924, &HF926 и &HF928 соответственно,​и занимают по два байта каждый.</​WRAP>​ +
- +
-Эти значения не могут быть изменены оператором ''​BASE'':​ Вы должны сделать это //​сами//​ (строка 110). Если Вы это не сделаете,​ то выход в непосредственный режим работы будет возможен только из //​нулевой//​ страницы,​ а +
-выйти на неё из другой страницы можно осуществить,​ если набрать "​вслепую"​ команду \\ ''​SCREEN М''​ , где М — номер режима. +
- +
-{{anchor:​e1111-01}} \\ {{.examples:​1111-01.bas|}} \\ [[+tab|wmsxbpge>​1111-01.bas]] +
-<​code>​ +
-10 SCREEN 0:WIDTH 40 +
-20 FOR I=0 TO 2 +
-30    GOSUB 100:GOSUB 200 '​──▶ +
-40 NEXT I +
-50 IF INKEY$=""​ THEN 50 +
-60 I=(I+1)MOD3:​GOSUB 100 '​──▶ +
-70 GOTO 50 +
-90 '​∗∗∗∗∗ Подпрограмма 1 ∗∗∗∗∗ +
-100 IF I=0 THEN BASE(0)=0 ELSE BASE(0)=&​H2000+(I-1)*&​H400 +
-110 IF I=0 THEN  POKE &​HF922,&​H00:​POKE &​HF923,&​H00 +
-           ​ELSE ​ POKE &​HF922,​0:​POKE &​HF923,&​H20+(I-1)*4'​Запись в слово +
-                      ──▲─── ​       ───▲── ​            '​ NAMBAS +
-   ​Адрес младшего байта─┘ ​             └─ Адрес старшего байта +
-120 RETURN '​──▶ +
-190 '​∗∗∗∗∗ Подпрограмма 2 ∗∗∗∗∗ +
-200 CLS:FOR J=0 TO 50:PRINT "​PAGE";​I;:​NEXT:​RETURN '​──▶ +
-</​code>​ +
- +
-==== XI.1.2. Функция VPEEK. Оператор VPOKE ==== +
-{{anchor:​vpeek}} +
-Вы всегда можете посмотреть,​ какое число находится в той или иной ячейке видеопамяти. Для этого используется функция ''​VPEEK'',​ общий вид которой:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VPEEK(адрес) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​VPEEK''​ ("​Video RAM PEEK") — служебное слово;​ +
-  * //​адрес//​ — арифметическое выражение,​ целая часть значения которого принадлежит отрезку [0,16383] для компьютеров [[msx:​msx_1]] и [0,65535] для компьютеров [[msx:​msx_2]]. Нарушение этого условия приводит к сообщению об ошибке <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Функция ''​VPEEK''​ возвращает содержимое ячейки VRAM с номером //"​адрес"//​. +
-Действия функций ''​VPEEK''​ и ''​PEEK''​ аналогичны. +
- +
-{{anchor:​vpoke}} +
-Для //​записи//​ данных в конкретную ячейку видеопамяти предназначен оператор ''​VPOKE'',​ синтаксис которого:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VPOKE адрес, данное +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​VPOKE''​ ("​Video RAM POKE") — служебное слово;​ +
-  * //​адрес//​ — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,16383] для компьютеров [[msx:​msx_1]] и отрезку [0,65535] для компьютеров [[msx:​msx_2]];​ +
-  * //​данное//​ — арифметическое выражение,​ целая часть значения которого должна принадлежать отрезку [0,255]. +
- +
-Если хотя бы одно из значений параметров //​адрес//​ или //​данное//​ не удовлетворяет требуемым условиям,​ то компьютер сообщает об ошибке:​ <WRAP centeralign>"​Illegal function call"​.</​WRAP>​ +
- +
-Приведём простейший пример:​ вначале запишем в ячейку VRAM с номером 16383 число 10 командой ''​VPOKE 16383,​10'',​ а затем "​прочтём"​содержимое этой ячейки:​ +
-<​code>​ +
-print VPEEK(16383) +
- 10 +
-Ok +
-</​code>​ +
- +
-Думаем,​ Вам ясна аналогия в действиях операторов ''​VPOKE''​ и ''​POKE''​. +
- +
-Если Вы посмотрите на структуру видеопамяти в различных экранных режимах,​ то заметите,​ что некоторые области видеопамяти не используются. Эти области могут служить в качестве дополнительного пространства для сохранения данных при помощи оператора ''​VPOKE'',​ когда RAM почти полностью использована! Однако при таком методе необходимо постоянно пользоваться нулевым текстовым режимом экрана — при смене режима Ваши данные будут уничтожены. +
- +
-{{anchor:​e1112-01}} __//​Пример 1//__. "​Спрячем"​ числовой массив (кстати,​ а где оператор ''​DIM''​ ?!) в видеопамяти,​ а затем "​извлечём его"​ оттуда. \\ {{.examples:​1112-01.bas|}} \\ [[+tab|wmsxbpge>​1112-01.bas]] +
-<​code>​ +
-10 SCREEN 0:WIDTH 40:ADR=4096 '​Начальный адрес хранения данных в VRAM +
-20 INPUT"​Число элементов массива";​N +
-30 FOR T=1 TO N +
-40    INPUT"​Очередной элемент";​Z +
-50    FOR I=0 TO 7 +
-60       VPOKE ADR+8*T+I,​PEEK(VARPTR(Z)+I) +
-70 NEXT I,T +
-80 '​Выведем элементы массива на экран +
-90 FOR T=1 TO N +
-100    IF VPEEK(ADR+8*T)\128=1 THEN Z$="​-."​ ELSE Z$="​+."​ '​Знак числа +
-110    FOR I=1 TO 7 +
-120       ​Z$=Z$+RIGHT$("​00"​+HEX$(VPEEK(ADR+8*T+I)),​2) '​Мантисса числа +
-130    NEXT I +
-140    IF(VPEEK(ADR+8*T) MOD 128)\64=1 THEN Z$=Z$+"​E+"​ ELSE Z$=Z$+"​E-"​ +
-150    Z$=Z$+MID$(STR$((VPEEK(ADR+8*T)MOD 128)-64),2) '​Порядок числа +
-160 U=VAL(Z$):​PRINT U;:NEXT T +
-</​code>​ +
- +
-{{anchor:​e1112-02}} __//​Пример 2//__. \\ {{.examples:​1112-02.bas|}} \\ [[+tab|wmsxbpge>​1112-02.bas]] +
-<​code>​ +
-10 TP=4096:​SCREEN 0:WIDTH 38 +
-30 INPUT"​Имя (символ '​*'​ - для окончания)";​N$ +
-40 IF LEFT$(N$,​1)="​*"​THEN 120 +
-50 IF TP+LEN(N$)+1>​16383 THEN PRINT"​Память заполнена":​GOTO 120 +
-60 FOR I=1 TO LEN(N$) +
-70      VPOKE TP,​ASC(MID$(N$,​I,​1)):​TP=TP+1 +
-90 NEXT +
-100 VPOKE TP,​0:​TP=TP+1 +
-110 GOTO 30 +
-120 CLS:​I=4096 +
-140 X=VPEEK(I) +
-150 IF X=0 THEN PRINT:GOTO 170 +
-160 PRINT CHR$(X) +
-170 I=I+1 +
-180 IF I<TP THEN 140 +
-190 END +
-</​code>​ +
- +
-Если скорость не является существенным фактором,​ то рассмотренный способ хранения данных в видеопамяти может быть весьма полезным,​ особенно для больших программ! +
- +
-==== XI.1.3. Текстовые режимы ==== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Они мастера накапливать факты, а вот извлечь из них пользу им удаётся не всегда. +
-<WRAP rightalign>​ +
-—//​Конан Дойль. Морской договор//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Введём понятия //​общей//​ ширины (высоты) экрана и //​доступной//​ ширины (высоты) экрана. +
- +
-//​Доступная//​ ширина экрана — это область экрана,​ "​доступная"​ текстовому курсору. Её размер устанавливается оператором ''​WIDTH''​. +
- +
-//​Общая//​ ширина экрана однозначно определяется оператором ''​SCREEN''​. +
- +
-В режиме ''​SCREEN 1''​ она равна 32 символам. +
- +
-В режиме ''​SCREEN 0''​ она устанавливается равной 40 символам,​ если аргумент в операторе ''​WIDTH''​ ≤ 40 и равной 80 символам в противном случае. +
- +
-Общая //​высота//​ экрана для текстовых режимов равна 24 символам,​ однако для режимов ''​SCREEN 0''​ (80 символов) и ''​SCREEN 1''​ она может быть равной 26.5 символам. +
- +
-<WRAP centeralign>​Для расположения символов в нужном Вам месте экрана используйте Таблицу имён образов (PNT)!</​WRAP>​ +
- +
-На рисунках показана нумерация возможных позиций курсора на текстовых экранах:​ +
- +
-  * ''​SCREEN 0''​ (40 символов)<​code>​ +
-┌───┬───┬─────┬───┬───┐ +
-│ 0 │ 1 │ ··· │ 38│ 39│ +
-├───┴───┘ ​    ​└───┴───┤ +
-│  ··· ​   ··· ​   ··· ​ │ +
-├───┬───┐ ​    ​┌───┬───┤ +
-│920│921│ ··· │958│959│ +
-└───┴───┴─────┴───┴───┘ +
-</​code>​ +
-  * ''​SCREEN 0''​ (80 символов),​ высота экрана — 24 симв.<​code>​ +
-┌────┬────┬─────┬────┬────┐ +
-│  0 │  1 │ ··· │ 78 │ 79 │ +
-├────┴────┘ ​    ​└────┴────┤ +
-│   ​··· ​    ​··· ​    ​··· ​  │ +
-├────┬────┐ ​    ​┌────┬────┤ +
-│1840│1841│ ··· │1918│1919│ +
-└────┴────┴─────┴────┴────┘ +
-</​code>​ +
-  * ''​SCREEN 1''​ , высота экрана — 24 симв.<​code>​ +
-┌───┬───┬─────┬───┬───┐ +
-│ 0 │ 1 │ ··· │ 30│ 31│ +
-├───┴───┘ ​    ​└───┴───┤ +
-│  ··· ​   ··· ​   ··· ​ │ +
-├───┬───┐ ​    ​┌───┬───┤ +
-│744│745│ ··· │766│767│ +
-└───┴───┴─────┴───┴───┘ +
-</​code>​ +
- +
-Чтобы изобразить символ в нужном месте экрана,​используйте оператор:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VPOKE BASE(5*T)+W,​K +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * T — номер режима экрана (0 или 1); +
-  * W — номер позиции символа на экране;​ +
-  * K — код ASCII символа. +
- +
-{{anchor:​e1113-01}} __//​Пример 1//__. Вывести "​A"​ (код ASCII 65) в 8–й строке и 10–м столбце экрана ''​SCREEN 0'':​ \\ {{.examples:​1113-01.bas|}} \\ [[+tab|wmsxbpge>​1113-01.bas]] +
- +
-<​code>​ +
-10 SCREEN 0:WIDTH 40 +
-20 VPOKE BASE(5*T)+40*8+10,​65 +
-                      ▲ ▲ +
-  Номер строки экрана─┘ └─ Номер столбца экрана +
-</​code>​ +
- +
-Описанная возможность позволяет,​ например,​ выводить информацию в те места экрана,​ которые //​недоступны//​ для вывода оператором ''​PRINT''​. +
- +
- +
-{{anchor:​e1113-02}} __//​Пример 2//__. Обратите внимание на то, что общая ширина экрана и доступная ширина экрана — различны! \\ {{.examples:​1113-02.bas|}} \\ [[+tab|wmsxbpge>​1113-02.bas]] +
-<​code>​ +
-10 TIME=0:​INTERVAL ON:ON INTERVAL=60 GOSUB 100 +
-20 GOTO 20 '​Место для основной программы. +
-100 WIDTH 28:​T1=INT(TIME/​3600):​T2=T2+1:​IF T2=60 THEN T2=0 +
-110 FOR J=0 TO 1 +
-120 VPOKE 40+J,​ASC(MID$(RIGHT$("​0"​+MID$(STR$(T1),​2),​2),​J+1)):​VPOKE 42,​ASC(":"​) +
-130 VPOKE 43+J,​ASC(MID$(RIGHT$("​0"​+MID$(STR$(T2),​2),​2),​J+1)):​NEXT:​RETURN +
-</​code>​ +
- +
-Оказывается,​ можно одновременно "​хранить"​ содержимое нескольких экранных //​страниц//,​ причём в любой момент можно "​открыть"​ любую страницу и "​прочесть"​ её содержимое. +
- +
-Вывод информации на нулевую страницу предполагает использование операторов ''​PRINT''​ или ''​VPOKE''​. Для остальных же страниц вывод информации оператором ''​PRINT''​ невозможен,​ и поэтому приходится пользоваться оператором ''​VPOKE''​. +
- +
-Вы всегда можете изобразить любой символ в нужном месте //​любой//​ экранной страницы при помощи оператора:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VPOKE 4096*T*(N+1)^2+W,​K +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * T — номер //​страницы//;​ +
-  * N — режим экрана (0 или 1); +
-  * W — номер позиции символа на экране;​ +
-  * K — код ASCII символа. +
- +
-При этом Вы сможете увидеть содержимое только нулевой страницы. +
-Чтобы "​просмотреть содержимое"​ других страниц,​ воспользуйтесь псевдопеременной ''​BASE''​. +
- +
- +
-{{anchor:​e1113-03}} __//​Пример 3//__. "​Полистаем"​ экранные страницы! \\ {{.examples:​1113-03.bas|}} \\ [[+tab|wmsxbpge>​1113-03.bas]] +
-<​code>​ +
-NEW +
-Ok                                   ​┌─ Код символа "​SPACE"​("​пробел"​) +
-10 FOR T=1 TO 3                      ▼ +
-20     FOR D=0 TO 959:VPOKE 4096*T+D,​32:​NEXT D '​Очистка T-ой страницы +
-30     PRINT "​Введите"​T"​слово";:​INPUT A$ +
-40     PRINT "С какого места печатать?"​ +
-50     INPUT "​X(от 0 до 39)";​VX:​INPUT "​Y(от 0 до 23)";​VY +
-60   FOR B=1 TO LEN(A$) +
-70    VPOKE 4096*T+40*VY+VX+B,​ASC(MID$(A$,​B,​1))'​Запись на T-ю страницу +
-80   NEXT B:NEXT T +
-90  FOR T=1 TO 3:​Z$=INPUT$(1):​ BASE(0)=4096*T '​4096=&​H1000 ──▶ &H10 00 +
-95    POKE &HF923, &H10*T: POKE &HF922, 0*T '​Чтение с экрана +
-           ​──▲─── ​              ​───▲── +
-             └ Адрес старшего байта└ Адрес младшего байта +
-97  NEXT T +
-100 A$=INPUT$(1):​BASE(0)=0:​POKE &​HF923,​0 '​Вывод "​содержимого"​ 0-й страницы +
-</​code>​ +
- +
-//​Внимание//​! Страницы могут быть "​засорены"​ посторонней информацией,​ оставшейся от прежнего обращения к ним. Ваши сообщения могут затеряться среди этого "​мусора"​. Поэтому рекомендуем своевременно заботиться о чистоте страниц (посмотрите на строку 20 примера 3)! +
- +
-Приведём структуру Таблицы имён образов (PNT) для 80–символьного режима ''​SCREEN 0''​ в соответствии с расположением символов на экране дисплея:​ +
- +
-|  0–й байт ​ |код символа в 0–ой строке и 0–ом столбце экрана| +
-|  1–й байт ​ |код символа в 0–ой строке и 1–ом столбце экрана| +
-|  …  | +
-|  79–й байт |код символа в 0–ой строке и 79–ом столбце экрана| +
-|  80–й байт |код символа в 1–ой строке и 0–ом столбце экрана| +
-|  …  | +
-|  1919–й байт ​ |код символа в 23–ой строке и 79–ом столбце экрана| +
- +
-Приведём структуру Таблицы имён образов (PNT) для режима ''​SCREEN 1''​ в соответствии с расположением символов на экране дисплея:​ +
-|  0–й байт ​ |код символа в 0–ой строке и 0–ом столбце экрана| +
-|  1–й байт ​ |код символа в 0–ой строке и 1–ом столбце экрана| +
-|  …  | +
-|  31–й байт |код символа в 0–ой строке и 31–ом столбце экрана| +
-|  32–й байт |код символа в 1–ой строке и 0–ом столбце экрана| +
-|  …  | +
-|  767–й байт ​ |код символа в 23–ой строке и 31–ом столбце экрана| +
- +
-Структуру Таблицы имён образов(PNT) для 40–символьного режима ''​SCREEN 0''​ в соответствии с расположением символов на экране дисплея Вы теперь легко изобразите самостоятельно! +
- +
-Информация о символах,​ имеющихся на клавиатуре компьютера,​ находится в ROM, начиная с адреса &H1BBF, и занимает 2 Кбайта памяти. При переходе в режимы ''​SCREEN 0''​ или ''​SCREEN 1''​ эта информация автоматически копируется в видеопамять,​ инициализируя тем самым Таблицу шаблонов образов (PGT). +
- +
-Место в ROM и видеопамяти,​ предназначенное для записи //​одного//​ символа,​ занимает //​восемь//​ байт. +
- +
-Адрес начала места, отведённого для символа в видеопамяти,​ можно определить обращением к функции ''​BASE'':​ +
-  BASE(5*N+2)+K*8 +
-где: +
-  * N — номер режима экрана (0 или 1); +
-  * K — код ASCII символа. +
- +
-Приведём пример "​хранения"​ информации о символе в ROM и VRAM (справа для каждого байта выписан его шестнадцатеричный код, который и задаёт содержимое данного байта):​ +
-<​code>​ +
-          ┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-0–й ​ байт │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​ &H00 +
-          ├───┼───┼───┼───┼───┼───┼───┼───┤ +
-1–й ​ байт │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​ &H00 +
-          ├───┼───┼───┼───┼───┼───┼───┼───┤ +
-2–й ​ байт │   │ █ │   ​│ ​  ​│ ​  ​│ ​  │ █ │   ​│ ​ &H42 +
-          ├───┼───┼───┼───┼───┼───┼───┼───┤ +
-3–й ​ байт │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │  &H81 +
-          ├───┼───┼───┼───┼───┤───┼───┼───┤ +
-4–й ​ байт │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │  &H81 +
-          ├───┼───┼───┼───┼───┼───┼───┼───┤ +
-5–й ​ байт │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │  &H81 +
-          ├───┼───┼───┼───┼───┼───┼───┼───┤ +
-6–й ​ байт │ █ │   ​│ ​  │ █ │ █ │   ​│ ​  │ █ │  &H99 +
-          ├───┼───┼───┼───┼───┼───┼───┼───┤ +
-7–й ​ байт │   │ █ │ █ │   ​│ ​  │ █ │ █ │   ​│ ​ &H66 +
-          └───┴───┴───┴───┴───┴───┴───┴───┘ +
-            8   ​4 ​  ​2 ​  ​1 ​  ​8 ​  ​4 ​  ​2 ​  1 +
-</​code>​ +
- +
-Расскажем Вам о том, как можно получить "​содержимое"​ конкретного байта видеопамяти. Разобьём каждый байт на две половинки (два полубайта). Под рисунком для каждого полубайта изображено по 4 числа (каждое из них назовём "​весом"​). Код полубайта получим суммированием "​весов"​ точек, содержащихся в нем (напомним шестнадцатеричные цифры: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F). Код байта получим,​ если справа от кода левого полубайта напишем код правого полубайта,​ а слева — символ "&​H"​. +
- +
-//​Внимание//​! Только режим ''​SCREEN 0'',​ а в компьютере серии [[msx:​msx_2]] также и режимы ''​SCREEN 6''​ и ''​SCREEN 7'',​ поддерживают вывод символов размером 6×8 точек; остальные режимы используют размер 8×8. Приведём пример вывода одного и того же символа в двух режимах:​ +
-<​code>​ +
-         ​SCREEN 0                        SCREEN 1 +
-┌───┬───┬───┬───┬───┬───┐ ​  ​┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┤ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┤ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │   ​│ ​  ​│ ​  ​│ ​  │ █ │   │ +
-├───┼───┼───┼───┼───┼───┼ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ +
-├───┼───┼───┼───┼───┼───┤ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ +
-├───┼───┼───┼───┼───┼───┤ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ +
-├───┼───┼───┼───┼───┼───┤ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │   ​│ ​  │ █ │ █ │   ​│ ​  │ █ │   ​│ ​  │ █ │ █ │   ​│ ​  │ █ │ +
-├───┼───┼───┼───┼───┼───┤ ​  ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   │ █ │ █ │   ​│ ​  │ █ │   ​│ ​  │ █ │ █ │   ​│ ​  │ █ │ █ │   │ +
-└───┴───┴───┴───┴───┴───┘ ​  ​└───┴───┴───┴───┴───┴───┴───┴───┘ +
-</​code>​ +
- +
-Важно отметить,​ что в языке [[msx:​basic:​]] есть возможность программным путём создавать "​собственные"​ символы (отличные от стандартных!). Взгляните на приведённые ниже примеры. +
- +
-{{anchor:​e1113-04}} __//​Пример 4//__. \\ {{.examples:​1113-04.bas|}} \\ [[+tab|wmsxbpge>​1113-04.bas]] +
-<​code>​ +
-              Код ASCII символа "​у"​┐ +
-5  SCREEN 0:WIDTH 40               ▼ +
-10 FOR I=0 TO 7:READ M:VPOKE 2048+213*8+I,​M:​NEXT +
-20 DATA &​H00,&​H00,&​H42,&​H81,&​H81,&​H81,&​H99,&​H66 +
-</​code>​ +
- +
-Данные в операторе DATA определяют шестнадцатеричные коды каждого байта "​нового"​ символа. Число 213 в операторе ''​VPOKE''​ означает,​ что "​построенному"​ нами символу присваивается код ASCII, равный 213. Если раньше коду 213 соответствовал символ "​у",​ то теперь это место занял символ,​ который мы "​сконструировали"​. Поэтому в тех местах экрана дисплея,​ где встречался символ "​у",​ Вы увидите новый символ. +
- +
-{{anchor:​e1113-05}} __//​Пример 5//__. \\ {{.examples:​1113-05.bas|}} \\ [[+tab|wmsxbpge>​1113-05.bas]] +
-<​code>​ +
-5  SCREEN 0:WIDTH 80 +
-10 FOR I=0 TO 7:READ M:VPOKE &​h1000+213*8+I,​M:​NEXT +
-20 DATA &​H00,&​H00,&​H42,&​H81,&​H81,&​H81,&​H99,&​H66 +
-</​code>​ +
- +
-{{anchor:​e1113-06}} __//​Пример 6//__. \\ {{.examples:​1113-06.bas|}} \\ [[+tab|wmsxbpge>​1113-06.bas]] +
-<​code>​ +
-5 PRINT"​Вводите последовательно байты шаблона символа:"​ +
-10 FOR I=0 TO 7:INPUT T(I):NEXT +
-20 INPUT"​Введите код изменяемого символа";​K% +
-30 FOR I=0 TO 7:VPOKE 2048+K%*8+I,​T(I):​NEXT +
-</​code>​ +
-Отметим,​ что вместо переменной K% можно использовать любое арифметическое выражение,​ целая часть значения которого определяет код ASCII заменяемого символа. А теперь взгляните на следующую программу! +
- +
- +
-{{anchor:​e1113-07}} __//​Пример 7//__. Изображение "​псевдослучайных"​ символов. \\ {{.examples:​1113-07.bas|}} \\ [[+tab|wmsxbpge>​1113-07.bas]] +
-<​code>​ +
-10 P=RND(-TIME):​FOR I=0 TO 7:​T(I)=INT(255*RND(1)):​NEXT +
-20 K=INT(223*RND(1)+31) +
-30 FOR I=0 TO 7:VPOKE 2048+K*8+I,​T(I):​NEXT:​PRINT K,CHR$(K) +
-</​code>​ +
- +
-После выполнения этой программы нажмите на кнопку <​key>​RESET</​key>​. +
- +
-<WRAP centeralign>​Отметим,​ что при выполнении оператора ''​SCREEN 0''​ (или ''​SCREEN 1''​) Таблица шаблонов образов (PGT) инициализируется вновь данными из ROM!</​WRAP>​ +
- +
-Ещё ряд примеров на изменение шаблонов символов:​ +
- +
-{{anchor:​e1113-08}} __//​Пример 8//__ [[bibliography#​b76|[76]]]. "​Мелкие"​ и обычные буквы латинского алфавита. \\ {{.examples:​1113-08.bas|}} \\ [[+tab|wmsxbpge>​1113-08.bas]] +
-<​code>​ +
-40 SCREEN 0:KEY OFF +
-50 BASE(2)=2048 +
-60 PRINT"​Загрузка данных":​PRINT +
-70 FOR I=4616 TO 4823 +
-80    READ A$:VPOKE I,​VAL("&​h"​+A$) +
-90    VPOKE I+256,​VAL("&​h"​+A$) +
-100 NEXT +
-120 PRINT"​Нажмите клавишу для изменения"​ +
-130 PRINT" ​     набора символов"​ +
-140 A$=INPUT$(1) +
-160 BASE(2)=4096 +
-180 ' Б у к в ы  а л ф а в и т а +
-200 DATA 00,​00,​70,​88,​F8,​88,​88,​00:'​A +
-210 DATA 00,​00,​F0,​48,​70,​48,​F0,​00:'​B +
-220 DATA 00,​00,​78,​80,​80,​80,​78,​00:'​C +
-230 DATA 00,​00,​F0,​88,​88,​88,​F0,​00:'​D +
-240 DATA 00,​00,​F0,​80,​E0,​80,​F0,​00:'​E +
-250 DATA 00,​00,​F0,​80,​E0,​80,​80,​00:'​F +
-260 DATA 00,​00,​78,​80,​B8,​88,​70,​00:'​G +
-270 DATA 00,​00,​88,​88,​F8,​88,​88,​00:'​H +
-280 DATA 00,​00,​70,​20,​20,​20,​70,​00:'​I +
-290 DATA 00,​00,​70,​20,​20,​A0,​E0,​00:'​J +
-300 DATA 00,​00,​90,​A0,​C0,​A0,​90,​00:'​K +
-310 DATA 00,​00,​80,​80,​80,​80,​F8,​00:'​L +
-320 DATA 00,​00,​88,​D8,​A8,​88,​88,​00:'​M +
-330 DATA 00,​00,​88,​C8,​A8,​98,​88,​00:'​N +
-340 DATA 00,​00,​F8,​88,​88,​88,​F8,​00:'​O +
-350 DATA 00,​00,​F0,​88,​F0,​80,​80,​00:'​P +
-360 DATA 00,​00,​F8,​88,​A8,​90,​E8,​00:'​Q +
-370 DATA 00,​00,​F8,​88,​F8,​A0,​90,​00:'​R +
-380 DATA 00,​00,​78,​80,​70,​08,​F0,​00:'​S +
-390 DATA 00,​00,​F8,​20,​20,​20,​20,​00:'​T +
-400 DATA 00,​00,​88,​88,​88,​88,​70,​00:'​U +
-410 DATA 00,​00,​88,​88,​90,​A0,​40,​00:'​V +
-420 DATA 00,​00,​88,​88,​A8,​D8,​88,​00:'​W +
-430 DATA 00,​00,​88,​50,​20,​50,​88,​00:'​X +
-440 DATA 00,​00,​88,​50,​20,​20,​20,​00:'​Y +
-450 DATA 00,​00,​F8,​10,​20,​40,​F8,​00:'​Z +
-</​code>​ +
- +
-{{anchor:​e1113-09}} __//​Пример 9//__. Автограф программиста! \\ {{.examples:​1113-09.bas|}} \\ [[+tab|wmsxbpge>​1113-09.bas]] +
-<​code>​ +
-10 COLOR15,​1,​1:​SCREEN 1 +
-20 J=33:​KEYOFF +
-30 DATA 0000000000000003,​00001E214346E098,​0000000000000000,​0001010101097595,​C850408000000000,​0409090701010262,​840404081C026291,​0202444464505162,​89A1C10F32C20206,​000000E010080810,​938584C870000000,​0102847800000000,​0202010000000000,​0A33C20000000000,​906000000 +
-40 READ A$:FOR T=2 TO 16 STEP 2:​VPOKE8*J+T/​2-1,​VAL("&​h"​+MID$(A$,​T-1,​2)):​NEXT +
-50 IF J<47 THEN J=J+1:GOTO 40 +
-60 A$=CHR$(33)+CHR$(34)+CHR$(35)+CHR$(36)+CHR$(37)+CHR$(29)+CHR$(29)+CHR$(29)+CHR$(29)+CHR$(29)+CHR$(31)+CHR$(38)+CHR$(39)+CHR$(40)+CHR$(41)+CHR$(42)+CHR$(29)+CHR$(29)+CHR$(29)+CHR$(29)+CHR$(29)+CHR$(31)+CHR$(43)+CHR$(44)+CHR$(45)+CHR$(46)+CHR$(47) +
-70 LOCATE 2,​2:​PRINTA$ +
-80 GOTO 80 +
-</​code>​ +
- +
-{{anchor:​e1113-10}} __//​Пример 10//__. "​Изготовление"​ //"​толстых"//​ символов! \\ {{.examples:​1113-10.bas|}} \\ [[+tab|wmsxbpge>​1113-10.bas]] +
-<​code>​ +
-5 SCREEN 1:​A1=0:​A2=255 ​       ' Имеющийся шаблон символа сдвигается +
-10 FOR X=A1*8 TO A2*8+7 ​      '​ на один разряд и складывается со +
-20 D=VPEEK(X):​VPOKE X,D OR D/​2' ​             "​старым"​. +
-30 NEXT +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Целью придумавших систему было, очевидно,​ скрыть,​ что в этих значках содержится какой–то смысл.<​WRAP rightalign>​ +
-—//​Конан Дойль. Пляшущие человечки//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-{{anchor:​e1113-11}} //​Пример 11//. //​Бегущий//​ человечек. \\ {{.examples:​1113-11.bas|}} \\ [[+tab|wmsxbpge>​1113-11.bas]] +
-<​code>​ +
-5 COLOR 15,​1,​1:​CLS:​INPUT"​Укажите желаемую скорость движения человечка (чем больше число - тем меньше скорость)";​C +
-10 CLS:SCREEN 1,2,90:DIM A$(50):​J=100 +
-30 DATA 0C0C7ADE38EC8406,​03030E171607050A,​0000010301000701 +
-60 DATA C0C0808080C08080,​0000000101000000,​3030E078606050A0 +
-90 READA$:FOR T=2 TO 16 STEP 2:VPOKE 8*J+T/​2-1,​VAL("&​h"​+MID$(A$,​T-1,​2)):​NEXT +
-100 IF J<105 THEN J=J+1:GOTO 90 '​──▶ +
-110 A$(0)=CHR$(100)+"​ ":​A$(1)=CHR$(101)+"​ ":​A$(2)=CHR$(102)+CHR$(103) +
-140 A$(3)=CHR$(104)+CHR$(105) +
-150 FOR I=0 TO 3:LOCATE Y,​7:​PRINT"​ ";​A$(I) +
-165 FOR W=0 TO C:NEXT +
-166 IF Y=27 THEN Y=0 +
-170 NEXT:​Y=Y+1:​A$=INKEY$:​IF A$=" " THEN END +
-171 GOTO 150 '​──▶ +
-</​code>​ +
-Приведём шаблоны четырёх символов из шести,​сформированных в данной программе:​ +
-<​code>​ +
-┌───┬───┬───┬───┬───┬───┬───┬───┐ ​      ​┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-│   ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │   ​│ ​  ​│0C ​  ​03│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │   ​│ ​  ​│0C ​  ​03│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   │ █ │ █ │ █ │ █ │   │ █ │   ​│7A ​  ​0E│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │ █ │   │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │ █ │   │ █ │ █ │ █ │ █ │   ​│DE ​  ​17│ ​  ​│ ​  ​│ ​  │ █ │   │ █ │ █ │ █ │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  │ █ │ █ │ █ │   ​│ ​  ​│ ​  ​│38 ​  ​16│ ​  ​│ ​  ​│ ​  │ █ │   │ █ │ █ │   │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │ █ │ █ │   │ █ │ █ │   ​│ ​  ​│EC ​  ​07│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │ █ │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│ █ │   ​│ ​  ​│ ​  ​│ ​  │ █ │   ​│ ​  ​│84 ​  ​05│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │   │ █ │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │   ​│06 ​  ​0A│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │   │ █ │   │ +
-└───┴───┴───┴───┴───┴───┴───┴───┘ ​      ​└───┴───┴───┴───┴───┴───┴───┴───┘ +
-┌───┬───┬───┬───┬───┬───┬───┬───┐ ​      ​┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│00 ​  C0│ █ │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│00 ​  C0│ █ │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │01   80│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │03   80│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │01   80│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│00 ​  C0│ █ │ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │ █ │ █ │07   80│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-├───┼───┼───┼───┼───┼───┼───┼───┤ ​      ​├───┼───┼───┼───┼───┼───┼───┼───┤ +
-│   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ █ │01   80│ █ │   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ +
-└───┴───┴───┴───┴───┴───┴───┴───┘ ​      ​└───┴───┴───┴───┴───┴───┴───┴───┘ +
-</​code>​ +
- +
-В режиме ''​SCREEN 1''​ Таблица цветов (CT) позволяет,​ вообще говоря,​ выводить текст, символы которого имеют разные цвета. Однако,​ учтите,​ что каждый из 32 байтов Таблицы CT действует на группу из 8 символов,​ причём за цвет //​изображения//​ данной группы "​отвечает"​ старший полубайт,​ а младший полубайт "​отвечает"​ за цвет //​фона//​ символов. +
- +
-//Байт Таблицы//​ CT +
-|Цвет изображения восьми символов||||Цвет фона восьми символов|||| +
-|  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  | +
- +
-{{anchor:​e1113-12}} __//​Пример 12//__. Вывод семи первых прописных букв латинского алфавита и символа "​@"​ в "​инвертированном"​ цвете: \\ {{.examples:​1113-12.bas|}} \\ [[+tab|wmsxbpge>​1113-12.bas]] +
-<​code>​ +
-10 SCREEN 1:COLOR 15,4,7 +
-20 VPOKE &​H2008,&​H4F +
-</​code>​ +
-Адрес Таблицы CT (&​H2000+8) связан с символами,​ у которых коды ASCII принадлежат отрезку [64,71] (символы @, A, B, C, D, E, F, G). Если Вы хотите напечатать в "​инвертированном"​ цвете символ "​H"​ (восьмую букву латинского +
-алфавита),​то адрес &H2009 видеопамяти должен быть загружен значением &H4F. +
-Это приведёт к выводу в "​инвертированном"​ цвете восьми символов:​ H, I, J, K, L, M, N, O. +
- +
- +
-{{anchor:​e1113-13}} //​Пример 13//. Изменение цвета символов (напомним,​что начальный адрес Таблицы цветов &H2000 = 8192). \\ {{.examples:​1113-13.bas|}} \\ [[+tab|wmsxbpge>​1113-13.bas]] +
-<​code>​ +
-40 SCREEN 1:COLOR 15,4,4 +
-50 FOR I=0 TO 255:PRINT CHR$(I);:​NEXT +
-60 FOR I=0 TO 255 +
-70    FOR J=8192 TO 8223 +
-80       VPOKE J,I +
-90       FOR K=1 TO 25:NEXT K +
-100   NEXT J +
-110 NEXT I +
-</​code>​ +
- +
-{{anchor:​e1113-14}} //​Пример 14//. Изменение цвета курсора (напомним Вам, что код ASCII символа "​█"​ равен 255). \\ {{.examples:​1113-14.bas|}} \\ [[+tab|wmsxbpge>​1113-14.bas]] +
-<​code>​ +
-SCREEN 1:VPOKE &​H201F,&​HFF +
-</​code>​ +
-Далее, команда VPOKE BASE(1*5+1)+255\8,&​H28 задаёт цвет курсора и цвет, которым через курсор "​просвечивается"​ тот символ,​ на который курсор "​наложен"​. Если оба этих цвета совпадают,​ то сам курсор и символ сливаются,​ создавая иллюзию непрозрачности курсора. +
- +
-<WRAP centeralign>​Обратите внимание на тот факт, что Таблица CT в режиме ''​SCREEN 1''​ инициализируется оператором ''​COLOR''​.</​WRAP>​ +
- +
-{{anchor:​e1113-15}} __//​Пример 15//__. Не поленитесь,​ наберите приведённую ниже программу. Затем включите принтер,​ вставьте лист бумаги и запустите программу. Результаты её работы пригодятся Вам в дальнейшем! \\ {{.examples:​1113-15.bas|}} \\ [[+tab|wmsxbpge>​1113-15.bas]] +
-<​code>​ +
-10 KEYOFF:​CLS +
-120 LOCATE 0,​12,​0:​PRINT CHR$(27);"​MFirst page ";:​MP=1:​INPUT MP:IF MP<1 OR MP>6 GOTO 120 +
-130 PRINT:​PRINT:​POKE &​HF418,​1:​DEFUSR=&​H156 +
-140 LPRINT CHR$(27);"​c1";​CHR$(27);"​p0";​CHR$(27);"​T15";​CHR$(27);">";​CHR$(27);"​Q";​ +
-150 IF MP=1 THEN I=0:LPRINT CHR$(27);"​E (c) LHsoft ​    ​ver.2":​LPRINT CHR$(27);"​Q"​ ELSE I=43*MP-45 +
-160 P=MP +
-170 GOSUB 460 +
-180 IF P=1 THEN K=41 ELSE K=43 +
-190 FOR N=1 TO K +
-200    GOSUB 260 +
-210    I=I+1 +
-220 NEXT N +
-230 LPRINT"​└────┴─────┴────┴──────┴──────┴──────┴──────┴──────┴──────┴─────────────────────────────────┴─────────────────────────┘ +
-240 LPRINT CHR$(12);:​IF P<6 THEN PRINT CHR$(27);"​MPut in a new sheet ";:​QQ=USR(0):​Q$=INPUT$(1):​P=P+1:​GOTO 170 +
-250 CLS:​KEYON:​END +
-260 LPRINT"​│ ​   │     ​│ ​   │      │      │      │      │      │      │                                 ​│ ​                        │ +
-270 LPRINT"​│ ​   │ "; +
-280 LPRINTUSING("###"​);​I;​ +
-290 A1=I*8:​A0=A1+2048:​LPRINT"​ │ ";​RIGHT$("​0"​+HEX$(I),​2);"​ │";​A0;"​│ 0";​HEX$(A0);"​ │ "; +
-300 LPRINTUSING("####"​);​A1;​ +
-310 LPRINT"​ │ ";​RIGHT$("​000"​+HEX$(A1),​4);"​ │";​ +
-320 IF IMOD8=0 THEN LPRINT 8192+I/​8;"​│ ";​HEX$(&​H2000+I/​8);"​ │";​ELSE LPRINT" ​     │      │";​ +
-330 FOR T=0 TO 7:​LPRINTUSING("​ ###"​);​PEEK(&​H1BBF+I*8+T);:​NEXT +
-340 LPRINT"​ │ "; +
-350 FOR T=0 TO 7:LPRINT RIGHT$("​0"​+HEX$(PEEK(&​H1BBF+I*8+T)),​2);"​ ";:​NEXT +
-360 LPRINT"​│";​CHR$(13);" ​  ";​CHR$(27);"​N";​CHR$(27);"​S0008";​ +
-370 M=128 +
-380 FOR K1=0 TO 7 +
-390    D=0 +
-400    FOR K2=7 TO 0 STEP-1 +
-410    D=D*2 +
-420    IF PEEK(&​H1BBF+I*8+K2)ANDM THEN D=D+1 +
-430 NEXT K2:LPRINT CHR$(D);:​M=M/​2:​NEXT K1 +
-440 LPRINT CHR$(27);"​Q"​ +
-450 RETURN +
-460 PRINT CHR$(27);"​MCurrent page is";​P;​ +
-470 LPRINT"​┌────┬──────────┬───────────────────────────┬─────────────┬───────────────────────────────────────────────────────────┐ +
-480 LPRINT"​│ ​   │   ​Код ​   │        Адрес в  PGT       ​│ ​ Адрес в CT │                                                           │ +
-490 LPRINT"​│Сим-│ ​         ├─────────────┬─────────────┼─────────────┤ ​               Стандартное значение ​                      │ +
-500 LPRINT"​│вол │  ASCII   ​│ ​ SCREEN 0   ​│ ​  ​SCREEN 1  │  SCREEN 1   ​│ ​                                                          │ +
-510 LPRINT"​│ ​   ├─────┬────┼──────┬──────┼──────┬──────┼──────┬──────┼─────────────────────────────────┬─────────────────────────┤ +
-520 LPRINT"​│ ​   │ дес.│шест│ дес. │ шест.│ дес. │ шест.│ дес. │ шест.│ ​           десятичное ​          ​│ ​    ​шестнадцатеричное ​  │ +
-530 LPRINT"​├────┼─────┼────┼──────┼──────┼──────┼──────┼──────┼──────┼─────────────────────────────────┼─────────────────────────┤ +
-540 RETURN +
-</​code>​ +
- +
-==== XI.1.4. Режимы SCREEN 2 и SCREEN 4 ==== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Есть медленно и умеренно,​ не пить во время еды, тщательно разжёвывать пищу и с лёгкостью вставать из–за стола с чувством,​ что мог бы съесть ещё. +
-<WRAP rightalign>​ +
-—//​Ж.Фрумузак//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Разделим экран (размером 256×192 точек) на //​квадраты//​ размером по 8×8 точек. Легко подсчитать,​ что мы получим 768 таких квадратов. Каждый из них имеет свой номер, который хранится в Таблице PNT. А так как максимальное целое число, которое можно "​разместить"​ в одном байте памяти (в данном случае VRAM), равно 255, поэтому Таблицу PNT необходимо разбить на //три// области,​ каждая из которых будет отвечать за нумерацию только 256 квадратов. +
- +
-При установке режимов ''​SCREEN 2''​ или ''​SCREEN 4''​ (при инициализации) в каждую треть Таблицы PNT последовательно заносятся целые числа от 0 до 255. +
- +
-Адрес байта PNT, отвечающего за //​квадрат//​ с номером n2, вычисляется при помощи арифметического выражения +
-  BASE(5·N) + 256·n1 + n2 +
-где: +
-  * N — номер режима ''​SCREEN''​ (2 или 4); +
-  * n1 — номер трети таблицы PNT, в которой находится квадрат;​ +
-  * n2 — номер квадрата. +
- +
-Соответственно Таблице PNT, весь экран также разбивается на три области (каждая размером 256×64 точек),​ которые мы будем называть //​окнами//​. +
-<​code>​ +
-┌───┬───┬─────────────────────┬───┐ +
-│ 0 │ 1 │··· ​              ​···│ 31│ +
-├───┴───┘ ​                    ​└───┤ +
-│  ··· ​         Окно 0         ​···│ +
-├───┬───┐ ​                    ​┌───┤ +
-│224│225│··· ​              ​···│255│ +
-├───┼───┼─────────────────────┼───┤ +
-│ 0 │ 1 │··· ​              ​···│ 31│ +
-├───┴───┘ ​                    ​└───┤ +
-│  ··· ​         Окно 1         ​···│ +
-├───┬───┐ ​                    ​┌───┤ +
-│224│225│··· ​              ​···│255│ +
-├───┼───┼─────────────────────┼───┤ +
-│ 0 │ 1 │··· ​              ​···│ 31│ +
-├───┴───┘ ​                    ​└───┤ +
-│  ··· ​         Окно 2         ​···│ +
-├───┬───┐ ​                    ​┌───┤ +
-│224│225│··· ​              ​···│255│ +
-└───┴───┴─────────────────────┴───┘ +
-</​code>​ +
-Если мы захотим изменить "​что–нибудь"​ в Таблице PNT, это немедленно скажется на изображении в соответствующем окне. +
- +
-Таблица PNT редко используется при составлении программ. Более того, можно рассматривать структуру экрана,​ "​забыв"​ о делении экрана на окна. Достаточно при этом мысленно пронумеровать квадраты экрана от 0 до 767. +
- +
-Покажем,​ как можно использовать Таблицу PNT для копирования изображения в пределах //​одного//​ экранного окна. Пусть, например,​ Вам нужно скопировать изображение из квадрата с номером A в квадрат с номером B.Для этого +
-в байт Таблицы PNT, отвечающий за квадрат с номером B, поместите номер квадрата A. Этого достаточно для того, чтобы произошёл процесс копирования! +
- +
-{{anchor:​e1114-01}} __//​Пример 1//__. \\ {{.examples:​1114-01.bas|}} \\ [[+tab|wmsxbpge>​1114-01.bas]] +
-<​code>​ +
-10 COLOR 1,15:SCREEN 2 +
-20 LINE(8,​8)-(15,​15),,​BF '​Сформировано изображение в квадрате 33 +
-30 A$=INPUT$(1) +
-40 VPOKE &​H1800+40,​33 ​   '​Скопировали его в квадрат 40 +
-50 GOTO 50 +
-</​code>​ +
- +
-Более того, Вы можете заранее (до того, как будете что–то рисовать на экране) "​размножить"​ по нужным адресам номер ​ определённого ​ блока. Далее, Вам достаточно лишь заполнить изображением тот квадрат,​номер которого был +
-"​размножен",​и,​ к Вашей радости,​это изображение появится и в других местах! +
- +
-{{anchor:​e1114-02}} __//​Пример 2//__. \\ {{.examples:​1114-02.bas|}} \\ [[+tab|wmsxbpge>​1114-02.bas]] +
-<​code>​ +
-10 COLOR 1,15:SCREEN 2 +
-20 VPOKE &​H1800+40,​33 ​              '​Квадрат 40 подготовлен для приема +
-30 A$=INPUT$(1) ​                    '​копии из квадрата 33 +
-40 LINE(8,​8)-(15,​15),,​BF ​           '​Сформировано изображение в 33-м и +
-50 GOTO 50                          'в 40-м квадрате +
-</​code>​ +
- +
-Если же Вы захотите скопировать какой–либо элемент в другое //​окно//​ экрана,​ то Вам поможет работа с Таблицами PGT и CT,к рассмотрению которых мы и переходим. +
- +
-Каждый квадрат 8×8 точек разобьём на 8 горизонтальных участков,​которые будем называть //​линиями//​ . +
- +
-Информация о каждой линии (1 байт) содержится в Таблице PGT. +
- +
-Следовательно,​ объем этой Таблицы равен 768×8 = 6144 байтам. +
- +
-Адрес байта Таблицы PGT, отвечающего за расположение //​линии//​ вычисляется при помощи арифметического выражения +
-  BASE(5·N+2) + (256·n1+n2)·8 + k +
-где: +
-  * N — номер режима SCREEN; +
-  * n1 — номер окна; +
-  * n2 — номер квадрата в этом окне; +
-  * k — номер линии в этом квадрате. +
- +
-Отметим,​ что если в Таблице PNT были изменения,​ то могут возникнуть затруднения при попытке "​нарисовать"​ что–либо в квадрате с изменённым номером. +
- +
-{{anchor:​e1114-03}} __//​Пример 3//__. \\ {{.examples:​1114-03.bas|}} \\ [[+tab|wmsxbpge>​1114-03.bas]] +
-<​code>​ +
-10 COLOR 1,15:SCREEN 2 +
-20 VPOKE 6144+40,​VPEEK(6144+33)'​Произошло изменение в Таблице PNT +
-30 A$=INPUT$(1) ​               '​Ждем нажатия клавиши! +
-40 LINE(64,​8)-(71,​15),,​BF ​     '​Попытка вывести изображение в квадрате +
-50 GOTO 50                     '​40 не привела к ожидаемому результату! +
-</​code>​ +
- +
-Так как информация о линии хранится в одном байте, то каждой точке линии соответствует определённый бит этого байта. Оказывается,​ что "​высветить точку на экране"​ — это значит установить нужный бит в 1,"​стереть точку с экрана"​ — это значит установить бит в 0 ! +
- +
-Если некоторый бит равен 0,то соответствующую ему точку на экране будем называть точкой //​фона//,​ в противном случае будем называть её точкой //​изображения//​. +
- +
-Каждому байту Таблицы PGT однозначно соответствует один байт в Таблице цветов (CT), причём четыре младших бита этого байта кодируют локальный цвет //​фона//​ для каждой линии, а четыре старших — локальный цвет //​изображения//​. +
- +
-Например:​ +
-<​code>​ +
-               ​Точки фона +
-        │    │    │              │    │ +
-┌────┬──▼─┬──▼─┬──▼─┬────┬────┬──▼─┬──▼─┐ +
-│  1 │  0 │  0 │  0 │  1 │  1 │  0 │  0 │  Байт PGT +
-└──▲─┴────┴────┴────┴──▲─┴──▲─┴────┴────┘ +
-   ​│ ​                  ​│ ​   │ +
-             ​Точки изображения +
-┌────┬────┬────┬────┬────┬────┬────┬────┐ +
-│  0 │  1 │  0 │  1 │  1 │  1 │  0 │  1 │  Байт CT +
-└────┴────┴────┴────┴────┴────┴────┴────┘ +
- ​└────────▲────────┘ └────────▲─────────┘ +
-          │                   │ +
-   ​Цвет изображения ​      ​Цвет фона +
-</​code>​ +
-Таким образом,​точки изображения будут иметь цвет 5, а точки фона будут иметь цвет 13. +
- +
-Так как из четырёх двоичных цифр можно составить только 16 комбинаций,​ то ясно, что <WRAP centeralign>​одновременно на экране может быть не //​более//​ 16 цветов.</​WRAP>​ +
- +
-<WRAP centeralign>​Вследствие этого, изменение цвета одной точки приводит к переопределению цвета //​изображения всей// линии!</​WRAP>​ +
- +
-Адрес байта Таблицы CT, отвечающего за //​цвет//​ линии, вычисляется при помощи арифметического выражения:​ +
-  BASE(5·N+1) + (256·n1+n2)·8 + k +
-где: +
-  * N — номер режима ''​SCREEN'';​ +
-  * n1 — номер окна; +
-  * n2 — номер квадрата в этом окне; +
-  * k — номер линии в этом квадрате. +
- +
-{{anchor:​e1114-04}} __//​Пример 4//__. Предположим,​ что Вам захотелось в 5–й линии 58–го квадрата 2–го окна в режиме SCREEN 2 точки 0÷3 изобразить цветом 3, а точки 4÷7 — цветом 15. \\ {{.examples:​1114-04.bas|}} \\ [[+tab|wmsxbpge>​1114-04.bas]] +
-<​code>​ +
-10 SCREEN 2 +
-20 A=BASE(5*2+1)+(256*2+58)*8+5 +
-30 B=BASE(5*2+2)+(256*2+58)*8+5 +
-40 VPOKE B,&​B11110000 +
-50 VPOKE A,&​H3F +
-60 GOTO 60 +
-</​code>​ +
-А теперь — давно обещанный Вам пример… +
- +
-{{anchor:​e1114-05}} __//​Пример 5//__. Копирование содержимого 0–го квадрата из 0–го окна в содержимое 0–го квадрата 2–го окна \\ {{.examples:​1114-05.bas|}} \\ [[+tab|wmsxbpge>​1114-05.bas]] +
-<​code>​ +
-10 COLOR 15,​1,​1:​SCREEN2 +
-20 LINE(0,​0)-(7,​7),,​BF +
-25 FOR I=0 TO 7 +
-30 VPOKE BASE(5*2+2)+(256*2+0)*8+I,​VPEEK(BASE(5*2+2)+(256*0+0)*8+I):​ '​Копирование изображения +
-35 VPOKE BASE(5*2+1)+(256*2+0)*8+I,​VPEEK(BASE(5*2+1)+(256*0+0)*8+I):​ '​Копирования цвета +
-40 NEXT +
-50 GOTO 50 +
-</​code>​ +
- +
-{{anchor:​e1114-06}} __//​Пример 6//__. Изобразим квадрат,​стороны которого имеют разные цвета, не используя оператор ''​PSET''​. \\ {{.examples:​1114-06.bas|}} \\ [[+tab|wmsxbpge>​1114-06.bas]] +
-<​code>​ +
-10 SCREEN 2 +
-14 DATA   ​0,​5,​1,​37,​2,​37,​4,​37,​8,​165,​4,​165,​2,​165,​1,​21,​0,​5,​0,​5,​128,​133,​64,​133,​32,​133,​64,​21,​128,​21,​0,​5:'​Фон синего цвета +
-15 FOR I=0 TO 1 +
-16   FOR J=0 TO 7 +
-20     ​A=BASE(5*2+2)+(256*0+I)*8+J +
-30     ​B=BASE(5*2+1)+(256*0+I)*8+J +
-40     READ Z,U:VPOKE A,Z:VPOKE B,U +
-60   NEXT J +
-70 NEXT I +
-80 GOTO 80 +
- +
-                · +
-  Точки ​       · ·       ​Точки +
-зелёного ​  ​──▶· ​  ​·◀── ​ красного +
-  цвета ​     ·     ​· ​    ​цвета +
-  Точки ​   ──▶· ​  ​·◀── ​  ​Точки +
- ​жёлтого ​      · ·      чёрного +
-  цвета ​        ​· ​       цвета +
-</​code>​ +
- +
-<WRAP centeralign>​Важно заметить,​ что Таблица CT инициализируется цветом //​фона//,​ задаваемым в операторе ''​COLOR''​.</​WRAP>​ +
- +
-Опишем алгоритм установки точки в режимах ''​SCREEN 2''​ и ''​SCREEN 4''​. +
- +
-  - <​WRAP>​1. Первый шаг состоит в нахождении адреса байта Таблицы PGT в зависимости от координат (X,Y) ("//​грубая//​ настройка"​). +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-Адрес = ((Y\8)*32+Х\8)*8+Y MOD 8 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-</​WRAP>​ +
-  - <​WRAP>​2. После этого нужно точно определить номер бита найденного байта, отвечающего за данную точку ("//​точная//​ настройка"​). +
-Трудность состоит в несоответствии номеров бит в байте и значений Х–координат тех точек, за которые этот байт отвечает:​ +
-^  Х MOD 8  |0|1|2|3|4|5|6|7| +
-^  Номер бита ​ |7|6|5|4|3|2|1|0|. +
- +
-Формула,​ при помощи которой можно найти номер бита по Х–//​координате//,​ выглядит следующим образом:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-NB = 2^(8+NOT(X MOD 8)) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-</​WRAP>​ +
-  - <​WRAP>​3. Теперь остаётся записать "​1"​ в найденный бит. +
-  VPOKE Адрес, VPEEK (Адрес) OR NB . +
- +
-И…точка появится в требуемом месте экрана. +
-</​WRAP>​ +
-  - <​WRAP>​4. Наконец,​ изменим цвет изображения выведенной точки:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-Адрес = Адрес + &​h2000 +
-VPOKE  Адрес, VPEEK(Адрес) MOD 16 + COL*16 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-  * где ''​COL''​ — номер цвета. +
-</​WRAP>​ +
-Опишем алгоритм работы видеопроцессора при выводе содержимого квадрата 8×8 на графические экраны ''​SCREEN 2''​ или ''​SCREEN 4''​. +
- +
-Предположим,​ что нам известно местоположение данного квадрата на экране. Пусть N — номер квадрата с координатами (X,Y) (0≤X≤31,​0≤Y≤23)(номер N пока нам неизвестен!). Взгляните на рисунок:​ +
-<​code>​ +
-     ​┌───┬───┬─────────────────────┬───┐ +
- Y=0 │ 0 │ 1 │··· ​              ​···│ 31│ +
-  ·  ├───┴───┘ ​                    ​└───┤ +
-  ·  │  ··· ​                    ​··· ​   │ Окно 0 +
-  ·  ├───┬───┐ ​                    ​┌───┤ +
- Y=7 │224│225│··· ​              ​···│255│ +
-     ​├───┼───┼─────────────────────┼───┤ +
- Y=8 │ 0 │ 1 │··· ​      ​┌───┐ ​  ​···│ 31│ +
-  ·  ├───┴───┘ ​        ​┼▼┼ ​ X      └───┤ +
-  ·  │  ··· ​       Y───▶N│ ​     ··· ​   │ Окно 1 +
-  ·  ├───┬───┐ ​        ​┼─┼ ​        ​┌───┤ +
-Y=15 │224│225│ ​                 ···│255│ +
-     ​├───┼───┼─────────────────────┼───┤ +
-Y=16 │ 0 │ 1 │                  ···│ 31│ +
-  ·  ├───┴───┘ ​                    ​└───┤ +
-  ·  │  ··· ​                    ​··· ​   │ Окно 2 +
-  ·  ├───┬───┐ ​                    ​┌───┤ +
-Y=23 │224│225│ ​                 ···│255│ +
-     ​└───┴───┴─────────────────────┴───┘ +
-</​code>​ +
- +
-"​Посмотрев"​ Таблицу PNT по адресу (Y\8)*256+(YMOD8)*32+X,​ найдём N. +
- +
-"​Запишем"​ информацию о квадрате в Таблицу PGT по адресам:​ +
-  * (Y\8)*2048+N*8,​ +
-  * (Y\8)*2048+N*8+1,​ +
-  * (Y\8)*2048+N*8+2,​ +
-  * (Y\8)*2048+N*8+3,​ +
-  * (Y\8)*2048+N*8+4,​ +
-  * (Y\8)*2048+N*8+5,​ +
-  * (Y\8)*2048+N*8+6,​ +
-  * (Y\8)*2048+N*8+7,​ +
-в результате на экране в квадрате (X,Y) Вы увидите то, что хотели! +
- +
-А теперь "​раскрасим"​ изображение. +
- +
-"​Запишем"​ информацию о цвете в Таблицу CT по адресам:​ +
-  * (Y\8)*2048+N*8 , +
-  * (Y\8)*2048+N*8+1,​ +
-  * (Y\8)*2048+N*8+2,​ +
-  * (Y\8)*2048+N*8+3,​ +
-  * (Y\8)*2048+N*8+4,​ +
-  * (Y\8)*2048+N*8+5,​ +
-  * (Y\8)*2048+N*8+6,​ +
-  * (Y\8)*2048+N*8+7,​ +
-в результате квадрат с координатами (X,Y) будет раскрашен в нужные Вам цвета. +
- +
-{{anchor:​e1114-07}} __//​Пример 7//__. \\ {{.examples:​1114-07.bas|}} \\ [[+tab|wmsxbpge>​1114-07.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​8:​SCREEN 2:​X=5:​Y=10 +
-20 N=VPEEK(BASE(5*2+0)+(Y\8)*256+(YMOD8)*32+X) '​Видеопроцессор "​опрашивает"​ байт номер 69 в окне 1 Таблицы PNT и находит значение N (N=69, если Таблица PNT не изменялась) +
-30 FOR I=0 TO 7 +
-40 VPOKE(&​H800+N*8+I),&​B11100011'​Таблица PGT разделена на три окна,​каждое из которых содержит по 2048 байтов. Следовательно,​ окно 1 этой Таблицы начинается по адресу 2048=&​H800.  +
-41 ' ​                            ​Первый из 8 байтов квадрата,​ на который указывает N в окне 1, размещается в ячейке &​Н800+N*8 +
-50 NEXT '​Содержимое этих 8 байтов и будет выведено в квадрате (X,Y) +
-60 GOTO 60 +
-</​code>​ +
- +
-{{anchor:​e1114-08}} __//​Пример 8//__. \\ {{.examples:​1114-08.bas|}} \\ [[+tab|wmsxbpge>​1114-08.bas]] +
-<​code>​ +
-10 SCREEN 2:​X=15:​Y=12 +
-20 A=VPEEK(BASE(5*2+0)+(Y\8)*256+(YMOD8)*32+X) '"​Смотрим"​ PNT +
-30 FOR I=0 TO 7 +
-40   ​VPOKE(BASE(5*2+2)+(Y\8)*2048+A*8+I),&​b11100011 '​Формируем "​содержимое"​ квадрата +
-50 NEXT +
-60 GOTO 60 +
-</​code>​ +
- +
-{{anchor:​e1114-09}} __//​Пример 9//__. Раскрасим выводимый квадрат 8–м и 10–м цветами. \\ {{.examples:​1114-09.bas|}} \\ [[+tab|wmsxbpge>​1114-09.bas]] +
-<​code>​ +
-10 SCREEN 2:​X=15:​Y=12 +
-20 A=VPEEK(BASE(5*2+0)+(Y\8)*256+(YMOD8)*32+X) '"​Смотрим"​ Таблицу PNT +
-30 FOR I=0 TO 7 +
-40   ​VPOKE(BASE(5*2+2)+(Y\8)*2048+A*8+I),&​B11100011 '​Формируем "​содержимое"​ квадрата +
-50 NEXT +
-60 FOR I=0 TO 7 +
-70   ​VPOKE(BASE(5*2+1)+(Y\8)*2048+A*8+I),&​H8A ' "​Раскрасим"​ квадрат +
-80 NEXT +
-90 GOTO 90 +
-</​code>​ +
-Однако в режимах ''​SCREEN 2''​ и ''​SCREEN 4''​ используется система координат (X,Y), в которой Х изменяется от 0 до 255, а Y от 0 до 191. Следующий пример иллюстрирует,​ как эта система координат соотносится с делением экрана +
-на квадраты. +
- +
-{{anchor:​e1114-10}} __//​Пример 10//__. \\ {{.examples:​1114-10.bas|}} \\ [[+tab|wmsxbpge>​1114-10.bas]] +
-<​code>​ +
-10 SCREEN 2:​X=100:​Y=75 +
-30 N=(Y\8)*32+(X\8) '​Номер квадрата,​ в котором будет выведена точка +
-40 M=Y MOD 8        '​Номер линии в квадрате +
-50 AP=N*8+M ​        '​Адрес соответствующего байта в Tаблице PGT +
-60 VA=&​b00001000 +
-65 AC=AP+&​H2000 ​    '​Для определения соответствующего адреса в Таблице CT прибавим &H2000 к адресу Таблицы PGT +
-70 VPOKE AP,VA      '​Значение ​ VA=&​B00001000 ​ загрузим в PGT +
-80 VPOKE AC,&​HF1 ​   '​Вводим значение &HF1 в Таблицу цветов для изображения точки белого цвета на черном фоне +
-90 IF INKEY$=""​ THEN 90 +
-100 PSET(X,​Y),​6 +
-110 GOTO 110 +
-</​code>​ +
-Сначала будет нарисована белая точка на чёрном фоне. Когда Вы нажмёте любую клавишу,​ эта точка приобретёт красный цвет. +
- +
-При программировании на [[msx:​basic:​]] этот способ формирования изображения применяется редко. Однако,​ если Вы хотите нарисовать что–либо с помощью программы на //​машинном языке//,​ то приведённый выше алгоритм несомненно поможет Вам! +
- +
-Ясно,​что обладая определённым набором графических элементов,​ можно синтезировать различные графические изображения. +
- +
-Приведём без комментариев ряд примеров:​ +
- +
-{{anchor:​e1114-11}} __//​Пример 11//__. Одинаковые шаблоны \\ {{.examples:​1114-11.bas|}} \\ [[+tab|wmsxbpge>​1114-11.bas]] +
-<​code>​ +
-20 COLOR 15,​1,​1:​CLS:​SCREEN 2:COLOR 15,1:CLS +
-60 FOR I=0 TO 7 +
-70    READ A:VPOKE I,A:VPOKE I+2048,​A:​VPOKE I+4096,A +
-80 NEXT +
-90 FOR I=6144 TO 6144+767:​VPOKE I,0:NEXT +
-120 FOR I=8192 TO 14435:VPOKE I,​241:​NEXT +
-150 GOTO 150 +
-160 DATA &​b11111111 +
-170 DATA &​b10011001 +
-180 DATA &​b10111101 +
-190 DATA &​b11100111 +
-200 DATA &​b11100111 +
-210 DATA &​b10111101 +
-220 DATA &​b10011001 +
-230 DATA &​b11111111 +
-</​code>​ +
- +
-{{anchor:​e1114-12}} __//​Пример 12//__. \\ {{.examples:​1114-12.bas|}} \\ [[+tab|wmsxbpge>​1114-12.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​6:​SCREEN 2 +
-20 FOR T=8 TO 15:​LINE(8,​T)-(15,​T),​T:​NEXT:​A$=INPUT$(1) +
-30 FOR T=0 T0 7:VPOKE 2048+33*8+T,​VPEEK(33*8+T):​NEXT +
-40 A$=INPUT$(1) +
-50 FOR T=0 TO 7:VPOKE 10240+33*8+T,​VPEEK(8192+33*8+T):​NEXT +
-60 A$=INPUT$(1) +
-</​code>​ +
- +
-{{anchor:​e1114-13}} __//​Пример 13//__. \\ {{.examples:​1114-13.bas|}} \\ [[+tab|wmsxbpge>​1114-13.bas]] +
-<​code>​ +
-10 '​Шахматная доска! +
-20 INPUT "​Координаты X,​Y";​X,​Y:​X=X-XMOD8:​Y=Y-YMOD8 +
-21 IF X=0 THEN X=8 +
-22 U=Y/​8*32+X/​8 +
-25 COLOR 1,​15,​1:​SCREEN 2 +
-30 FOR T=0 TO 3:FOR I1=0 TO 1:FOR I2=0 TO 1:FOR F=U TO U+12 STEP 4:FOR K=0 TO 1 +
-40 VPOKE BASE(10)+(F+(64+2)*K)+I2+32*I1+128*T,​VPEEK (BASE(10)):​NEXT K,​F,​I2,​I1,​T +
-50 LINE(0,​0)-(8,​192),​1,​BF:​LINE(X,​Y)-STEP(128,​128),​1,​B:​A$=INPUT$(1) +
-</​code>​ +
- +
-{{anchor:​e1114-14}} __//​Пример 14//__. \\ {{.examples:​1114-14.bas|}} \\ [[+tab|wmsxbpge>​1114-14.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​8:​SCREEN 2:​LINE(0,​64)-(255,​127),,​BF '​Фон! +
-20 LINE(0,​64)-(7,​71),​8,​BF '​Перемещаемый объект! +
-30 FOR T=1 TO 31 +
-40 F=VPEEK(6400+T):​VPOKE 6400+T,​VPEEK(6400+T-1):​VPOKE 6400+T-1,​F'​Обмен значений между ячейками видеопамяти! +
-50 IF T=31 THEN VPOKE 6400+T,​T:​VPOKE 6400,0 +
-60 NEXT T:GOTO 30 +
-</​code>​ +
- +
-{{anchor:​e1114-15}} __//​Пример 15//__. \\ {{.examples:​1114-15.bas|}} \\ [[+tab|wmsxbpge>​1114-15.bas]] +
-<​code>​ +
-10 CLEAR 200,&​HC300:​SCREEN 2 +
-20 CIRCLE(90,​70),​56:​PAINT STEP(0,0) '​Сформировано изображение +
-25 '​Сохраняем изображения в памяти (RAM) +
-30 FOR I=BASE(5*2+1) TO BASE(5*2+1)+6143:​POKE &​HC300-BASE(5*2+1)+I,​ VPEEK(I):​NEXT +
-40 FOR I=BASE(5*2+2) TO BASE(5*2+2)+6143:​POKE &​HC300+6144-BASE(5*2+2)+I,​VPEEK(I):​NEXT +
-50 SCREEN 0 +
-60 SCREEN 2 '​Вывод изображения на экран +
-70 FOR I=BASE(5*2+1) TO BASE(5*2+1)+6143:​VPOKE I,​PEEK(&​HC300-BASE(5*2+1)+I):​NEXT +
-80 FOR I=BASE(5*2+2) TO BASE(5*2+2)+6143:​VPOKE I,​PEEK(&​HC300-BASE(5*2+2)+6144+I):​NEXT +
-90 A$=INPUT$(1) '​Программа работает ≈ 5 минут +
-</​code>​ +
- +
-==== XI.1.5. Режим SCREEN 3 ==== +
- +
-Как и в режиме ''​SCREEN 2'',​ экран в режиме ''​SCREEN 3''​ разбит на //​квадраты//​ размером 8×8 точек (32×24 квадрата). Каждый квадрат разобьём на две //​линии//​ толщиной четыре точки (на экране расположено 32×48 "​толстых"​ линий). Каждая из этих "​толстых"​ линий разбита на две "​большие"​ точки (4×4 "​маленьких"​ точек). +
- +
-<​code>​ +
-         ​──▲──┌────┬────┬────┬────┐ ​ ┌────┬────┬────┬────┐ +
-           ​│ ​ │    │    │    │    │  │    │    │    │████│◀── "​Маленькая"​ +
-           ​│ ​ │────│────│────│────│ ​ │────│────│────│────│ ​      ​точка +
-  "​Толщина"​│ ​ │    │    │    │    │  │    │    │    │    │ +
-           ​│ ​ │────│────│────│────│ ​ │────│────│────│────│ +
-    линии ​ │  │    │    │    │    │  │    │    │    │    │ +
-           ​│ ​ │────│────│────│────│ ​ │────│────│────│────│ +
-           ​│ ​ │    │    │                      │    │    │ +
-         ​──▼──└────┴────┴──── ​   Квадрат ​  ​────┴────┴────┘ +
-              ┌────┬────┬──── ​             ────┬────┬────┐ +
-              │    │    │    │    │  │████│████│████│████│ +
-              │────│────│────│────│ ​ │────│────│────│────│ +
-"​Толстая" ​    ​│ ​   │    │    │    │  │████│████│████│████│ +
-         ​───▶ │────│────│────│────│ ​ │────│────│────│────│ ◀── "​Большая"​ +
-  линия ​      ​│ ​   │    │    │    │  │████│████│████│████│ ​      ​точка +
-              │────│────│────│────│ ​ │────│────│────│────│ +
-              │    │    │    │    │  │████│████│████│████│ +
-              ├────┴────┴────┴────┘ ​ └────┴────┴────┴────┤ +
-              │◀─────────────"​Длина"​ линии ─────────────▶│ +
-</​code>​ +
- +
-Каждая из "​больших"​ точек может быть раскрашена только в //​один//​ цвет. +
-Попытка расположить в "​большой"​ точке "​маленькую"​ точку другого цвета приведёт к //​изменению//​ цвета //​всей//​ "​большой"​ точки. +
- +
-Информация о цвете "​толстой"​ линии находится в Таблице PGT, причём левый полубайт байта PGT кодирует цвет левой "​большой"​ точки "​толстой"​ линии, а правый полубайт отвечает за цвет правой "​большой"​ точки. +
- +
-<​code>​ +
-                        Байт PGT +
-           ​┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-           │ 1 │ 0 │ 0 │ 0 │ 1 │ 0 │ 1 │ 0 │ +
-           ​└───┴───┴───┴───┴───┴───┴───┴───┘ +
-            └──────▲──────┘ └──────▲──────┘ +
-                   ​│ ​              │ +
-Цвет левой "​большой"​ точки ​    ​Цвет правой "​большой"​ точки +
-</​code>​ +
- +
-<WRAP centeralign>​Поскольку один байт Таблицы PGT кодирует цвета "​толстой"​ линии, то эта Таблица требует 32×48=1536 байт VRAM.</​WRAP>​ +
- +
-{{anchor:​e1115-01}} __//​Пример 1//__. \\ {{.examples:​1115-01.bas|}} \\ [[+tab|wmsxbpge>​1115-01.bas]] +
-<​code>​ +
-10 SCREEN 3:​OPEN"​GRP:"​ AS#1 +
-20 PSET(8,​0),​3:​PSET(12,​0),​1 '​Рисуем "​толстую"​ линию +
-30 PSET(30,​80):​PRINT #​1,​HEX$(VPEEK(8)) +
-40 A$=INPUT$(1) +
-</​code>​ +
- +
-<WRAP centeralign>​Оператор ''​COLOR''​ с последующим оператором ''​CLS''​ инициализируют Таблицу PGT,</​WRAP>​ причём все байты Таблицы PGT инициализируются цветом фона, закодированным как в левом, так и в правом полубайтах. +
- +
-А в следующей табличке показаны номера позиций "​толстых"​ линий на экране:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-┌────┬────┬────┬─────┬────┐ +
-│  0 │  8 │ 16 │ ··· │ 248│ +
-├────┼────┼────┼─────┼────┤ +
-│  1 │  9 │ 17 │ ··· │ 249│ +
-├────┼────┼────┼─────┼────┤ +
-│  2 │ 10 │ 18 │ ··· │ 250│ +
-├────┼────┼────┼─────┼────┤ +
-│  3 │ 11 │ 19 │ ··· │ 251│ +
-├────┼────┼────┼─────┼────┤ +
-│  4 │ 12 │ 20 │ ··· │ 252│ +
-├────┼────┼────┼─────┼────┤ +
-│  5 │ 13 │ 21 │ ··· │ 253│ +
-├────┼────┼────┼─────┼────┤ +
-│  6 │ 14 │ 22 │ ··· │ 254│ +
-├────┼────┼────┼─────┼────┤ +
-│  7 │ 15 │ 23 │ ··· │ 255│ +
-├────┼────┼────┼─────┼────┤ +
-│ 256│ 264│ 272│ ··· │ 504│ +
-├────┼────┼────┼─────┼────┤ +
-│ 257│ 265│ 273│ ··· │ 505│ +
-├────┼────┼────┼─────┼────┤ +
-│ ···│ ···│ ···│ ··· │ ···│ +
-├────┼────┼────┼─────┼────┤ +
-│ 263│ 271│ 279│ ··· │ 511│ +
-├────┼────┼────┼─────┼────┤ +
-│ ···│ ···│ ···│ ··· │ ···│ +
-├────┼────┼────┼─────┼────┤ +
-│1285│1293│1301│ ··· │1534│ +
-├────┼────┼────┼─────┼────┤ +
-│1286│1294│1302│ ··· │1535│ +
-└────┴────┴──│─┴─────┴────┘ +
-  ┌──┬──┬──┬─▼┬──┬──┬──┬──┐ +
-  │ 1│ 0│ 0│ 0│ 0│ 0│ 1│ 0│ +
-  └──┴──┴──┴──┴──┴──┴──┴──┘ +
-</​code>​ +
- +
- +
-</​WRAP>​ +
- +
-<WRAP half column>​ +
- +
-{{anchor:​e1115-02}} __//​Пример 2//__. Выполнив эту программу Вы можете убедиться в правильности заполнения данной таблички. \\ {{.examples:​1115-02.bas|}} \\ [[+tab|wmsxbpge>​1115-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 SCREEN 3 +
-20 VPOKE BASE(5*3+2)+6,&​H56 +
-30 VPOKE BASE(5*3+2)+7,&​H34 +
-40 VPOKE BASE(5*3+2)+8,&​H78 +
-50 VPOKE BASE(5*3+2)+9,&​H9A +
-60 A$=INPUT$(1) +
-</​code>​ +
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Байт из Таблицы PGT (в нем хранится цвет "​толстой"​ линии с номером 1302) +
- +
-Приведём таблицу,​ по которой можно определить адрес байта Таблицы PGT, отвечающего за точку (X,Y), в режимах 2÷4: +
-^  Режим экрана ​ ^  //​Адрес байта//​ в PGT  ^ +
-|  2 и 4  |  %% ((Y\8)*32+(Х\8))*8+Y MOD 8 %%  | +
-|  3  |  BASE(5*3+2)+(Х\8)*8+(Y\32)*256+(Y\4) MOD 8  | +
- +
-{{anchor:​e1115-11}} __//​Пример 1//__. Заполнение экрана чёрными и белыми клетками в шахматном порядке. \\ {{.examples:​1115-11.bas|}} \\ [[+tab|wmsxbpge>​1115-11.bas]] +
-<​code>​ +
-10 '​Шахматная доска +
-20 COLOR 15,​1,​1:​CLS:​SCREEN 3 +
-50 FOR I=0 TO 7 STEP 2 +
-60    VPOKE I,&​HF1:​VPOKE I+1,&​H1F +
-70 NEXT +
-80  FOR I=BASE(5*3+0) TO I+767 +
-90     VPOKE I,0 +
-100 NEXT +
-110 GOTO 110 +
-</​code>​ +
-Таблица PGT разбита на 192 "​кусочка"​ размером по 8 байт. Каждый "​кусочек"​ отвечает за 4 квадрата размером 2×2 "​больших"​ точки (такой квадрат называется //​именем//​). Упомянутые 4 имени имеют один и тот же номер, который записывается в Таблицу PNT. +
- +
-Но //​первый//​ квадрат — это имя с данным номером для строк (строка имеет высоту 2 "​большие"​ точки) с номерами 0, 4, 8, 12, 16, 20; +
-  * //​второй//​ — для строк с номерами 1, 5, 9, 13, 17, 21; +
-  * //​третий//​ — для строк с номерами 2, 6, 10, 14, 18, 22; +
-  * //​четвёртый//​ — для строк с номерами 3, 7, 11, 15, 19, 23. +
- +
-Следовательно,​ весь экран разбит на //​четыре окна// (понятие экранного окна см. в описании режима ''​SCREEN 2''​). +
- +
-За имя с номером N в окне с номером M отвечают байты PGT +
-  N·8+M·2 и N·8+M·2+1,​ +
-где N∈[0,​191],​ a M∈[0,3] +
- +
-Приведём структуру PGT с учётом разбивки экрана на имена и окна. +
-<​code>​ +
-            ┌────┬────┬────┬─────┬────┐ +
-Номер имени │  0 │  1 │  2 │ ··· │ 15 │ +
-    N       ​├────┼────┼────┼─────┼────┤ +
-            ├────┼────┼────┼─────┼────┤ ─┐ +
-            │  0 │  8 │ 16 │ ··· │ 248│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ​ ├─ Имя с номером N для окна 0 +
-            │  1 │  9 │ 17 │ ··· │ 249│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ─┤ +
-            │  2 │ 10 │ 18 │ ··· │ 250│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ​ ├─ Имя с номером N для окна 1 +
-            │  3 │ 11 │ 19 │ ··· │ 251│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ─┤ +
-            │  4 │ 12 │ 20 │ ··· │ 252│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ​ ├─ Имя с номером N для окна 2 +
-            │  5 │ 13 │ 31 │ ··· │ 253│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ─┤ +
-            │  6 │ 14 │ 22 │ ··· │ 254│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ​ ├─ Имя с номером N для окна 3 +
-         ​│ ​ │  7 │ 15 │ 23 │ ··· │ 255│ ​ │ +
-        ─▼─ ├────┼────┼────┼─────┼────┤ ─┘ +
-            │ ···│ ···│ ···│ ··· │ ···│ +
-            ├────┼────┼────┼─────┼────┤ +
-            │ 263│ 271│ 279│ ··· │ 511│ +
-            ├────┼────┼────┼─────┼────┤ +
-            │ ···│ ···│ ···│ ··· │ ···│ +
-            ├────┼────┼────┼─────┼────┤ ─┐ +
-            │1285│1293│1301│ ··· │1534│ ​ │ +
-            ├────┼────┼────┼─────┼────┤ ​ ├─ Имя с номером N для окна 3 +
-            │1286│1294│1302│ ··· │1535│ ​ │ +
-            └────┴────┴────┴─────┴──▲─┘ ─┘ +
-                                    └─ Имя с номером 191 +
-</​code>​ +
- +
-Приведём структуру PNT с номерами имён и их расположением на экране:​ +
-<​code>​ +
-      0   ​1 ​  ​2 ​  ​3 ​  ​· ​  ​· ​  ​· ​  31 ◀─ Номер столбца +
-    ┌───┬───┬───┬───┬───┬───┬───┬────┐ +
-  0 │ 0 │ 1 │ 2 │ 3 │···│···│···│ 31 │  Окно 0: строки 0,4, 8,​12,​16,​20 +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  1 │ 0 │ 1 │ 2 │···│···│···│ 30│ 31 │  Окно 1: строки 1,5, 9,​13,​17,​21 +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  2 │ 0 │ 1 │···│···│···│ 29│ 30│ 31 │  Окно 2: строки 2,​6,​10,​14,​18,​22 +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  3 │ 0 │···│···│···│ 28│ 29│ 30│ 31 │  Окно 3: строки 3,​7,​11,​15,​19,​23 +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  4 │ 32│ 33│ 34│ 35│···│ 61│ 62│ 63 │ +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  · │···│···│···│···│···│···│···│ ···│ +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  7 │ 32│33 │···│···│···│···│ 62│ 63 │ +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  · │···│···│···│···│···│···│···│ ···│ +
-    ├───┼───┼───┼───┼───┼───┼───┼────┤ +
-  23│160│161│···│···│···│189│190│ 191│ +
-  ▲ └───┴───┴───┴───┴───┴───┴───┴────┘ +
-  └─ Номер строки +
-</​code>​ +
- +
-Номер имени в квадрате с координатами X,Y (X∈[0,​31],​Y∈[0,​23]) хранится в ячейке VRAM с адресом:​ +
-  BASE(5*3+0)+(Y\4)*32+X +
-Это имя находится в окне с номером Y MOD 4 +
- +
-{{anchor:​e1115-12}} __//​Пример 2//__. \\ {{.examples:​1115-12.bas|}} \\ [[+tab|wmsxbpge>​1115-12.bas]] +
-<​code>​ +
-10 COLOR 15,​1,​1:​CLS:​SCREEN 3 +
-20 FOR I=0 TO 1 STEP 2 +
-30   VPOKE I,&​HF1:​VPOKE I+1,&​H1F ​  '​Имя 0 для окна 0 (черно-белое) +
-40   VPOKE I+2,&​HF8:​VPOKE I+3,&​H8F '​Имя 0 для окна 1 (красно-белое) +
-45 '​Имя с номером 0 для окон 2 и 3 - пустое +
-60 NEXT +
-70 FOR I=BASE(5*3+0) TO I+767      ' Заполним PNT нулями +
-80     VPOKE I,0 +
-90 NEXT +
-95 'На экране появятся 6 (24/4) черно-белых и красно-белых полос +
-100 GOTO 100 +
-</​code>​ +
- +
-==== XI.1.6. Режимы SCREEN 5, SCREEN 6, SCREEN 7 и SCREEN 8 (для компьютеров MSX 2) ==== +
- +
-<WRAP centeralign>​В режимах ''​SCREEN 5''​ ÷ ''​SCREEN 8''​ Таблицы PGT и CT //​отсутствуют//​!</​WRAP>​ +
-Поэтому вся информация об изображении точек находится в Таблице PNT. +
- +
-В отличие от рассмотренных ранее режимов,​ эти режимы не имеют деления экрана на //​квадраты//​. +
- +
-Вначале приведём важную табличку,​ которая поможет Вам определить адрес байта Таблицы PNT, отвечающего за точку с координатами (X,Y), в различных режимах ''​SCREEN''>:​ +
- +
-^  Режим экрана ​ ^  //​Адрес байта//​ в  PNT  ^ +
-|  ''​SCREEN 5'' ​ |  BASE(5*5)+(256/​2)*Y+(X\2) ​ | +
-|  ''​SCREEN 6'' ​ |  BASE(5*6)+(512/​4)*Y+(X\4) ​ | +
-|  ''​SCREEN 7'' ​ |  BASE(5*7)+(512/​2)*Y+(X\2) ​ | +
-|  ''​SCREEN 8'' ​ |  BASE(5*8)+(256/​1)*Y+(X\1) ​ | +
- +
-  - <​WRAP>​ В режиме ''​SCREEN 5''​ экран разделен на 212 строк, состоящих из 256 точек каждая,​ или на 192 строки,​ состоящих из 256 точек каждая. +
-Совокупность двух точек по горизонтали будем называть //​линией//​ (точки 0 и 1 образуют 1–ю линию, точки 2 и 3 — 2–ю линию ,… , точки 254 и 255 — 128–ю линию). +
- +
-Каждая линия кодируется в //​одном//​ байте, причём четыре старших бита этого байта определяют цвет первой точки, а четыре младших — цвет второй точки. Ясно, что требуется 212×256/​2=27136 байтов для хранения сведений о цветах линий (как раз объем Таблицы PNT в режиме ''​SCREEN 5''​ !). +
- +
-Первый байт Таблицы PNT "​хранит"​ информацию ​ о  цвете первой линии первой строки экрана,​ второй байт — о цвете второй линии той же строки,​ и так далее:​ +
-^  1–й байт Таблицы PNT  ^| ^  2–й байт Таблицы PNT  ^^ +
-|Цвет ​ 1–й точки \\ первой линии ​ |  Цвет ​ 2–й точки \\ первой линии ​ | |  Цвет ​ 1–й точки \\ второй линии ​ |  Цвет ​ 2–й точки \\ второй линии ​ | +
- +
-<WRAP centeralign>​Таблица PNT инициализируется цветом фона, который устанавливается оператором ''​COLOR''​.</​WRAP>​ +
- +
-{{anchor:​e1116-01}} __//​Пример 1//__. Изобразим в режиме ''​SCREEN 5''​ точку с координатами (X,Y) белым цветом. \\ {{.examples:​1116-01.bas|}} \\ [[+tab|wmsxbpge>​1116-01.bas]] +
- +
-<​code>​ +
-10 COLOR 15,​4,​7:​INPUT"​X,​Y";​X,​Y +
-20 SCREEN 5                        ┌───────── Код цвета фона +
-30 AD=BASE(5*5)+Y*128+(X\2) ​       │┌──────── Код цвета изображения +
-                                   ​▼▼ +
-40 IF XMOD2=0 THEN C=&HF4 ELSE C=&​H4F'​Если не будет этого условия,​ то изобразятся две соседние точки +
-50 VPOKE AD,C   '​Вы легко можете убедиться,​что этот оператор эквивалентен оператору PSET(X,​Y),​15. +
-60 GOTO 60 +
-</​code>​ +
- +
-Приведём схематическое изображение PNT для режима ''​SCREEN 5''​. +
-|  0–й байт ​ |отвечает за точки с координатами (0,0) и (1,0)| +
-|  1–й байт ​ |отвечает за точки с координатами (2,0) и (3,0)| +
-|  …  |  …  | +
-|  127–й байт ​ |отвечает за точки с координатами (254,0) и (255,0)| +
-|  128–й байт ​ |отвечает за точки с координатами (0,1) и (1,1)| +
-|  …  |  …  | +
-|  27134–й байт ​ |отвечает за точки с координатами (252,211) и (253,​211)| +
-|  27135–й байт ​ |отвечает за точки с координатами (254,211) и (255,​211)| +
-</​WRAP>​ +
-  - <​WRAP>​ В режиме ''​SCREEN 6''​ экран имеет 212 строк из 512 точек или 192 строки по 512 точек в каждой строке. Количество байтов в Таблице PNT точно такое же, как и в Таблице PNT режима ''​SCREEN 5'':​ информация об одной строке экрана кодируется в 128 байтах. +
- +
-//​Линия//​ в режиме ''​SCREEN 6''​ состоит из четырёх точек и кодируется в //​одном//​ байте. А тогда //​палитра//​ каждой точки кодируется в двух битах, а так как из двух двоичных цифр можно составить только четыре комбинации (00, 01, 10, 11), то каждую точку экрана можно раскрасить не более, чем //​четырьмя//​ различными способами. Так, например,​ оператор +
-  VPOKE 0,&​B11100100 +
-присваивает палитру 3 первой точке первой линии, палитру 2 — второй точке первой линии, палитру 1 — третьей точке первой линии и палитру 0 — четвёртой точке первой линии. +
-<​code>​ +
-         ​Байт Таблицы PNT +
-┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-│ 1 │ 1 │ 1 │ 0 │ 0 │ 1 │ 0 │ 0 │ +
-└───┴───┴───┴───┴───┴───┴───┴───┘ +
-└───▲───┘└──▲──┘└───▲───┘└──▲───┘ +
-    │       ​│ ​      ​│ ​      │ +
- ​Палитра Палитра Палитра Палитра +
- ​первой ​ второй ​ третьей четвёртой +
- ​точки ​  ​точки ​   точки ​  ​точки +
-</​code>​ +
- +
-<WRAP centeralign>​Таблица PNT инициализируется последними двумя битами цвета фона, задаваемого в операторе ''​COLOR''​.</​WRAP>​ +
- +
-Поясним сказанное примером. Если цвет фона имеет номер 13=&​B1101,​ то в каждый байт Таблицы PNT будет занесено число &​B01010101 (четыре раза повторяются последние два бита кода цвета фона). +
- +
-Приведём схематическое изображение PNT для режима ''​SCREEN 6''​. +
-|  (0,0)  |  (1,0)  |  (2,0)  |  (3,0)  |  0–й байт ​ | +
-|  (4,0)  |  (5,0)  |  (6,0)  |  (7,0)  |  1–й байт ​ | +
-|  …  |  …  |  …  |  …  |  …  | +
-|  (508,​0) ​ |  (509,​0) ​ |  (510,​0) ​ |  (511,​0) ​ |  127–й байт ​ | +
-|  (0,1)  |  (1,1)  |  (2,1)  |  (3,1)  |  128–й байт ​ | +
-|  …  |  …  |  …  |  …  |  …  | +
-|  (508,​211) ​ |  (509,​211) ​ |  (510,​211) ​ |  (511,​211) ​ |  27135–й байт ​ | +
-</​WRAP>​ +
-  - <​WRAP>​ Как и в режиме SCREEN 6,в режиме SCREEN 7 на экране расположено 212 +
-строк, состоящих из 512 точек каждая,​ или 512 строк, состоящих из 192 +
-строк каждая. Однако,​ один байт Таблицы PNT кодирует //​линию//,​ состоящую из //​двух//​ точек: старшие четыре бита определяют палитру левой точки, младшие четыре — палитру правой точки. +
- +
-^  1–й байт Таблицы PNT  ^| ^  2–й байт Таблицы PNT  ^^ +
-|  Палитра первой \\ точки 1–й линии |  Палитра второй \\ точки 1–й линии | |  Палитра первой \\ точки 2–й линии |  Палитра второй \\ точки 2–й линии ​ | +
- +
-Следовательно,​ каждой точке может быть присвоена любая из 16 палитр. +
- +
-Поскольку для кодирования номера палитры необходимо четыре бита, то Таблица PNT занимает объем 212×512/2 = 54272 байта. +
- +
-Уже отсюда становится понятно,​ что для использования этого режима VRAM должна иметь объем не менее 128 Кбайт! +
- +
-Режим ''​SCREEN 7''​ аналогичен режиму ''​SCREEN 5'',​ за исключением того, что в режиме ''​SCREEN 7''​ в строке экрана в два раза //​больше//​ точек. +
- +
-<WRAP centeralign>​Таблица PNT инициализируется цветом фона, который устанавливает оператор ''​COLOR''​.</​WRAP>​ +
- +
-Приведём схематическое изображение PNT для режима ''​SCREEN 7''​. +
-|  0–й байт ​ |отвечает за точки с координатами (0,0) и (1,0)| +
-|  1–й байт ​ │отвечает за точки с координатами (2,0) и (3,0)| +
-|  …  |  …  | +
-|  255–й байт ​ │отвечает за точки с координатами (510,0) и (511,0)| +
-|  256–й байт ​ |отвечает за точки с координатами (0,1) и (1,1)| +
-|  …  |  …  | +
-|  54270–й байт ​ |отвечает за точки с координатами (508,211) и (509,​211)| +
-|  54271–й байт ​ |отвечает за точки с координатами (510,211) и (511,​211)| +
-</​WRAP>​ +
-  - <​WRAP>​ В режиме ''​SCREEN 8''​ экран состоит из 212 строк по 256 точек в каждой или из 212 строк по 192 точки в каждой. +
- +
-//​Линия//​ состоит из одной–единственной точки. Цвет линии здесь уже определяется не кодом палитры,​ а непосредственным заданием "​смеси"​ основных цветов. Этот оригинальный способ кодирования цвета требует по  одному //​байту//​(!) на линию, а, значит,​ на точку! Поэтому Таблица PNT имеет объем 212·256=54272 байта. +
- +
-Уже отсюда становится понятно,​ что для использования этого режима VRAM должна иметь объем не менее 128 Кбайт! +
- +
-Информация о линии с координатами (X,Y)  находится ​ по адресу +
-  X+256·Y +
-в Таблице PNT. Для высвечивания этой линии достаточно занести по этому адресу значение цвета из отрезка [0,255], которое можно найти по формуле:​ +
-  C = 32·G+4·R+B ​  , +
-где +
-G, R, B — значения в диапазоне от 0 до 7, определяющие интенсивность зелёного ("​Green"​),​ красного ("​Red"​) и  синего ("​Blue"​) цветов ​ соответственно. Например,​ цвету с номером ​ 187=&​b10111011 ​ соответствует следующее "​содержимое"​ байта Таблицы PNT: +
-<​code>​ +
-          Байт Таблицы PNT +
-  ┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-  │ 1 │ 0 │ 1 │ 1 │ 1 │ 0 │ 1 │ 1 │ +
-  └───┴───┴───┴───┴───┴───┴───┴───┘ +
-  └──────────┘ └──────────┘└──────┘ +
-Интенсивность Интенсивность Интенсивность +
-   ​зелёного ​     красного ​     синего +
-   ​цвета ​         цвета ​       цвета +
-</​code>​ +
- +
-<WRAP centeralign>​При инициализации байты Таблицы PNT получают номер цвета фона (который изменяется в пределах от 0 до 255).</​WRAP>​ +
- +
-Приведём схематическое изображение PNT для режима ''​SCREEN 8''​. +
- +
-Базовый адрес PNT +
-|  0–й байт ​ |отвечает за точку с координатами (0,0)| +
-|  1–й байт ​ |отвечает за точку с координатами (1,0)| +
-|  …  |  …  | +
-|  255–й байт ​ |отвечает за точку с координатами (255,0)| +
-|  256–й байт ​ |отвечает за точку с координатами (0,1)| +
-|  …  |  …  | +
-|  54270–й байт ​ |отвечает за точку с координатами (256,​210)| +
-|  54271–й байт ​ |отвечает за точку с координатами (256,​211)| +
-</​WRAP>​ +
- +
-==== XI.1.7. Таблица палитр (для компьютеров MSX 2) ==== +
- +
-Независимо от режима ''​SCREEN'',​ Таблица PT занимает в видеопамяти объём 32 байта. "​Местоположение"​ этой Таблицы зависит от режима ''​SCREEN''​. +
-|  Режим ​ |  Адрес ​ |  Комментарий ​ | +
-|''​SCREEN 0''​ (40 символов) ​ |  &​H0400 ​ |Не используется в [[msx:​msx_1]]| +
-|''​SCREEN 0''​ (80 символов) ​ |  &​H0800 ​ | | +
-|''​SCREEN 1'' ​ |  &​H2020 ​ |Не используется в [[msx:​msx_1]]| +
-|''​SCREEN 2'' ​ |  &​H1B80 ​ |Не используется в [[msx:​msx_1]]| +
-|''​SCREEN 3'' ​ |  &​H2020 ​ |Не используется в [[msx:​msx_1]]| +
-|''​SCREEN 4'' ​ |  &​H1E80 ​ | | +
-|''​SCREEN 5'' ​ |  &​H7680 ​ | | +
-|''​SCREEN 6'' ​ |  &​H7680 ​ |Используются палитры 0÷3| +
-|''​SCREEN 7'' ​ |  &​HFA80 ​ | | +
-|''​SCREEN 8'' ​ |  &​HFA80 ​ |Не используется| +
- +
-Каждая из палитр закодирована в //​двух//​ байтах. +
- +
-Адрес AD первого байта палитры N в Таблице PT вычисляется по формуле:​ +
-  AD=A0+2·N +
-где А0 — адрес начала Таблицы PT (например,​в режиме ''​SCREEN 1''​ Таблица PT начинается по адресу &​h2020). +
- +
-По адресу AD в Таблице PT находится байт, который мы назовём "​красный–синий"​. Биты 4÷6 этого байта определяют пропорцию //​красного//,​ а биты 0÷2 — пропорцию //​синего//​ цвета. Байт Таблицы PT с адресом AD+1 определяет пропорцию зелёного цвета, закодированную в битах 0÷2 : +
-<​code>​ +
-        7   ​6 ​  ​5 ​  ​4 ​  ​3 ​  ​2 ​  ​1 ​  ​0 ​ ◀── ​ Номера бит +
-       ​┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-  AD   ​│ ​  │ ∗ │ ∗ │ ∗ │   │ ∗ │ ∗ │ ∗ │◀──────┐ +
-       ​└───┴───┴───┴───┴───┴───┴───┴───┘ ​      │ +
-           ​└─────▲─────┘ ​  ​└─────▲─────┘ ​      ​│ ​          ​Два +
-                 ​│ ​              ​│ ​             ◀── ​ последовательных +
-     ​Красный цвет ("​Red"​) ​ Синий цвет ("​Blue"​) │          байта +
-       ​┌───┬───┬───┬───┬───┬───┬───┬───┐ ​      ​│ ​      ​Таблицы PT +
-AD+1   ​│ ​  ​│ ​  ​│ ​  ​│ ​  ​│ ​  │ ∗ │ ∗ │ ∗ │◀──────┘ +
-       ​└───┴───┴───┴───┴───┴───┴───┴───┘ +
-                           ​└─────▲─────┘ +
-                                 ​└── Зелёный цвет ("​Green"​) +
-</​code>​ +
- +
-{{anchor:​e1117-01}} __//​Пример 1//__. "​Чтение"​ Таблицы палитр в режиме ''​SCREEN 1''​. Выполнив программу,​ Вы узнаете,​ каким образом оператор ''​SCREEN''​ инициализирует Таблицу PT. \\ {{.examples:​1117-01.bas|}} \\ [[+tab|wmsxbpge>​1117-01.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​7:​SCREEN 1 +
-20 ' :::::::::::::::​ +
-30  FOR N=0 TO 15 +
-40     ​AD=&​H2020+2*N +
-50     ​RB=VPEEK(AD):​G=VPEEK(AD+1)'​Обратите внимание на мнемонику имен: 'RB и G! +
-60     PRINT N;​TAB(4);​HEX$(RB);​HEX$(G) +
-70  NEXT +
-</​code>​ +
-Отметим,​ что оператор ''​COLOR=(…)''​ переопределяет байты Таблицы PT в соответствии с указанной палитрой. +
- +
-{{anchor:​e1117-02}} //​Пример 2//. Изменим Таблицу PT и вновь "​прочитаем"​ её. \\ {{.examples:​1117-02.bas|}} \\ [[+tab|wmsxbpge>​1117-02.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​7:​SCREEN 1 +
-20 GOSUB 30:​COLOR=(7,​7,​2,​7):​GOSUB 30:​COLOR=(7,​7,​7,​4):​GOSUB 30:END +
-30  FOR N=0 TO 15 +
-40     ​AD=&​H2020+2*N +
-50     ​RB=VPEEK(AD):​G=VPEEK(AD+1) +
-60     PRINT N;​TAB(4);​HEX$(RB);​HEX$(G) +
-70  NEXT +
-80 A$=INPUT$(1):​CLS:​RETURN +
-</​code>​ +
-Как видите,​ байты, соответствующие палитре 7,​изменяются;​ немедленно изменяется и цвет бордюра! +
- +
-Разумеется,​ палитры в Таблице PT могут быть изменены и операторами ''​VPOKE''​. Однако,​ следует отметить,​ что изменение Таблицы PT операторами ''​VPOKE''​ само по себе не приводит к изменению цветов. Для считывания содержимого Таблицы PT и присвоения цвета новой палитре существует специальный оператор. Его синтаксис предельно прост:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-COLOR = RESTORE +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-{{anchor:​e1117-03}} __//​Пример 3//__. \\ {{.examples:​1117-03.bas|}} \\ [[+tab|wmsxbpge>​1117-03.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​7:​SCREEN 1 +
-20 GOSUB 30:VPOKE &​H2020+14,&​H77:​VPOKE &​H2020+15,​2 +
-25 COLOR=RESTORE:​GOSUB 30:END +
-30  FOR N=0 TO 15 +
-40     ​AD=&​H2020+2*N +
-50     ​RB=VPEEK(AD):​G=VPEEK(AD+1) +
-60     PRINT N;​TAB(4);​HEX$(RB);​HEX$(G) +
-70  NEXT +
-80 A$=INPUT$(1):​CLS:​RETURN +
-</​code>​ +
- +
-Для инициализации Таблицы PT используются:​ +
-  * оператор ''​SCREEN''​ ; +
-  * оператор ''​COLOR=NEW''​ ; +
-  * оператор ''​COLOR''​ (без параметров!) . +
- +
-==== XI.1.8. Спрайты ==== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Вопрос в том, кто за это отвечает?​ +
-<WRAP rightalign>​ +
-—//​Шалтай–Болтай//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Видеопроцессор имеет //два// режима отображения спрайтов. Режим отображения спрайтов выбирается автоматически в соответствии с выбранным Вами режимом ''​SCREEN''​. +
- +
-Если в Вашей программе присутствует один из операторов:​ +
-  SCREEN 1, SCREEN 2, SCREEN 3, +
-то Вы находитесь в //​режиме спрайтов//​ 1. +
- +
-Если же в Вашей программе присутствует один из операторов:​ +
-  SCREEN 4, SCREEN 5, SCREEN 6, SCREEN 7, SCREEN 8, +
-то Вы находитесь в //​режиме спрайтов//​ 2. +
- +
-Вкратце напомним уже известные нам результаты. +
- +
-В //​режиме спрайтов//​ 1 на экран одновременно можно вывести 32 спрайта с номерами от 0 до 31. Спрайты с //​меньшими//​ номерами имеют более высокий приоритет. На одной горизонтальной линии экрана размещается до //​четырёх//​ спрайтов с высшим приоритетом,​ а в пересекающейся части спрайты с более низким приоритетом становятся невидимыми. +
- +
-Когда два спрайта //​сталкиваются//,​ т.е. пересекаются заполненные части их образов (если сталкиваются два спрайта,​ шаблоны которых занулены,​ или спрайты сталкиваются занулёнными участками шаблонов,​то столкновение не бнаруживается),​ тогда бит 5 регистра состояния с номером 0 устанавливается в 1. +
- +
-Кроме того, если на одной горизонтальной линии находятся //​пять//​ или более спрайтов,​ то 6–й бит регистра состояния будет установлен в 1, а пять младших бит зафиксируют номер пятого спрайта. +
- +
-В //​режиме спрайтов//​ 2 на экран одновременно можно вывести 32 спрайта,​ пронумерованных от 0 до 31. Спрайты с //​меньшими//​ номерами имеют более высокий приоритет. На одной горизонтальной линии экрана изображается до //​восьми//​ спрайтов с высшим приоритетом,​ а в перекрывающийся части спрайты с меньшим приоритетом не видны. +
- +
-Столкновение //​двух//​ спрайтов обнаруживается по состоянию 5–го бита регистра состояния с номером 0 (он устанавливается в 1). Интересно отметить,​ что в этом случае координаты столкновения фиксируются в регистрах состояния с номерами от 3 до 5. +
- +
-Вдобавок,​ если на одной горизонтальной линии экрана появляются девять или более спрайтов,​ то 6–й бит регистра состояния с номером 0 будет установлен в 1,а 5 младших бит этого регистра зафиксируют номер девятого спрайта. +
- +
-В режимах ''​SCREEN 1''​ ÷ ''​SCREEN 3''​ спрайты задаются при помощи двух Таблиц:​ +
-  * Таблицы ​ //​шаблонов//​ спрайтов (SGT); +
-  * Таблицы ​ //​атрибутов//​ спрайтов (SAT);\\ +
-В режимах ''​SCREEN 4''​ ÷ ''​SCREEN 8''​ дополнительно используется ещё и +
-  * Таблица ​ //​цветов//​ спрайтов (SCT). +
- +
-В этом разделе мы расскажем Вам о каждой Таблице. +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-//​Шаблон//​ (от нем. Schablone — образец,​ модель),​ пластина с вырезами,​ очертания которых соответствуют контуру чертежа,​ изделия и т.п.<​WRAP rightalign>​ +
-—//​Советский Энциклопедический Словарь//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-  - <​WRAP>​ Таблица SGT содержит образы спрайтов (которые ниже мы будем называть //​шаблонами//​),​ установленные оператором +
-  SPRITE$(N)= строковое выражение +
-Эта Таблица инициализируется нулями оператором SCREEN, причём оператор ''​SCREEN ,​T''​ приводит к исчезновению спрайтов с экрана,​ сохраняя при этом на экране остальную информацию,​ а операторы ''​SCREEN M,​T''​ и ''​SCREEN M''​ инициализируют всю видеопамять. +
- +
-2048 байт Таблицы SGT позволяют хранить информацию о 256 шаблонах спрайтов,​ если //​вторым//​ параметром в операторе ''​SCREEN''​ является 0 или 1, и информацию о 64–х шаблонах,​ если этот параметр равен 2 или 3. +
- +
-Адрес шаблона спрайта в Таблице SGT, созданного при помощи оператора ''​SPRITE$(N)=…'',​ вычисляется по формуле:​ +
-  A0 +8·N +
-или  +
-  A0+32·N ​   , +
-где ​ А0 — адрес начала Таблицы SGT. +
- +
-Напомним Вам, что начальный адрес Таблицы SGT для разных режимов ''​SCREEN''​ возвращает функция ''​BASE()'':​ +
-  BASE(M*5+4) +
-где M — номер режима ''​SCREEN''​. +
- +
-<WRAP centeralign>​Байты шаблона записаны в Таблице SGT в том же порядке,​ как и байты (символы!) значения строкового выражения,​ стоящего в правой части оператора ''​SPRITE$(N)=…''</​WRAP>​ +
- +
-Теперь,​ надеемся,​ Вам понятно,​ что действие,​ например,​ операторов:​ +
-<​code>​ +
-SCREEN 1:​SPRITE$(0)=STRING(8,​255) +
-</​code>​ +
-эквивалентно действию цикла:​ +
-<​code>​ +
-FOR I=0 TO 7:VPOKE &​H3800+I,​255:​NEXT +
-                   ​───▲── +
-                      └─ BASE(1*5+4) +
-</​code>​ +
- +
-{{anchor:​e1118-01}} __//​Пример 1//__. \\ {{.examples:​1118-01.bas|}} \\ [[+tab|wmsxbpge>​1118-01.bas]] +
-<​code>​ +
-10 SCREEN 1,0 +
-20 A$="​Microsoft"​ +
-30 FORI=1TOLEN(A$):​B$=MID$(A$,​I,​1) +
-50 VPOKEBASE(1*5+4)+8*2+(I-1),​ASC(B$) +
-60 NEXT +
-70 PRINT SPRITE$(2) +
- +
-      8 байтов ​       8 байтов ​         8 байтов +
-┌────────────────┬────────────────┬────────────────┐ +
-│  "​Место"​ в SGT │  "​Место"​ в SGT │ "​Место в SGT   │ +
-│для 0–го спрайта│для 1–го спрайта│для 2–го спрайта│ +
-└────────────────┴────────────────┴▲───────────────┘ +
-                                   │ +
-                            BASE(1*5+4)+8*2 +
-</​code>​ +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Атрибут (от лат. Attribuo — придаю,​ наделяю),​ необходимое,​ существенное,​ неотъемлемое свойство объекта. +
-<WRAP rightalign>​ +
-—//​Советский Энциклопедический Словарь//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-</​WRAP>​ +
-  - <​WRAP>​ В 128 байтах Таблицы атрибутов спрайтов (Таблицы SAT) кодируется информация о //​способе//​ вывода образов (шаблонов) спрайтов на экран. Поскольку одновременно на экране могут отображаться не более 32 спрайтов,​ то +
-атрибуты одного спрайта кодируются в 128/32 = 4 байтах. +
-Вероятно,​ Вас заинтересует их содержимое?​ Поспешим удовлетворить Ваше любопытство:​ +
-<​code>​ +
-                      Байты Таблицы SAT +
-┌──────────────┬──────────────┬──────────────┬───────────────┐ +
-│  Первый байт │  Второй байт │  Третий байт │ Четвёртый байт│ +
-└──────▲───────┴───────▲──────┴───────▲──────┴────────▲──────┘ +
-       ​│ ​              ​│ ​             │               │ +
-  Координата Y   ​Координата X   ​Номер шаблона ​      ​Номер +
-    (0÷255) ​       (0÷255) ​     в SGT (0÷255) ​     палитры +
-</​code>​ +
- +
-Отметим,​ что если величина Y–координаты спрайта равна 216, то все спрайты с меньшим приоритетом не будут отображаться. Например,​ если Y–координата спрайта с номером 10 равна 216,то спрайты с номерами от 10 до 31 не будут отображаться. +
- +
-Если размер спрайта — 16×16, то, как известно,​ одному спрайту соответствуют //​четыре//​ номера шаблонов спрайта. В этом случае можно задать любой из четырёх номеров шаблонов спрайта! +
- +
-Таким образом,​ если мы обозначим A0 — начальный адрес Таблицы SAT, то оператор +
-<​code>​ +
-PUT SPRITE SN,​(X,​Y),​C,​NP +
-<​code>​ +
-эквивалентен следующим операторам:​ +
-<​code>​ +
-AD=A0+4*SN:​VPOKE AD,Y:VPOKE AD+1,​X:​VPOKE AD+2,​NP:​VPOKE AD+3,C +
-         ​▲ ​         ▲            ▲            ▲             ▲ +
-         ​└─!!! ​     └─!!! ​       └─!!! ​       └─!!! ​        ​└─!!! +
-</​code>​ +
- +
-{{anchor:​e1118-02}} __//​Пример 2//__. \\ {{.examples:​1118-02.bas|}} \\ [[+tab|wmsxbpge>​1118-02.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​8:​SCREEN 1,​1:​SPRITE$(20)="​СПРАЙТ!"​ +
-20 PUT SPRITE 2,​(165,​38),​7,​20 +
-30 ? "​X=";​VPEEK(6921):?​ "​Y="​VPEEK(6920):?"​Цвет номер";​VPEEK(6923):?"​Шаблон";​VPEEK(6922) +
-40 FOR T=0 TO 8:? CHR$(VPEEK(14336+VPEEK(6922)*8+T));:​ +
-NEXT +
-</​code>​ +
- +
-Рассмотрим подробнее четвёртый байт Таблицы SAT для какого–нибудь выбранного спрайта. +
-<​code>​ +
-           ​┌───┬───┬───┬───┬───┬───┬───┬───┐ +
-Старший бит│ ​  │ 0 │ 0 │ 0 │  Цвет спрайта │ Младший бит +
-           ​└─▲─┴───┴───┴───┴───┴───┴───┴───┘ +
-             ​└── Синхронизирующий бит (его имя EC) +
-</​code>​ +
- +
-Его //​младшие//​ четыре бита определяют текущий //​цвет//​ спрайта (для высвечиваемых точек шаблона). Невысвечиваемые точки шаблона "​окрашены"​ в прозрачный цвет. +
- +
-Старший бит этого байта называется //​синхронизирующим//​. +
-Если его значение равно 1, то положение спрайта смещается //​влево//​ на 32 точки. +
- +
- +
-{{anchor:​e1118-03}} __//​Пример 3//__. "​Работа"​ синхронизирующего бита. \\ {{.examples:​1118-03.bas|}} \\ [[+tab|wmsxbpge>​1118-03.bas]] +
-<​code>​ +
-20 COLOR 1,15,15 +
-30 SCREEN 1,3:WIDTH 30 +
-40 SPRITE$(0)=STRING$(32,​255) +
-50 PUT SPRITE 0,​(80,​80),​8,​0 +
-60 VPOKE 6915,&​B10001000 +
-61 ' ​           ▲ +
-63 ' ​           │──────────── ​ 1 - координаты спрайта (X-32,Y) +
-65 ' ​           └──────────── ​ 0 - координаты спрайта (X,Y) +
-70 LOCATE 2,​8,​0:​PRINT"​Нажмите клавишу"​ +
-80 A$=INPUT$(1) +
-90 VPOKE 6915,&​B00001000 +
-100 END +
-</​code>​ +
- +
-Разумеется,​ при программировании на языке [[msx:​basic:​]] лучше использовать оператор ''​PUT SPRITE'',​ а не последовательность операторов ''​VPOKE''​. +
- +
-<WRAP centeralign>​Однако,​ последовательность операторов ''​VPOKE''​ гораздо проще моделировать на //​машинном языке//,​ чем оператор ''​PUT SPRITE''​.</​WRAP>​ +
- +
-Более того, знание структуры Таблицы SAT позволяет "​прочитать"​ атрибуты спрайта непосредственно из //​памяти//​ ! +
- +
-{{anchor:​e1118-04}} __//​Пример 4//__. Превращение белого спрайта в чёрный и наоборот. \\ {{.examples:​1118-04.bas|}} \\ [[+tab|wmsxbpge>​1118-04.bas]] +
-<​code>​ +
-10 COLOR 1,​4,​8:​SCREEN 1,1 +
-20 SPRITE$(0)=STRING$(8,​255) +
-30 PUT SPRITE 0,​(115,​80),​15,​0 +
-40 IF INKEY$=""​ THEN 40 +
-50 GOSUB 100:GOTO 40 +
-100 VPOKE &​H1B03,​VPEEK(&​H1B03) XOR 14  '​BASE(1*5+3) ──▶ &​H1B00 +
-110 RETURN ​      ​──────────▲───────── +
-                           │ +
-               &​b00001111 XOR &​b00001110 = &​b00000001 ──▶ цвет 1 +
-</​code>​ +
- +
-Оператор ''​SCREEN''​ инициализирует четыре байта Таблицы SAT, кодирующих атрибуты одного спрайта,​ следующим образом:​ +
-<​code>​ +
-┌──────────────┬──────────────┬──────────────┬───────────────┐ +
-│  Первый байт │  Второй байт │  Третий байт │ Четвёртый байт│ +
-└──────▲───────┴───────▲──────┴───────▲──────┴────────▲──────┘ +
-       ​│ ​              ​│ ​             │               │ +
-  Координата Y   ​Координата X   ​Номер шаблона ​   Текущий цвет +
-                                в Таблице SGT     ​изображения +
-</​code>​ +
- +
-//​Координата Y// отображения спрайта по умолчанию приведена в следующей табличке (из неё видно, что при таких Y неважно,​ каково Х): +
- +
-^  Серия компьютера| ​ [[msx:​msx_1]] ​ |  [[msx:​msx_2]] ​ | +
-^  //​Режим экрана// ​ ^  Y  ^  Y  ^ +
-|  ''​SCREEN 1'' ​ |  209  |  209  | +
-|  ''​SCREEN 2'' ​ |  209  |  209  | +
-|  ''​SCREEN 3'' ​ |  209  |  209  | +
-|  ''​SCREEN 4'' ​ | |  217  | +
-|  ''​SCREEN 5'' ​ | |  217  | +
-|  ''​SCREEN 6'' ​ | |  217  | +
-|  ''​SCREEN 7'' ​ | |  217  | +
-|  ''​SCREEN 8'' ​ | |  217  | +
- +
-С учётом значения координаты Y спрайт является //​невидимым//​. Координата Y обладает интересной особенностью. Если Y–координата спрайта с номером N равна 209 (в режимах ''​SCREEN 1'',​ ''​SCREEN 2'',​ ''​SCREEN 3''​) или 217 (в режимах ''​SCREEN 4'',​ ''​SCREEN 5'',​ ''​SCREEN 6'',​ ''​SCREEN 7'',​ ''​SCREEN 8''​),​ то этот спрайт не отображается на экране. Самое интересное заключается в том, что не отображаются и все остальные спрайты с номерами,​ большими,​ чем N. +
- +
-{{anchor:​e1118-05}} __//​Пример 5//__. \\ {{.examples:​1118-05.bas|}} \\ [[+tab|wmsxbpge>​1118-05.bas]] +
-<​code>​ +
-10 DIM X(3):SCREEN 2,0 +
-20 A$="​ЧЧЧЧЧЧЧЧ":​Y=0 +
-30 FOR I=1 TO 3:​SPRITE$(I)=A$:​X(I)=10*I:​NEXT I +
-40 PUT SPRITE 1,​(X(1),​Y),​1,​1 +
-50 PUT SPRITE 3,​(X(3),​Y),​15,​3 +
-60 PUT SPRITE 2,​(X(2),​Y),​8,​2 +
-70 Y=Y+1:IF Y>208 THEN BEEP:​A$=INPUT$(1):​END '​Исчезли два спрайта! +
-80 GOTO 60 +
-</​code>​ +
- +
-//"​Экранный"​ номер//​ спрайта по умолчанию равен номеру шаблона спрайта. +
- +
-//​Цветом//​ спрайта по умолчанию является текущий цвет изображения. +
-</​WRAP>​ +
-  - <​WRAP>​ <WRAP centeralign>​Таблица SCT используется только в режимах ''​SCREEN 4''​ ÷ ''​SCREEN 8''​.</​WRAP>​ +
- +
-Базовый адрес Таблицы цветов спрайтов (SCT) будет всегда автоматически вычисляться вычитанием числа 512 из базового адреса Таблицы атрибутов спрайтов (SAT). +
- +
-С помощью SCT можно моделировать оператор ''​COLOR SPRITE$()'',​ который,​ как Вы, конечно,​ помните,​ позволяет определить цвет для высвечиваемых точек шаблона спрайта для //​каждой//​ спрайтовой линии (цвет невысвечиваемых +
-точек шаблона спрайта всегда //​прозрачный//​). +
- +
-Так как для каждого из 32 спрайтов необходимо хранить информацию максимум о 16 спрайтовых линиях различного цвета, эта Таблица занимает +
-  32·16 = 512 байтов VRAM . +
- +
-Адрес байта, начиная с которого располагается информация о //​цвете//​ спрайта в Таблице SCT, вычисляется по формуле:​ +
-  AD = A0 + 16·SN +
-где: +
-  * A0 — адрес начала Таблицы SCT; +
-  * SN — номер шаблона спрайта +
- +
-{{anchor:​e1118-06}} __//​Пример 6//__. Вторая спрайтовая линия изображения девятого спрайта раскрашена восьмым цветом. \\ {{.examples:​1118-06.bas|}} \\ [[+tab|wmsxbpge>​1118-06.bas]] +
-<​code>​ +
-10 COLOR 15,​1,​8:​SCREEN 4,0 +
-20 SPRITE$(3)="​пример":​PUT SPRITE 9,​(40,​80),​15,​3 +
-40 VPOKE &​H1C00+16*9+2,​8 +
-50 GOTO 50 +
-</​code>​ +
-</​WRAP>​ +
- +
-Заметим,​ что для информации о цвете шаблона спрайта размером 8×8 точек отводятся //​только//​ 16 младших полубайтов 16–ти байтов SCT, отводимых для одного шаблона. +
- +
-Опишем содержимое оставшихся 16–ти //​старших//​ полубайтов… +
-Оказывается с их помощью можно разрешить или запретить приоритеты спрайтов,​ обработать определённым образом столкновения и задать или отменить так называемое "​опережение"​ для спрайта. +
- +
-Изобразим схематически Таблицу SCT… +
-<​code>​ +
-                      Номера бит +
-        ┌────┬────┬────┬────┬───┬───┬───┬───┐ +
-        │ 7  │ 6  │  5 │  4 │ 3 │ 2 │ 1 │ 0 │             +
-        ├────┼────┼────┼────┼───┴───┴───┴───┤ +
-  0 байт│ ​   │    │    │  0 │   ​Код цвета ​  │ Спр.лин. 1 для спрайта ​ 0 +
-        ├────┼────┼────┼────┼───────────────┤ +
-  1 байт│ ​   │    │    │  0 │   ​Код цвета ​  │ Спр.лин. 2 для спрайта ​ 0 +
-        ├────┴────┴────┴────┴───────────────┤ +
-    …   ​│ ​           …              …       ​│ ​           … +
-        ├────┬────┬────┬────┬───────────────┤ +
- 15 байт│ ​   │    │    │  0 │   ​Код цвета ​  │ Спр.лин. 16 для спрайта 0 +
-        ├────┴────┴────┴────┼───────────────┤ +
-    …   ​│ ​           …              …       ​│ ​           … +
-        ├────┬────┬────┬────┼───────────────┤ +
-496 байт│ ​   │    │    │  0 │   ​Код цвета ​  │ Спр.лин. ​ 1 для спрайта 31 +
-        ├────┼────┼────┼────┼───────────────┤ +
-497 байт│ ​   │    │    │  0 │   ​Код цвета ​  │ Спр.лин. ​ 2 для спрайта 31 +
-        ├────┴────┴────┴────┼───────────────┤ +
-    …   ​│ ​           …              …       ​│ ​           … +
-        ├────┬────┬────┬────┼───────────────┤ +
-511 байт│ ​   │    │    │  0 │   ​Код цвета ​  │ Спр.лин. 16 для спрайта 31 +
-        └──▲─┴──▲─┴──▲─┴────┴───────────────┘ +
-           ​│ ​   │    └─ Бит IC (определитель столкновений):​1 — нет, 0 — да; +
-           ​│ ​   └────── Бит CC (разрешение приоритета) ​   :0 — нет, 1 — да; +
-           ​└─────────── Бит EC ("​опережение"​) ​            :1 — да,  0 — нет. +
-</​code>​ +
- +
-В режиме спрайтов 2, если СС–бит Таблицы SCT установлен в 1, порядок приоритетности спрайтов для данной спрайтовой линии //​отменяется//​. +
-Спрайтовая линия, для которой бит СС установлен в 1 , будет отображаться только на горизонтальных линиях,​где существуют спрайты с низшими номерами. +
- +
-Отметим,​ что и в этом случае,​ если на одной линии экрана более 8 спрайтов,​ то //​девятый//​ спрайт и все последующие не будут изображаться на экране дисплея. +
- +
-Более того не фиксируется столкновение спрайта,​ для которого с SCT бит СС установлен в 1, с другим спрайтом (даже если у этого спрайта в SCT бит СС установлен в 0). В этом случае для пересекающихся спрайтов над их цветовыми кодами производится логическая операция OR. +
- +
-Говорят,​ что в режиме ''​SCREEN 6''​ цвет фона и цвета спрайтов подвергаются //​аппаратному тилингу//​. Эти цвета кодируются четырьмя битами:​ два //​старших//​ бита определяют код цвета нечётных точек, а два //​младших//​ бита определяют код цвета чётных точек по X–координате (от 0 до 511). +
- +
-В режиме SCREEN 6 размер одной точки спрайта в 2 раза больше,​чем у графической точки (пикселя),​ однако,​ за счёт наличия аппаратного тилинга,​ одна точка спрайта может обладать двумя цветами одновременно (чётные и нечётные точки фонового цвета могут быть определены таким же образом). +
-<​code>​ +
-        ┌─────────────────── Чётные точки ​  ​(0,​2,​…,​510) +
-        │    ┌────────────── Нечётные точки (1,​3,​…,​511) +
-     ​┌──▼─┬──▼─┐ +
-     ​│ ​   │    │   ​Две графические точки +
-     ​└────┴────┘ +
-     ​┌────┬────┐ ​   +
-     ​│ ​   │    │   ​Одна точка спрайта +
-     ​└──▲─┴─▲──┘ +
-        │   ​│ ​     +
-┌───┬───┐ ​  ​┌───┬───┐ +
-│ █ │ █ │   │ █ │ █ │  Биты, определяющие цвета спрайта +
-└───┴───┘ ​  ​└───┴───┘ +
-</​code>​ +
- +
-Приведём табличку начальных адресов Таблиц SCT для различных режимов:​ +
- +
-^  Режим ​ ^  Адрес ​ ^ +
-|  ''​SCREEN 4'' ​ |  &​H1C00 ​ | +
-|  ''​SCREEN 5'' ​ |  &​H7400 ​ | +
-|  ''​SCREEN 6'' ​ |  &​H7400 ​ | +
-|  ''​SCREEN 7'' ​ |  &​HF800 ​ | +
-|  ''​SCREEN 8'' ​ |  &​HF800 ​ | +
- +
-Отметим,​ что 16 байтов Таблицы SCT, отвечающих за цвет спрайта,​ первоначально инициализируются текущим цветом изображения или цветом,​ заданным в операторе ''​PUT SPRITE''​. "​Содержимое"​ этих байтов может быть переопределено +
-непосредственно операторами ''​VPOKE''​ или оператором ''​COLOR SPRITE()''​ (''​COLOR +
-SPRITE$()''​). +
- +
-В режиме ''​SCREEN 8''​ цвета спрайта фиксированы и не зависят от регистра палитры. Цвета спрайта в режиме ''​SCREEN 8''​ показаны на следующей таблице. +
-^  Код цвета ​ ^^^^  Зелёный ​ ^^^  Красный ​ ^^^  Синий ​ ^^^ +
-^С3^С2^С1^С0^G2^G1^G0^R2^R1^R0^B2^B1^B0^ +
-|  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  | +
-|  0  |  0  |  0  |  1  |  0  |  0  |  0  |  0  |  0  |  0  |  0  |  1  |  0  | +
-|  0  |  0  |  1  |  0  |  0  |  0  |  0  |  0  |  1  |  1  |  0  |  0  |  0  | +
-|  0  |  0  |  1  |  1  |  0  |  0  |  0  |  0  |  1  |  1  |  0  |  1  |  0  | +
-|     ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    | +
-|  0  |  1  |  0  |  0  |  0  |  1  |  1  |  0  |  0  |  0  |  0  |  0  |  0  | +
-|  0  |  1  |  0  |  1  |  0  |  1  |  1  |  0  |  0  |  0  |  0  |  1  |  0  | +
-|  0  |  1  |  1  |  0  |  0  |  1  |  1  |  0  |  1  |  1  |  0  |  0  |  0  | +
-|  0  |  1  |  1  |  1  |  0  |  1  |  1  |  0  |  1  |  1  |  0  |  1  |  0  | +
-|     ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    | +
-|  1  |  0  |  0  |  0  |  1  |  0  |  0  |  1  |  1  |  1  |  0  |  1  |  0  | +
-|  1  |  0  |  0  |  1  |  0  |  0  |  0  |  0  |  0  |  0  |  1  |  1  |  1  | +
-|  1  |  0  |  1  |  0  |  0  |  0  |  0  |  1  |  1  |  1  |  0  |  0  |  0  | +
-|  1  |  0  |  1  |  1  |  0  |  0  |  0  |  1  |  1  |  1  |  1  |  1  |  1  | +
-|     ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    ​| ​    | +
-|  1  |  1  |  0  |  0  |  1  |  1  |  1  |  0  |  0  |  0  |  0  |  0  |  0  | +
-|  1  |  1  |  0  |  1  |  1  |  1  |  1  |  0  |  0  |  0  |  1  |  1  |  1  | +
-|  1  |  1  |  1  |  0  |  1  |  1  |  1  |  1  |  1  |  1  |  0  |  0  |  0  | +
-|  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  | +
- +
-==== XI.1.9. Слоты видеопамяти ==== +
- +
-Вся видеопамять на компьютерах серии [[msx:​msx_2]] разбита на два больших участка объёмом по 64 Кбайта каждый. Эти участки будем называть //​слотами//​ видеопамяти (по аналогии с участками RAM и ROM объёмом по 64 Кбайта,​ называемыми //​слотами//​ памяти). На компьютерах серии [[msx:​msx_1]] имеется только один слот VRAM объёмом в 16 Кбайт. +
- +
-Для того, чтобы переключиться с работы со слотом 0 на работу со слотом 1, достаточно выполнить оператор:​ +
-  * ''​SET PAGE 2''​ или ''​SET PAGE 3''​ в режимах ''​SCREEN 5''​ и ''​SCREEN 6'';​ +
-  * ''​SET PAGE 1''​ в режимах ''​SCREEN 7''​ и ''​SCREEN 8''​. +
- +
-После этого оператором ''​VPOKE''​ и функцией ''​VPEEK''​ можно работать с логическими адресами видеопамяти. В помощь Вам предлагаем следующие таблички:​ +
-^  Физические адреса ​ ^  Логические адреса ​ ^  Номера слотов ​ ^Способ включения слота ​ |  +
-|  от &​H00000 ​ |  от &​H0000 ​ |  Слот 0  |  SET PAGE 0  |  Для режимов SCREEN 5 и SCREEN 6  | +
-|  до &​H07FFF ​ |  до &​H7FFF ​ |:::​|:::​|:::​| +
-|  от &​H08000 ​ |  от &​H8000 ​ |:::|  SET PAGE 1  |:::| +
-|  до &​H0FFFF ​ |  до &​HFFFF ​ |:::​|:::​|:::​| +
-|  от &​H10000 ​ |  от &​H0000 ​ |  Слот 1  |  SET PAGE 2  |:::| +
-|  до &​H17FFF ​ |  до &​H7FFF ​ |:::​|:::​|:::​| +
-|  от &​H18000 ​ |  от &​H8000 ​ |:::|  SET PAGE 3  |:::| +
-|  до &​H1FFFF ​ |  до &​HFFFF ​ |:::​|:::​|:::​| +
-|  от &​H00000 ​ |  от &​H0000 ​ |  Слот 0  |  SET PAGE 0  |  Для режимов SCREEN 7 и SCREEN 8  | +
-|  до &​H0FFFF ​ |  до &​HFFFF ​ |:::​|:::​|:::​| +
-|  от &​H10000 ​ |  от &​H0000 ​ |  Слот 1  |  SET PAGE 1  |:::| +
-|  до &​H1FFFF ​ |  до &​HFFFF ​ |:::​|:::​|:::​| +
- +
-Отметим также, что в режимах ''​SCREEN 0''​ ÷ ''​SCREEN 4''​ работа со слотом 1 запрещена. +
- +
-==== XI.1.10. Порты, отвечающие за работу с видеопамятью ==== +
- +
-Другой способ доступа к видеопамяти заключается в работе с //​портами//​ ввода–вывода. Этот способ очень часто используется при написании программ в машинных кодах. +
- +
-<WRAP centeralign>​Напомним,​ что перед использованием команды (оператора) ''​OUT''​ на компьютерах серии [[msx:​msx_2]] необходимо выполнить команду ''​[[msx:​network_basic#​CALL NETEND]]''​.</​WRAP>​ +
- +
-  - <​WRAP>​ Для //​записи//​ числа в ячейку видеопамяти примените серию команд:​ +
-    * <​code>​OUT &H99, Младший байт номера ячейки</​code>​ +
-    * <​code>​OUT &H99, Старший байт номера ячейки OR &​H40</​code>​ +
-    * <​code>​OUT &H98, Число</​code>​ +
- +
-{{anchor:​e11110-01}} __//​Пример//​__. \\ {{.examples:​11110-01.bas|}} \\ [[+tab|wmsxbpge>​11110-01.bas]] +
-<​code>​ +
-10 SCREEN 0:​CLS:​KEYOFF +
-20 OUT &​H99,​0:​OUT &H99,0 OR &H40 +
-30 FOR I=1 TO 20 +
-40    READ R$:​R=ASC(R$):​OUT &​H98,​R +
-50 NEXT I:PRINT '​Попробуйте убрать в этой строке оператор PRINT +
-60 DATA Г,​р,​у,​п,​п,​о,​в,​а,​я,"​ ",​п,​е,​р,​е,​с,​ы,​л,​к,​а,​! +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​ Для //​чтения//​ числа из ячейки видеопамяти,​ примените следующие команды:​ +
-    * <​code>​OUT &H99, Младший байт номера ячейки</​code>​ +
-    * <​code>​OUT &H99, Старший байт номера ячейки</​code>​ +
-    * <​code>​A=INP(&​H98)</​code>​ +
-</​WRAP>​ +
- +
-Важно отметить следующее. Изменение содержимого видеопамяти или видеопроцессора приводит к немедленной корректировке содержимого экрана. Однако,​ отсюда вовсе не следует истинность обратного утверждения. +
- +
-<WRAP centeralign>​Изменение "​содержимого"​ экрана не всегда приводит к изменению VRAM.</​WRAP>​ +
- +
-Если Вы не будете в программе "​работать"​ с портами ввода–вывода,​то можно утверждать,​ что ''​VRAM''​ и VDP "​управляют"​ "​содержимым"​ экрана.На самом же деле состояние экрана изменяют //​порты//​ ввода–вывода с адресами &H98, &H99, &H9A и &H9B. На эти порты можно "​воздействовать"​ оператором ''​VPOKE''​. +
-В этом случае сигнал из VRAM сразу же поступает в порт, а тот,в свою очередь изменяет "​рисунок"​ на экране. +
-<​code>​ +
-          ┌───────────┐ +
-          │   ​Экран ​  │ +
-          └───▲─▲─▲───┘ +
-              │ │ │ +
-┌─────────────────────────────┐ ◀── +
-│      Порты ввода–вывода ​    │ ◀── Оператор OUT +
-└────▲─▲─▲────────────▲─▲─▲───┘ ◀── +
-     │ │ │            │ │ │ +
-┌──────────────┐ ​ ┌───────────┐ ◀── +
-│Видеопроцессор│─▶│Видеопамять│ ◀── Оператор VPOKE +
-└──────────────┘ ​ └───────────┘ ◀── +
-</​code>​ +
- +
-Если же воздействовать непосредственно на порт оператором ''​OUT'',​ минуя видеопамять,​ то могут возникнуть следующие ситуации:​ +
-  - если адрес VRAM принадлежит отрезку [0,&​H3FFE],​ то после записи оператором ''​OUT''​ в ячейку с этим адресом её содержимое можно прочесть как функцией ''​INP'',​ так и функцией ''​VPEEK'';​ +
-  - если адрес VRAM принадлежит отрезку [&​H3FFF,&​HFFFF],​ то после записи оператором ''​OUT''​ в ячейку с этим адресом её содержимое можно прочесть только функцией ''​INP''​. +
- +
-{{anchor:​e11110-02}} __//​Пример//​__. Сравните результаты работы этой программы на компьютерах серий [[msx:​msx_1]] и [[msx:​msx_2]] ! \\ {{.examples:​11110-02.bas|}} \\ [[+tab|wmsxbpge>​11110-02.bas]] +
-<​code>​ +
-10 CALL NETEND +
-20 INPUT"​Младший байт";​N1:​INPUT"​Старший байт";​N2:​INPUT"​Значение";​D +
-30 PRINT"​Старое значение:";​ +
-40 OUT&​H99,​N1:​OUT&​H99,​N2:​PRINT INP(&​H98) +
-50 OUT&​H99,​N1:​OUT&​H99,​N2 OR&​H40:​OUT&​H98,​D +
-60 PRINT"​Новое значение:";​ +
-70 OUT&​H99,​N1:​OUT&​H99,​N2:​PRINT INP(&​H98) +
-80 CALL NETINI:'​Отмена действия команды CALL NETEND +
-</​code>​ +
- +
-===== XI.2. Работа с видеопроцессором ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Четыре величайших изобретения в истории человечества:​ +
-  - колесо;​ +
-  - электрическая лампочка;​ +
-  - микрокомпьютер;​ +
-  - руководства по микрокомпьютерам вместе с их авторами. +
-<WRAP rightalign>​ +
-—//​М.Уэйт,​ С.Прата,​ Д.Мартин//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Работа с псевдопеременными ''​[[#​base|BASE]]''​ и ''​[[#​vdp|VDP]]''​ — весьма эффективное средство управления видеопамятью. Однако при использовании этих средств нужно быть крайне осторожным,​ ибо малейшая ошибка в программировании может сделать экран "​неуправляемым",​ что вынудит Вас нажать кнопку <​key>​RESET</​key>​! +
- +
-Мы познакомим Вас с несколькими сравнительно "​безопасными"​ примерами. +
- +
-{{anchor:​vdp}} +
-Более детальная информация о способах работы с видеопамятью содержится в книгах [[bibliography#​b65|[65]]],​ [[bibliography#​b89|[89]]] (если Вы, конечно,​ сможете их раздобыть!). +
- +
-Работой видеопамяти управляет специальный процессор,​который называется //​видеопроцессором//​. Видеопроцессор "​работает"​ с двумя группами восьмибитных //​регистров//:​ 47 регистров VDP и 16 регистров статуса. +
- +
-//​Регистр//​ — электронное устройство для временного хранения информации во время её обработки. Регистры называют ​ часто сверхоперативной памятью,​ т.к. для регистров используются специальные электронные схемы, позволяющие значительно быстрее записывать информацию в регистры и читать информацию из регистров. +
- +
-Регистры VDP можно разделить на несколько категорий:​ +
-  * по назначению:​ +
-    - регистры //​установки режима//​ (0, 1, 8, 9); +
-    - регистры //​базовых адресов//​ (2÷6, 10, 11); +
-    - регистры //​цветов//​ (7, 12, 13, 20÷22); +
-    - регистры //​управления экраном//​ (18, 19, 23); +
-    - регистры //​доступа//​ (14÷17); +
-    - регистры //​команд//​ (32÷46); +
-  * по способу доступа:​ +
-    - разрешены чтение и запись на компьютерах и серии [[msx:​msx_1]],​ и серии [[msx:​msx_2]] (регистры 0÷7); +
-    - разрешены чтение и запись на компьютерах [[msx:​msx_2]] и только запись на компьютерах [[msx:​msx_1]] (регистры 8÷23); +
-    - разрешена только //​запись//​ (регистры 32÷46). +
-Для //​чтения//​ "​содержимого"​ регистров VDP предназначена одноименная псевдопеременная,​ используемая в правой части оператора присваивания. +
- +
-Её синтаксис:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VDP(N) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * ''​VDP''​ ("​ViDeo Processor"​) — служебное слово;​ +
-  * N — арифметическое выражение,​ целая часть значения которого указывает на номер регистра VDP, причём:​ +
-    * α) если используется регистр с номером из диапазона [0,7], то значение параметра N должно быть равно номеру регистра;​ +
-    * β) если используется регистр с номером из диапазона [8,23] (для компьютера [[msx:​msx_2]]),​ то N=RG+1, где RG — номер регистра. +
- +
-Теперь мы расскажем Вам о способах //​записи//​ в регистры VDP: +
-  - <​WRAP>​ запись с использованием псевдопеременной VDP. Этот способ является самым простым:​ оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VDP(N) = M +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: ​  +
-  * ''​VDP''​ ("​ViDeo Processor"​) — служебное слово;​ +
-  * N — арифметическое выражение,​ целая часть значения которого указывает на номер регистра VDP, причём:​ +
-    * α) если используется регистр с номером из диапазона [0,7], то значение параметра N должно быть равно номеру регистра;​ +
-    * β) если используется регистр с номером из диапазона [8,23], либо из диапазона [32,46] (для компьютера [[msx:​msx_2]]),​ то N=RG+1, где RG — номер регистра;​ +
-  * M — арифметическое выражение,​ целая часть значения которого принадлежит отрезку [0,255], +
-позволяет поместить значение выражения M в регистр VDP; </​WRAP>​ +
-  - <​WRAP>​ запись через //​порты//​ ввода–вывода (для всех регистров). +
-Этот способ заключается в использовании порта с номером &H99, связывающего видеопроцессор с центральным процессором MSX–компьютера (Z–80). Чтобы записать число A в регистр VDP с номером N, примените следующие +
-операторы:​ +
-  OUT &​H99,​A:​OUT &H99,RG OR &H80 . +
-Данные операторы последовательно выводят данные и номер регистра в порт 99h. +
-^Номер бита^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-^Первый байт| ​ Данные ​ |||||||| +
-^Второй байт| ​ 1  |  0  |  Номер регистра ​ |||||| +
- +
-//​Замечание//​. Будьте особенно внимательными при обращении к видеопроцессору из подпрограммы обработки прерываний.</​WRAP>​ +
-  - <​WRAP>​ //​косвенная//​ запись в регистры VDP. Про неё будет рассказано в [[#XI.2.6. Доступ к видеопамяти|разделе XI.2.6.]]. +
- +
-Напомним,​ что если Вы работаете с компьютером серии [[msx:​msx_2]],​ то перед набором программы,​ использующей порты ввода–вывода,​ нужно выполнить команду +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-CALL NETEND +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-</​WRAP>​ +
- +
-==== XI.2.1. Регистры установки режима ==== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Нехватка информации восполняется избытком интуиции. +
-<WRAP rightalign>​ +
-—//​М.Мишин//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Перейдём теперь к описанию "​содержимого"​ некоторых регистров VDP. +
- +
-Вначале напомним Вам принятую нумерацию бит в байте:​ +
-|  7–й \\ бит ​ |  6–й \\ бит ​ |  5–й \\ бит ​ |  4–й \\ бит ​ |  3–й \\ бит ​ |  2–й \\ бит ​ |  1–й \\ бит ​ |  0–й \\ бит ​ | +
- +
-__//​Регистр 0//__. +
-^  Номер бита ​ ^  Значение бита ​ ^  Комментарий ​ ^^ +
-|  7  |  0  |  Не используется ​ || +
-|  6  |  1  |  Устанавливает цветовую шину в режиме ввода и вводит данные в видеопамять ​ || +
-|  5  |  1  |  Бит "​IE2" ​ |  Запретить прерывания от светового пера ​ | +
-|:::|  0  |:::|  Разрешить прерывания от светового пера ​ | +
-|  4  |  1  |  Бит "​IE1" ​ |  Запретить прерывание от горизонтального сканирования линии по "​IE1"​ и отключить сигналы с клавиатуры ​ | +
-|:::|  0  |:::|  Разрешить прерывания по "​IE1" ​ | +
-|  3  | |  Бит "​M5"​ установки графических режимов ​ || +
-|  2  | |  Бит "​M4"​ установки графических режимов ​ || +
-|  1  | |  Бит "​M3"​ установки графических режимов ​ || +
-|  0  | |  Внешний видеосигнал (бит "​IV"​) ​ || +
- +
-{{anchor:​e1121-00}} __//​Пример//​__. \\ {{.examples:​1121-00.bas|}} \\ [[+tab|wmsxbpge>​1121-00.bas]] +
-<​code>​ +
-10 OUT &​H99,​VDP(0) OR 16:OUT &H99,0 OR &H80 '​Отключение клавиатуры! +
-</​code>​ +
- +
-__//​Регистр 1//__. +
- +
-^  Номер бита ​ ^  Значение бита ​ ^  Комментарий ​ ^^ +
-|  7  |  0  |Не используется|| +
-|  6  |  0  |Применение аналогично нажатию кнопки питания дисплея|изображение отключено| +
-|:::|  1  |:::​|изображение включено| +
-|  5  |  0  |  Бит "​IE0" ​ |Запретить прерывание от горизонтального сканирования линии по "​IE0"​ и отключить сигналы с клавиатуры| +
-|:::|  1  |:::​|Разрешить прерывания по "​IE0"​| +
-|  4  | |Бит "​M1"​ установки графических режимов|| +
-|  3  | |Бит "​M2"​ установки графических режимов|| +
-|  2  |  0  |Не используется|| +
-|  1  |  0  |Размер спрайтов 8×8|Использование этих бит позволяет моделировать оператор ''​SCREEN,​n''​| +
-|:::|  1  |Размер спрайтов 16×16|:::​| +
-|  0  |  0  |Нормальный размер спрайтов|:::​| +
-|:::|  1  |"​Увеличение"​ размера спрайтов|:::​| +
- +
-Назначение 6–го бита регистра 1 иллюстрируется примерами 1 и 2: +
- +
-{{anchor:​e1121-01}} __//​Пример 1//__. +
-  - \\ {{.examples:1121-011.bas|}} \\ [[+tab|wmsxbpge>​1121-011.bas]]<​code>​ +
-10 SCREEN 2 +
-15 :::::::::::::::::​ +
-20 CIRCLE(125,​95),​90 +
-30 PAINT STEP(0,0) +
-35 :::::::::::::::::​ +
-40 GOTO 40 +
-</​code>​ +
-  - \\ {{.examples:​1021-012.bas|}} \\ [[+tab|wmsxbpge>​1021-012.bas]]<​code>​ +
-             ​┌─ OFF +
-10 SCREEN 2  ▼ +
-15 VDP(1)=&​B10100000 +
-20 CIRCLE(125,​95),​90 +
-30 PAINT STEP(0,0) +
-35 VDP(1)=&​B11100000 +
-40 GOTO 40   ▲ +
-             ​└─ ON +
-</​code>​ +
-  - \\ {{.examples:​1021-013.bas|}} \\ [[+tab|wmsxbpge>​1021-013.bas]]<​code>​ +
-10 SCREEN 2 +
-15 OUT &​H99,&​B10100000:​OUT &H99,1 OR &H80 +
-20 CIRCLE(125,​95),​90:​PAINT STEP (0,0) +
-35 VDP(1)=&​B11100000 +
-40 GOTO 40 +
-</​code>​ +
- +
-Перед записью в регистр лучше всего сначала прочитать его текущее содержимое,​ а лишь затем с помощью логических операций ''​AND'',​ ''​OR''​ и ''​XOR''​ установить или "​сбросить"​ нужные биты. +
- +
- +
-{{anchor:​e1121-02}} __//​Пример 2//__. Включение и выключение экрана дисплея \\ {{.examples:​1121-02.bas|}} \\ [[+tab|wmsxbpge>​1121-02.bas]] +
-<​code>​ +
-VDP(1)=VDP(1) XOR 64 +
-</​code>​ +
-Эта команда включает экран, если он был выключен,​ и наоборот. +
- +
-А теперь разберёмся с //​нулевым//​ битом регистра 1… +
- +
-{{anchor:​e1121-03}} //​Пример 3//. Изменение размера спрайта без очистки шаблонов. \\ {{.examples:​1121-031.bas|}} \\ [[+tab|wmsxbpge>​1121-031.bas]] +
-<​code>​ +
-10 SCREEN 2,1 +
-20 SPRITE$(0)="​0123456789ABCDEF"​ +
-30 PUT SPRITE 0,​(50,​50),,​0 +
-40 FOR I=1 TO 1000:NEXT +
-50 VDP(1)=VDP(1) XOR 1 '​Эта команда переключает масштаб спрайтов без очистки шаблонов +
-60 GOTO 60 +
-</​code>​ +
-А теперь замените строку 50 на строку +
-\\ {{.examples:​1121-032.bas|}} \\ [[+tab|wmsxbpge>​1121-032.bas]] +
-<​code>​ +
-50 OUT &​H99,​VDP(1) XOR 1:OUT &H99,1 OR &H80 +
-</​code>​ +
-и выполните программу. +
- +
-Биты "​M1","​M2","​M3","​M4","​M5"​ "​отвечают"​ за выбор режима экрана:​ +
-^  Биты и их значение ​ ^^^^^  Режим видеопроцессора ​ ^ +
-^  M1  ^  M2  ^  M3  ^  M4  ^  M5  ^:::^ +
-|  1  |  0  |  0  |  0  |  0  |''​SCREEN 0''​ (40 символов)| +
-|  1  |  0  |  0  |  1  |  0  |''​SCREEN 0''​ (80 символов)| +
-|  0  |  0  |  0  |  0  |  0  |''​SCREEN 1''​| +
-|  0  |  0  |  1  |  0  |  0  |''​SCREEN 2''​| +
-|  0  |  1  |  0  |  0  |  0  |''​SCREEN 3''​| +
-|  0  |  0  |  0  |  1  |  0  |''​SCREEN 4''​| +
-|  0  |  0  |  1  |  1  |  0  |''​SCREEN 5''​| +
-|  0  |  0  |  0  |  1  |  1  |''​SCREEN 6''​| +
-|  0  |  0  |  1  |  0  |  1  |''​SCREEN 7''​| +
-|  0  |  0  |  1  |  1  |  1  |''​SCREEN 8''​| +
- +
-Изменять содержимое бит "​M1","​M2","​M3","​M4"​ и "​M5"​ не рекомендуется! +
-Эти биты используются видеопроцессором при инициализации режима ''​SCREEN'',​ однако следует помнить,​ что для полной инициализации этого надостаточно! +
- +
-Легко, например,​ проверить,​ что команда ''​VDP(0)=4''​ не устанавливает полностью 80–символьный режим ''​SCREEN 0''​. Зато чтение этих бит поможет Вам "​вспомнить",​ в каком режиме ''​SCREEN''​ Вы работаете в данный момент. +
- +
-Для полной инициализации экрана нужно выполнить следующие действия:​ +
-  - установить биты M1, M2, M3, M4, M5; +
-  - установить начальные адреса Таблиц VRAM в регистрах базовых адресов;​ +
-  - заполнить таблицы видеопамяти необходимыми данными;​ +
-  - занести в ячейку памяти с адресом &HFCAF номер режима ''​SCREEN''​. +
- +
-__//​Регистр 8//__. +
- +
-^  Номер бита ​ ^  Значение бита ​ ^  Комментарий ​ ^ +
-|  7  |  1  |Цветовая шина устанавливается на режим //​ввода//​ и разрешается использование манипулятора "​мышь"​| +
-|:::|  0  |Цветовая шина устанавливается на режим //​вывода//​ и запрещается использование манипулятора "​мышь"​| +
-|  6  |  1  |Разрешается обработка светового пера| +
-|:::|  0  |Запрещается обработка светового пера| +
-|  5  |Бит с именем TP. Устанавливается цвет кода 0 в цветовой палитре|| +
-|:::|  1  |изображение 0–го цвета имеет цвет 0 из Таблицы PT| +
-|:::|  0  |изображение 0–го цвета имеет цвет бордюра| +
-|  4  | Моделирует оператор ''​SET VIDEO,,​n''​|| +
-|:::|  1  |происходит вывод данных на видеомагнитофон| +
-|:::|  0  |происходит ввод данных от внешнего TV–источника или от компьютера;​| +
-|  3  |Содержимое бита изменять не рекомендуется!|| +
-|:::|  1  |Размер видеопамяти ≥64 Кб (для компьютеров [[msx:​msx_2]])| +
-|:::|  0  |Размер видеопамяти ≤64 Кб (для компьютеров [[msx:​msx_1]])| +
-|  2  |  0  |Не используется| +
-|  1  |  1  |Запрещается отображение спрайтов| +
-|:::|  0  |Разрешается отображение спрайтов| +
-|  0  |  1  |Установить черно–белый режим с 32 градациями тона| +
-|:::|  0  |Установить цветовой режим| +
- +
-По умолчанию 5–й бит регистра с номером 8 равен 0. В этом случае объект нулевого цвета будет окрашиваться цветом бордюра (т.е. будет //​прозрачным//​). Участки спрайтов с нулевым цветом на экране не отображаются. Но если спрайты пересекаются "​невидимыми"​ частями,​ то столкновение спрайтов не будет установлено. Для получения на экране одновременно 16 цветов необходимо,​ чтобы бордюр был окрашен в //​нулевой//​ цвет. +
- +
-Если 5–й бит 8–го регистра равен 1, то объект нулевого цвета не будет окрашиваться цветом бордюра (если, конечно,​ бордюр сам не окрашен в нулевой цвет). Код цвета 0 будет кодом, который определяется в регистре палитры (только в режиме ''​SCREEN 8''​ R=0, G=0, B=0). На экране одновременно могут отображаться 16 цветов,​ причём в области,​ отличной от бордюра;​ более того, отображаются спрайты всех цветов. Участки спрайтов с нулевым цветом на экране по–прежнему не отображаются. Но если спрайты пересекаются "​невидимыми"​ частями,​ то столкновение спрайтов //​будет установлено//​. +
- +
-{{anchor:​e1121-04}} __//​Пример 4//__. \\ {{.examples:​1121-04.bas|}} \\ [[+tab|wmsxbpge>​1121-04.bas]] +
-<​code>​ +
-10 COLOR =(0,2,4,7) '​Изменим палитру нулевого цвета +
-20 COLOR 1,​15,​8:​SCREEN 2 +
-30 VDP(8+1)=8 '​Инициализация 8-го регистра +
-40 CIRCLE (90,​90),​45,​0 '​Изображение имеет цвет бордюра +
-50 A$=INPUT$(1) +
-60 VDP(8+1)=&​B00101000 '​Бордюр окрашен в 8-й цвет, +
-70 GOTO 70             '​а изображение - в нулевой +
-</​code>​ +
- +
-__//​Регистр 9//__. +
- +
-^  Номер \\ бита ​ ^  Значение \\ бита ​ ^  Комментарий ​ ^^ +
-|  7  |Бит "​LN"​ Отвечает за //​общую//​ высоту экрана (за доступную высоту отвечает ячейка &hF3B1 в рабочей области RAM)||| +
-|:::|  1  |На экране 212 графических или 26.5 текстовых строк|| +
-|:::|  0  |На экране 192 графических или 24 текстовых строк|| +
-|  6  |  0  |Не используется|| +
-|  5  |  1  |Поступает сигнал только от внешнего TV–источника|Эти биты моделируют оператор ''​SET VIDEO n''​| +
-|:::|  0  |Разрешено изображение от компьютера|:::​| +
-|  4  |  1   ​|Происходит смешивание изображения от компьютера и от TV–источника|:::​| +
-|:::|  0  |Смешивания сигналов не происходит|:::​| +
-|  3  |  1  |Происходит "​дрожание"​ экрана|Эти биты моделируют оператор ''​SCREEN ,,,,,​n''​ (5 запятых!)| +
-|:::|  0  |"​Дрожания"​ не происходит|:::​| +
-|  2  |  1  |Происходит поочерёдный показ страниц на страницах с нечётными номерами в режимах ''​SCREEN 5''​ ÷ ''​SCREEN 8''​|:::​| +
-|:::|  0  |Отображается одна и та же страница на чётное/​нечётное поле|:::​| +
-|  1  |Выбор системы телевидения||| +
-|:::|  1  |PAL  (313 линий, американский стандарт)|| +
-|:::|  0  |NTSC (262 линии, японский стандарт) — только для RGB–выхода|| +
-|  0  |  1  |Установка на режим //​ввода//​|| +
-|:::|  0  |Установка на режим //​вывода//​|| +
- +
-{{anchor:​e1121-05}} //​Пример 5//. Установим высоту экрана равной 26.5 строкам. \\ {{.examples:​1121-05.bas|}} \\ [[+tab|wmsxbpge>​1121-05.bas]] +
-<​code>​ +
-10 SCREEN 0:WIDTH 80 +
-20 VDP(9+1)=VDP(9+1) OR 128 +
-30 POKE &​hF3B1,​27 +
-40 FOR T=BASE(0)+(1920-80) TO BASE(0)+(1920-80)+240 +
-50 VPOKE T,32:NEXT +
-</​code>​ +
- +
-==== XI.2.2. Регистры базовых адресов ==== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Мы находимся в положении,​ несколько аналогичном положению человека,​ держащего в руках связку ключей и пытающегося открыть одну за другой несколько дверей. Рано или поздно ему всегда удаётся подобрать ключ к очередной двери, но сомнения относительно взаимнооднозначного соответствия между ключами и дверями у него остаются. +
-<WRAP rightalign>​ +
-—//​Юджин Вигнер//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-Адрес байта видеопамяти кодируется 17–ю двоичными цифрами,​ которые мы будем обозначать Ai, где i=0,​1,​2,​…,​16,​ причём через A16 будем обозначать //​старший//​ бит, через A0 — //​младший//​ бит. +
- +
-^Старший бит| ​ A16  |  A15  |  A14  |  A13  |  A12  |  A11  |  A10  |  A9  |  A8  |  A7  |  A6  |  A5  |  A4  |  A3  |  A2  |  A1  |  A0  ^Младший бит| +
- +
-В регистрах базовых адресов хранятся старшие биты начальных адресов Таблиц VRAM для текущего режима ''​SCREEN''​. +
- +
-<WRAP centeralign>​Эти регистры инициализируются псевдопеременной ''​BASE''​.</​WRAP>​ +
- +
-Отметим,​что при использовании этих регистров рекомендуется маскировать //​ненужные//​ в текущем режиме отображения биты. +
- +
-Регистр с номером 2 VDP содержит семь старших бит начального адреса Таблицы PNT: +
-|  0  |  A16  |  A15  |  A14  |  A13  |  A12  |  A11  |  A10  | +
- +
-{{anchor:​e1122-01}} __//​Пример 1//__. \\ {{.examples:​1122-01.bas|}} \\ [[+tab|wmsxbpge>​1122-01.bas]] +
-<​code>​ +
-10 SCREEN 1 +
-20 A$=RIGHT$("​0000000000000000"​+BIN$(BASE(5*1+0)),​16) +
-30 ?​A$:​B$=RIGHT$("​00000000"​+BIN$(VDP(2)),​8):?​B$ '​Читаем текущий адрес PNT +
-run +
-┌──────┐ +
-│000110│0000000000◀── Начальный адрес Таблицы PNT в SCREEN1 +
-└──────┘ +
-   ​┌──────┐ +
- ​00│000110│ ​      ​◀── Содержимое регистра с номером 2 +
-Ok └──────┘ +
-</​code>​ +
- +
-Регистры с номерами 10 и 3 содержат одиннадцать старших бит начального адреса Таблицы CT: +
- +
-Регистр 10                    +
-|  0  |  0  |  0  |  0  |  0  |  A16  |  A15  |  A14  | +
- +
-Регистр 3 +
-|  A13  |  A12  |  A11  |  A10  |  A9  |  A8  |  A7  |  A6  | +
- +
-{{anchor:​e1122-02}} __//​Пример 2//__. \\ {{.examples:​1122-02.bas|}} \\ [[+tab|wmsxbpge>​1122-02.bas]] +
-<​code>​ +
-10 SCREEN 1 +
-20 A$=RIGHT$("​0000000000000000"​+BIN$(BASE(5*1+1)),​16) +
-30 ?​A$:​B$=RIGHT$("​0000000000000000"​+BIN$(VDP(10+1))+BIN$(VDP(3)),​16):?​B$ +
-run +
-┌──────────┐ +
-│0010000000│000000 ◀── Начальный адрес Таблицы CT в SCREEN1 +
-└──────────┘ +
-       ​┌──────────┐ +
- ​000000│0010000000│◀── Содержимое регистров с номерами 10 и 3 +
-Ok     ​└──────────┘ +
-</​code>​ +
- +
-Регистр с номером 4 содержит шесть старших бит начального адреса Таблицы PGT: +
-|  0  |  0  |  A16  |  A15  |  A14  |  A13  |  A12  |  A11  | +
- +
-{{anchor:​e1122-03}} __//​Пример 3//__. \\ {{.examples:​1122-03.bas|}} \\ [[+tab|wmsxbpge>​1122-03.bas]] +
-<​code>​ +
-10 SCREEN 0:WIDTH 80 +
-20 A$=RIGHT$("​0000000000000000"​+BIN$(BASE(5*0+2)),​16) +
-30 ?​A$:​B$=RIGHT$("​00000000"​+BIN$(VDP(4)),​8):?​B$ +
-run +
-┌─────┐ +
-│00010│00000000000◀── Начальный адрес Таблицы PGT +
-└─────┘ ​                     в SCREEN0 +
-    ┌─────┐ +
- ​000│00010│ ​      ​◀── Содержимое регистра с номером 4 +
-Ok  └─────┘ +
-</​code>​ +
-Регистры с номерами 11 и 5 содержат десять старших бит начального адреса Таблицы SAT: +
- +
-Регистр 11                   +
-|  0  |  0  |  0  |  0  |  0  |  0  |  A16  |  А15  | +
- +
-Регистр 5 +
-|  А14  |  A13  |  A12  |  A11  |  A10  |  A9  |  A8  |  А7  | +
- +
-{{anchor:​e1122-04}} __//​Пример 4//__. \\ {{.examples:​1122-04.bas|}} \\ [[+tab|wmsxbpge>​1122-04.bas]] +
-<​code>​ +
-10 SCREEN 1 +
-20 A$=RIGHT$("​0000000000000000"​+BIN$(BASE(5*1+3)),​16) +
-30 ?​A$:​A$=RIGHT$("​0000000000000000"​+BIN$(VDP(1+11))+BIN$(VDP(5)),​16):?​A$ +
-run +
-┌─────────┐ +
-│000110110│0000000 ◀── Начальный адрес Таблицы SAT в SCREEN1 +
-└─────────┘ +
-        ┌─────────┐ +
- ​0000000│000110110│◀── Содержимое регистров с номерами 11 и 5 +
-Ok      └─────────┘ +
-</​code>​ +
- +
-//​Замечание//​. С Таблицей SAT связана Таблица SCT, адрес которой получается вычитанием 512 байт из начального адреса Таблицы SAT. +
- +
-Регистр с номером 6 содержит шесть старших бит начального адреса Таблицы SGT: +
-|  0  |  0  |  A16  |  A15  |  A14  |  A13  |  A12  |  A11  | +
- +
-{{anchor:​e1122-05}} __//​Пример 5//__. \\ {{.examples:​1122-05.bas|}} \\ [[+tab|wmsxbpge>​1122-05.bas]] +
-<​code>​ +
-10 SCREEN 1 +
-20 A$=RIGHT$("​0000000000000000"​+BIN$(BASE(5*1+4)),​16) +
-30 ?​A$:​B$=RIGHT$("​00000000"​+BIN$(VDP(6)),​8):?​B$ '​Читаем текущий адрес SGT +
-run +
-┌─────┐ +
-│00111│00000000000◀── Начальный адрес Таблицы SGT +
-└─────┘ ​                     в SCREEN1 +
-    ┌─────┐ +
- ​000│00111│ ​      ​◀── Содержимое регистра с номером 6 +
-Ok  └─────┘ +
-</​code>​ +
- +
-<WRAP centeralign>​Отметим,​ что при использовании этих регистров рекомендуется //​маскировать//​ ненужные в текущем режиме отображения биты.</​WRAP>​ +
- +
-==== XI.2.3. Регистры цветов ==== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-— Вы знаете отличительные способности животного,​ называемого раком?​\\  +
-— Да, конечно. Рак — это рыба //​красного цвета//,​ которая ходит боком.\\  +
-— Ну, что ж. Я вижу, что Вы кое–что //​знаете//​ о раке… +
-<WRAP rightalign>​ +
-—//​Студенческий фольклор//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-  - <​WRAP>​ Регистр с номером 7 видеопроцессора в режиме ''​SCREEN 0''​ определяет цвет изображения и фона. +
- +
-Четыре старших бита этого регистра "​хранят"​ цвет //​изображения//,​ а четыре младших — цвет //​фона//​. +
- +
-Например,​ команда +
-<​code>​ +
-           ​VDP(7)=&​H4B +
-                    ▲▲ +
-Цвет изображения ​ ──┘└── Цвет фона +
-</​code>​ +
-в режиме SCREEN 0 эквивалентна команде ''​COLOR 4,​11''​ . +
- +
-А команда ''​VDP(7)=&​H1F''​ приводит к тому же результату,​ что и оператор ''​COLOR 1,​15''​ . +
- +
-//​Регистр//​ с номером 7 (регистр цвета текста/​фона) +
-^Номер бита^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-^Имя бита| ​ TC3  |  TC2  |  TC1  |  TC0  |  BD3  |  BD2  |  BD1  |  BD0  | +
-^Назначение|определяет цвет текста в режимах ''​SCREEN 0''​ и ''​SCREEN 1''​||||определяет цвет фона во всех режимах отображения|||| +
- +
-В других режимах ''​SCREEN''​ этот регистр "​хранит"​ цвет //​бордюра//​. +
- +
-{{anchor:​e1123-01}} __//​Пример 1//__. \\ {{.examples:​1123-01.bas|}} \\ [[+tab|wmsxbpge>​1123-01.bas]] +
-<​code>​ +
-10 COLOR 1,​15,​4:​SCREEN 2:​Z=VDP(7) +
-20 SCREEN 0:PRINT Z +
-run +
- 4 +
-Ok +
-</​code>​ +
- +
-<WRAP centeralign>​Содержимое седьмого регистра инициализируется оператором ''​COLOR''</​WRAP>​ +
-</​WRAP>​ +
-  - <​WRAP>​ В 80–символьном режиме ''​SCREEN 0''​ существует явление,​ которое мы назовём //​миганием//​. Информация о символах,​ которые должны мигать,​ находится в Таблице цветов (CT), которая занимает 270 байтов с адреса,​ возвращаемого псевдопеременной ''​BASE(0*5+1)''​. +
-Рассмотрим,​ как она располагается. +
- +
-Каждая строка экрана разбивается на 10 участков по 8 квадратов (знакомест) в каждом. За каждый из этих участков отвечает один байт, а за квадрат,​ естественно,​ один бит. Если значение бита равно 1, то символ на соответствующем знакоместе (в соответствующем квадрате) //​мигает//​. В противном случае мигания не происходит. +
- +
-Запись в Таблицу CT ещё не означает,​ что какое–то знакоместо на экране сразу замигает. Для начала мигания необходимо обратиться к регистрам VDP, отвечающим за этот процесс. +
- +
-Вначале договоримся о терминологии. +
- +
-// Основным//​ цветом текста (фона) будем называть цвет, задаваемый оператором ''​COLOR''​ и хранящийся в 7–м регистре VDP. +
- +
-//​Цветом мигания//​ текста (фона) будем называть цвет,​который приобретает текст (фон) при мигании. +
- +
-//​Частотой включения мигания//​ назовём промежуток времени,​ в течение которого текст и фон приобретают цвет мигания. +
- +
-//​Частотой выключения мигания//​ будем называть промежуток времени,​ в течении которого текст и фон приобретают основной цвет. +
- +
-Единица измерения частоты мигания равна 1/6 секунды. Максимально возможный период мигания составляет 5 секунд (15/6 секунд на включение мигания и столько же на выключение мигания). +
- +
-Регистр с номером //​двенадцать//​ VDP содержит информацию о цвете мигания текста и фона. Старший полубайт этого регистра отвечает за цвет мигания текста,​ а младший полубайт отвечает за цвет мигания фона. +
- +
-//​Регистр//​ с номером 12 (регистр цвета текста/​фона) +
-^Номер бита^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-^Имя бита| ​ TC3  |  TC2  |  TC1  |  TC0  |  BC3  |  BC2  |  BC1  |  BC0  | +
-^Назначение|определяют цвет части 1 шаблона||||определяют цвет части 0 шаблона|||| +
- +
-Если в режиме ''​SCREEN 1''​ установлен признак мерцания,​ то цвета из этого регистра и из регистра с номером 7 поочерёдно отображаются. +
- +
-За частоту мигания "​отвечает"​ регистр с номером //​тринадцать//,​ причём в его старшем полубайте хранится информация о частоте включения мигания,​ а в младшем — информация о частоте выключения мигания. +
- +
-//​Регистр//​ с номером 13 (регистр периода мерцания) +
-^Номер бита^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-^Имя бита| ​ ON3  |  ON2  |  ON1  |  ON0  |  OF3  |  OF2  |  OF1  |  OF0  | +
-^Назначение|определяют период отображения для чётной страницы||||определяют период отображения для нечётной страницы|||| +
- +
-В режимах растровой графики (''​SCREEN 5''​ ÷ ''​SCREEN 8''​) попеременно сменяются две страницы памяти. Данные помещаются в этот регистр для установления отображаемой страницы как нечётной страницы для начала мерцания. Этот регистр используется также в режиме ''​SCREEN 1''​. +
- +
- ​Приведём табличку… +
-^  Содержимое \\ полубайта \\ регистра 13  ^  Время (мс) ​ ^ +
-|  0000  |  0  | +
-|  0001  |  166,9  | +
-|  0010  |  333,8  | +
-|  0011  |  500,6  | +
-|  0100  |  667,5  | +
-|  0101  |  834,4  | +
-|  0110  |  1001,​3 ​ | +
-|  0111  |  1168,​2 ​ | +
-|  1000  |  1335,​1 ​ | +
-|  1001  |  1501,​9 ​ | +
-|  1010  |  1668,​8 ​ | +
-|  1011  |  1835,​7 ​ | +
-|  1100  |  2002,​6 ​ | +
-|  1101  |  2169,​5 ​ | +
-|  1110  |  2336,​3 ​ | +
-|  1111  |  2503,​2 ​ | +
- +
-А теперь взгляните на следующий пример. +
- +
-{{anchor:​e1123-02}} __//​Пример 2//__. \\ {{.examples:​1123-02.bas|}} \\ [[+tab|wmsxbpge>​1123-02.bas]] +
-<​code>​ +
-NEW +
-Ok +
-10 SCREEN 0:WIDTH 80 '​Установка режима для мигания +
-20 FOR T=2048 TO 2048+269:​VPOKE T,0:NEXT '​Очистка Таблицы мигания +
-30 LINEINPUT "​Введите слово:";​B$ +
-40 INPUT "​Где ему мигать (X,​Y)";​X,​Y +
-50 INPUT "​Цвет слова для мигания";​MI +
-60 INPUT "​Цвет фона для мигания";​MF +
-70 INPUT "​Частота включения мигания (от 0 до 15)";​TN +
-80 INPUT "​Частота выключения мигания (от 0 до 15)";​TK +
-90 VPOKE 2048+10*Y+X/​8,&​B11111111 '​Будуть мигать 8 символов +
-100 CLS:LOCATE X,Y:PRINT B$ +
-110 COL=16*MI+MF:​TIM=16*TN+TK +
-120 VDP(12+1)=COL:​VDP(13+1)=TIM +
-</​code>​ +
-Для прекращения мигания поместите в старший полубайт 13–го регистра число 0. +
-</​WRAP>​ +
-  - <​WRAP>​ Две графические страницы экрана могут отображаться //​попеременно//​ (в режимах ''​SCREEN 5''​ ÷ ''​SCREEN 8''​). Страницы,​ которые будут попеременно отображаться,​ расположены следующим образом:​ +
- +
-<​code>​ +
-Режим SCREEN 5 и  SCREEN 6       ​Режим SCREEN 7 и SCREEN 8 +
-     ​┌─────────────┐ ​                 ┌────────────┐ +
-     │ Страница 0  │─┐ ​               │            │─┐ +
-     ​├─────────────┤ │                │ Страница 0 │ │ +
-     │ Страница 1  │─┘ ​               │            │ │ +
-     ​├─────────────┤ ​                 ├────────────┤ │ +
-     │ Страница 2  │─┐ ​               │            │ │  +
-     ​├─────────────┤ │                │ Страница 1 │─┘ +
-     │ Страница 3  │─┘ ​               │            │  +
-     ​└─────────────┘ ​                 └────────────┘ +
-</​code>​ +
- +
-Период отображения,​находящийся в промежутке между 166 мсек и 2053 мсек, может быть определён для каждой страницы. Для этого необходимо:​ +
-  - задать базовый адрес Таблицы имён шаблонов //​нечётной//​ страницы (регистр с номером 2); +
-  - <​WRAP>​задать время включения (интервал,​ в течение которого отображается //​чётная//​ страница) и время выключения (интервал,​ в течение которого отображается //​нечётная//​ страница) в регистре с номером 13. +
- +
-//​Регистр//​ с номером 13 (регистр периода мерцания) +
-^Номер бита^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-^Имя бита| ​ ON3  |  ON2  |  ON1  |  ON0  |  OF3  |  OF2  |  OF1  |  OF0  | +
-^Назначение|Время включения||||Время выключения|||| +
-</​WRAP>​ +
-  - После этого начнётся процесс мигания. +
- +
-{{anchor:​e1123-03}} __//​Пример 3//__. \\ {{.examples:​1123-03.bas|}} \\ [[+tab|wmsxbpge>​1123-03.bas]] +
-<​code>​ +
-10 SCREEN 7                    :' Режим растровой графики (SCREEN 5÷8) +
-20 SET PAGE 0,0: CLS           :'​ На странице 0 +
-30 CIRCLE (254,​106),​30,​15 ​     :' рисуем окружность +
-40 SET PAGE 1,1: CLS           :'​ А на странице 1 +
-50 CIRCLE (254,​106),​60,​15 ​     :' рисуем окружность побольше +
-60 VDP(13+1)=&​H11 ​             :' Включим смену страниц +
-70                             :'​ Окружность ​ п у л ь с и р у е т ! +
-80 A$=INPUT$(1) ​               :' Немного подождем... +
-90 VDP(13+1)=0 ​                :'​ Выключим смену страниц +
-</​code>​ +
- +
-Опишем ещё один способ осуществления смены двух графических страниц на экране. +
- +
-Бит ЕО (второй бит регистра с номером 9), используется для попеременной демонстрации //​двух//​ графических страниц экрана с частотой 60 Гц. +
- +
-Для этого необходимо:​ +
-1) задать базовый адрес Таблицы имён шаблонов //​нечётной//​ страницы (регистр с номером 2); +
-2) установить //​второй//​ бит регистра с номером 9 в 1. +
- +
-{{anchor:​e1123-04}} __//​Пример 4//__. \\ {{.examples:​1123-04.bas|}} \\ [[+tab|wmsxbpge>​1123-04.bas]] +
-<​code>​ +
-10 SCREEN 7:​VDP(10)=0 ​      :'​ Режим растровой графики (SCREEN 5÷8) +
-20 SET PAGE 0,0: CLS        :' Рисуем на странице 0 +
-30 CIRCLE (256,​106),​30,​15 ​  :'​ окружность радиусом 30 +
-31 FOR I=1 TO 100:​NEXT ​     :' З а д е р ж к а... +
-40 SET PAGE 1,1: CLS        :' А на странице 1 - +
-50 CIRCLE (256,​106),​60,​15 ​  :'​ окружность радиусом 60 +
-51 FOR I=1 TO 100:​NEXT ​     :' З а д е р ж к а... +
-59 :' ​                      :'​ А теперь - п о м и г а е м ... +
-60 VDP(9+1)=&​B00000100:'​ Включаем попеременное отображение страниц. +
-70 :' Окружности с двух страниц одновременно отображаются на экране ! +
-80 :' Недостаток:​ заметное мигание изображения +
-81 :' Эта возможность используется в программе PAINTER +
-82 :' (меню Tool.Show Canvas) +
-90 A$=INPUT$(1) ​            :'​ З а д е р ж к а +
-</​code>​ +
- +
-Кроме того, видеопроцессор поддерживает функцию черезстрочного отображения. Отображение первого и второго //​полей//​ на одной и той же странице можно получить,​ установив бит IL (третий бит регистра с номером 9) в 1. +
- +
-Отображение чётной страницы в первом поле и нечётной страницы во втором поле можно получить,​ выполнив следующее:​ +
-1) установить бит IL (третий бит регистра с номером 9) в 1; +
-2) установить бит ЕО (второй бит регистра с номером 9) в 1; +
-3) задать базовый адрес Таблицы имён шаблонов нечётной страницы (регистр с номером 2). +
- +
-{{anchor:​e1123-05}} __//​Пример 5//__. \\ {{.examples:​1123-05.bas|}} \\ [[+tab|wmsxbpge>​1123-05.bas]] +
-<​code>​ +
-10 COLOR 15,1,1: SCREEN 7                   '​ Режим растровой графики +
-15 ' Обратите внимание на координаты линий ! +
-20 SET PAGE 0,​0:​CLS:​LINE (0,​100)-(511,​100),​15 'На странице 0 рисуем линию +
-30 SET PAGE 1,​1:​CLS:​LINE (0,​100)-(511,​100),​8 ' На 1–й странице тоже рисуем линию +
-31 VDP(9+1)=&​B00001100 +
-32 ' ​             │└─────── Отображаем четную страницу в первом поле +
-33 ' ​             └──────── и нечетную страницу во втором поле +
-34 '​Линии накладываются друг на друга на 1/2 (!) точки +
-40 A$=INPUT$(1) ​  '​ Задержка +
-41 VDP(9+1)=0 ​    '​ Выключим мигание +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​ +
-  * Регистр с номером 20 называется регистром цветовой вспышки 1. +
-  * Регистр с номером 21 называется регистром цветовой вспышки 2. +
-  * Регистр с номером 22 называется регистром цветовой вспышки 3. +
-Данные регистры инициализируются при включении компьютера следующим образом:​ +
- +
-^Номер бита^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-^Регистр 20|  0  |  0  |  0  |  0  |  0  |  0  |  0  |  0  | +
-^Регистр 21|  0  |  0  |  1  |  1  |  1  |  0  |  1  |  1  | +
-^Регистр 22|  0  |  0  |  0  |  1  |  0  |  1  |  0  |  1  | +
- +
-Если все величины в трёх вышеуказанных регистрах равны нулю, то сигнал "​цветовой вспышки"​ на NTSC–видеовыходе будет отсутствовать. Если же вышеуказанные величины затем возвращаются в исходное состояние,​ то будет получен обычный сигнал "​цветовой вспышки"​ на NTSC–видеовыходе. +
-</​WRAP>​ +
- +
-==== XI.2.4. Регистры управления экраном ==== +
- +
-Регистрами //​управления экраном//​ будем называть регистры с номерами 18, 19, 23. Эти регистры используются для управления отображением на дисплее. +
-  - <​WRAP>​ Использование регистра с номером //​восемнадцать//​ даёт возможность центрирования изображения относительно электронно–лучевой трубки дисплея:​ +
-<​code>​ +
-                          Регистр с номером 18 +
-        ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐ +
-        │      │  Параметр смещения │      │  Параметр смешения │ +
-        │      │      вверх–вниз ​   │      │     ​вправо–влево ​  │ +
-        └──▲───┴──────┴──────┴──────┴──▲───┴──────┴──────┴──────┘ +
-           ​│ ​                          │ +
- ​Флаг смещения вверх–вниз: ​         Флаг смещения вправо–влево:​ +
- 1 означает смещение экрана вниз; ​  1 означает смещение экрана вправо;​ +
- 0 означает смещение экрана вверх ​  0 означает смещение экрана влево +
-</​code>​ +
- +
-А теперь посмотрите на фрагмент алгоритма нахождения величины смещения экрана,​ который записан на школьном алгоритмическом языке:​ +
-<​code>​ +
-  если ​  ​Флаг смещения = 1 +
-  ──── +
-│     ​то ​     Величина смещения = 8 - параметр смещения +
-│     ​── +
-│     ​иначе ​  ​Величина смещения = параметр смещения +
-│     ​───── +
-│ все +
-  ─── +
-</​code>​ +
- +
-{{anchor:​e1124-01}} __//​Пример 1//__. Сдвинем экран влево на 2 точки и вниз на 5 точек. \\ {{.examples:​1124-01.bas|}} \\ [[+tab|wmsxbpge>​1124-01.bas]] +
-<​code>​ +
-       10 VDP(18+1)=&​B10110010 +
-                      ▲└▲┘▲└▲┘ +
-Смещение экрана вниз ─┘ │ │ └─ 2 точки +
-               5=8-3 ───┘ └─── Смещение экрана влево +
-</​code>​ +
- +
-На компьютерах [[msx:​msx_2]] по умолчанию "​содержимое"​ регистра с номером 18 по умолчанию задаётся оператором +
-<​code>​ +
-SET ADJUST (X,Y) +
-</​code>​ +
-Значения выражений X и Y принадлежат отрезку [-7,8]. +
-</​WRAP>​ +
-  - Можно установить прерывание в момент,​ когда видeопроцессор начинает сканировать определённую линию. Для получения прерывания используется регистр с номером //​девятнадцать//,​ в котором хранится номер линии. +
-  - <​WRAP>​ __//​Регистр 23//__. +
- +
-Взгляните на рисунок,​ и Вы увидите,​ как изменяется изображение символов на //​текстовом//​ экране в зависимости от содержимого 23–го регистра (значимыми при этом являются только три младших бита):​ +
-<​code>​ +
-    VDP(23+1)=0 ​      ​VDP(23+1)=1 ​      ​VDP(23+1)=2 ​      ​VDP(23+1)=3 +
- ​┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ +
- ​│█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │█│ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│ │█│ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│█│ │█│█│ │ │ │ +
- ​│█│ │█│ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│█│ │█│█│ │ │ │ │█│ │ │ │█│ │ │ │ +
- ​│█│ │█│ │█│ │ │ │ │█│█│ │█│█│ │ │ │ │█│ │ │ │█│ │ │ │ │ │ │ │ │ │ │ │ │ +
- ​│█│█│ │█│█│ │ │ │ │█│ │ │ │█│ │ │ │ │ │ │ │ │ │ │ │ │ │█│ │ │ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │ │ │ │ │ │ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ +
- │ │ │ │ │ │ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ +
- ​└─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘ +
- +
-    VDP(23+1)=4 ​      ​VDP(23+1)=5 ​      ​VDP(23+1)=6 ​      ​VDP(23+1)=7 +
- ​┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ ┌─┬─┬─┬─┬─┬─┬─┬─┐ +
- ​│█│ │█│ │█│ │ │ │ │█│█│ │█│█│ │ │ │ │█│ │ │ │█│ │ │ │ │ │ │ │ │ │ │ │ │ +
- ​│█│█│ │█│█│ │ │ │ │█│ │ │ │█│ │ │ │ │ │ │ │ │ │ │ │ │ │█│ │ │ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │ │ │ │ │ │ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ +
- │ │ │ │ │ │ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │█│ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │█│ │ │ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│ │█│ │█│ │ │ │ +
- ​│█│ │ │ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│█│ │█│█│ │ │ │ +
- ​│█│ │█│ │█│ │ │ │ │█│ │█│ │█│ │ │ │ │█│█│ │█│█│ │ │ │ │█│ │ │ │█│ │ │ │ +
- ​└─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘ +
-</​code>​ +
- +
-{{anchor:​e1124-02}} __//​Пример 2//__. \\ {{.examples:​1124-02.bas|}} \\ [[+tab|wmsxbpge>​1124-02.bas]] +
-<​code>​ +
-5 SCREEN 0 +
-10 CLS:​KEYOFF +
-20 FOR I=0 TO 5:PRINT "​▧▨▧▨▧":​NEXT +
-30 FOR J=0 TO 7 +
-40    FOR K=0 TO 10:NEXT K +
-50    VDP(23+1)=J +
-60 NEXT J +
-70 IF INKEY$=""​ THEN 30 +
-80 VDP(23+1)=0:​END +
-</​code>​ +
- +
-В //​графических//​ режимах регистр с номером 23 предоставляет другую интересную возможность. Вначале следует вспомнить,​ что доступная высота графического экрана равна 192 или 212 линиям (в зависимости от девятого регистра VDP). Однако,​ Вы можете,​ воздействуя на VRAM (используя,​ например,​ оператор ''​VPOKE''​),​ сформировать шаблоны 256 линий, просмотрев которые Вы можете,​ использовав регистр с номером 23. Понять,​ как это происходит,​ Вы можете из следующих рисунков:​ +
- +
-<​code>​ +
-VDP(23+1)=0: ​     ┌─────────────────┐ Y=0 +
-                  │  Видимые линии ​ │ +
-                  ├─────────────────┤ Y=192 или 212 +
-                  │ Невидимые линии │ +
-                  └─────────────────┘ Y=255 +
- +
-VDP(23+1)=200: ​   ┌─────────────────┐ Y=0 +
-                  │  Видимые линии ​ │ +
-                  ├─────────────────┤ Y=136 или 156 +
-                  │ Невидимые линии │ +
-                  ├─────────────────┤ Y=200 +
-                  │  Видимые линии ​ │ +
-                  └─────────────────┘ Y=255 +
-</​code>​ +
-</​WRAP>​ +
- +
-==== XI.2.5. Некоторые регистры доступа ==== +
- +
-Имеется возможность изменить палитру некоторого цвета. +
- +
-Для установки данных в //​девятибитные//​ регистры палитры видеопроцессора (с номерами от 0 до 15) следует вначале установить номер регистра палитры в регистре с номером //​шестнадцать//,​ а затем последовательно вывести //два// байта данных (по порядку) через порт &H9A. +
-^Номера бит^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0   ^ +
-|//​Регистр//​ 16|  0  |  0  |  0  |  0  |  //​Номер палитры// ​ |||| +
-|//​Порт//​ &​H9A| ​ 0  |  //​Красный// ​ |||  0  |  //​Синий// ​ ||| +
-|//​Порт//​ &​H9A| ​ 0  |  0  |  0  |  0  |  0  |  //​Зелёный// ​ ||| +
- +
-Для изменения цвета надо набрать последовательно команды (операторы):​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VDP(16+1)=C:​OUT &​H9A,​16*R+B:​OUT &​H9A,​G +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * C — номер цветовой палитры,​ которую Вы хотите изменить;​ +
-  * R, B, G — числа, определяющие соотношение красного,​ синего и зелёного цветов в палитре. +
- +
-{{anchor:​e1125-01}} __//​Пример 1//__. \\ {{.examples:​1125-01.bas|}} \\ [[+tab|wmsxbpge>​1125-01.bas]] +
-<​code>​ +
-COLOR 15,3 +
-Ok +
-VDP(16+1)=3:​OUT &​H9A,​64:​OUT &​H9A,​3 +
-Ok +
-</​code>​ +
-Отметим,​ что для компьютеров [[msx:​msx_1]] этот способ изменения цветов является единственно возможным! +
- +
-{{anchor:​e1125-02}} __//​Пример 2//__. \\ {{.examples:​1125-02.bas|}} \\ [[+tab|wmsxbpge>​1125-02.bas]] +
-<​code>​ +
-10 COLOR 8,15,0:KEY OFF:SCREEN 1 +
-20 FOR R=0 TO 7:FOR G=0 TO 7:FOR B=0 TO 7 +
-30 OUT &​H99,​0:​OUT &H99,16 OR &​H80:​OUT &​H9A,​16*R+B:​OUT &​H9A,​G +
-40 LOCATE 10,​10:?"​R="​R:​LOCATE 10,​11:?"​G="​G:​LOCATE 10,​12:?"​B="​B +
-50 FOR T=1 TO 500:NEXT T:NEXT B,G,R +
-</​code>​ +
-Регистр с номером //​семнадцать//​ хранит информацию о //​косвенном//​ доступе в регистры VDP. +
- +
-Взгляните на его содержимое:​ +
-^  7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-|  ∗  |  0  |  //​Номер регистра// ​ |||||| +
-|  0  |//​запрещено//​||||||| +
-|  1  |//​разрешено//​||||||| +
-| ∗ = автоинкрементирование|||||||| +
- +
-В соответствии со значением 7–го бита регистра 17 содержимое этого регистра может автоматически увеличиваться. Если автoинкрементирование запрещено,​ то содержимое 17–го регистра останется прежним. +
- +
-Приведём два способа //​косвенной записи//​ в видеопроцессор с использованием регистра с номером 17: +
-  - α) <​WRAP>​ +
-<​code>​ +
-10 VDP(17+1)=N OR &​H80'​или OUT &H99,N OR &​H80:​OUT &H99,17 OR &H80 +
-20 OUT &h9B, Число для регистра с номером N +
-30 OUT &h9B, Число для регистра с номером N+1 +
-40 OUT &H9B, Число для регистра с номером N+2 +
-50 ' ··· +
-</​code>​ +
- +
-{{anchor:​e1125-03}} __//​Пример 3//__. \\ {{.examples:​1125-03.bas|}} \\ [[+tab|wmsxbpge>​1125-03.bas]] +
-<​code>​ +
-5 SCREEN 1:COLOR 15,0,8 +
-10 VDP(17+1)=8 OR &H40 '​Установка регистра с номером 17 на косвенный доступ +
-20 OUT &​H9B,​VDP(8+1) OR &​H20 ​ '​Цвет 0 из Таблицы палитр +
-30 OUT &​H9B,​VDP(9+1) OR &​H80 ​ 'На экране - 26.5 строк +
-</​code>​ +
-</​WRAP>​ +
-  - β) <​WRAP>​ +
-<​code>​ +
-10 VDP(17+1)=N ​              '​или OUT &​H99,​N:​OUT &H99,17 OR &H80 +
-20 OUT &H9B, Число для регистра N +
-30 OUT &H9B, Число для регистра N +
-40 OUT &H9B, Число для регистра N +
-50 ' ··· +
-</​code>​ +
- +
-Косвенный доступ к регистрам видеопроцессора применяется тогда, когда необходимо записать информацию в несколько регистров,​ адреса которых идут //​подряд//​. При этом запись через порт с адресом &H9B будет происходить до тех пор, пока не будет сделана новая установка на косвенный доступ. +
-</​WRAP>​ +
- +
-<WRAP centeralign>​Данные в 17–ом регистре не могут быть изменены косвенной адресацией!</​WRAP>​ +
- +
-==== XI.2.6. Доступ к видеопамяти ==== +
- +
-__//​Регистр 14//__ (регистр базового адреса доступа к VRAM). +
- +
-Этот регистр видеопроцессора используется при доступе к видеопамяти. +
-Если Вы располагаете видеопамятью объёмом до 16 Кбайт, то использование этого регистра не имеет смысла,​ так как в нем хранятся //​старшие//​ биты текущего адреса видеопамяти. +
- +
-//​Регистр с номером//​ 14 +
- +
-^Номера бит^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-| |  0  |  0  |  0  |  0  |  0  |  A16  |  A15  |  A14  | +
- +
-В регистре с номером 14 устанавливаются три старших бита адреса ячейки видеопамяти (A16, A15, A14). +
- +
-Сейчас мы расскажем,​ как обратиться к //​любой//​ ячейке видеопамяти. +
- +
-На компьютерах серии [[msx:​msx_2]] существует 2 типа видеопамяти:​ VRAM и ERAM. +
-VRAM ("​Video RAM") имеет объем в 128 Кб, а ERAM ("​Expanded RAM") — 64 Кб. +
-Информация о том, какая видеопамять используется в настоящий момент,​ хранится в регистре с номером 45. +
- +
-Доступ к видеопамяти осуществляется в следующей последовательности:​ +
- +
-  - выберите //тип// видеопамяти:​ <​code>​ +
-VDP(45+1)=&​B0∗∗∗∗∗∗∗ +
-             ​▲└──▲─┘ +
-             ​│ ​  ​└── эти биты используются для других целей +
-             ​├────── 1 — если используется ERAM +
-             ​└────── 0 — если используется VRAM +
-</​code>​ Отметим,​ что содержимое регистра с номером 45 не меняется при очередном обращении к памяти. +
-  - установите биты A14÷A16 адреса видеопамяти:​ <​code>​ +
-VDP(14+1)=&​B00000∗∗∗ +
-                 ​▲▲▲ +
-          A16 ───┘│└─── A14 +
-                  └──── A15 +
-</​code>​ +
-  - установите биты A0÷A7 счётчика адреса посредством вывода данных в порт &​H99:<​code>​ +
-OUT &​H99,&​B∗∗∗∗∗∗∗∗ +
-           ​▲▲▲▲▲▲▲▲ +
-           ​│││││││└──── A0 +
-           ​││││││└───── A1 +
-           ​│││││└────── A2 +
-           ​││││└─────── A3 +
-           ​│││└──────── A4 +
-           ​││└───────── A5 +
-           ​│└────────── A6 +
-           ​└─────────── A7 +
-</​code>​ +
-  - установите биты A8÷A13 счётчика адреса и признак чтения или записи посредством вывода данных в порт &H99: <​code>​ +
-OUT &​H99,&​B∗∗∗∗∗∗∗∗ +
-           ​▲▲▲▲▲▲▲▲ +
-           ​│││││││└──── A8 +
-           ​││││││└───── A9 +
-           ​│││││└────── A10 +
-           ​││││└─────── A11 +
-           ​│││└──────── A12 +
-           ​││└───────── A13 +
-           ​└┼────────── 00 — признак чтения +
-            └────────── 01 — признак записи +
-</​code>​ +
-  - А теперь остаётся прочитать или записать данные в нужный байт: <​code>​ +
-A=INP(&​H98) — чтение +
-OUT &​H98,​A ​ — запись +
-</​code>​ +
-  - После чтения или записи данных содержимое адресного счётчика автоматически увеличивается на единицу. При этом, если есть перенос из бита A13, то в режимах ''​SCREEN''​ 4÷8 происходит увеличение содержимого регистра с номером 14. В режимах ''​SCREEN''​ 1÷3 и в 40–символьном режиме ''​SCREEN 0''​ увеличения содержимого 14–го регистра не происходит. +
- +
-Из сказанного следует,​ что если нужно записать информацию в несколько подряд расположенных ячеек видеопамяти,​ достаточно установить лишь начальный адрес этой группы ячеек. +
- +
-==== XI.2.7. Регистры статуса ==== +
- +
-Кроме регистров VDP, видеопроцессор работает с группой регистров,​ называемыми регистрами //​статуса//​. Данные регистры содержат информацию о состоянии видеопроцессора. Из них информацию можно только //​читать//​. +
- +
-Текущий номер регистра статуса записывается в регистр VDP с номером //​пятнадцать//​ (регистр–указатель регистра состояния). +
- +
-^Номера бит^ ​ 7  ^  6  ^  5  ^  4  ^  3  ^  2  ^  1  ^  0  ^ +
-| |  0  |  0  |  0  |  0  |  Номер регистра статуса ​ |||| +
- +
-Для доступа к регистрам //​состояния//​ видеопроцессора (с номерами 0,​1,​2,​3,​…,​9) вначале нужно установить номер регистра статуса в регистре с номером 15, а затем прочесть данные через порт &H99. +
- +
-Для записи в переменную W числа из регистра статуса с номером S, выполните следующие действия:​ +
-<​code>​ +
-VDP(15+1)=S:​W=INP(&​H99):​VDP(15+1)=0 +
-</​code>​ +
- +
-__//​Регистр статуса номер 0//__. +
- +
-<​code>​ +
-    7      6      5      4      3      2      1      0 +
-┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┐ +
-│      │      │      │   ​∗ ​ │   ​∗ ​ │   ​∗ ​ │   ​∗ ​ │   ​∗ ​ │ +
-└───▲──┴───▲──┴──▲───┴──────┴──────┴──────┴──────┴──────┘ +
-    │      │     ​│ ​   └───▲──────────────────────────────┘ +
-    │      │     ​│ ​       └ Экранный номер пятого или девятого +
-    │      │     ​│ ​         (в зависимости от режима SCREEN) спрайта в строке +
-    │      │     ​└─── Флаг, указывающий на столкновение 2–х спрайтов +
-    │      │ +
-    │      └───────── Флаг обнаружения пятого (или девятого) спрайта в строке +
-    │                  +
-    └──────────────── Флаг прерывания от вертикального сканирования +
-                      (после чтения регистра состояния 0 данный флаг сбрасывается) +
-</​code>​ +
- +
-Если бит СС=0 и высвечиваемые части шаблонов спрайтов перекрываются,​ то устанавливается столкновение спрайтов. Если столкновение спрайтов обнаружено,​ то бит 5 регистра статуса с номером 0 устанавливается в 1. +
- +
-Этот бит устанавливается в 0 после чтения регистра статуса с номером 0. +
- +
-Использование регистра статуса с номером 0 рассмотрим на примерах. +
- +
-{{anchor:​e1127-01}} __//​Пример 1//__. \\ {{.examples:​1127-01.bas|}} \\ [[+tab|wmsxbpge>​1127-01.bas]] +
-<​code>​ +
-10 SCREEN 1,2 +
-20 SPRITE$(2)="​Проверка":​SPRITE$(3)="​на столкновение"​ +
-30 FOR T=1 TO 130 +
-40 PUT SPRITE 2,​(T,​80):​PUT SPRITE 3,​(240-T,​80) +
-50 VDP(15+1)=0:​Z=INP(&​H99) AND 32 +
-60 IF Z<>0 THEN PRINT "​Столкновение состоялось!"​ +
-70 NEXT +
-</​code>​ +
- +
-{{anchor:​e1127-02}} __//​Пример 2//__. \\ {{.examples:​1127-02.bas|}} \\ [[+tab|wmsxbpge>​1127-02.bas]] +
-<​code>​ +
-10 SCREEN 1:KEYOFF +
-20 FOR I=0 TO 7:READ E:VPOKE &​H3800+I,​E:​NEXT +
-30 A0=BASE(1*5+3):​AD=A0+4*1:​AP=A0+4*2 +
-40 VPOKE AP,50:VPOKE AP+1,​100:​VPOKE AP+2,​0:​VPOKE AP+3,15 +
-50 FOR X=0 TO 255 +
-60 VPOKE AD,50:VPOKE AD+1,​X:​VPOKE AD+2,​0:​VPOKE AD+3,15 +
-70 VDP(15+1)=0:​Z=INP(&​H99) AND 32 +
-80 IF Z<>0 THEN LOCATE 1,​1:​PRINT"​столкновение":​FOR L=0 TO 100:​NEXT:​LOCATE1,​1:​PRINT" ​              "​ +
-90 NEXT +
-100 GOTO 50 +
-110 DATA 255,​255,​195,​195,​195,​195,​255,​255 +
-</​code>​ +
- +
-{{anchor:​e1127-03}} __//​Пример 3//__. \\ {{.examples:​1127-03.bas|}} \\ [[+tab|wmsxbpge>​1127-03.bas]] +
-<​code>​ +
-10 SCREEN1,2 +
-20 SPRITE$(1)="​Проверка":​SPRITE$(2)="​появления":​SPRITE$(3)="​пятого":​SPRITE$(4)="​спрайта":​SPRITE$(5)="​в строке"​ +
-30 PUT SPRITE0,​(10,​80),,​5:​PUT SPRITE1,​(20,​80),,​4:​PUT SPRITE2,​(30,​80),,​3:​PUT SPRITE3,​(40,​80),,​2 +
-40 VDP(15+1)=0:​Z=INP(&​H99) +
-50 PRINT RIGHT$("​00000000"​+BIN$(Z),​8) +
-55 A$=INPUT$(1) +
-60 PUT SPRITE4,​(50,​80),,​1 +
-70 VDP(15+1)=0:​Z=INP(&​H99) +
-80 ? RIGHT$("​00000000"​+BIN$(Z),​8);"​◀─ Появился 5-ый спрайт в строке!"​ +
-</​code>​ +
- +
-Отметим,​ что содержимое регистра статуса с номером 0 можно прочесть не только функцией ''​INP'',​ но и при помощи псевдопеременной ''​VDP'':​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-A = VDP(8) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-{{anchor:​e1127-04}} __//​Пример 4//__. Управление столкновениями спрайтов. \\ {{.examples:​1127-04.bas|}} \\ [[+tab|wmsxbpge>​1127-04.bas]] +
-<​code>​ +
-20 SCREEN 2,2 +
-30 SPRITE$(0)=STRING$(32,​255) +
-40 PUT SPRITE 0,​(112,​80),​1,​0 +
-50 PUT SPRITE 1,​(10,​80),​8,​0 +
-60 IF (VDP(8)AND32)=32 THEN GOTO 90 +
-70 PUT SPRITE 1,​STEP(1,​0),​8,​0 +
-80 GOTO 60 +
-90 BEEP:GOTO 90 +
-</​code>​ +
- +
-//​Замечание//​. Назначения бит регистров статуса с номерами 1, 2, 3, 4, 5, 6, 7, 8, 9 рассмотрены в Приложении 2 ((Пока не найдено,​ подробнее [[start#​Список отсутствующего материала|здесь]])). Там же рассмотрены назначения бит командных регистров с номерами 32,33,… ,45,46. +
- +
-===== XI.3. Нестандартные режимы видеопроцессора ===== +
- +
-<WRAP group 99%> +
-<WRAP half column> \\ </​WRAP>​ +
-<WRAP half column><​WRAP justify>​ +
-Боги открыли людям не все.\\ +
-В поиск пустившись,​ люди сами открыли немало. +
-<WRAP rightalign>​ +
-—//​Ксенофан//​ +
-</​WRAP></​WRAP>​ +
-</​WRAP></​WRAP>​ +
- +
-==== XI.3.1. Режим SCREEN 4 на компьютерах MSX 1 ==== +
- +
-Для Вас, наверное,​ окажется неожиданностью,​ что на компьютерах [[msx:​msx_1]] можно использовать режимы ''​SCREEN 4''​ ÷ ''​SCREEN 8''​. Доступ к этим режимам осуществляется путём непосредственной записи в регистры видеопроцессора. +
- +
-Режим ''​SCREEN 4''​ вызывается из режима ''​SCREEN 2''​ путём обращения к видеопроцессору:​ +
-  VDP(0)=4 ​   . +
-При этом изображение,​ нарисованное в режиме ''​SCREEN 2'',​ останется на экране. Этот режим выгодно отличается возможностями работы со спрайтами. +
- +
-Приведём начальные адреса Таблиц VRAM, отвечающих за спрайты,​ в этом режиме:​ +
-^  //Имя// Таблицы ​ ^  Начальный адрес Таблицы ​ ^ +
-|  SGT  |  &​H3800 ​ | +
-|  SAT  |  &​H1A00 ​ | +
-|  SCT  |  &​H1800 ​ | +
- +
-Чтобы вернуться в режим ''​SCREEN 2'',​ достаточно снова обратиться к видеопроцессору:​ +
-   ​VDP(0)=2 ​    . +
-Учтите,​ что режим ''​SCREEN 4''​ на компьютерах серии [[msx:​msx_1]] имеет некоторые //​особенности//:​ +
-  - происходит частичное "​наложение"​ Таблиц SAT и SCT на Таблицу PNT, что приводит к искажению неподвижного изображения. Поэтому необходимо "​спасти"​ Таблицу PNT, т.е. передвинуть её на свободное место в видеопамяти;​ +
-  - при переходе в этот режим возникает несоответствие между начальным адресом Таблицы SAT, возвращаемым псевдопеременной ''​BASE(13)'',​и тем же адресом,​хранящимся в рабочей области RAM. Поместите поэтому в рабочую область RAM по адресам &HF928 и &HF929 число, записанное в псевдопеременной ''​BASE(13)'';​ +
-  - образы спрайтов выводятся на экран уже на стадии формирования спрайтовых переменных.Единственный способ избавиться от этого — временно отключить изображение (без очистки экрана) и включить его непосредственно перед обращением к Таблице атрибутов спрайтов (SAT). +
- +
-А теперь взгляните на +
- +
-{{anchor:​e1131-01}} __//​Пример 1//__. Вы, конечно,​ помните,​ что текущий адрес Таблицы PNT хранится в рабочей области по адресам &HF922 и &HF923. \\ {{.examples:​1131-01.bas|}} \\ [[+tab|wmsxbpge>​1131-01.bas]] +
-<​code>​ +
-10 SCREEN 2,2 +
-20 '​Инициализация режима SCREEN 4 +
-50 VDP(2)=7:​POKE &​HF923,&​H1C '​Передвинем Таблицу PNT +
-60 VDP(5)=52:​POKE &​HF929,&​H1A '​Приведем в порядок SAT +
-65 VDP(0)=4 '​Установим режим SCREEN 4 +
-70 '​Основная программа +
-75 VDP(1)=VDP(1) XOR 64 '​Отключим изображение +
-80 CIRCLE(100,​100),​50,​15 +
-90 FOR X=0 TO 8 +
-100 SPRITE$(X)=STRING$(32,​255):​NEXT '​Сформируем спрайты +
-110 FOR Y=0 TO 15:​V=INT(RND(1)*16) +
-120    FOR X=0 TO 8 +
-130    VPOKE &​H1800+X*16+Y,​V '​Раскрасим спрайты,​ используя Таблицу SCT +
-140 NEXT X,Y +
-150 VDP(1)=VDP(1) XOR64 '​Включим изображение +
-160 PUT SPRITE 8,​(70,​30),,​0 +
-170 X=128:​Y=96 +
-180 A=STICK(0) +
-190 IF A=1 OR A=2 OR A=8 THEN Y=Y-2 +
-200 IF A=2 OR A=3 OR A=4 THEN X=X+2 +
-210 IF A=4 OR A=5 OR A=6 THEN Y=Y+2 +
-220 IF A=6 OR A=7 OR A=8 THEN X=X-2 +
-230 FOR Z=0 TO 7 +
-240    PUT SPRITE Z,​(X-Z*17,​Y),,​0 ​ 'В о с е м ь  спрайтов в строке! +
-250 NEXT Z +
-260 GOTO 180 +
-</​code>​ +
-Вас, конечно,​ не удивляет тот факт, что на экране — //​восемь//​ спрайтов в //​строке//,​ так как Вам, наверное,​ известно,​ что режимы ''​SCREEN 4''​ ÷ ''​SCREEN 8''​ предоставляют такую возможность! +
- +
-==== XI.3.2. Текстово–графические режимы ==== +
- +
-Мы опишем здесь два текстово–графических режима:​ +
-  * режим ''​SCREEN''​ 1–2 ("​совмещённый"​ режим ''​SCREEN 1''​ и ''​SCREEN 2''​);​ +
-  * режим ''​SCREEN''​ 1–4 ("​совмещённый"​ режим ''​SCREEN 1''​ и ''​SCREEN 4''​). +
- +
-"​Совмещенный"​ режим ''​SCREEN''​ 1–2 устанавливается операторами:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-SCREEN 1:​DEFUSR=&​H7E:​A=USR(0) +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-{{anchor:​e1132-00}}Однако прежде чем начать "​работать"​ в этом режиме,​ его надо инициализировать следующим образом:​ +
-\\ {{.examples:​1132-00.bas|}} \\ [[+tab|wmsxbpge>​1132-00.bas]] +
-<​code>​ +
-10 SCREEN1:​WIDTH 32 +
-20 DEFUSR=&​H7E:​A=USR(0) '​Установили совмещенный режим +
-30 '​Считываем шаблоны символов из ROM в Таблицу PGT +
-40 FOR T=0 TO 2 +
-50    FOR K=0 TO 2047 +
-60       VPOKE BASE(7)+2048*T+K,​PEEK(&​H1BBF+K) +
-70 NEXT K,T +
-80 '​Инициализируем цвета символов в Таблице CT +
-90 FOR I=0 TO 6143:VPOKE BASE(6)+I,&​HF4:​NEXT I +
-100 '​Установим форму курсора во 2-м и 3-м окне экрана +
-110 FOR Y=1 TO 2:FOR X=0 TO 7:VPOKE &​H800*Y+255*8+X,​255:​NEXT X,Y +
-120 NEW +
-</​code>​ +
- +
-Не беда, что для инициализации требуется более двух минут. При соответствующей подготовке Вы сможете написать программу в машинных кодах, которая будет работать в несколько десятков раз быстрее:​ +
- +
-{{anchor:​e1132-01}} __//​Пример 1//__. Смотрите и завидуйте! \\ {{.examples:​1132-01.bas|}} \\ [[+tab|wmsxbpge>​1132-01.bas]] +
-<​code>​ +
-100 CLEAR 100,&​HD000 +
-110 SCREEN 1:WIDTH 32:​DEFUSR=&​H7E:​A=USR(0) +
-120 A$="​21000011BF1B1ACD1CD03EF0CBECCD1CD0CBAC13237CD608C206D0C947CD4D00CBDC78CD4D00CB9CCBE478CD4D00CBA4C9"​ +
-130 FOR X=0 TO 48:POKE &​HD000+X,​VAL("&​h"​+MID$(A$,​X*2+1,​2)):​NEXT +
-140 DEFUSR=&​HD000:​A=USR(0) +
-150 FOR Y=1 TO 2:FOR X=0 TO 7:VPOKE &​H800*Y+255*8+X,​255:​NEXT X,Y +
-</​code>​ +
- +
-Поговорим об //​особенностях//​ режима ''​SCREEN''​ 1–2 : +
- +
-  - <​WRAP>​ Данный режим позволяет формировать многоцветные символы,​ причём информация о цветах каждого из них хранится в //​восьми//​ байтах Таблицы CT: +
-<​code>​ +
-           ​1–й байт ​          ​… ​             8–й байт +
-┌─────────────┬─────────────┬─────┬─────────────┬─────────────┐ +
-│  Код цвета ​    ​Код цвета ​ │     ​│ ​ Код цвета ​    ​Код цвета ​ │ +
-│ изображения │     ​фона ​   │     │ изображения │     ​фона ​   │ +
-│ для ​ первой ​  ​для ​ первой │  …  │ для восьмой ​  ​для восьмой │ +
-│   ​строки ​   │   ​строки ​   │     ​│ ​  ​строки ​   │    строки ​  │ +
-│   ​символа ​      ​символа ​  ​│ ​    ​│ ​  ​символа ​       символа ​ │ +
-└─────────────┴─────────────┴─────┴─────────────┴─────────────┘ +
-</​code>​ +
-Проведём аналогию с режимом ''​SCREEN 1'':​ +
-<​code>​ +
-          1–й байт CT +
-┌─────────────┬─────────────┐ +
-│  Код цвета ​    ​Код цвета ​ │ +
-│ изображения │     ​фона ​   │ +
-│ для первых ​   для ​ первых │ +
-│   ​восьми ​   │    восьми ​  │ +
-│  символов ​      ​символов ​ │ +
-└─────────────┴─────────────┘ +
-</​code>​ +
-</​WRAP>​ +
-  - <​WRAP>​ Режим ''​SCREEN''​ 1–2 имеет трёхоконную структуру(как и режим ''​SCREEN 2''​):​ +
- +
-Внимательно изучите следующую табличку:​ +
- +
-^  Адрес ​ ^  //​Комментарий// ​ ^ +
-|  &​H0000 ​ |Таблица шаблонов образов,​ расположенных в верхней части экрана,​ т.е. с 0–й по 7–ю строку. На каждый символ отводится 8 байтов| +
-|  &​H0800 ​ |Таблица шаблонов символов,​ расположенных в средней части экрана,​ т.е. с 8–й по 15–ю строку| +
-|  &​H1000 ​ |Таблица шаблонов символов,​ расположенных в нижней части экрана,​ т.е. с 16–й по 23–ю строку| +
-|  &​H1800 ​ |Таблица имён образов (строки 0÷7)| +
-|  &​H1900 ​ |Таблица имён образов (строки 8÷15)| +
-|  &​H1A00 ​ |Таблица имён образов (строки 16÷23)| +
-|  &​H1B00 ​ |Таблица атрибутов спрайтов| +
-|  &​H2000 ​ |Таблица цветов символов,​ расположенных с 0–ой по 7–ю строку.\\ На каждый символ отводится 8 байтов. На каждую строку символа отводится 1 байт, старший полубайт которого отвечает за цвет установленных бит в Таблице шаблонов символов| +
-|  &​H2800 ​ |Таблица цветов символов,​ расположенных с 8–ой по 15–ю строку| +
-|  &​H3000 ​ |Таблица цветов символов,​ расположенных с 16–ой по 23–ю строку| +
-|  &​H3800 ​ |Таблица шаблонов спрайтов| +
-</​WRAP>​ +
-  - В режиме ''​SCREEN''​ 1–2 разрешено использование как текстовых,​так и графических операторов,​ т.о. "​совмещённый"​ режим ''​SCREEN''​ 1–2 может находиться в двух "​состояниях"​. +
- +
-//​Во–первых//,​ это — //​текстовый//​ режим.В нем "​работают"​ все операторы текстового экрана. Однако,​ он отличается от текстового режима ''​SCREEN 1''​ в следующих моментах:​ +
-  - весь экран разбит на //три// горизонтальных окна; +
-  - символ,​ вообще говоря,​ раскрашен //​одновременно//​ в 16 цветов (по два цвета на линию);​ +
-  - один и тот же символ (определяемый кодом АSCII), может быть различным по начертанию и цвету в трёх различных окнах экрана. +
- +
-Для изменения цвета какой–либо строки любого символа в любой трети экрана,​ примените оператор:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VPOKE BASE(5+1)+2048*N+8*K+S,&​HIF +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * N — номер окна экрана;​ +
-  * K — код ASCII символа;​ +
-  * S — номер строки символа;​ +
-  * I — цвет изображения;​ +
-  * F — цвет фона. +
- +
-Для изменения шаблона одной строки символа используйте оператор +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-VPOKE BASE(5+2)+2048*N+8*K+S,&​B∗∗∗∗∗∗∗∗ +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где: +
-  * N — номер окна экрана;​ +
-  * K — код ASCII символа;​ +
-  * S — номер строки символа;​ +
-  * ∗∗∗∗∗∗∗∗ — двоичное представление шаблона строки символа. +
- +
-Приведём несколько примеров:​ +
- +
-{{anchor:​e1132-02}} __//​Пример 2//__. Полюбуйтесь на //​цветной//​ курсор! \\ {{.examples:​1132-02.bas|}} \\ [[+tab|wmsxbpge>​1132-02.bas]] +
-<​code>​ +
-10 FOR X=0 TO 2 +
-20    A=&​H2000+&​H800*X+255*8 +
-30    FOR Y=0 TO 7 +
-40       VPOKE A+Y,Y*16 +
-50    NEXT Y +
-60 NEXT X +
-</​code>​ +
- +
-{{anchor:​e1132-03}} __//​Пример 3//__. А вот "​переливание"​ латинских букв "​А"​ в верхней трети экрана! \\ {{.examples:​1132-03.bas|}} \\ [[+tab|wmsxbpge>​1132-03.bas]] +
-<​code>​ +
-10 FOR A=0 TO 8 +
-20    FOR X=0 TO 7 +
-30       VPOKE &​H2000+65*8+X,​(X+A)*16 +
-40    NEXT X +
-50 NEXT A +
-60 GOTO 10 +
-</​code>​ +
-Чтобы прекратить процесс "​переливания",​ нажмите клавиши <​key>​CTRL+STOP</​key>​. +
- +
-{{anchor:​e1132-04}} __//​Пример 4//__. Вместо буквы "​W"​ в верхнем углу экрана Вы уведите… "​яблоко"​! \\ {{.examples:​1132-04.bas|}} \\ [[+tab|wmsxbpge>​1132-04.bas]] +
-<​code>​ +
-10 OUT&​H99,​6:​OUT&​H99,​144:​OUT&​H98,​16*4:​OUT&​H98,​2 '​Изменим 6-й цвет +
-20 A$="​3C7E307830787E3C8484B8B8B8866414"​ +
-30 FOR X=0 TO 7 +
-40  VPOKE 87*8+X,​VAL("&​H"​+MID$(A$,​X*2+1,​2)) +
-50  VPOKE &​H2000+87*8+X,​VAL("&​H"​+MID$(A$,​2*X+17,​2)) +
-60 NEXT X +
-</​code>​ +
- +
-{{anchor:​e1132-05}} __//​Пример 5//__. //"​Толстые"//​ символы — только в верхней трети экрана! \\ {{.examples:​1132-05.bas|}} \\ [[+tab|wmsxbpge>​1132-05.bas]] +
-<​code>​ +
-10 FOR X=&HFF TO &H7F7 +
-20    A=VPEEK(X):​VPOKE X,A OR A/2 +
-30 NEXT X +
-</​code>​ +
- +
-{{anchor:​e1132-06}} __//​Пример 6//__. Теперь повращаем "​трубу"​ вокруг своей оси! \\ {{.examples:​1132-06.bas|}} \\ [[+tab|wmsxbpge>​1132-06.bas]] +
-<​code>​ +
-10 FOR I=0 TO 7:VPOKE 8*43+I,​255:​NEXT +
-20 CLS:​PRINT"​++++++++++++++++++++++++++++++"​ +
-30 FOR F=7 TO 0 STEP -1 +
-40    VPOKE &​H2000+&​H800*0+8*43+F,&​H71 +
-50    IF F=7 THEN W=0 ELSE W=F+1 +
-60    VPOKE &​H2000+&​H800*0+8*43+W,&​H51 +
-70    IF W=7 THEN WC=0 ELSE WC=W+1 +
-80    VPOKE &​H2000+&​H800*0+8*43+WC,&​H41 +
-90    IF WC=7 THEN JC=0 ELSE JC=WC+1 +
-100   VPOKE &​H2000+&​H800*0+8*43+JC,&​H51 +
-110   IF JC=7 THEN JJ=0 ELSE JJ=JC+1 +
-120   VPOKE &​H2000+&​H800*0+8*43+JJ,&​H71 +
-130   IF JJ=7 THEN YJ=0 ELSE YJ=JJ+1 +
-140   VPOKE &​H2000+&​H800*0+8*43+YJ,&​HF1 +
-150 NEXT:GOTO 30 +
-</​code>​ +
- +
-//​Во–вторых//,​ режим ''​SCREEN''​ 1–2 — это графический режим, в котором можно одновременно и рисовать,​ и выводить текст. Для этого предварительно решите,​ в какой части экрана (одной или нескольких) Вы будете рисовать,​ а +
-в какой — писать. +
- +
-Для того, чтобы рисовать в какой–либо части экрана,​ её надо предварительно подготовить следующим образом:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-FOR T=0 TO 255 :VPOKE BASE(5)+256*N+T,​T ​     :NEXT +
-FOR T=0 TO 2047:VPOKE BASE(5+1)+2048*N+T,&​HF4:​NEXT +
-FOR T=0 TO 2047:VPOKE BASE(5+2)+2048*N+T,​0 ​  :​NEXT +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
-где N — номер части экрана,​ в которой Вы хотите применить графические операторы. +
- +
-Таким образом,​ Вы инициализируете участки Таблиц PNT, CT и PGT, отвечающие за изображение в нужном окне экрана. +
- +
-Теперь в приготовленной части экрана можно применять графические операторы. Однако,​ их можно применять только после выполнения оператора:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-POKE &​HFCAF,​2 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Для выхода в //​текстовый//​ режим "​пригодится"​ оператор:​ +
-<WRAP group> +
-<WRAP half column>​ +
-<​code>​ +
-POKE &​HFCAF,​1 +
-</​code>​ +
-</​WRAP>​ +
-<WRAP half column>​ +
-+
-</​WRAP>​ +
-</​WRAP>​ +
- +
-Если Вы его не выполните,​ то произойдёт переход в режим ''​SCREEN 1''​ ! +
- +
-Нужно постоянно помнить о том, что Ваши рисунки могут "​портиться",​ так как любой символ,​ напечатанный в графической части экрана,​ портит рисунок. +
-Однако,​ рисунок можно восстановить,​ применив операторы:​ +
-<​code>​ +
-FOR T=0 TO 255:VPOKE BASE(5)+256*N+T,​T:​NEXT +
-</​code>​ +
- +
-{{anchor:​e1132-07}} __//​Пример 7//__. В верхней части экрана — //​графический//​ режим! \\ {{.examples:​1132-07.bas|}} \\ [[+tab|wmsxbpge>​1132-07.bas]] +
-<​code>​ +
-10 CLS +
-20 FOR X=0 TO 255:VPOKE &​H1800+X,​X:​NEXT +
-30 FOR X=0 TO &​H7FF:​VPOKE X,0:NEXT +
-40 LOCATE 5,​10:​PRINT"​Вверху графика!"​ +
-50 POKE &​HFCAF,​2 +
-60 LINE (20,​10)-(100,​40),​15,​BF +
-70 CIRCLE (80,​30),​40,​8 +
-80 POKE &​HFCAF,​1 +
-</​code>​ +
- +
-Рассмотрим теперь "​совмещённый"​ режим ''​SCREEN''​ 1–4. +
-Единственное отличие режима ''​SCREEN''​ 1–4 от режима ''​SCREEN''​ 1–2 состоит в том, что в нем разрешена работа с //​многоцветными//​ спрайтами (как и в режиме ''​SCREEN 4''​). +
- +
-{{anchor:​e1132-08}} Инициализируется режим ''​SCREEN''​ 1–4 следующим образом:​ \\ {{.examples:​1132-08.bas|}} \\ [[+tab|wmsxbpge>​1132-08.bas]] +
-<​code>​ +
-10 SCREEN 1:WIDTH 32 +
-15 '​Установим режим SCREEN 1-2 +
-20 DEFUSR=&​H7E:​A=USR(0) +
-30 '​Считываем шаблоны символов из ROM в Таблицу PGT +
-40 FOR T=0 TO 2 +
-50    FOR K=0 TO 2047 +
-60       VPOKE BASE(7)+2048*T+K,​PEEK(&​H1BBF+K) +
-70 NEXT K,T +
-80 '​Инициализируем цвета символов в Таблице CT +
-90 FOR I=0 TO 6143:VPOKE BASE(6)+I,&​HF4:​NEXT I +
-100 '​Установим форму курсора во 2-м и 3-м окнах экрана +
-110 FOR Y=1 TO 2:FOR X=0 TO 7:VPOKE &​H800*Y+255*8+X,​255:​NEXT X,Y +
-115 '​Теперь установим режим SCREEN 1-4 +
-120 VDP(2)= 7:POKE &​HF923,&​H1C '​Передвинем Таблицу PNT +
-140 VDP(5)=52:​POKE &​HF929,&​H1A '​Приведем в порядок SAT +
-150 VDP(0)=4:​CLS:​NEW +
-</​code>​ +
- +
-Все сказанное о режиме ''​SCREEN''​ 1–2, распространяется и на режим ''​SCREEN''​ 1–4. Остаётся только добавить,​ что структура видеопамяти в "​совмещённом"​ режиме ''​SCREEN''​ 1–4 полностью совпадает со структурой VRAM в режиме ''​SCREEN 4''​ для компьютеров серии [[msx:​msx_1]]. +
- +
-====== Диск с примерами ====== +
- +
-{{.examples:​examples11.dsk|Загрузить образ диска}} +
- +
-[[+tab|wmsxbpged>​examples11.dsk|Открыть диск в WebMSX]] +
- +
- +
----- +
- +
-[<>​] +
- +
- +
-{{tag>​MSX BASIC Book_msxbpg}}+
msx/basic_programming_guide/11.1584819951.txt.gz · Последние изменения: 2020-03-21 22:45 (внешнее изменение)