Makine Dilinin Püf Noktaları
Selam programcılar. Yepyeni bir sayıda, yepyeni tekniklerle karşınızdayız gene. Konuya geçmeden önce, geçen sayıda yaptığım uyarıyı tekrarlamak istiyorum. Her ay yeni konu bulmak benim için zorlaşıyor. İşin daha kötüsü, bulduğum konuların sizin işinize yarayacak şeyler olduğundan emin değilim. Bu sebeple, nasıl yapıldığını merak ettiğiniz intro ya da demo parçalarının detaylı bir açıklamasını, mümkünse programın kendisini veya ekranın bir fotoğrafını yollarsanız, size yardımcı olmaya çalışacağım. Hatta sadece yapılmış olan programları değil, yapmayı düşündüğünüz intro veya demonun başa çıkamadığınız kısımları hakkında da bilgi isteyebilirsiniz. Bu konuda mektuplarınızı Derginin 1. sayfasında yer alan Commodore Dergisi adresine, Vedat Hallaç adına yollayabilirsiniz. Katılımlarınızı bekliyorum. Bu ay, gene bir logo üzerine uygulanabilecek yeni bir efekt anlatacağım. Yapacağımız efekt, her raster satırında $D016 adresinin ilk üç bitinin değeriyle oynayarak, logoyu dalgalandırmaktan ibaret. Aslında bu efekti yaratmak için, yazı dizimin en başlarında açıkladığım renk şeritleri rutinini kullanabilirsiniz. Fakat bir taşla iki kuş vurmak amacıyla, rutinde (Exodus'un kullandığı ismiyle) saydırma tekniğini kullanarak zamanlama ayarlayacağız.
Geçen ayın yazısını okuduysanız, ekranda bulunan her karakter satırının ilk pikselinde belleğe doğrudan erişim yapıldığını ve programınızın işletilmesinin kesildiğini hatırlıyorsunuzdur. Bu sebeple, her raster satırında çerçeve rengini değiştirmek için bile sabit bir zamanlama kullanamazsınız. Demin bahsettiğim DMA (Direct Memory Access — Doğrudan Bellek Erişimi) satırlarında, bekleme miktarını azaltmanız gerekir.
Daha önce anlattığım renk rutininde, her komutun ne kadar zaman sürdüğünü dikkate alarak, sekiz satırda bir belli işlemleri atlıyorduk. Tabi ki bu işi yapabilmek için her komutun kaç birim zaman harcadığını bilmeniz gerekir. Komutların işletim süresini belirtmek için CYCLE birimi kullanılır. Çok ince zamanlama ayarlarında sık sık komut CYCLE'larını hesaplamanız gerekir. Mesela border'ı (çerçeveyi) yanlara doğru açmaya çalıştığınızda bir cycle'lık bir hata yaparsanız (ki bu süre, ekranı tarayan elektronun sekiz piksel (nokta) yol alması için geçen zamana denktir), yalnızca ekranı 38 kolona indirebilirsiniz. Bu arada en kısa sürede işletilen NOP komutunun iki cycle yediğini belirtmem gerek. Anladığınız gibi oturup komut cycle'larını hesaplamaya çalışmak oldukça kafa yedirici bir iş. Bu yüzden on-onbeş cycle'dan büyük zamanlama hesaplarında komut zamanlamaları yerine şimdi anlatacağım saydırma zamanlamasını kullanmamız daha yerinde (daha doğrusu: daha kolay) olacaktır. Eh gelelim şu tekniğin ne olduğuna. Aslında oldukça basit bir tekniktir bu. Temelinde, her raster satırının değişik miktarda zamanda aşılacağı düşüncesi yatar. Her raster satırının “uzunluğu” farklı olduğu için, bu satırların her birinde değişik miktarda beklersek, yani değişik bir sayıdan geri sayarsak, kısa ve genel bir program kullanarak DMA satırlarıyla, sprite bulunan satırlarla veya herhangi bir sebeple zamanlamamıza uymayan satırlarla başa çıkabiliriz. Bu genel program, yapması gereken işi yaptıktan sonra, bir zamanlama tablosundan, bulunduğu raster satırında ne kadar bekleyeceğini okur, gerekli miktar bekler ve bir sonraki satırın işini yapmaya geçer. Tabi ki bu işi hızlı bir şekilde yapmak için bazı kurallara uymanız gereklidir. Mesela, X ve Y register'ını raster satırı sayıcı olarak kullanmak zorundasınız. Bu sayede diğer Index Register'ına (X ve Y, index register'larıdır) beklenmesi gereken süreyi yükleyebilir ve bu register sıfır olana kadar sayabilirsiniz. Bunu yapmak için her satırda yapacağınız işler için iki register ayırmalı (A ve X veya A ve Y) geri kalanı sayaç olarak kullanmalısınız. Bunun yanında sayaç olarak kullanılmayan index register'ına sadece tek raster satırı içinde gerekli değerler vermelisiniz, çünkü raster satırında yap gereken iş biter bitmez bu register'a LDY Adres,X veya LDX Adres,Y komutuyla bekleme süresi (zamanlama baytı) yüklenecek ve register'ın değeri sıfır olana kadar geri sayılacaktır. Yani birden fazla raster satırında kullanmanız gereken değerleri bu zamanlama rutininden önce herhangi bir adrese saklamanız, geri saydırma işi bittikten sonra da buradan okumanız gereklidir. Eh saydırma tekniği oldukça basitmiş değil mi? Şimdi de saydırma tekniğini kullanarak ekran renginin her raster satırında değişmesini sağlayalım. Aslında bu işi düzgün bir şekilde yaptığınız anda $D016 dalgalanmasını da yapmışsınız demektir. İlk olarak bir interrupt başlangıç rutini yazın (Mesela $C000 adresine). Yaklaşık olarak $0030 raster satırında interrupt programınız başlasın. İlk iş olarak X'i 1'den 0'a kadar saydırın (size garip gelebilir ama dediğimi yapın). Bu döngünün sonucunda X'in değeri 0 olacağı için tekrar X'i sıfırlamaya gerek kalmaz. Daha sonra herhangi bir renk tablosundan X indeksiyle (Lda Renk,X) ekran rengini alın (Renk için $C100'ı seçebilirsiniz) ve bunu doğrudan doğruya $D021 adresine yazın. Sonra Y registerine zamanlama baytını alın (Ldy Zaman,Y) ve bunu sıfıra kadar geri saydırın (Zaman için $C200'ı seçebilirsiniz). X'i bir artırın ve değeri (mesela) 40 olana kadar bu işlemi tekrarlatın. D019'un değerini değiştirin ve sıçrayın. Eh bu kadar. Şimdi asıl zor kısma geldik işte. Tüm zamanlama baytlarını ayarlamanın zamanıdır. İlk iş olarak Renk tablosunu 0,1,0,1 ile doldurun. Bu sayede ardışık iki satırın farklı renkte olup olmadığını kolayca anlayabilirsiniz. Daha sonra da zamanlama tablosunu 8 ile doldurun. Programınızı çalıştırın ve doğru çalışmadığını görün. Şimdi
RUN STOP 4 RESTORE ile programdan çıkın ve monitör'e girin. İlk renk doğru yere gelene kadar interrupt'un başındaki X sayacının değeriyle oynayın. Ekranın ilk pikselinin başının rengi siyah olunca bu sayacı ayarlamışsınız demektir. Bundan sonra zamanlama tablosunun değerlerini ayarlamanız gerekecek. İkinci satırın rengi beyaz olana kadar zamanlama tablosunun ilk baytının değeriyle oynayın. İkinci satır beyaz olduğu anda ikinci zamanlama baytını düzeltin ve ardışık raster satırları farklı renk alana kadar tüm tabloyu ayarlayın. Satırlarınız siyah-beyaz-siyah sırasına girdiği zaman, renk tablosuyla istediğiniz gibi oynayın ve programınız kullanıma hazır duruma gelsin. Eğer zamanlama tutturmaya çalışırken bir raster satırının rengi satır başı yerine ortalarda bir yerde değişiyorsa, bir önceki satırın zamanlama baytının değerini bir azaltın. Artık programın nasıl tasarlanacağını da bildiğinize göre bizim programı anlatmaya geçebilirim: Program, bundan önce yaptıklarım gibi standart bir interrupt girişiyle başlamıyor. Daha önce Logo datalarını ekrana yerleştirme, karakter seti göstericisi olan $D018'in değerini düzeltme, logonun renklerini ayarlama ve multicolor'a geçme gibi bazı angarya işleri halletmemiz gerekiyor. Programı yazması kolay olsun diye rutinlerin hepsini ve grafik datalarını düzenli bir şekilde Basic başlangıç adresinin arkasına sıraladım ve Basic'den çağrılan bir rutinle gereken her şeyi yerli yerine taşıyıp ekran sallama rutinine sıçrıyorum. İlk yüklediğiniz programda rutinler ve datalar şu şekilde yerleşmiş durumdalar: $0D00-$1100: Logonun karakter dataları (FONT'u) $0B00-$0CFF: Logonun ekran dataları (MATRİS'i) $0880-$0AFF: Ekranı dalgalandıran rutin. Bu programlar gerekli yerlere taşındıktan ve ekranın renkleri ayarlandıktan sonra $C000'daki rutine sıçrıyoruz. Her zamanki standart interrupt başlangıçlarından biri yer almakta. Asıl işi $C030'dan başlayan interrupt programımız yüklenmiş durumda tabi ki. Raster satırı $002D olduğunda (garantili olsun diye biraz erken giriyorum) interrupt başlıyor ve X'i $39'dan geri saydırıyor. Bu sayede elektron ekranın ilk satırının tam başındayken $D016'yı değiştirme şansımız bulunuyor. Daha sonra $C070 adresinden, ilk satırın tam başına gelebilmek için gereken zamanlama baytını okuyoruz (önce bekleme yapıp sonra raster satırına ait işlemleri yaptığım için, bu rutinde 0. zamanlama baytı, ekranın başlangıcından bir önceki raster satırına ait zamanlama baytı oluyor). Gereken miktarda bekledikten sonra (elektron satırın başına gelince), $C0C0 adresindeki tablodan, gerekli kayma miktarının ilkini okuyor ve bunu $D016'ya yazıyoruz. Dikkat! Logonuz multi-color ise (çok renkli ise) D016'ya verilecek baytın $D0+Kayma (0 Kayma 8) olmasına çok dikkat edin. X'i bir arttırıyoruz ve bütün bu işlemleri X'in değeri $50 olana kadar tekrarlıyoruz. Yani 10 karakter satırını ($50/8 = 10($0A)) dalgalandırıyoruz. Bu işlemleri yapan kısa rutini aşağıda görebilirsiniz.
Bu işi bitirdikten sonra $D016'nın değerini eski haline çevirmeliyiz (ekranın X koordinatını sıfırlamalı ve kolon sayısını 40'a çıkarmalıyız). Yani $D016'ya Multicolor için $D8, normal için $C8 olursa tüm ekran siyah olacaktı. Programlarınızda bu tür ufak noktalara çok dikkat etmelisiniz. Hataların yüzde 90'ı bu tür noktalara gizlenirler çünkü. On satıra belli bir dalga şekli verildikten sonra, dalgalanmanın yukarı kayması için, $C111'de yer alan 256 baytlık sinüs tablosundaki yerimizi bir ileri alıyoruz ve bu yeni yerden $50(80) baytı $C0C0 adresine okuyoruz. Böylece gelecek ekran taramasında dalgalanma şeklimiz bir piksel yukarı kaymış oluyor. Eğer ne demek istediğimi tam olarak anlayamadıysanız, $C061'de bulunan INC $C110 komutunu LDA $C110'a çevirin ve bu sayede sinüs tablosundaki yerimizin ilerlemesini durdurun. Programı bu halde (SYS 49152, G
C000) çalıştırdığınızda dalganın niye yukarı kayması gerektiğini anlayacaksınız. Bu işlemi yapan rutin de aşağıda yer almaktadır.
— PROGRAM>2
., CO50 Ldy $C110
., €055 Lda XY
Sta $coco,x —
Inx
#$50
Bne $C055
Inc $C110; sayaç
Gördüğünüz gibi oldukça basit programlar kullanarak çok hoş bir efekt elde etmemiz mümkün. Fakat bu rutinde asıl göz alıcı nokta, sinüslerin hoş bir şekilde dizilmesi (benim yaptığım gibi değil) olacaktır. Bunu yapmak için belli birkaç adrese uzunlukları, 8, 16, 24, 32, vb. olan sinüsler yerleştirin (benim kullandığım programda 16 ve 32 baytlık sinüsler var sadece). Daha sonra bu sinüslerin tamamını, yarısını, çeyreğini, vb. değişik kombinasyonlarla (Birinin yarısını diğerinin ikinci yarısıyla birleştirerek bile olabilir) asıl sinüs tablosuna dizin. 0'dan 7'ye kadar değerler alabilecek bu sinüs baytlarını multicolor (çok renkli) ekran modu için $D0'la, normal (iki renkli) ekran modu için $C0'la ORA'layın (ya da değerlerine $C0 veya $D0'ı ekleyin). Programın tablo uzunluğunu doldurunca da bu halini saklayın (kasede veya diske) ve daha sonra programınızı çalıştırın. Her tür intro'da kullanılabilecek hoş bir efekt elde etmiş olacaksınız. Şimdi de size bir soru... Eğer logonun ardışık satırlarının ayrı bir sinüs ile dalgalanmasını isterseniz (1. piksel sinüsün en tepesindeyken ikinci en altında olacak şekilde mesela... Fakat hemen sonra 1. piksel maksimumun bir altına, 2.'si ise minimumun bir üstüne çıkmalı, ya da daha açıkçası 1. piksel minimuma 2. ise maksimumun bir altı olmamalı) bu programı kullanabilir misiniz? Kullanabilirseniz nerelerini değiştirmeniz gereklidir? Eh, bu aylık bu kadar. Gelecek ay görüşmek üzere hoşçakalın.
|
| |