![]() |
|
:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №4 (17.03.2001) Просмотров: 4788
Автор: Joker. Рубрика: Читатель читателю. Номер: №4 (17.03.2001). Быстрая процедура печатиЗдравствуйте, уважаемые читатели. Вот и я написал СВОЙ абзац. Не знаю как вы, а я вот соскучился по статьям посвящённым не глубоким абстрактным размышлениям (хотя они нужны и полезны), а самым простым вещам - coding’у, графике, музыке, железу, demo и gamemaking’у и всему прочему, что для меня, например, и составляет предмет творчества на Speccy. Посему статья эта будет посвящена одной из таких вещей -программированию.Хочу предложить вам несколько идей по поводу печати строк шестипиксельным font’ом. Я знаю, что вам такая печать жизненно необходима, хотя бы потому что сейчас каждый уважающий себя синклерист выпускает свой компьютерный журнал, газету, боевой листок и так далее (я и сам выпускаю, чего уж там... :-)). Кроме того, я надеюсь, что данная публикация подтолкнет других к написанию статей в «Абзац» на тему coding’а и т.п. (смотрим выше (даешь, понимаешь, гасилку как...). Итак, быстрая печать. Сразу скажу, что речь далее будет вестись не об универсальных процедурах, а о печати именно строк (не отдельных символов), оптимизированной по скорости (в ущерб, кстати, памяти). Для ускорения вывода создадим к основному шрифту ещё 3, символы в которых будут располагаться, соответственно, со смещением в 2, 4 и 6 пикселей от левого края. Чтобы при печати строки не тратить время на вычисление адреса нужного символа, лучше создавать font’ы таким образом, чтобы изображение первого символа лежало в байтах с адресами: font, font+#100, font+#200, ... , font+#700, изображение 2-го в байтах с адресами: font+#001, font+#101, font+#201, ... , font+#701, где font - адрес шрифта в памяти, кратный 256. Таким образом для вычисления адреса символа нужно будет занести в старший регистр старший байт адреса фонта, а в младший поместить код символа. Для пояснения всего вышесказанного приведу пример подпрограммы, формирующей соответствующие шрифты: INS_FON LD DE,SH60 ; формируем шрифт
CALL INSF_1 ; со смещением 0
LD A,#0F,(IFF_1),A
LD (IFF_1+1),A
LD DE,SH63 ; -- / --
CALL INSF_1 ; со смещением 2
LD DE,SH61 ; -- / --
CALL INSF_2 ; со смещением 6
LD A,0,(IFF_2),A
LD DE,SH62 ; -- / --
CALL INSF_2 ; со смещением 4
RET
INSF_2 LD IX,font
LD E,#20 ; код 1го символа (пробел)
LD C,224 ; считаем, что всего в
; шрифте 224 символа
SF2_1 PUSH DE
LD B,4
SF2_3 CALL SF2_2
LD A,L,(DE),A:INC D; зачем сделано
LD A,H,(DE),A:INC D; именно так
CALL SF2_2 ; можно прочи-
LD A,H,(DE),A:INC D; тать ниже
LD A,L,(DE),A:INC D;
DJNZ SF2_3
SF2_3B POP DE
INC E,IX
DEC C:JR NZ,SF2_1
RET
SF2_2 LD H,(IX+0),L,0:INC IX
.2 AND A:RL H,L
IFF_2 RET
.2 AND A:RL H,L
RET
INSF_1 LD HL,font
LD E,#20,C,224
SF1_1 PUSH DE
LD B,8
SF1_2 LD A,(HL):INC HL
IFF_1 NOP:NOP
LD (DE),A:INC D
DJNZ SF1_2
POP DE
INC E,HL
DEC C:JR NZ,SF1_1
RETЗдесь font - адрес исходного обычного шрифта; SH60, SH61, SH62, SH63 - адреса формируемых шрифтов, должны быть кратны 256. В INSF_2 формируются шрифты по размеру в два раза больше, чем в INSF_1 из-за того, что при смещении изображения символа на 4 и 6 пикселей вправо оно выходит за границы одного байта. Причём, в INSF_2 шрифт формируется таким образом, что 2-я, 4-я, 6-я и 8-я линии изображения каждого символа хранятся в обратном порядке, т.е. сначала идёт правый байт, потом левый (чтобы понять, что я тут хотел сказать лучше посмотреть на саму эту процедуру и всё сразу станет ясно). В таком виде будет удобней выводить строку символов. Теперь непосредственно о самой печати. Основная идея: при печати шестипиксельным шрифтом рассматриваются четвёрки символов, которые очень хорошо вписываются по ширине в три байта. Поэтому нужно выводить символы не отдельно друг от друга, а одновременно печатать на экран сразу всю четвёрку. В этом случае исчезает много ненужных команд, типа LD A,(DE), LD (DE),A, которые нужны при последовательном выводе (так, например, для вывода 2-го символа четвёрки нужно взять с экрана изображение уже напечатанного 1-го, совместить его со 2-м, положить обратно на экран. То же самое с 3-м и 4-м). Для вывода одновременно всей четвёрки нам нужно иметь следующие адреса: адрес текста - допустим он в DE'; Сделаем набросок процедуры вывода всей строки: LIN_1 LD B,SH60[ ; заносим старшие
LD H,SH61[ ; байты адресов в
EXX
LD H,SH62[ ; соответствующие
LD B,SH63[ ; регистры
LD A,(DE):INC DE ; код 1го символа
; четвёрки
...
; здесь следовало бы поставить проверку
; на различные управляющие коды,
; как то: конец строки, цвет и т.д.
; Думаю это каждый сможет сделать сам
EXX:LD C,A:EXX ; в BC уже есть
; адрес
LD A,(DE):INC DE ; 2-ой символ
...
EXX:LD L,A:EXX ; 2-ой адрес
LD A,(DE):INC DE ; 3-й
...
LD L,A ; и так далее
LD A,(DE):INC DE
...
LD C,A
EXX
; теперь непосредственно сам вывод
LD A,(BC):INC B ; выводим 1-ю
OR (HL):INC H ; (3-ю, 5-ю, 7-ю)
LD (DE),A:INC E ; строчку слева
LD A,(HL):INC H ; направо, т.е.
EXX ; как обычно
OR (HL):INC H ;
EXX ;
LD (DE),A:INC E ;
EXX ;
LD A,(BC):INC B ;
OR (HL):INC H ;
EXX:LD (DE),A:
INC D;
EXX ;
LD A,(BC):INC B ; выводим 2ую
OR (HL):INC H ; (4-ю, 6-ю, 8-ю)
EXX ; строку справа
LD (DE),A:DEC E ; налево - для
EXX ; этого в процедуре
LD A,(HL):INC H ; INSF_2 мы и сде-
EXX ; лали небольшой
OR (HL):INC H ; изврат в формате
LD (DE),A:DEC E ; шрифтов
LD A,(BC):INC B ;
OR (HL):INC H ;
LD (DE),A:INC D ;
...
; повторяем эти два блока ещё 3 раза
; для вывода всех восьми строк
LD A,D:SUB 8:LD D,A
.3 INC E;
; переходим на три байта вправо и
; восстанавливаем значение регистра D
...
; здесь можно было бы поставить проверку
; на то, выходит ли строчка за экран и
; т.д.
JP LIN_1Про вывод цветов говорить, наверное, не стоит - ничего сложного в нём нет, к тому же особого влияния на скорость работы всей программы этот вывод не оказывает. В программе не показано ещё много мелочей - цель статьи изложить лишь идею, которую каждый может воплотить по-своему. Средняя скорость работы viewer’а, написанного с использованием данного алгоритма - 5-6 фреймов на обновление экрана размером 22*40 символов. От редакции: В листинге присутствуют особенности ассемблера Storm. Например: .3 INC E, что при компиляции дает 3 команды INC E. |