Печать текстовой строки шрифтом 8х8 с/без атрибутов
Для вывода текста необходимо знать расположение данных шрифта, хранящихся в ПЗУ ZX Spectrum: порядковое расположение соответствует кодам ASCII.Каждый символ описывается блоком данных размером 8 байт, таким образом любой символ представлен 8х8 точек. Например, символ 'X' выглядит как: Двоичные данные:
00000000
01000010
00100100
00011000
00011000
00100100
01000010
00000000
все 96 символов располагаются по адресу #3D00, для печати на экран удобнее всего скопировать 8 байт, описывающих символ на экран:
Входные данные процедуры printtext: DE=адрес вывода на экран, HL=адрес сообщения, используется BC.
ORG #8000
;-1
ld de,#4000
ld hl,message1
call printtext
;-2
ld de,#4021
ld hl,message2
call printtext
;-color
ld hl,#5800
ld ix,message3
call printattrtext
stu: jr stu
printtext
m11:
ld a,(hl);получиnь первый код символа
inc hl
or a;для завершения печати используется трюк: текст ограничен байтом 0, который не используется
ret z;таким образом не надо вычислять и определять длину сообщения
push hl;перед вычислением адреса данных символа HL нужно запомнить
ld l,a
ld h,0; все данные в шрифте занимают 8 байт, легче будит умножить код символа на 8
add hl,hl;hl=hl+hl или hl*2
add hl,hl;hl*4
add hl,hl;hl*8
ld bc,#3C00;адрес шрифта ;1
add hl,bc;hl=адрес данных необходимого символа;1
;! ld a,h;для сохранения регистра BC
;! add a,#3C;удобнее заменить команды, помеченные ;1 на команды с меткой;!
;! ld h,a
push de;сохранение адреса DE
dup 8; операция выполняется 8 раз
ld a,(hl);Данные шрифта
ld (de),a;копируются на экран
inc hl;следующие данные
inc d;вниз на линию в экране
edup;операция завершена
pop de
inc de; восстановлен адрес DE из стэка и переход к следующему знакоместу
pop hl;восстановлен адрес сообщения в HL
jr m11; переход к циклу печати
С печатью текста с помощью аттрибутов экрана процедура выглядит сложнее. Для вывода текста нужно побитно выполнить тест над восемью байтами и заполнять экран в зависимости от результата теста Входные данные:HL=адрес экранной памяти,IX=сообщение.используется BC,DE
printattrtext
m1:
ld a,(ix)
or a
ret z; если код сообщения 0, то печать завершается
inc ix
push hl
ld l,a
ld h,0
add hl,hl
add hl,hl
add hl,hl; каждый символ состоит из 8 байт, умножим код на 8
;ld de,#3C00
;add hl,de;3C00 - адрес, где хранятся символы
ld a,h
add a,#3C
ld h,a
ld de,hl;DE=адрес шрифта для символа
pop hl;HL был нужен для вычисления адреса
push hl; значение восстановлено
ld a,8; начинается цикл 8 раз
m3: ld b,#80;Битовая маска для проверки данных в шрифте
exa; замена AF на AF', таким образом A запоминать не нужно
m2: ld a,(de)
and b;тест байта шрифта
jr z, writeatr;если результат=0, то занести в атрибуты пустое значение
ld a,8; атрибут paper= синий(1)*8;если тест прошел, то запись в атрибуты будет проведена другим значением
writeatr:
or 7; добавить к атрибутам белый INK=7
ld (hl),a;запись цвета в атрибуты
inc hl;следующий атрибут в памяти
rrc b;сдвиг маски вправо #80->#40->...->#4->#2->#1
jr nc, m2; сдвиг перенес данные во флаг переноса C, это и есть условие завершение цикла
ld bc,24;первая линия нарисована 8 атрибутов
add hl,bc; 24=32-8 переход к следующей линии
inc de;следующий байт шрифта
exa;AF'<->AF
dec a
jr nz,m3;цикл обработки от 8 до 0
pop hl;прежний адрес атрибутов восстановлен
ld bc,8
add hl,bc; переход к следующему адресу на 8
jp m1
;сами сообщения
message1: db "print Text 123456",0
message2: db "Moar messages",0
message3: db "TEXT",0
а теперь посчитаем такты команд пр расчете адреса шрифта:
ld l,a;4
ld h,0;7
add hl,hl;11
add hl,hl;11
add hl,hl;11
ld a,h;4
add a,#3C;7
ld h,a;4
выходит 59 тактов на символ,не считая того, что тратится на обработку данных при печати. Поэтому удобнее сформировать любой шрифт и расположить данные в памяти:
Font+256*0: первые байты шрифтов подряд
Font+256*1: вторые байты шрифтов подряд
...
Font+256*7: последние(седьмые по счету) байты шрифтов подряд
Процедура печати:
ORG #8000
font_place equ #4800;адрес для наглядности шрифта, при использовании удобно поменять на #6000
font_place_hi equ font_place/256
begin
;-------формирование шрифта
ld hl,#3c00
ld de,font_place
m1:
push de
call myfont1;serzhfont;future;lordsfont;italic;bold;simple
pop de
inc e
jr nz,m1
Печать текста
ld hl,messaget
ld de,#4021
call printtext
stu: jr stu
messaget: db "Pretty text with font!",0
printtext
ptlp1: ld c,(hl)
ld b,font_place_hi
push de
dup 8
ld a,(bc)
ld (de),a
inc b
inc d
edup
pop de
inc de
inc hl
ld a,(hl)
or a
ret z
jr ptlp1
формирование других шрифтов Для удобства команды внесены в директиву dupN..edup,например 8 означает 8 повторов команд.
simple
dup 8
ld a,(hl)
ld(de),a
inc hl
inc d
edup
ret
myfont1
ld a,(hl)
ld(de),a
inc hl
inc d
ld a,(hl)
rra
or(hl)
ld(de),a
inc hl
inc d
dup 4
ld a,(hl)
ld(de),a
inc hl
inc d
edup
ld a,(hl)
rra
or(hl)
ld(de),a
inc hl
inc d
ld a,(hl)
ld(de),a
inc hl
inc d
ret
serzhfont
dup 4
ld a,(hl)
rra
or(hl)
ld(de),a
inc hl
inc d
ld a,(hl)
ld(de),a
inc hl
inc d
edup
ret
future
dup 4
ld a,(hl)
ld(de),a
inc hl
inc d
edup
dup 4
ld a,(hl)
rra
or (hl)
ld(de),a
inc hl
inc d
edup
ret
lordsfont
dup 8
ld a,(hl)
ld c,a
srl c
srl c
or c
ld(de),a
inc hl
inc d
edup
ret
bold
dup 8
ld a,(hl)
rra
or (hl)
ld(de),a
inc hl
inc d
edup
ret
italic
dup 3
ld a,(hl)
rra
ld(de),a
inc hl
inc d
edup
dup 2
ld a,(hl)
ld(de),a
inc hl
inc d
edup
dup 3
ld a,(hl)
rla
ld(de),a
inc hl
inc d
edup
ret