ROM RUTİNLERİ

NEREDEN : İSTANBUL NİCK / GRUP(LAR) : HADES / HI3S WEB SİTE : WWW.HI3S.ORG HTTP://HADES6510.SITEMYNET.COM

(Programlar C64ASM V1.1 ile compile edilecek şekilde yazılmıştır) ROM rutinlerini tanıtmaya devam ediyoruz. İlk adresimiz $A3BF (41919). ADRES : $A3BF (41919) GÖREVİ : Data blok taşıma. Bu adresi bellekteki bir bölgeyi başka bir yere taşıma amaçlı olarak kullanabilirsiniz. Zero Page’de bulunan 6 adet adresi kullanıp istediğiniz uzunluktaki bir bölgeyi taşıyabilirsiniz. Şimdi bir örnek ile bu adresin nasıl kullanıldığını öğrenelim. Örneğimizde $c000-$c750 arasındaki bölgeyi $2600-$2d50 arasına taşıyalım. *=$0801 .word nextline .word 2004 ; 2004 .byte $9e ; SYS .text "2061" ; 2061 .byte 0 ; komutu nextline .word 0 transfer1 lda #$00 ;Başlangıç adresi LOW byte ldx #$c0 ;Başlangıç adresi HIGH byte sta $5f ;Başlangıç LOW byte pointer stx $60 ;Başlangıç HIGH byte pointer lda #$50 ;Bitiş adresi LOW byte ldx #$c7 ;Bitiş adresi HIGH byte sta $5a ;Bitiş LOW byte pointer stx $5b ;Bitiş HIGH byte pointer lda #$50 ;Hedef bitiş adresi LOW byte ldx #$2d ;Hedef bitiş adresi HIGH byte sta $58 ;Hedef bitiş LOW byte pointer stx $59 ;Hedef bitiş HIGH byte pointer jsr $a3bf rts Transfer işlemini yapan rutin 28 byte yer kaplamaktadır. Bu adresin kullanılışı şöyledir. Kopyalayacağınız bölgenin başlangıç adresi $5f-$60 adreslerine, bitiş adresi $5a-$5b adreslerine, yeni bölgenin bitiş adresi ise $58-$59 adreslerine yazılır ve rutin çağrılır. Bu rutini kullanacağınız zaman BASIC ROM'un devrede olması gereklidir. Aynı taşıma işlemini bir de başka rutin yazarak yapalım. Taşınacak bölgenin uzunluğu $c750-$c000=$0750 byte olup 8 döngüde rahatça transfer edebiliriz.

transfer2 
ldx 
#$08  
;Döngü sayacı 
ldy 
#$00  
;Byte sayacı 
kaynak 
lda 
$c000,y 
;Kaynak adresi 
hedef  
sta 
$2600,y 
;Hedef adresi 
iny 
bne 
kaynak 
inc 
kaynak+2 
inc 
hedef+2 
dex 
bne 
kaynak 
rts 
Transfer2 rutinimiz 23 byte uzunluğundadır. Yani üstteki rutinden  
5 byte daha kısadır. Ama bana göre 2 dezavantajı vardır. Birincisi : Transfer1  
rutininde istediğiniz uzunlukta byte transfer edebilirken, transfer2 rutininde 
transfer edilen byte uzunluğu 256'nın katları şeklinde olacaktır. Transfer1  
rutininde $0750 (1872) byte transfer edilirken, transfer2 rutininde 
256'nın katları şeklinde olduğu için 2048 byte transfer edilecektir. Eğer  
hafıza düzenlemeniz biraz karışıksa fazladan transfer edilen 1 byte bile 
programınızın bozulmasına neden olabilir. Bununda çaresi var aslında. 
Önce $0750 byte'ın $0700 byte'ını transfer edersiniz, sonrada uygun $50 byte 
için işlem yaparsınız. Bu ise fazladan 9 byte'lık bir code demektir. 
İkinci dezavantaj ise, transfer2 rutinini bu şekliyle sadece bir kez 
kullanılabilir. Çünkü kaynak ve hedef adreslerinin high byte'ları her 
döngüde 1 arttırılmaktadır. Eğer rutini ikinci kez kullanmak istiyorsanız, 
rutinin başında kaynak ve hedef adreslerinin high bytle'rını program 
içindeki yerlerine yazmanız geerekir. Bu işlem ise 10 byte daha  
kullanmak demektir. Böylece TRANSFER1=28 byte, TRANSFER2=33 byte yer  
kaplamış olacak, ayrıca 1. dezavantaj yine devam edecektir.  
ADRES  
: $E8EA (59626) 
GÖREVİ 
: Ekranı bir satır yukarı kaydırma. 
The anatomy of a COMMODORE 64 isimli kitapta SCROLL SCREEN olarak 
isimlendirilen bu rutin ekranı bir satır yukarı kaydırır. Normalde ekranın 
yukarı kayması için kursörün en alt satırda olması ve RETURN veya CURSOR DOWN 
tuşuna basılmış olması gerekir. Bu adres ise kursörün pozisyonunu dikkate 
almayıp ekranı olduğu gibi bir satır yukarı kaydırır. Peki bu adresle ne 
yapılabilir? Mesela Basic'e ROLL komutu ekleyip, Basic ile hazırladığınız bir 
açılış ekranını 1 satır yukarı kaydırıp, üstten kaybolan satırı en alt satırda 
tekrar çıkartabilirsiniz. Tabii bunun için gerekli olan programı yazmanız lazım. 
İsterseniz bu efekti ufak bir assembler rutiniyle yapmayı deneyelim. 
*=$0801 
.word nextline 
.word 2004  
; 2004 
.byte $9e 
; SYS 
.text "2061" 
; 2061 
.byte 0 
; komutu 
nextline 
.word 0 
ldx 
#$00  
;Sayacı sıfırlayalım 
loop0  
lda 
$0400,x 
;Ekranın ilk satırındaki 
sta 
temp0,x 
;bilgileri kopyalayalım 
lda 
$d800,x 
;Aynı işi renk belleği 
sta 
temp1,x 
;için de yapalım. 
inx 
;sayacı 1 arttır 
cpx 
#$28  
;40 oldu mu? 
bne 
loop0  
;olmadıysa tekrarla 
jsr 
$e8ea  
;Olduysa ekranı 1 satır yukarı kaydır
ldx 
#$00  
;sayacı sıfırlayalım 
loop1  
lda 
temp0,x 
;kopyaladığımız değerleri ekranın 
sta 
$07c0,x 
;en alt satırına yazalım. 
lda 
temp1,x 
;Aynı işi renk belleği 
sta 
$dbc0,x 
;için de yapalım. 
inx 
;sayacı 1 arttır 
cpx 
#$28  
;40 oldu mu? 
bne 
loop1  
;olmadıysa tekrarla 
son 
rts 
;evet oldu. Öyleyse çıkalım. 
temp0  
=son+1 
temp1  
=temp0+40 
.end 
Eğer bu efekti $EA8A adresini kullanmadan yapsaydık oldukça uzun 
bir program yazmak zorunda kalacaktık. 
ADRES  
: $FFF0 (65520) 
GÖREVİ 
: Kursör pozisyonunu ayarlama / okuma 
Romda öyle rutinler vardır ki sizleri birçok işten kurtarır. Birazdan 
anlatacağımız bu rutinde bunlardan biridir. Bir program yazmaya başladınız ve 
ekranın 12. Satır 10. Sütun pozisyonundan başlayan 10 harflik bir yazı yazmanız 
gerekiyor. Bu işlemi normalde iki şekilde yapabilirsiniz. Birinci olarak ekranın 
ilgili pozisyonunun ekran belleği adresini öğrenip yazınızı ekran kodu olarak 
yazdırırsınız. İkincisi kursörü önce en üst köşeye alırsınız. Daha sonra 
“return” tuşunun kodunu kullanarak kursörü istediğiniz satıra getirirsiniz. 
Yazacağınız yazıya biraz “boşluk” karakteri ekleyerek istediğiniz pozisyona 
yazmış olusunuz. İkisinden birini tercih edin. Birinci seçenekte ekran 
belleğinin adresleriyle uğraşırsınız. İkinci seçenekte ise fazladan byte 
kullanarak programınızı uzatırsınız. 
Aranızda “Başka bir alternatif yok mu ?” diye soranlar olabilir. Evet var. 
KERNAL ROM’da, işletim sistemi rutinleri için sıçrama tablosu denilen ve Rom’un 
son 128 byte’ında yer alan, direct ve indirect jump komutlarından oluşan bir 
bölge vardır. Bu bölgenin $FFF0 adresi tam bize göredir. Ekranın istediğiniz 
yerine bir yazı yazmak için yapmanız gereken işlemler şunlardır. Önce “carry” 
bitini sıfırlayın. Sonra X registerine satır numarasını, Y registerine süttun 
değerini yükleyin. En son olarak bir JSR komutuyla rutini çağırın. Böylece 
kursörün pozisyonunu ayarlamış olduk. Daha sonra ise geçen sayıda tanıtmış 
olduğumuz $AB1E adresini kullanarak yazıyı ekrana yazdırın. İsterseniz buraya 
kadar yazdıklarımızla ilgili örnekler verelim. 
Yazımız 10. Satır 5. Sütunda olsun. 
İlk önce doğrudan ekran adresi vererek bu yazıyı yazdıralım. Bu arada ufak bir 
not düşelim. Vereceğimiz örneklerde satır ve sütun numaraları “0” dan 
başlamaktadır. Program yazarken buna dikkat edin. 
POZİSYON = EKRAN BELLEĞİ BAŞLANGIÇ + SATIR * 40 + SÜTUN formülüne göre adresi 
hesaplayalım.  
EKRAN BELLEĞİ BAŞLANGIÇ ADRESİ = 1024 
POZİSYON = 1024 + 10*40 + 5 = 1024 + 400 + 5 = 1429  ($0595) 
Şimdi yazıyı yazdıralım. 
ldx 
#$00 
loop0  
lda 
text,x 
sta 
$0595,x 
inx 
cpx 
#$0b 
bne 
loop0 
rts 
text  
.scrl “c64 turkiye”

İşin hesaplama kısmı olmasa her şey çok güzel olacak. Şimdi de ikinci şıkkı deneyelim. jsr $e544 ldx #$00 loop0 lda text,x jsr $ffd2 inx cpx #$1a bne loop0 rts text .byte $0d,$0d,$0d,$0d,$0d,$0d,$0d,$0d,$0d,$0d .byte $20,$20,$20,$20,$20 .text “c64 turkiye” $0d sayısı return tuşunun, $20 sayısı ise “boşluk” karakterinin kodudur. Şimdi de $FFF0 adresini kullanarak yazıyı yazdıralım. clc ;”carry” bitini sıfırla ldx #$0a ;satır değeri ldy #$05 ;sütun değeri jsr $fff0 ;kursörü ayarla lda #<text ldy #>text jsr $ab1e rts text .text “c64 turkiye” .byte 0 Örnekleri karşılaştırarak hangisi daha kolayınıza geliyorsa onu kullanın. Şimdi de kursörün pozisyonunu okuyalım. sec ;”carry” bitini “1” yap jsr $fff0 ;rutini çağır. ... ... rts

Rutinden geri dönüşte kursörün satır değeri X registerinde, sütun değeri ise Y registerinde bulunur.

Bildiğiniz gibi C64’ün BASIC komutlarında kursörle ilgili bir komut yoktur. $FFF0 adresini kullanarak, kursörü istediğiniz pozisyona getirmek için “CURSOR” komutu ekleyebilirsiniz. CURSOR 10,10 : PRINT “C64 TURKIYE” vs. kullanmak ne güzel olurdu değil mi? (Bu yazıyı yazdıktan sonra “HADES’BASIC” bölümüne “CURSOR” komutunu ekledim.)