Bu sayfadaki yazılar
Sayfanın metni
Sayfa 20
C64 TÜRKİYE #7 20 İşte bunun için IRQ vektörünü değiştirmeden önce SEI komutunu kullanıp işlemciye sen şimdilik interruptları unut, biraz bekle diyoruz. IRQ vektörünü değiştirip CLI komutuyla işlemciye kaldığın yerden devam et diyoruz. Bu arada kendi IRQ rutinimiz de yazmalıyız ki CLI komutundan sonra işlemci IRQ vektörü üzerinden bizim rutinimize uğradığında çalıştırabilecek bir şeyler bulsun. Kendi IRQ rutinimizi yazdık ama bir sorun var gibi. Normalde bir assembler programı yazıldığında, program bir kez çalışacaksa program sonunda “RTS” komutu, sürekli çalışacaksa “JMP prg. başlangıcı” komutu olmalıdır. IRQ rutinlerinde ise işiniz bittikten hemen sonra mutlaka JMP $EA31 veya JMP $EA81 komutu kullanılmalıdır. Aslında JMP $EA81 komutu $EA31 adresindeki rutinin sonunda yer alır ve ikisinin arasında kursör yakıp söndürme, klavye tarama gibi işlemler yapılır. Eğer JMP $EA31 kullanırsanız kendi IRQ rutininiz çalışırken hiçbir şey olmamış gibi klavyeyi kullanabilir veya bir başka assembler rutini çalıştırabilirsiniz. Eğer $EA81 kullanırsanız sadece IRQ rutinleri çalışmış olacaktır. Dikkat ettiyseniz -JMP $EA31 kullanırsanız hiçbir şey olmamış gibi klavyeyi kullanabilir veya başka bir assembler rutin çalıştırabilirsiniz- ifadesini kullandım. Yani aynı anda iki program çalışabilir gibi bir durum var. Şimdi biraz başa dönelim ve interrupt kelimesinin anlamlarına bir daha bakalım. “Akışını durdurmak, yarıda kesmek” demişiz. İnterrupt mikroişlemcinin içinde saniyede 60 kez oluşur, yani asıl çalışan program saniyede 60 kez durdurulur, interrupt rutini çalışır ve işlem bittikten sonra asıl program kaldığı yerden çalışmaya devam eder. Bu nedenle interrupt rutiniyle asıl program aynı anda çalışıyormuş gibi görünür. (SEI komutu işlemci içinde interrupt işlemlerini durdurur) Özetleyecek olursak; 1- İnterrupt vektörü $0314 ve $0315 adreslerinde bulunur. 2- Bu vektörü değiştirmeden önce SEI komutu kullanılmalıdır. 3- Vektör değiştirildikten sonra CLI komutu kullanılmalıdır. 4- Eğer vektörü değiştirdiyseniz kendi rutininiz mutlaka olmalıdır. 5- Kendi rutininizin son komutu mutlaka JMP $EA31 veya JMP $EA81 olmalıdır. 6- İnterrupt saniyede 60 kez meydana geldiği için kendi interrupt rutininiz içinde sonsuz döngü veya çok sayıda iç içe döngü olmamalıdır. Yani rutininizin çalışma süresi 1/60 saniyeden uzun olmamalıdır. İşte örnekler.... *=$0900 start sei ;İnterruptları durdur lda #<user ;kullanıcı rutini adresinin LOW byte’ını sta $0314 ;IRQ vektörü LOW byte adresine yaz ldx #>user ;kullanıcı rutini adresinin HIGH byte’ını sta $0315 ;IRQ vektörü HIGH byte adresine yaz cli ;İnterruptları serbest bırak rts ;BASIC’e dönüş user jmp $ea31 ;İşletim sistemi IRQ rutinine geri dön .end İlk örnekte sadece irq vektörünü nasıl değiştireceğimizi öğreniyoruz. Kendi rutinimizde hiçbir işlem yapmayıp doğrudan işletim sisteminin interrupt rutinine geri dönüyoruz. 2. örnek *=$0900 start sei ;İnterruptları durdur lda #<user ;kullanıcı rutini adresinin LOW byte’ını sta $0314 ;IRQ vektörü LOW byte adresine yaz ldx #>user ;kullanıcı rutini adresinin HIGH byte’ını sta $0315 ;IRQ vektörü HIGH byte adresine yaz cli ;İnterruptları serbest bırak rts ;BASIC’e dönüş user inc $d020 ;Ekranın dış rengini değiştir. jmp $ea31 ;İşletim sistemi IRQ rutinine geri dön. .end
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 21
C64 TÜRKİYE #7 21 2. örnekte ise çok basit bir şekilde “flashing border” efekti yaptık. Bunun için INC $D020 komutunu kullandık. $D020 adresinde ekranın BORDER dediğimiz dış kısmının renk değeri bulunur. “inc $d020” komutu ise bu adresin değerini 1 arttırır. Böylece renk değişmiş olur. Bu işlem saniyede 60 kez yapıldığı için ekran flash yapıyor gibi gözükür. 3. örnek *=$0900 start sei ;İnterruptları durdur lda #<user ;kullanıcı rutini adresinin LOW byte’ını sta $0314 ;IRQ vektörü LOW byte adresine yaz ldx #>user ;kullanıcı rutini adresinin HIGH byte’ını sta $0315 ;IRQ vektörü HIGH byte adresine yaz lda #$00 ;başlangıç değeri 0 sta cnt ;cnt (sayaç) adresine yaz cli ;İnterruptları serbest bırak rts ;BASIC’e dönüş user dec cnt ;sayacı 1 azalt bne exit ;sıfır olmadıysa “exit” yazan yere git inc $d020 ;sıfır olduysa ekranın dış rengini değiştir. exit jmp $ea31 ;İşletim sistemi IRQ rutinine geri dön. cnt .byte 0 .end 3. örnekte ise interrupt içinde sayaç kullanmayı gördük. İşletim sistemi rutinimize her uğrayışında sayacın değerini 1 azaltmakta ve sayaç değeri 0 olmadıysa rutinden çıkmaktadır. Eğer sayaç değeri 0 olduysa ekranın dış rengi değiştirilmektedir. Yaklaşık 6-7 saniyede bir ekranın dış rengi değişmektedir. Eğer daha kısa zaman süresi isterseniz sayaç değerini belli değer için kontrol etmeniz gerekmektedir. Mesela sayaç değerini $40 (64) olarak belirleyin. Yaklaşık 2 saniyede bir renk değişecektir. Şu anki haliyle sayaç değeri 0 gözükse bile aslında 256 dır. Nasıl oluyor derseniz açıklayalım. Sayacın ilk değeri sıfırdır. Rutinimizin ilk komutu “DEC CNT” olduğundan sayacımız bir azalmakta ve 255 olmaktadır. Rutinimize her uğrayışta sayaç bir azaltıldığı için ancak 256. kez uğrandığında tekrar 0 olmakta ve renk değiştirme işlemi yapılmaktadır.
TARAMA SATIRI İNTERRUPTI (RASTER LINE INTERRUPT)
C64’te çeşitli interrupt kaynakları vardır. Bunlardan 4 tanesi VIC ile, 5 tanesi CIA dediğimiz 6526 ile ilgilidir. Aslında C64’te 2 adet 6526 olduğu için C64’teki interrupt kaynağı 14 adettir diyebiliriz.
VIC’e ait olan interruptlar şunlardır.
1- Tarama satırı interruptı 2- Sprite-arkaplan çarpışması interruptı 3- Sprite-sprite çarpışması interruptı 4- Light pen interruptı CIA’lara ait olan interruptlar ise şunlardır.
1- A zamanlayıcısı interruptı 2- B zamanlayıcısı interruptı 3- Gün saati alarm interruptı 4- Seri port dolu/boş sinyali interruptı 5- /FLAG (user port’ta bulunur) girişi interruptı
Yukarıdaki interrupt kaynaklarından en çok kullanılanı tarama satırı interruptıdır. Tarama satırı (raster) bir ekran görüntüsü oluşturulurken VIC tarafından üretilir ve bu satırın (rasterin) değeri $D012 adresinde tutulur ve sürekli değişir. $D012 adresi çift fonksiyonlu bir register olup okunduğunda o anki raster konumunun en alt 8 bitidir. 9.bit ise $D011 adresindeki registerin en soldaki (7.bit) bitidir. Normalde kullanılabilen ekran bölümü 51 ($33) ile 251 ($FB) raster satırları arasındadır. $D012’ye ve $D011’in 7. bitine yazılacak bir değer iç raster karşılaştırmasında kullanılır. O anki raster değeri