Gönderen Konu: 27 Text Lines  (Okunma sayısı 124 defa)

0 Üye ve 1 Ziyaretçi konuyu incelemekte.

Çevrimdışı hades

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 184
27 Text Lines
« : 14 Mayıs 2022, 00:55:40 »
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.

Kod: [Seç]
;========================================
; 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
;========================================

Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 186
Ynt: 27 Text Lines
« Yanıtla #1 : 14 Mayıs 2022, 16:57:05 »
Çok güzel olmuş @hades, bunu GeOS'un içinde gelen Word benzeri araçlara dönüştürebilir ya da bir ZX Spectrum disk magazine motorunun altyapısı olarak kullanabilirsin.

Fixed font yani ekranı bir grid gibi düşüneceksen tabii ki 7x7 font güzel bir boyut seçimi. Ancak benim proportional önerim olacak. Her harf kendi genişliğine göre çizilsin derim.

Biliyorsun, eskiden fontların genişliklerini elle tablolardık. Ben bir kaç sene önce proportional font'un karakter tablosunu otomatik oluşturan bir kod yazdım. Kick Assembler'da yazdım bunu, sadece örnek teşkil etmesi açısından paylaşıyorum.

Kod: [Seç]
* = Font "Font"
.var font = LoadBinary("font.bin")
.fill font.getSize(), font.get(i)
fontLength:
.for (var i = 0; i < font.getSize(); i+=8) {
.var length = 0
.for (var j = 0; j < 8; j++) {
.var value = font.get(i+j)
.var temp = 8
.if ((value & 1) == 0) {
.eval temp -= 1
.if ((value & 2) == 0) {
.eval temp -= 1
.if ((value & 4) == 0) {
.eval temp -= 1
.if ((value & 8) == 0) {
.eval temp -= 1
.if ((value & 16) == 0) {
.eval temp -= 1
.if ((value & 32) == 0) {
.eval temp -= 1
.if ((value & 64) == 0) {
.eval temp -= 1
.if ((value & 128) == 0) {
.eval temp -= 1
}
}
}
}
}
}
}
}
.eval length = max(length, temp)
}
.if (i == $100) { // space character
.byte 6
} else {
.byte length+1
}
}

Font olarak herhangi bir 1x1 fontu kullanabiliyorsun ancak karakterlerin sollarında boşluk olmayacak, tüm karakterler sola yapışık olacak. Gerisini bu gönderdiğim kod parçası hallediyor. Tek tek karakterlerin maksimum genişlikteki satırlarını bulup, ona göre karakter genişliklerini belirliyor. En altta dikkat edersen boşluk karakterine özel bir koşul var. Boşluk karakteri ise doğal olarak ne kadar boşluk bırakacağını elle belirliyoruz. Diğer karakterlerde genişlik+1 şeklinde belirlemiş durumdayım. +1 olmazsa hiç boşluk bırakılmayıp tam yapışık oluyorlar.

Proportional text rutini yazacak olursan dediğim gibi bir disk magazinin ilk ve önemli adımlarından birini atmış olursun, ne dersin? :)

Çevrimiçi Ref

  • Yönetici
  • Özgür Retrocu
  • *
  • İleti: 2962
  • Advanced User Simulator
    • ae unutmadan
Ynt: 27 Text Lines
« Yanıtla #2 : 14 Mayıs 2022, 20:09:46 »
valla ben de bir ZX Disk mag'in fantezilerini kuruyorum ama kimse okumaz ki oniii :D

bide şimdi divide ile falan okuyor herkes, bayağı videolu falan bişeyler yapılabilir fantezi olsun diye :D


Çevrimdışı Skate

  • RAAT
  • Retro Meraklısı
  • *
  • İleti: 186
Ynt: 27 Text Lines
« Yanıtla #3 : 17 Mayıs 2022, 22:49:05 »
Bu arada Commodore Türkiye dergilerini hatırlıyorsunuzdur. @hades tek başına çok başarılı iş çıkarmıştı. Sıfırdan dergi formatı oluşturup, onca yazı yazıp, sayfa düzeni yapıp yayınlamıştı hem de kaç sayı. Biz aynısını ekip işi olarak yapıyorduk, @hades yanılmıyorsam tek başına yapıyordu. O yüzden ZX Spectrum'da bir disk magazini çıkacaksa @hades bence çok iyi bir aday bu iş için. Tabii hala eski enerjiyi bulabilirse, kolay iş değil.

Okuyan olup olmamasına gelince, ister PDF yap, ister ZX Spectrum binary'si, okuyan kişi sayısı çok değişmez. Zaten artık online emülatörler var. Benim yaptığım gibi online emülatörü koyarız bir siteye, dileyen oradan erişir.