Murzilka #07 |
|
Coding - Быстрая печать шестипиксельным фонтом.
БЫСТРАЯ ПЕЧАТЬ ШЕСТИПИКСЛЕЬНЫМ ФОНТОМ Данная статейка уже публиковалась в газете "Абзац", но почитав свежие ЭСМИ мне показалась, что её прочитали немно- гие. Итак, быстрая печать. Сразу скажу, что речь далее будет вестись не об уни- версальных процедурах, а о печати именно строк ( не отдельных символов ), оптими- зированной по скорости ( в ущерб, кста- ти, памяти ). Для ускорения вывода создадим к ос- новному шрифту ещё З, символы в которых будут распологаться, соответственно, со смещением в 2, 4 и 6 пикселей от левого края. Чтобы при печати строки не тратить время на вычисление адреса нужного сим- вола лучше создавать font'ы таким обра- зом, чтобы изображение первого символа лежало в байтах с адресами: font, font+#1ОО, font+#2ОО, ... , font+#7ОО, изображение 2го в байтах с адресами: font+#ОО1, font+#1О1, font+#2О1, ... , font+#7О1, где font - адрес шрифта в па- мяти, кратный 256. Таким образом для вы- числения адреса символа нужно будет за- нести в старшый регистр старший байт ад- реса фонта, а в младший поместить код символа. Для пояснения всего вышесказан- ного приведу пример подпрограммы, форми- рующей соответствующие шрифты: INS FON LD DE,SH6O ; формируем шрифт CALL INSF 1; со смещением О LD A,#OF,(IFF 1),A LD (IFF 1+1),A LD DE,SНбЗ ; -- / -- CALL INSF 1; со смещением 2 LD DE,SH61 ; -- / -- CALL INSF 2; со смещением 6 LD A,О,(IFF 2),A LD DE,SH62 ; -- / -- CALL INSF 2; со смещением 4 RET INSF 2 LD IX,font LD Е,#2О; код 1го символа (пробел) LD С,224; считаем, что всего в ; шрифте 224 символа SF2 1 PUSH DE LD В,4 SF2 З CALL SF2 2 LD A,L,(DE),A:INC D; зачем сделано LD A,Н,(DE),A:INC D; именно так CALL SF2 2 ; можно про- LD A,Н,(DE),A:INC D; читать ниже LD A,L,(DE),A:INC D; DJNZ SF2 З SF2 ЗВ РОР DE INC Е,IX DEC С:JR NZ,SF2 1 RET SF2 2 LD Н,(IX+О),L,О:INC IX .2 AND A:RL Н,L IFF 2 RET .2 AND A:RL Н,L RET INSF 1 LD HL,font LD Е,#2О,С,224 SF1 1 PUSH DE LD В,8 SF1 2 LD A,(HL):INC HL IFF 1 NOP:NOP LD (DE),A:INC D DJNZ SF1 2 РОР DE INC Е,HL DEC С:JR NZ,SF1 1 RET Здесь font - адрес исходного обычного шрифта; SH6O, SH61, SH62, SНбЗ - адреса формируемых шрифтов, должны быть кратны 256. В INSF 2 формируются шрифты по раз- меру в два раза больше, чем в INSF 1 из- за того, что при смещении изображения символа на 4 и 6 пикселей вправо оно вы- ходит за границы одного байта. Причём, в INSF 2 шрифт формируется таким образом, что 2ая, Чая, бая и 8ая линии изображе- ния каждого символа хранятся в обратном порядке, т.е. сначала идёт правый байт, потом левый ( чтобы понять, что я тут хотел сказать лучше посмотреть на саму эту процедуру и всё сразу станет ясно ). В таком виде будет удобней выводить строку символов. Теперь непосредственно о самой печа- ти. Основная идея: при печати шестипик- сельным шрифтом рассматриваются четвёрки символов, которые очень хорошо вписы- ваются по ширине в три байта. Поэтому нужно выводить символы не отдельно друг от друга, а одновременно печатать на эк- ран сразу всю четвёрку. В этом случае исчезает много ненужных команд, типа LD A,(DE), LD (DE),A, которые нужны при последовательном выводе ( так, например, для вывода 2го символа четвёрки нужно взять с экрана изображение уже напечатанного 1го, совместить его со 2ым, положить обратно на экран. То же самое с Зим и Чым ). Для вывода одновре- менно всей четвёрки нам нужно иметь сле- дующие адреса: адрес текста - допустим он в DE'; адрес на экране, куда выводится строка - DE; адрес 1го символа - ВС; адрес 2го символа - HL; адрес Зего символа - HL'; адрес Чго символа - ВС'; Сделаем набросок процедуры вывода всей строки: LIN 1 LD В,SH6O[; заносим старшие LD Н,SH61[; байты адресов в EXX LD Н,SH62[; соответствующие LD В,SНбЗ[; регистры LD A,(DE):INC DE; код 1го ; символа четвёрки ... ; здесь следовало бы поставить про- ; верку на различные управляющие коды, ; как то: конец строки, цвет и т.д. ; Думаю это каждый сможет сделать сам EXX:LD С,A:EXX; в ВС уже есть ; адрес LD A,(DE):INC DE; 2ой символ ... EXX:LD L,A:EXX; 2ой адрес LD A,(DE):INC DE; Зий ... LD L,A; и так далее LD A,(DE):INC DE ... LD С,A EXX ; теперь непосредственно сам вывод LD A,(ВС):INC В; выводим 1ую OR (HL):INC Н ; (Зью, Sую, 7ую) LD (DE),A:INC Е; строчку слева LD A,(HL):INC Н; направо, т.е. EXX ; как обычно OR (HL):INC Н ; EXX ; LD (DE),A:INC Е; EXX ; LD A,(ВС):INC В; OR (HL):INC Н ; EXX:LD (DE),A: INC D; EXX ; LD A,(ВС):INC В; выводим 2ую OR (HL):INC Н ; (Чую, бую, 8ую) EXX ; строку справа LD (DE),A:DEC Е; налево - для EXX ; этого в проце- ; дуре LD A,(HL):INC Н; INSF 2 мы и сде- EXX ; лали небольшой OR (HL):INC Н ; изврат в фор- LD (DE),A:DEC Е; мате шрифтов LD A,(ВС):INC В; OR (HL):INC Н ; LD (DE),A:INC D; ... ; повторяем эти два блока ещё З раза ; для вывода всех восьми строк LD A,D:SUB 8:LD D,A .З INC Е; ; переходим на три байта вправо и ; восстанавливаем значение регистра D ... ; здесь можно было бы поставить проверку ; на то, выходит ли строчка за экран и ; т.д. JP LIN 1 Про вывод цветов говорить, наверное, не стоит - ничего сложного в нём нет, к тому же особого влияния на скорость ра- боты всей программы этот вывод не оказы- вает. В программе не показано ещё много мелочей - цель статьи изложить лишь идею, которую каждый может воплотить по- своему. Средняя скорость работы viewer'а, написанного с использованием данного алгоритма - 5-6 фреймов на об- новление экрана размером 22*4О символов. Хочу заметить ещё раз, что основная идея - это печать одновременно (а не по очереди) всех четырех символов. Всё ос- тальное: использование 4 фонтов и т.д. второстепенно.
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября