KARAKTER SETİ
Belki fark etmişsinizdir, oyunlarda ve bazı programlarda yazılar değişik bir şekildedir ve C64'ün alışık olduğunuz karakterlerinden çok farklıdır. Peki bu nasıl oluyor? Cevabı ise karakter seti değiştiriliyor olacaktır. Cevap bu kadar basittir ama o karakter setini hazırlamak biraz emek ister. En basitinden değişik bir "1x1" karakter seti hazırlamak için önce bir yerlerden "FONT EDİTÖR" olarak bilinen utility'lerden bulacaksınız ve elinize bir joystick alıp her karakteri baştan çizeceksiniz. Eğer eliniz (benim gibi :)) grafiğe yatkın değilse 4096 byte'ı yeniden düzenlemek tam bir işkence olacaktır. Eğer sadece rakamları, harfleri ve noktalama işaretlerini yeniden çizecekseniz işiniz biraz daha kısa sürecektir. Bu arada C64'te karakterler hafızada nerede ve ne şekilde duruyor kısa bir bilgi verelim.
C64'ün karakter seti $D000-$DFFF adresleri arasında bulunan KARAKTER ROM'da saklanmaktadır. Derginin önceki sayılarında verdiğimiz "BELLEK HARİTASI" köşesinde aynı adreslerde "I/O CHİPLERİ" ve 4K'lık bir RAM vardır. C64 mühendisleri öyle bir sistem tasarlamışlar ki C64'ün ilk açılıştaki konfigürasyonunda CPU $D000-$DFFF adreslerindeki "I/O" çiplerine erişebilirken, "karakter rom"a sadece, C64'ün grafik çipi VIC-II erişebilmektedir. Burada bir çelişki var gibi gözükmektedir. Şöyle ki, VIC-II'nin kendisi $D000-$D3FF adresleri arasında, Karakter Rom'u da $D000-$DFFF adresleri arasındadır. Yani bir tür adres çakışması vardır. Fakat bizim mühendisler bir hile yaparak karakter setini VIC-II'ye $1000-$1FFF adresleri arasındaymış gibi göstermişlerdir. Oysa gerçekte bu adresler tamamen kullanıcıya kalmıştır. Yani siz $1000-$1FFF arasını kullanarak karakter setini değiştiremezsiniz. VIC-II çipi 16K'lık bir belleğe erişebilir ve bu 16K'lık bölgelere BANK denir. C64'ün belleği 64K olduğu için toplam 4 adet BANK'ımız vardır ve BANK 0, BANK 1, BANK 2 ve BANK 3 olarak adlandırılır. C64 ilk açılışta $0000-$3FFF (BANK 0) arasını kullanır. Karakter Rom'u normalde $C000-$FFFF adresleri arasındaki BANK 3'ün adreslerinin bir kısmını ($D000-$DFFF) kullanmaktadır. İşte bu $D000-$DFFF adresleri BANK 0'daki $1000-$1FFF adreslerine karşılık gelmektedir ve ROM GÖRÜNTÜSÜ olarak adlandırılmaktadır. Şimdi gelelim karakterlerin hafızada ne şekilde saklandıklarına.
Normal bir karakter seti 256 karakterden oluşur ve her karakter 8 byte'lık yer kaplar. Böylece 256*8=2048 byte bir karakter setinin kaplayacağı alandır. Fakat Karakter Rom'u 4096 Byte'tır. Yani C64'ün aslında 2 tane karakter seti vardır. C64 açılışta $D000-$D7FF adresler arasındaki ilk seti kullanır. İkinci set ise $D800-$DFFF adresleri arasındadır ve setler arasındaki geçiş "SHIFT" ve
"C=" (Commodore) tuşlarıyla yapılır. Hangi karakterler hangi adreslerde olduğunu öğrenmek istiyorsanız tablo-1 işinize yarayacaktır.
Sırada ise yeni oluşturduğumuz karakter setini C64'e nasıl bildireceğiz sorusunun cevabı var. Bir karakter setinin 256 karakterden oluştuğunu ve 2048 byte (2K) yer kapladığını biliyoruz. Bu durumda bir karakter seti BANK içinde 8 farklı adresten başlayabilir. İster bütün karakterleri, isterseniz sadece bir karakteri değiştirin karakter setiniz mutlaka 8 adresin birinden başlamak zorundadır. Yani kafanıza göre adres kullanamazsınız. Karakter setinin yerini $D018 (53272) adresindeki VIC-II kontrol registerinin 3 bit'i belirler. Bit 3, 2 ve 1 2K'lık bloklar halinde, karakter setinin nerede olduğunu belirler. Bit 0 dikkate alınmaz. Tablo-2'de karakter setinin yerleşebileceği adresleri bulabilirsiniz.
Tablo-2, BANK 0 için kullanılabilecek adresleri göstermektedir. Her ne kadar 8 adet yerimiz var gibi gözükse de $0000 - $07FF, $1000 - $17FF ve $1800 - $1FFF adreslerini kullanamıyoruz. $0000 - $07FF arası bölgenin $0000 - $03FF arasındaki kısmında işletim sistemi tarafından kullanılan sistem değişkenleri, mikro işlemci tarafından kullanılan STACK (Yığın) ve vektör adresleri vs. bulunmaktadır. $0400 - $07FF arası ise ekran belleği olarak kullanılmaktadır. Dolayısıyla $0000 - $07FF arasını, eğer bana işletim sistemi lazım değil, ekran belleğini de başka bir yere taşırım derseniz belki kullanabilirsiniz. Belki diyorum çünkü özellikle $0100 - $01FF arasındaki STACK denilen bölgenin içeriğini değiştirdiğiniz anda programınızın çalışması bozulabilir, C64 kilitlenebilir. Nedeni ise -hatta kendi işletim sisteminizi yazmış bile olsanız- STACK denilen bölgenin mikro işlemci tarafından mutlaka kullanılan bir bölge olmasıdır. Kısaca tablodaki ilk adresleri unutun.
Diğer adreslerden $1000 - $17FF ve $1800 - $1FFF arası ise daha önce bahsetmiş olduğumuz ROM GÖRÜNTÜSÜ adresleri olup bu adreslere yeni karakter setinizi yerleştirip $D018'e uygun değeri verseniz bile C64'ün kendi karakterlerini görürsünüz. Daha farklı bir ifadeyle POKE 53272,20 komutu ile C64'ün normal karakter setini seçmiş olursunuz. Örnek karakter setimizle ilgili programı incelerseniz $D018'e $1C değerini verdiğimizi görebilirsiniz.
Karakterlerin Rom'daki sıralanışı karakterlerin ekran koduna göredir. Örnek verecek olursak "A" karakterinin ekran kodu "1" olup Rom'da $D008 - $D00F adresleri arasındadır. Bir karakter 8 byte yer kaplamaktadır. Bu durumda bir karakterin Rom'daki adresi şöyle bulunur.
ADRES = $D000 + KARAKTERİN EKRAN KODU * 8
Eğer karakter setiniz Ram'de ise formüldeki $D000 yerine karakter setinin Ram'deki başlangıç adresini yazmanız yeterli olacaktır.
Bir byte'ın toplam değeri dolu olan bitlerin "bit değeri" toplanarak bulunur. Bir karakter 8 byte olduğuna göre bütün byte'lar hesaplanarak karakterin hafıza adresine POKE komutuyla yazılır. Eğer sadece harf, rakam ve noktalama işaretlerini değiştirecekseniz 2K yerine ilk 64 karakteri değiştirmeniz yeterlidir. Son olarak bizim programımızda bütün karakter seti "sağa italik" olarak değiştiriliyor.
;--------------------------------------------;
;PROGRAM ADI : C64 İÇİN YENİ KARAKTER SETİ #01
;(SAĞA İTALİK FONTLAR)
;
;PROGRAM TARİHİ : 24-09-2003
;
;PROGRAMI YAZAN : İSMAİL "HADES" ŞAHİN ;
;C64 TÜRKİYE SAYI 4 İÇİN HAZIRLANMIŞTIR
;
;(wordpad, c64asm v1.1 ve VICE v1.11 kul-
lanılmıştır)
;
;--------------------------------------------;
*=$0801
.word
nextline
.word
2003
; 2003
.byte
$9e
; SYS
.text
"2061" ; 2061
.byte
0
; komutu
nextline
.word
0
;--------------------------------------------; ;ROMDAKİ KARAKTER SETİ RAM'E TRANSFER EDİLECEK ;============================================= ;Transfere başlamadan önce hafıza ;düzenlenecek. Bunun için önce interruplar ;engelleniyor ve daha sonra karakter rom'unun ;CPU (6510) tarafından okunabilmesi için I/O ;bölgesi düzenleniyor. ;--------------------------------------------;
sei
;İnterruptları engelle
lda
$01
;Karakter ROM'u
and
#$fb
;artık CPU tarafından
sta
$01
;okunabilir
;--------------------------------------------;
; Transfer için adresler ayarlanıyor... ;
;--------------------------------------------;
lda
#$d0
;ROM adresi = $D000
ldx
#$30
;RAM adresi = $3000
ldy
#$00
;olacak şekilde ayarla.
sty
$fb
;$FB ve $FC adreslerinde
sta
$fc
;ROM adresi tutuluyor.
sty
$fd
;$FD ve $FE adreslerinde
stx $fe ;RAM adresi tutuluyor. ;--------------------------------------------; ;4096 Byte $D000 adresinden $3000 adresine ;taşınıyor.Karakter seti 4096 byte ;uzunluğundadır ve bu bilgi 4096/256 = 16 ;döngüde transfer edilebilir.
;--------------------------------------------;
ldx
#$10
;Blok sayacı = $10 (16)
transfer
lda
($fb),y
;ROM'dan o anki adresi
sta
($fd),y
;oku ve RAM'e kopyala
iny
;byte sayacını 1 arttır
bne
transfer
;"0" değilse geri dön
inc
$fc
;ROM HIGH adresi 1 arttır
inc
$fe
;RAM HIGH adresi 1 arttır
dex
;Blok sayacını 1 azalt
bne
transfer
;"0" olmadıysa geri dön.
lda
$01
;I/O bölgesi eski haline
ora
#$04
;getiriliyor. CPU artık
sta
$01
;karakter roma erişemez
cli
;interruptlara izin ver
lda
#$1c
;VIC'e yeni karakter
sta
$d018
;setinin yerini bildir.
;--------------------------------------------;
; Karakter setimiz sağa italik olacak ;
;--------------------------------------------;
lda
#$30
;Karakter seti başlangıç
ldy
#$00
;adresi $3000 olarak
sty
$fb
;$FB ve $FC adreslerine
sta $fc ;kaydediliyor ;--------------------------------------------; ;Y registeri karakterin byte sayıcısı olacak. ;Bir karakterin datası 8 byte'tan oluştuğu ;için Y registeri 8 kez arttırılıyor ve "0" ;olup olmadığı kontrol ediliyor. "0" olunca ;bir döngüde 256/8 = 32 karakter değiştirilmiş ;oluyor. Bu işlemler Blok sayıcısı kadar ;tekrarlanınca bütün karakter seti ;değiştirilmiş oluyor. ;--------------------------------------------; ; Değişikliğin yapıldığı asıl bölüm burası ; ;--------------------------------------------;
new_fonts
ldx
#$10
;Blok sayıcı = $10 (16)
nextchar
lda
($fb),y
;Karakterin ilk datasını
byte1
lsr
;okuyup ve bir kez sağa
sta
($fb),y
;kaydırıp geri yazıyoruz
iny
;2. data için arttır.
lda
($fb),y
;2. datayı oku ve
byte2
lsr
;bir kez sağa kaydır
sta
($fb),y
;Sonra geri yaz
iny
;3. data için arttır.
iny
;4. data için arttır.
iny
;5. data için arttır.
iny
;6. data için arttır.
lda
($fb),y
;6. datayı oku ve
byte6
asl
;bir kez sola kaydır.
sta
($fb),y
;Sonra geri yaz.
iny
;7. dta için arttır.
lda
($fb),y
;7. datayı oku ve
byte7
asl
;bir kez sola kaydır.
sta
($fb),y
;Sonra geri yaz.
iny
;8. data için arttır.
lda
($fb),y
;8. datayı oku ve
byte8
asl
;bir kez sola kaydır.
sta
($fb),y
;Sonra geri yaz
iny
;Bir sonraki karakterin
bne
nextchar
;ilk datası için arttır.
;"0" olmadıysa tekrar
inc
$fc
;RAM HIGH adresi arttır.
dex
;Blok sayıcısını azalt.
bne
nextchar
;"0" olmadıysa tekrar
rts
;Programı bitir.
;--------------------------------------------;
;NOT : Program listesindeki "asl" komutları
;"lsr" ve "lsr" komutları "asl" olarak
;değiştirilirse yeni karakter seti sola italik
;olur.
;--------------------------------------------;
.end
Derginin bir sonraki sayısında bütün karakter setini başaşağı çevireceğiz. İsteyen uğraşabilir ve çözümünü .txt dosyası olarak bana gönderebilir. Veya sadece program ile değişik bir karakter seti yaparsanız dergide yayınlayabilirim. Şimdiden iyi çalışmalar....
SET
1
2
ADRES D000-D1FF D200-D3FF D400-D5FF D600-D7FF D800-D9FF DA00-DBFF DC00-DDFF DE00-DFFF
VIC-II ROM GÖRÜNTÜSÜ
1000-11FF 1200-13FF 1400-15FF 1600-17FF 1800-19FF 1A00-1BFF 1C00-1DFF 1E00-1FFF
AÇIKLAMA Büyük harf karakterler
Grafik karakterleri Büyük harf karakterler (negatif)
Grafik karakterleri (negatif)
Küçük harf karakterler Büyük harf ve grafik karakterler
Küçük harf karakterler (negatif) Büyük harf ve grafik karakterler (negatif)
ONLU KARAKTER SETİ ADRESİ
$0000-$07FF $0800-$0FFF $1000-$17FF $1800-$1FFF $2000-$27FF $2800-$2FFF $3000-$37FF $3800-$3FFF
0 2048 4096 6144 8192 10240 12288 14336
$D018 DEĞERİ
$10 (16) $12 (18) $14 (20) $16 (22) $18 (24) $1A (26) $1C (28) $1E (30)
(Tablo-1)
(Tablo-2)