Bu sayfadaki yazılar
Sayfanın metni
Sayfa 129
Çünkü bu yöntem çarpma işlemi gerektiriyor ve Commodore'da çarpma işlemi yapmak da başlı başına bir meseledir. Ayrıca 8 bitlik bir sayıyla 8 bitlik bir sayıyı çarpıp 16 bit sonuç elde etmek nispeten açıklaması kolay bir durumdur. Ancak x koordinatı 9 bit olduğu için 16 bitlik bir sayıyla 8 bitlik bir sayıyı çarpan ve 24 bit sonuç veren bir rutine ihtiyaç vardır ve bu noktada işler gittikçe zorlaşıyor. Elbette ki 9 bitlik koordinat sisteminin hassasiyeti bir miktar bozularak bu işi sahte yöntemlerle çözmek mümkün. Ama şu seviyede bu tür konulara girmeyi uygun görmediğim için sabit tablolardan okunan değerleri olduğu gibi kullanmayı tercih ettim.
İşler giderek detaylanıyor ve bu sayıda da burada bırakıyoruz. Sizlere iyi beyin jimnastikleri diliyorum.
Benimle irtibata geçmek isteyenler için e-mail adresim;
skate <at> glance <dot> ws (mailto:c64hydrogen@yahoo.com)
Emir Akaydın
Skate / Glance / Clash
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 128
Gelelim elips örneğine. Burada VIC Simülatör'ündeki;
x = 160 + 160 * Math.cos(i / 128 * Math.PI);
y = 100 + 100 * Math.sin(i / 128 * Math.PI);
satırlarını nasıl uyarladık? Aslında çıtayı iyice yükseltmemek için kötü bir yöntem kullandık. Öyle ki bu çizdiğimiz elipsin çaplarından birini bile değiştirmek istesek "sinus.htm" dosyasını değiştirip, yeni sinüs tabloları elde edip, çıktıları "elipsciz.a" kaynak koduna yapıştırdıktan sonra programı yeniden derlememiz gerekecek. Peki neden?
Sorunu şöyle ele alalım. Commodore 64'de sinüs fonksiyonu yok. Peki sinüs fonksiyonunu nasıl uyarlayabiliriz? Aslında matematiksel olarak bunun yöntemleri var, hatta hatta çok kısa assembler kodlarıyla bile sinüs hesaplatılabiliyor. Ancak en hızlı yöntem önceden hazırlanmış bir tablo. Peki bu tabloyu hafızada nasıl tutacağız?
Sinüs fonksiyonu ne yazık ki yalnızca ondalıklı sonuçlar vermekle kalmıyor, hatta hatta yalnızca -1 ile 1 arası sonuçlar veriyor. Bu durumda byte değerleri tam sayı olduğu için küsuratları atacak olursak, tabloda yalnızca -1, 0 ve 1 değerleri bulunur. Bytelar negatif değerler de alamayacağı için muhtemelen -1 yerine 7 bit kullanarak (en soldaki bit pozitif negatif işareti belirtecek şekilde) 255 ya da 128 benzeri bir değer kullanmamız gerekecektir. En mantıklı yöntem sin(x) değil de a*sin(x)'i tablolamak. Bu durumda küsurat kaybından önemli ölçüde kurtulmuş oluyoruz. Kaybolan küsuratlar ise bu tür bir örnekte hiç önemli değil. Ancak negatif sayılarla ilgili problemimiz hala devam etmekte. Bu durumda JavaScript'deki örneğin birebir aynısını tablolayarak bu işi çözüyoruz yani a + a * sin(x)
Burada x ve y için a değerleri 160 ve 100 olduğuna göre;
160 + 160 * cos(x)
100 + 100 * sin(x)
hesaplamamız gerekiyor. Cosinüs fonksiyonu sinüs tablosunu biraz ilerden okumaya başlayarak elde edilebildiği için cosinüs ayrıca tablolanmıyor yalnızca sinüs tablosu peş peşe iki kez hafızaya konuluyor.
Burada yaşanan son sorun x koordinatlarında çıkıyor. x 255 değerini geçtiği ve tek byte ile ifade edilemediği için iki tabloya bölünmek zorunda kalıyor. Bir tablo alt 8 bitini 1 byte ile ifade ederken diğer tablo ise 9. bitini bir byte ile ifade ediyor. Bu hesaplama işleri "sinus.htm" dosyasında halledildikten sonra kaynak koda yerleştiriliyor ve basit bir döngüyle tablodaki hazır değerler okunarak ekrana pixeller yerleştiriliyor. Peki buradaki yöntem ne derece yanlış?
Aslında yöntem hemen hemen doğru. Tek eksik tabloların sabit değerlerle çarpılarak hazırlandıktan sonra olduğu gibi kullanılması. Olması gereken tabloların mümkün olan en geniş değerlerle hesaplandıktan sonra bir katsayıyla çarpılarak kullanılmasıdır. Mümkün olan en geniş katsayıya örnek vermek gerekirse buradaki formülde 8 bitlik bir tablo için en geniş "a" değeri 128'dir. Yani 128 + 128 * sin(x) şeklinde 0 - 255 arasındaki değerler elde edilebilir. 256'ya taşma önlenmek amacıyla 128 + 127.9 * sin(x) haline getirilmesi gerekebilir. Neden bu yöntem kullanılmadı?