C64 için Püf Noktaları
Retro bilgisayarMAKİNA DİLİNİN PÜF NOKTALARI
Hepinize merhaba. Bu ay da sizlerle birlikteyiz ve yazımıza makina dilinin interruptlarını anlatarak devam ediyoruz. daha önce de bir "kayan yazılar” (smooth scroll) programı yayınlamıştık. Ama bu program RASTER INTERRUPT tekniklerini kullanmadığı için aynı rutinin interruptlarla çalışan versiyonunu anlatacağız. Konuya girmeden önce interruptların çalışma prensibini detaylı olarak inceleyelim. İnterruptlar yapı olarak ikiye ayrılırlar: 41) IRE (maskelenebilir interruptlar): Programcının, kullanacağı bir SEl komutuyla bu interrupt'ın oluşmasını engelleyebilmesi, bu tür interruptlara maskelenebilir interruptlar denmesine yol açmıştır. İstendiği anda oluşması engellenebildiği için programcıların kullanımda tercih ettikleri bir yöntemdir. VIC tarafından üretilen (ve bizim işimize yarayan) dört çeşit IRO bulunur: a) RASTER interrupt: Ekranı tarayan elektron ışınının hangi satırda bulunduğu C-64'ünüz tarafından bilinir ve $DO12 adresinde tutulur. Eğer isterseniz elektron belirli bir satıra geldiği zaman 64'ünüzün bir İnterrupt oluşturmasını sağlayabilirsiniz. Fakat bilmeniz gereken şey RASTER satırlarının normal ekran satırlarıyla aynı olmadığıdır. 1. tabloda da açıkça gördüğünüz gibi yazılabilir ekranın 1. pikseli 50. raster satırına denk gelmektedir. 0. raster satırı ise genelde televizyonlarda görülmeyecek kadar yukarıda bulunur. Tablomuzda dikkat etmeniz gereken başka bir şey de en alt raster satırının 255'ten büyük olduğudur. Bir bayttâ en fazla 255 sayısını tutabildiğimize göre ekranın altında bulunan elektronun yerini nasıl saptayacağız peki? Bu:
sorunu çözmek için C-64'ün tasarımcıları adresinin RASTER satırının 9. biti olarak ayırmışlar. Bu sayede $DO14 ve $DO12 adreslerini kullanarak (512) satırı adresleyebiliriz. Bu sayı da ekranınızda görünen raster satırların hepsini tanımlamaya yeterlidir. Bir RASTER INTERRUPT oluşmasını sağlamak için $DO12 adresine ve adresinin 8. bitine İnterrupt oluşması istenen satırın numarasını yazmak ve adresinin 1. bitinin değerini 1 yapmak yeterlidir. ($DO1A— $01) Bu işlemlerden sonra elektronün belirlenen satıra her gelişinde bir interrupt oluşturulacaktır.
Tablo 1: İşte bir ekranın raster numaraları. Görünen ekran 50. satırdan başlıyor ve 250. satırda sona eriyor. En alt satırın numarası belirli değildir ve TV ekranının dışında sona erer.
b) Light Pen (ışıklı kalem) interrupt'ı: C-64'ümüz aslında elektronun yalnızca hangi satırda olduğunu degil hangi x koordinatında olduğunu da bilmektedir ama elektronun ekranı tarama hızı çok yüksek olduğundan x koordinatını herhangi bir bellek alanına yazmaya vakti yoktur. Ama lightpen kullanmanın temeli elektronu belirli bir x,y koordinatında yakalamak olduğundan C-64'ün herhangi bir yolla bize x koordinatını da bildirebilmesi gerekir. Lightpen elektronu yakaladığı anda bilgisayara bunu bildirir ve bilgisayar da © andaki x koordinatını $DO13, y koordinatını da $DO14 adreslerine yerleştirir. Lightpen yalnızca her taramada bir kez elektronu yakalayacağı için x koordinatını yazmak fazla bir zaman kaybına yol açmayacaktır. Bu arada eğer $DO1A adresinde 4. bitin değerini 1 yaparsanız ($DO1A — $08) x ve y koordinatları yazılır yazılmaz bir interrupt oluşturulacaktır. Bu sayede lightpen üzerinde etkin bir kontrole sahip olabilirsiniz. c) Sprite-Sprite çarpışması: Eğer C-64'ün sekiz sprite'ından Ji ikisi birbirine değerse ve adresinin 3. biti 1 $04) değerindeyse bir inter- Tupt oluşturulur.
d) Sprite-karakter çarpışması: Eğer bir sprite herhangi bir ekran karakterine değerse ve 2. biti 1 ise bir interrupt oluşur. Tabii ki bu interruptların birkaçını veya hepsini birden kullanabilirsiniz. Bunu yapmak için adresine, yapmak istediğiniz interrupt'ların değerlerini OR'layarak vermelisiniz. Mesela $D01A'ya $05 verirseniz RASTER ve LIGHTPEN interruptlarını aktive etmiş olursunuz. Bu durumda interrupt'un hangi sebepten dolayı oluştuğunu anlamak için interrupt rutininizin başında $D019 registerinin değerini incelemeniz gereklidir. Bu adresin bit anlamları $D01A'dakiyle aynıdır fakat interrupt hangi sebepten oluştuysa yalnızca o bitin değeri 1'dir. 2) (maskelenemez interruptlar): Aslında bu tür interruptlar konumuzun oldukça dışındadır çünkü NMI'lar genelde hardware (donanım) olaylarını kontrol etmek için yapılır. (Diskle iletişim vb.) Eğer bilgisayarınız bu tür bir interrupt yaratmak istiyorsa sizin programcı olarak yapabileceğiniz hiçbir şey yoktur. NMI kesinlikle gerçekleşir ve programa geri dönülür. Interrupt olayının mantığını kavradıktan sonra bir interrupt'un sizin rutininize atlamasını nasıl sağlayacağımızı tartışalım. C-64 ROM'unun en sonunda (yani $FFFE-$FFFF adreslerinde) IRQ rutini vektörleri bulunur. Bir interrupt oluştuğu anda işlenmekte olan komut bitirilir ve programın kesildiği adres yığına (stack) yazılır. Bundan sonra Flag'lerin tutulduğu durum registeri de buraya yazılır ve IRQ vektörlerinin gösterdiği adrese atlanır. Buradaki en büyük problem, bu vektörleri değiştirmek için ROM'u değiştirmek gerekmesidir. Bu işlemi program yardımıyla yapmak çok zor olduğundan bu vektörlerin gösterdiği adresi kontrol ederek bilgisayar yapımcıların bize bu olay üstünde kontrol hakkı tanımış olmalarını ummamız gerekiyor. Eğer Kernal interrupt rutinini incelersek rutinin en sonunda bir
TST
JMP (80314)
komutuyla karşılaşırız. Bu komut $0314 vektörü üzerinden bir dolaylı sçırama yapmaktadır. Yani RAM içinde bulunan $0314 ve $0315 adreslerinin değerini bizim rutinimizi gösterecek şekilde değiştirirsek ların oluşumu sırasında bizim rutinimize de uğranmasını sağlamış oluruz. Tabi ki rutinimizin sonunda, $0314 vektöründe önceden bulunan $EA31 adresine bir sıç- Tama yapmamız ve kontrolü tekrar KERNAL'a bırakmamız gereklidir. Eğer kontrolü KERNAL'a vermeden geri dönmek istiyorsanız (imlecin yanıp sönmesi, basılan tuşların kabul edilmesi gibi işlemlerin yapılması gereksizse sizin için) JMP SEA84 komutuyla interrupt'u terkedebilirsiniz. Bu adreste bulunan rutin yalnızca yeni bir İnterrupt'ın oluşmasına İzin verecek ve yığına Kernal tarafından yazılan değerleri geri okuyacaktır. NMI rutini için ayrılan vektör de adreslerinde bulunur. Bu kernal rutini de $0318-$0319 adresleriyle oynayarak NMI'ları da kontrol edebilirsiniz. Sanırım hepiniz yazımızın başında bahsettiğimiz Smooth Seroll programının nerede olduğunu merak ediyorsunuzdur. Program ve ayrıntılı açıklamalarını Program döküm eki'nde bulabilirsiniz. Hoşçakalın.