C64'te ekran belleğine bir poke komutu ile istediğimiz harfi, rakamı vs kolayca gösterebilirken Spectrum'da Vic benzeri bir çip olmadığı için böyle bir şansımız yoktur. Ekrana bir karakter yazmak için mutlaka rom rutini kullanılmalıdır. Veya romdan/ramden karakter datasını okuyup kendimiz bir custom print rutini yazabiliriz. Rom'daki print rutini ile karakterler ekrana 8 pixel satırından oluşan bloklar halinde basılır ve 24 karakter satırı vardır. Yani rom rutini ile satır değeri vererek ekrana karakter basabilirsiniz.
Aşağıdaki rutin ile karakter satır değeri yerine pixel satırı değeri ile yazı yazılmaktadır. Normal rom rutininde karakter satırlarının başlangıçları arasındaki mesafe 8 pixeldir. Bizim rutinimizde ise bu mesafe ayarlanarak (default 7 tanımlamıştır) ekrana 27 karakter satırı sığması sağlanmıştır. Font dataları 8x7 pixelmiş gibi düşünebilir. Daha ufak fontlar kullanılarak 32 karakter satırı elde edilebilir. (Rutinin bir sonraki aşaması font datasını 7x7 pixelmiş gibi işlem yaparak bir karakter satırında 32 yerine 36 karakter basmak.)
Rutini ilk olarak 2017 yılında yazmışım. Geçtiğimiz günlerde biraz optimizasyon yaparak toplamda 36 byte kısalttım. Ciddi bir hız optimizasyonu oldu.
Program ilk olarak ekran pixel satır adresi üretilerek bir tablo oluşturuluyor. Sonra ilk karakterin basılmaya başlayacağı pixel satırına göre tablodan gerekli ekran adresi bulunuyor ve karakterin dataları romdan okunarak ekrana basılıyor. Bir sonraki karakteri basmak için hesaplanan ekran adresine kolon değeri eklenerek 32 karakterin hepsi basılıyor. Pixel satırına mesafe değeri eklenerek bir alt satır için yeni adres elde ediliyor ve bütün bu işlemler 27 karakter satırı basılıncaya kadar devam ediyor.
;========================================
; PIXEL PRINT V1.0 or 27 Text Lines
; 02.05.2022 - HADES/RET
; 140 bytes code + 3 bytes variables
; 32 bytes text + 384 bytes generated table
;========================================
org $8000
;----------------------------------------
; Ekran Piksel Satır Adres Üreteci
;----------------------------------------
adr_gen ld de,$4000
ld hl,tablo
loop02 ld c,8
loop01 ld b,8
loop00 ld (hl),e
inc hl
ld (hl),d
inc d
inc hl
djnz loop00
ld a,e
add a,$20
ld e,a
ld a,d
sub 8
ld d,a
dec c
jr nz,loop01
add a,8
ld d,a
cp $58
jr nz,loop02
call $0db6 ; ekranı sil
out (254),a
;-----------------------------------------
; Yazıyı 27 text satırı olarak ekrana bas
;-----------------------------------------
ld b,27 ; satır sayacı
loop05 push bc
call pixel_print
;----------------------------------------
; Yeni satırın adresini ayarla
;----------------------------------------
ld a,(mesafe)
ld b,a
ld a,(y_pixel)
add a,b
ld (y_pixel),a
pop bc
djnz loop05
ld b,80
wait halt
djnz wait
ret
;-----------------------------------------
; 32 bytlık yazıyı ekrana bas.
;-----------------------------------------
pixel_print xor a ; ld a, ; yazının başlayacağı kolon
ld (kolon),a
ld b,32 ; text uzunluğu. Kolon numarası 0'dan
; büyükse text uzunluğu daha az olmalıdır.
ld hl,text
loop03 push bc ; yazı uzunluğunu yığına at
push hl ; text adresini yığına at
;----------------------------------------
; Y pixel pozisyonuna bir karakter bas.
; Önce fontun data adresini hesapla.
;----------------------------------------
print ld a,(hl)
ld d,0
rla
rl d
rla
rl d
rla
rl d
ld e,a
ld ix,(23606) ; karakter setinin başlangıç adresi
add ix,de ; IX registerinde font data adresi var
;----------------------------------------
; y_pixel değerine göre pixel satır
; adresini hesapla ve tablodaki yerini bul
; pixel satırının adresi=y_pixel*2 + tablo başlangıç adresi
;----------------------------------------
ld b,8
ld a,(y_pixel)
loop04 ld c,a
ld h,0
rla
rl h
ld l,a
ld de,tablo
add hl,de
ld e,(hl) ; E'de pixel satır adresinin LO baytı var
inc hl
ld d,(hl) ; D'de pixel satır adresinin HI baytı var
ld a,(kolon)
adc a,e
ld e,a
;----------------------------------------
; Font datasını ekrana bas.
;----------------------------------------
ld a,(ix+0)
ld (de),a
inc ix
ld a,c
inc a ; bir sonraki y_pixel değeri
djnz loop04
;----------------------------------------
; Bir sonraki karakterin yerini ayarla
;----------------------------------------
ld hl,kolon
inc (hl)
pop hl
inc hl ; textin bir sonraki karakteri
pop bc
djnz loop03 ; karakter sayacı
ret
;----------------------------------------
text defm "27 TextLines v1 02.05.2022-HADES"
;----------------------------------------
mesafe defb 7 ; Yazı satırları arasındaki mesafe
; 7'den büyük değerler için satır
; sayacı azaltılmalıdır.
y_pixel defb 0 ; Yazının yazılacağı pixel satırı
kolon defb 0
;----------------------------------------
tablo
;----------------------------------------
end $8000
;========================================