ÇİZGİ KURSÖR
NEREDEN : İSTANBUL NİCK / GRUP(LAR) : HADES / HI3S WEB SİTE : WWW.HI3S.ORG HTTP://HADES6510.SITEMYNET.COM
Eğer C64’ün yanıp sönen kare şeklindeki kursöründen sıkıldıysanız aşağıdaki kısa programla (sadece 96 byte uzunluğundadır) kursörünüz artık PC’lerin DOS zamanındaki kursörü şeklinde olacaktır. Peki bu değişiklik nasıl oluyor? Yeni kursörümüz aslında bir sprite’dır ve interrupt tekniği kullanılmıştır. Normal kursörün satır ve sütun değerleri okunarak programda sprite’ın X ve Y koordinat değerlerine dönüştürülmektedir.
*=$0801
.word nextline
.word 2004
; 2004
.byte $9e
; SYS
.text "2061"
; 2061
.byte 0
; komutu
nextline
.word 0
sei
;interruptları durdur
lda
#<cursor
;programın low byte’ını
sta
$0134
;interrupt vektörünün low byte’ına yaz
lda
#>cursor
;programın high byte’ını
sta
$0315
;interrupt vektörünün high byte’ına yaz
ldx
#$00
;X registerini sıfırla
txa
;Akü’ye X registerinin değerini yükle
loop0
sta
$03c0,x
;Sprite data adresine 0 yaz
inx
;sayacı 1 arttır
cpx
#$40
;#$40 (64) oldumu ?
bne
loop0
;olmadıysa tekrarla
lda
#$ff
;çizgi şekli olması için $ff sayısını
sta
$03c0+21
;sprite’ın uygun data adresine yaz
lda
#$03c0/64
;sprite data başlangıcını
sta
$07f8
;1. sprite pointerine yaz
lda
#$01
;1. Sprite’ı
sta
$d015
;görünür yap
cli
;interruptları başlat
rts
;programı bitir
cursor
lda $d3
;normal kursörün sütun pozisyonunu oku
cmp #$1d
;$1d (19) ile karşılaştır
bcc no_extra
;$1d’den küçükse git
ldx
#$01
;sprite’ın extra x koordinatı var
.byte $2c
;bilgisayarı kandırma sayısı
no_extra
ldx
#$00
;sprite’ın extra x koordinatı yok
stx
$d010
;spritelar için extra x koordinat adresi
asl ;sütun değerini 2 ile çarp asl ;sonucu 2 ile çarp asl ;önceki sonucu 2 ile çarp clc ;”carry” bitini sıfırla adc #$18 ;$18 (24) ile topla sta $d000 ;1. sprite’ın X koordinat adresine yaz. Burada biraz bilgi verelim. Yukarıda 3 defa asl komutunu kullandık. Peki neden böyle bir işlem yaptık? Normalde kursörün sütun değerini olduğu gibi sprite’ın x koordinatına veremeyiz. Eğer verirsek sprite’ımız sadece 1 pixel ilerlemiş olur. Bir karakter normalde 8 pixel genişliğindedir. Kursör dediğimiz şekil aslında bir karakterdir ve reverse space karakterinden başka bir şey değildir. Kursörün bir sonraki sütuna gitmesi demek sprite’ımızında 8 pixel ilerlemesi demektir. Kursörün sütun değeri*8 sayısı bize sprite’ın X koordinatını verecektir. Assemblerde bir sayıyı 8 ile çarpmak, o sayıyı 3 defa sola kaydırmak yani 3 defa ASL komutu kullanmak demektir. Buraya kadar tamam. Peki $18 (24) sayısı nereden geliyor. Bir sprite’ın ekranda tamamen görünür halde olması için X koordinatı $18 olmalıdır. Bu sayıyı 3 ASL komutu sonunda elde ettiğimiz sayıyla toplarsak işimiz tamam olacaktır. lda $d6 ;kursörün satır değerini oku asl ; 2 ile çarp asl ; bir daha 2 ile çarp asl ; son kez 2 ile çarp clc ;”carry” bitini sıfırla adc #$32 ;$32 (50) ile topla sta $d001 ;1. sprite’ın Y koordinat adresine yaz. Yukarıdaki açıklamanın bir benzerini satır değeri için yapıp sonucu sprite’ın Y koordinat adresine yazdığımızda kursörün o anki pozisyonunda birde sprite göstermiş oluruz. inc $d027 ;1. sprite’ın rengini değiştir. jsr $ffea ;zamanı ilerlet ve stop tuşunu kontrol et. jmp $ea61 ;Romdaki interrupt rutinine geri dön. .end Geldik son açıklamaya. Kendi yazdığımız bir interrupt rutininin çalışması bitince son komutun normalde JMP $EA31 veya $EA81 olması gerekir. $EA81 deki komutlar $EA31’den başlayan komutların devamıdır. Peki aradaki $50 (80) byte’ta neler olmaktadır? İlk önce Stop tuşu kontrolü ve zaman ilerletme yapılıyor. Sonra kursörün yakılıp söndürülmesi ve kursörle ilgili karakter ve renk işlemleri yapılıyor. Daha sonra ise teyp tuşlarına basılıp basılmadığı ve teyp motor on / off işlemleri yapılıyor. En son olarak ise klavye kontrolü yapılmakta ve $EA81 adresine gelinmektedir. $EA81’den itibaren ise sırayla Y, X ve A registerleri yığından geri alınıp interrupt rutini bitirilmektedir. Bizim rutinimizde ise önce JSR $FFEA ile bir işlem yapılmakta ve JMP $EA61 ile çıkış yapılmaktadır. Eğer JMP $EA31 kullansak kursör işlemleri yapılacak, JMP $EA81 kullansak tuşlar çalışmaz hale gelecek. Bu nedenle önce JSR $FFEA ile stop tuşunun kontrol edilmesini sağlıyoruz, sonrada kursör işlemlerine hiç uğramadan geri kalan işler için JMP $EA61 komutuyla işimizi bitiriyoruz.
C64 İÇİN BAŞ AŞAĞI KARAKTER SETİ PROGRAMI
HAZIRLAYAN : İSMAİL ŞAHİN
İLETİŞİM : HADES@HI3S.ORG
HADES6510@YAHOO.COM
NEREDEN : İSTANBUL
NİCK / GRUP(LAR) : HADES / HI3S
WEB SİTE : WWW.HI3S.ORG
HTTP://HADES6510.SITEMYNET.COM
*=$0801
.word nextline
.word 2004
; 2004
.byte $9e
; SYS
.text "2061"
; 2061
.byte 0
; komutu
nextline
.word 0
sei
;İnterruptları engelle
lda
$01
;Karakter ROM'u
and
#$fb
;artık CPU tarafından
sta
$01
;okunabilir
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.
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.
new_fonts
lda
#$30
;Karakter seti başlangıç
ldy
#$00
;adresi $3000 olarak
sty
$fb
;$FB ve $FC adreslerine
sta
$fc
;kaydediliyor
loop2
ldy
#$00
;Y registeri byte sayacı=0
loop0
lda
($fb),y
;O anki adresten bir byte oku
pha
;okunan değeri yığına at
iny
;sayacı 1 arttır
cpy
#$08
;8 oldumu ?
bne
loop0
;olmadıysa bir byte daha oku
ldy
#$00
;Y registeri byte sayacı=0
loop1
pla
;yığındaki değeri al
sta
($fb),y
;O anki adrese yaz
iny
;sayacı 1 arttır
cpy
#$08
;8 oldumu ?
bne
loop1
;olmadıysa yeni değeri al.
Yukarıdaki komutlarla bir karakteri baş aşağı çeviriyoruz. Burada asıl can alıcı nokta "YIĞIN" dediğimiz bölgenin kullanılmasıdır Yığın "LIFO" -Last In First Out- mantığıyla çalışır. Yani yığına atılan en son sayı ilk önce geri alınır. Bizim komutlar ilk çalışmaya başladığında önce $3000'den itibaren ilk 8 byte'ı okuyup yığına atmaktadır. Böylece yığına en son $3007 adresindeki değer atılmış olmaktadır. Yığından geri alma işlemi sırasında ise ilk önce $3007 adresinin değeri alınmaktadır. Bu işlemi 8 defa tekrarladığımızda ise bir karakterin datalarını kendi içinde tersten yerleştirmiş oluyoruz. Aşağıdaki tablo daha açıklayıcı olacaktır.
$3000 --> yığın --> $3007
$3001 --> yığın --> $3006
$3002 --> yığın --> $3005
$3003 --> yığın --> $3004
$3004 --> yığın --> $3003
$3005 --> yığın --> $3002
$3006 --> yığın --> $3001
$3007 --> yığın --> $3000
lda
$fb
;Karakter setinin LO adresini al
clc
;Elde bitini sfırla
adc
#$08
;8 ile topla
sta
$fb
;LO adrese geri yaz.
bcc
next_char
;Toplama sonucu "elde" biti "0" ise git
inc
$fc
;Karakter setinin HI adresini 1 arttır
next_char
lda
$fc
;HI adresi al
cmp
#$40
;#$40 oldumu? Olmadıysa bir sonraki
bne
loop2
;karakter için işlemleri tekrarla
rts
;Olduysa programı bitir.
.end
Gördüğünüz gibi kısacık bir programla $3000-$4000 arasındaki karakter
setimizi baş aşağı çevirmiş olduk. Programın listesini “program dökümleri”
sayfasında bulabilirsiniz. Ekran görüntülerimiz ise aşağıdadır.


Normal karakter setli ekran görüntüsü Ters karakter setli ekran görüntüsü. Bir başka karakter setinde görüşmek dileğiyle.