:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №4 (17.03.2001) Просмотров: 4452
Автор: 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. |