[title = Test Platformu - Bölüm 3]
Yeni bir sayıda tekrar merhaba sevgili Plazma okurları. Plazma'nın ilk sayısından beri süre gelen "Test Platformu" bu sayıda artık daha da detaylı bir biçimde devam ediyor. Önceki sayıları okumamış başlangıç seviyesindeki programcılar bu sayıda zorlanabilirler. Her sayı birbirinin devamı niteliğinde olduğu için bu bölümü okumadan önce bölüm 1 ve bölüm 2'yi okumanızı tavsiye ediyorum.

[b]Bu Bölümde Neler Anlatılacak?[/b]

• Bu yazı dizisinin misyonu Commodore 64 için PC destekli yazılım geliştirmeyle ilgili yöntemler sunmak olduğu için bu sayıda öncelikle JavaScript'den bir "VIC Simülatörü" nasıl hazırlanır onu göreceğiz. Bu VIC Simülatörü, Commodore 64'ün ekran çipi olan VIC'in hafızadaki byte dizilişini ekrana nasıl yansıttığıyla ilgili bir simülasyon yapacak. Bu sayede bir efekti Commodore 64'de programlamaya başlamadan JavaScript'den çeşitli testler yapabileceğiz.

• VIC Simülatörünü kullanarak bir nokta basma rutini hazırlayacağız. Bu rutin ekranda verilen x ve y koordinatına nokta koyacak.

• Aynı örnek içersinde basit bir sinüs, cosinüs hesabıyla ekrana tam sınırlarına denk gelecek şekilde bir elips çizdireceğiz.

• Daha sonra Commodore 64 üzerinde grafik ekranı açıp ekrana nokta basma işleminin nasıl yapıldığını kod örnekleriyle göreceğiz.

• Sonraki adımda VIC Simülatöründen denediğimiz elips çizdirme rutininin nasıl Commodore 64'e aktarılabileceğini inceleyeceğiz.

• En son olarak da bu son yaptığımız işlemin Commodore 64'e aktarma işleminin eksik, zayıf yönlerini ve alternatiflerini tartışacağız. Ancak diğer yöntemleri sonraki bölümlere saklayacağız.

[b]VIC Simülatörü[/b]

Çok uzun bir zamandır VIC simülatörü türü birşeyi JavaScript'den yapmak istiyordum. Aslında C++ ve .NET'den hazırladığım benzer birçok program olmasına rağmen, JavaScript'in scripting dili olması ve dolayısıyla derlenmeden çalışabilmesi, gittiğim heryerde herkesin PC'sinde kolaylıkla çalışabiliyor olmamı sağlaması gibi avantajlarından dolayı JavaScript'de de benzer birşeyler yapmayı hedeflemiştim. Ancak JavaScript'den VIC simülatörü yapmak o kadar da kolay değil. Gelin ne olduğunu ve nasıl yapıldığını inceleyelim.

[b]VIC simülasyonu tam olarak nedir?[/b]

Commodore 64'ün tek renk grafik modu 320x200 çözünürlükten, yani toplam 64000 pixelden oluşur. Ancak PC'de 13h (320x200 256 renk) gibi modlarda çalışmaya alışmış insanlara commodoredaki hafıza yapısı başlangıçta epey bir ters gelecektir. Çünkü 13h modunda her bir pixel bir byte'a denk gelirken ve byte değerleri renkleri simgelerken, Commodore'da 1 byte'ın her biti 1 pixeli sembolize edecek şekilde 1 byte = 8 pixel'e denk gelir. Örneğin 197 byte değerini ele alalım:

[b]197 = %11000101[/b]

Yani bunun ekrandaki görüntüsü X'ler dolu o'lar boş pixelleri sembolize edecek olursa;

[b]XXoooXoX[/b]

şeklinde olacaktır. Ekrana örnek olarak ard arda bir dolu bir boş pixel çizmek istediğimiz durumda ise tersten bir hesap yaparak byte değerine ulaşabiliriz.

[b]XoXoXoXo -> %10101010 = 170[/b]

Bir diğer konu byteların nasıl dizileceği konusu. Yani her 8 pixellik alan hangi sırayla ekrana basılıyor. Bu da commodoreda programlama ile yeni tanışan insanların genelde sıkıntıya düştüğü bir başka konu.

Dizilim öncelikle aşağıya doğru başlar. Yani 8 pixeli temsil eden bir byte, diğerinin altına yerleşir. Ancak bu tüm ekran için değil yalnızca 8x8 pixellik bir alan için geçerlidir.

Commodore'un 320x200 çözünürlüğündeki ekranı aşağıdaki resimde de göründüğü gibi 8x8 pixellik karakter alanları halinde 40x25'lik 1000 adet parçaya bölünmüştür.

[img = CTR data/articles/test_platformu/images/c64screengrid.gif]

Parçalardan her biri ise 8x8 pixelden oluşmaktadır. İşte bu her 8x8'lik alan hafızada peş peşe gelen 8 byte ile ifade edilir. Örnek olarak ekrana yazılan bir A harfi şu şekilde bytelara çevrilebilir.

[img = CTR data/articles/test_platformu/images/aharfi.gif]

Görüldüğü üzere 8x8lik bir alanı bu şekilde peş peşe 8 byte ile ifade edebiliyoruz. Peki hafızada bundan sonra yazılacak 9. byte ekranda nereye denk gelecek? Bu karakterin bitişiğindeki karakter alanının en üst 8 pixeline denk gelecek. Yani biz peş peşe iki kez şekildeki sayıları yazacak olursak;

[b]24, 60, 102, 126, 102, 102, 0, 24, 60, 102, 126, 102, 102, 0[/b]

Bu 16 byte bize yan yana iki A hrafi gösterecektir. Bu durumun tek bir istisnası olabilir. O da bu byteların satır sonuna, yani 40. karaktere denk gelmeleri durumudur. Bu durumda ise bir alttaki karakter satırından devam eder byte dizilimi. Eğer byteların 320x200lük alandaki koordinatlarını idafe edecek olursak aşağıdaki gibi bir sonuçla karşılaşırız. Buradaki parantez içindeki değerler sırasıyla pixel cinsinden x ve y değerleridir. Unutulmaması gereken şey, her bir byteın verilen x koordinatı değerinden itibaren 8 pixeli kapsadığıdır.
[b]
byte:0 -> (0,0)
byte:1 -> (0,1)
byte:2 -> (0,2)
byte:3 -> (0,3)
byte:4 -> (0,4)
byte:5 -> (0,5)
byte:6 -> (0,6)
byte:7 -> (0,7)
byte:8 -> (8,0)
byte:9 -> (8,1)
byte:10 -> (8,2)
byte:11 -> (8,3)
byte:12 -> (8,4)
byte:13 -> (8,5)
byte:14 -> (8,6)
byte:15 -> (8,7)
byte:16 -> (16,0)
byte:17 -> (16,1)
byte:18 -> (16,2)
byte:19 -> (16,3)
byte:20 -> (16,4)
byte:21 -> (16,5)
byte:22 -> (16,6)
byte:23 -> (16,7)
...
...
...
byte:312 -> (312,0)
byte:313 -> (312,1)
byte:314 -> (312,2)
byte:315 -> (312,3)
byte:316 -> (312,4)
byte:317 -> (312,5)
byte:318 -> (312,6)
byte:319 -> (312,7)
byte:320 -> (0,8)
byte:321 -> (0,9)
byte:322 -> (0,10)
byte:323 -> (0,11)
byte:324 -> (0,12)
byte:325 -> (0,13)
byte:326 -> (0,14)
byte:327 -> (0,15)
byte:328 -> (8,8)
byte:329 -> (8,9)
byte:330 -> (8,10)
byte:331 -> (8,11)
byte:332 -> (8,12)
byte:333 -> (8,13)
byte:334 -> (8,14)
byte:335 -> (8,15)
...
...
...
...
...
byte:63992 -> (312,192)
byte:63993 -> (312,193)
byte:63994 -> (312,194)
byte:63995 -> (312,195)
byte:63996 -> (312,196)
byte:63997 -> (312,197)
byte:63998 -> (312,198)
byte:63999 -> (312,199)
[/b]
Eğer yukardaki tablo kafanızı karıştırdıysa size daha rahat anlaşılır bir model ile açıklayayım. Örneğin karşınızda raflar var ve her rafın üstünde yan yana duran bir sürü su kabı var. Siz aynı rafta duran su kaplarının hepsini hortumarla birbirlerine bağlıyorsunuz. Kısacası biri dolduktan sonra fazla gelen suyu yanındakine aktarıyor. Her rafın en sağındaki kap bir alttaki rafın en solundaki kaba hortumla bağlı.

[img = CTR data/articles/test_platformu/images/duzenek1.gif]

Siz en üst rafın en solunda duran kaba su doldurmaya başladıkça 8 birimlik kap dolduğunda yanındaki kaba, o da yanındakine aktarıyor.

[img = CTR data/articles/test_platformu/images/duzenek2.gif]

En son bir raftaki tüm kaplar dolunca ise alt rafın en solundaki kaptan devam ediyor.

[img = CTR data/articles/test_platformu/images/duzenek3.gif]

Burdaki her kap 8x8'lik bir karakter alanına denk geliyor ve 8 byte alabiliyor. Eğer her rafta toplam 40 kap olur ve 25 tane de rafımız olursa alın size Commodore'un ekranının hafıza dizilimi. Tek farkı bardaklar Commodore'da tersten doluyor. Yani yukarıdan aşağıya.

VIC simülatörü ise bu hafıza dizilimini PC'de simüle ederek bize hiç Commodore ya da Commodore emülasyonu kullanmadan test ortamı sağlayacak bir araç olacak.

[b]"VIC Simülatörü"nü JavaScript'den yapmanın zor olan yanı ve çözümü nedir?[/b]

Aslında flash, java ve benzeri tarayıcı teknolojilerini kullanmaksınız basit bir yöntemle JavaScript'den 320x200'lük alanın tamamını simüle etmek hemen hemen imkansızdır. Çünkü bu 64000 pixellik bir alan demektir ve HTML yapı itibariyle 64000 nesne ya da 64000 parçaya bölünmüş bir tabloyu kolay kolay kaldıramaz. Kaldırsa da çok ama çok yavaş olur. Peki ne yapmak lazım? Hadi bu yukardaki raf, bardak modelini ele alalım. Biz eğer her bir bardağı birer resim olarak kullanacak olursak bu yalnızca 40x25 = 1000 resim eder ki bu HTML için oldukça makul bir sayı. Peki kaç farklı resim oluşturmamız gerekir bu durumda? 2^64 = 18,446,744,073,709,551,616 adet resim oluşturmamız gerekir. Hmmm... O zaman bu olayı birazcık optimize etmemiz gerekecek. Tarayıcıya 1000 resim yerine 8000 resim yüklemek onu yaklaşık 8 kat yavaşlatacaktır. Peki bu resim sayısında yeterli bir fark yaratacak mı? Bu durumda her 1 byte 1 resme denk gelecek yani 2^8 = 256 adet resim oluşturmamız yeterli olacak. 8 kat hız kaybederek resim sayısını 72,057,594,037,927,936'de 1'e düşürdük. Fena sayılmaz.

Yukardaki paragraf elbette ki biraz espiri içeriyor. Bu "niye her bir byte bir resme karşılık geliyor?" sorusuna yanıt olsun diye yazdığım, benim düşünce metodumu anlatan bir paragraf. Ancak sonuç olarak her 8 pixel, yani her 1 byte'ı 1 resime denk getirmemiz lazım. Peki bu resimleri nasıl oluşturacağız? 256 her ne kadar aşırı büyük bir sayı değilse de inanın oturup tek tek photoshopda 256 resmi pixellemek istemezsiniz. Bunun için ben PHP kullandım. Çünkü PHP'nin grafik kütüphanesi olan GD2 çok basit bir kullanıma sahip. Sizler de PHP kurup, php.ini'nin içersinden ";extension=php_gd2.dll" satırının başındaki noktalıvirgülü kaldıracak olursanız aşağıdaki scripti çalıştırarak ihtiyacımız olan 256 resmi oluşturabilirsiniz.

Not: Php klasörünün içinde "extensions" isminde bir klasör ve altında "php_gd2.dll" olması gerekiyor. Eğer bu dll yoksa php.net sitesinden en son sürümün installerını değil, zipli paketini indirecek olursanız extensionlar da beraberinde gelecektir.

[b]gifolustur.php[/b]
[b]
<?php
    ob_start();
    @mkdir("i");
    for($i = 0; $i < 256; $i++)
    {
        header("Content-type: image/gif");
        $resimDosyasi = @imagecreate(8, 1);
        $renk1 = imagecolorallocate($resimDosyasi, 0, 0, 0); // siyah
        $renk2 = imagecolorallocate($resimDosyasi, 255, 255, 255); // beyaz
        for($bit = 0; $bit < 8; $bit++)
        {
            if($i & pow(2, 7 - $bit))
                imagesetpixel($resimDosyasi, $bit, 0, $renk2);
            else
                imagesetpixel($resimDosyasi, $bit, 0, $renk1);
        }
        imagegif($resimDosyasi, "./i/".$i.".gif");
        imagedestroy($resimDosyasi);
    }
    ob_end_flush();
?>
[/b]
Bu PHP dosyasını çalıştırmak için bir web server kurulu olması şart değil. İsterseniz doğrudan konsol penceresinden de scripti tetikleyebilirsiniz. Örnek olarak "VicSimulator" klasörünün "D" sabit diskinde kök dizinde durduğunu varsayalım.

[img = CTR data/articles/test_platformu/images/console1.gif]

Bu şekilde bir çıktı almanız gerekir. Eğer "php" komutunu bulamaz ve hata verirse bu durumda php.exe'yi yer aldığı klasörle birlikte çift tırnak işareti içine alarak verirseniz sorun kalmayacaktır. Örnek:

[b]"c:\php\php.exe" gifolustur.php[/b]

Ancak her zaman "gifolustur.php" dosyasının bulunduğu klasörde olmaya dikkat edin. Çünkü bu script çalıştırıldığı dizine "i" isimli bir klasör açıp içersine 0'dan 255'e kadar numerik olarak isimlendirilmiş gif dosyaları yaratır.

Peki neden daha açıklayıcı olan "images" yerine yalnızca "i" seçtik klasör ismi olarak? Çünkü birazdan oluşturacağımız HTML dosyasında resimler bu klasörden okunacak ve klasör ismi 8000 kez tekrar edeceği için oluşturulacak HTML'in toplam uzunluğunu azaltmak ve çıktıyı hızlandırmak için tek harf kullanmayı tercih ettik. Bu tür ufak ayrıntılar sonucu oldukça etkiler. Aslında en hızlısı resimleri doğrudan kök dizine koymak olacaktır ama düzen için bu kadar taviz verilebilir.

PHP'ye çok uzaksanız, bir türlü yukardaki scripti çalıştıramadıysanız, Windows'un security ayarları scripte engel oluyor ve nasıl düzelticeğinizi bilmiyorsanız ya da yalnızca PHP kurmaya/kullanmaya üşeniyorsanız bu durumda derginin içersinde yer alan hazır gifleri kullanabilirsiniz.

VIC Simülatörü'nün JavaScript Kodları

Sırada iş VIC Simülatörü'nü yazmaya geldi. Kolaylıkla kullanılabilmesi ve kopyala&yapıştır işleriyle uğraştırmamak için kodları ayrı bir JS uzantılı dosyada tutacağız. JS uzantılı dosyalar kolaylıkla HTML'lere linklenebilir ve kullanılabilirler.

[b]vicsim.js[/b]
[b]
var VICHaritasi = new Array(8000);

function ekraniTemizle()
{
  for(i = 0; i < VICHaritasi.length; i++)
    VICHaritasi[i] = 0;
}

function ekraniCiz()
{
  alert("VIC haritasının oluşturulması biraz zaman alabilir.
\nHarita oluşturulurken sabırlı olun.");

  cikti = "<table width=320 height=200 border=0 cellspacing=0 cellpadding=0>";
  for (y = 0; y < 25; y++)
  {
    cikti += "<tr>";
    for (x = 0; x < 40; x++)
    {
      cikti += "<td>";
      for (i = 0; i < 8; i++)
      {
        haritaIndeksi = y * 320 + x * 8 + i;
        cikti += "<img src=i/" + (VICHaritasi[haritaIndeksi] & 255) + ".gif>";
        if(i != 7)
          cikti += "<br>";
      }
      cikti += "</td>";
    }
    cikti += "</tr>";
  }
  cikti += "</table>";
  document.body.innerHTML = cikti;
}
ekraniTemizle();
[/b]
İşte VIC simülatörü yapmak bu kadar kolay. Bu kodu açıklamaya ihtiyaç duymuyorum. Sonuç olarak ne yaptığını bilmeniz önemli. Kodun en başında global olarak tanımlanan "VICHaritasi" dizisi 8000 bytelık bir dizi. ekraniTemizle() fonksiyonu bu diziyi 0 değerleriyle dolduruyor ve ekraniCiz ise bu değerleri VIC'in çalışma prensibine uygun bir şekilde simüle ederek uygun gif parçaları ile bir tablo halinde ekrana basıyor. ekraniTemizle() fonksiyonu bu scriptin sonunda çağrılırken ekraniCiz() fonksiyonu bu scriptin linklendiği HTML dosyasından kullanılmak üzere hazırlandı.

Şimdi bu yukardaki scripti kullanan bir HTML örneği görelim.

[b]vicsim.htm[/b]
[b]
<html>
<head>
<title>VIC Simülatörü</title>
<script src="vicsim.js"></script>
</head>
<body bgcolor="#cccccc"></body>
<script>
  function nokta(x,y)
  {
    adres = ((y >> 3) * 320) + (y & 7) + (x & 0x1f8);
    byteDegeri = Math.pow(2, 7 - (x & 7));
    VICHaritasi[adres] = VICHaritasi[adres] | byteDegeri;
  }

  function ekraniOlustur()
  {
    for(i = 0; i < 256; i++)
    {
      x = 160 + 160 * Math.cos(i / 128 * Math.PI);
      y = 100 + 100 * Math.sin(i / 128 * Math.PI);
      nokta(x,y);
    }
  }

  ekraniOlustur();
  ekraniCiz();
</script>
</html>
[/b]
[b]HTML'in çıktısı:[/b]

Öncelikle ekrana aşağıdaki uyarı mesajı gelir.

[img = CTR data/articles/test_platformu/images/vicsim1.gif]

Daha sonra ekrana bir elips çizilir.

[img = CTR data/articles/test_platformu/images/vicsim2.gif]

Bu örnekte ne yaptık? Standart HTML yapısını çıkaracak olursak iki bölge bizi ilgilendiriyor. Birincisi

[b]<script src="vicsim.js"></script>[/b]

satırı. Bu satırda az önce oluşturduğumuz "vicsim.js" dosyasını HTML'e ekliyoruz. Diğer önemli bölge ise
[b]
<script>
  function nokta(x,y)
  {
    adres = ((y >> 3) * 320) + (y & 7) + (x & 0x1f8);
    byteDegeri = Math.pow(2, 7 - (x & 7));
    VICHaritasi[adres] = VICHaritasi[adres] | byteDegeri;
  }

  function ekraniOlustur()
  {
    for(i = 0; i < 256; i++)
    {
      x = 160 + 160 * Math.cos(i / 128 * Math.PI);
      y = 100 + 100 * Math.sin(i / 128 * Math.PI);
      nokta(x,y);
    }
  }

  ekraniOlustur();
  ekraniCiz();
</script>
[/b]
Bu script taginin yer aldığı alan. Burada iki yeni fonksiyon tanımlıyoruz. Bunlardan birincisi verilen (x,y) koordinatına nokta basan bir rutin. Elbette ki bu rutin VICHaritasi dizisini kullanıyor. Yani aslında bu fonksiyonu çağırarak ekrana henüz birşey çizmiyoruz. Bunun yerine noktayı VICHaritasi dizisindeki ilgili byteları değiştirerek koyuyoruz.

Diğer fonksiyonumuz ise ekraniOlustur() fonksiyonu. Bu fonksiyon ise ekrana çizilecek şeyin belirlendiği kısım. Bu örnekte ekrana tam sınırlarına denk gelecek bir elips çizdiriyoruz. Öncelikle sinüs, cosinüs fonksiyonları yardımıyla elipsin çevresini oluşturan (x,y) değerleri elde ediliyor, daha sonra az öncesinde yaratılmış nokta(x,y) fonksiyonu çağırlılarak noktalar VICHaritasi dizisindeki yerlerini alıyorlar.

Son olarak ekraniOlustur() fonksiyonu çağırıldıktan sonra önceki JS dosyasında bulunan ekraniCiz() çağırılarak sonucu HTML içersinde görüntülüyoruz.

İşin özet bu. Burada sinüs, cosinüs kullanılarak çember ya da elips nasıl çizdirilir bunu açıklamayı yersiz buluyorum. Formül olarak zaten açık bir şekilde duruyor. 160 ve 100 nerden geldi diyecek olursanız 320 ve 200'ün yarısı yani ekranın orta koordinatları. 256 adım sayısı ve 128 ise bu adım sayısının yarısı. Aslında 128 yerine 256'yı olduğu şekilde kullanmak gerekir ancak derece -> radyan dönüşümünde kullanılan bir kısaltma ile (i / 256 * 2 * pi) yerine (i / 128 * pi) şeklinde kısalttığımız için 128 değerini kullandık.

Gelelim en can alıcı noktaya. nokta(x,y) fonksiyonu. Buradaki adres ve byteDegeri'ni nasıl hesaplıyoruz? Gelin birlikte buna kafa yoralım.

Elimizde bir x ve bir y değeri var. Bizim ulaşmak istediğimiz 8000'lik dizinin kaçıncı elemanına denk geldiği ve bu elemanın değerini nasıl etkilediğini (hangi bitini set ettiğini) bulmak. Öncelikle şunu biliyoruz. Ekranın en sol üstünden yani dizinin ilk elemanından itibaren bytelar birer birer arttıkça y'de 8'lik alanda birer birer artıp her 8'den sonra yeniden 0'a dönüyor. Bunu yine bardak, raf örneğini inceyerek anlayabilirsiniz. İlk byte'da y koordinatı 0, ikincide 1, üçüncüde 2....sekizincide 7 ve dokuzuncuda yine 0... Peki bu nereye kadar böyle devam ediyor? 40. karaktere kadar yani 40x8=320. byte'a kadar. 320. byteda y koordinatı 8 atlayarak 8 ile 15 arası değerler almaya başlıyor. 640'da 16-23, 960'da 24-31 şeklinde devam ediyor bu. Peki bunu nasıl formülüze edeceğiz? Madem "her 8'de bir" diyoruz öncelikle bu 8'deki kırılma noktasını ilk okuldan kalma yöntemle bölme işlemi yaparak inceleyelim.

[img = CTR data/articles/test_platformu/images/bolmeislemi.gif]

Buradaki s sonuç ve k kalan'ı temsil ediyor. Peki bu iki parametreyi nasıl formülize edeceğiz? Elbette ki aşağıdaki şekilde.
[b]
ys = int(y / 8)
yk = y mod 8
[/b]
Yani "ys", y / 8 işleminden çıkan sonucun tam sayı kısmı ve "yk" ise 8 ile bölümden kalan yani matematiksel ifadesiyle "mod 8". Peki bu "ys" ve "yk" bize neyi veriyor. Hadi bir tablo yaparak görelim sonucu.
[b]
işlem: y/8
y: 0 ys: 0 yk: 0
y: 1 ys: 0 yk: 1
y: 2 ys: 0 yk: 2
....
y: 7 ys: 0 yk: 7
y: 8 ys: 1 yk: 0
y: 9 ys: 1 yk: 1
y: 10 ys: 1 yk: 2
y: 11 ys: 1 yk: 3
....
y: 15 ys: 1 yk: 7
y: 16 ys: 2 yk: 0
y: 17 ys: 2 yk: 1
....
y: 198 ys: 24 yk: 6
y: 199 ys: 24 yk: 7
[/b]
Hmmm, işte bu tablodaki değerler birşeyleri ortaya çıkarıyor. Dökümanın en başında verdiğim tabloya bakarsanız ve az önce bahsettiğim gibi 320'de bir y'de 8'lik bir artış olduğunu düşünecek olursak hafızadaki doğru adresi bulmak için "ys" parametresini 320 ile çarpmak ve "yk" ile toplamak gerekiyor. Bu durumda formülümüz;

[b]yi = ys * 320 + yk[/b]

Haline dönüşüyor. Burdaki "yi" bize dizinin y koordinatına bağlı indeksini veriyor. Ne yazık ki işimiz bitmedi. Bir de x koordinatımız var. Ama x koordinatında işimiz biraz daha kolay. Tek bir noktayı unutmamak koşuluyla! x koordinatındaki 1 pixellik ilerleme y koordinatında olduğu gibi hafızada 1 byte'lık ilerlemeye denk gelmiyor. 8 pixel aynı byte üzerinde yer alıyor. Yani x = 0 ve x = 7 değerleri aslında bize aynı byte'ı veriyor. Ancak bu byte'da değiştirmemiz gereken bit değerleri değişiyor. Şimdilik yalnızca hafıza adresini bulmaya çalıştığımıza göre x = 0 ve x = 7 bizim için aynı şey ifade ediyor. Bu ne demektir? x'i 8'e bölebiliriz. Böylece;
[b]
xs = int(x / 8)
xk = x mod 8

işlem: x/8
x: 0 xs:0 xk:0
x: 1 xs:0 xk:1
x: 2 xs:0 xk:2
....
x: 7 xs:0 xk:7
x: 8 xs:1 xk:0
x: 9 xs:1 xk:1
....
x: 15 xs:1 xk:0
x: 16 xs:2 xk:1
x: 17 xs:2 xk:2
....
x: 318 xs:39 xk:6
x: 319 xs:39 xk:7
[/b]
"xs" parametresinde 0'dan 39'a kadar byte değerlerini elde ediyoruz. Ekran adreslerinde bir sırada toplam 40 byte var. Ancak unutmamamız gereken hafızada bu byteların peş peşe gelmediği 8'er aralıklarla dizildiği. Çünkü aralarda aynı karakter alanında yer alan diğer y koordinatlarına ait değerler duruyor. Peki 8'er 8'er gittiğine göre ne yapmak lazım? Tabii ki bu "xs" değerini 8 ile çarpmak lazım.

[b]xi = xs * 8[/b]

Hadi artık bu kadar uzun işlemden sonra şu adres indeksini bulalım.

[b]ai = yi + xi[/b]

İşte bu kadar. Artık dizinin kaçıncı elemanına erişmemiz gerektiğini biliyoruz. Ama hala ona hangi değeri vermemiz gerektiğini bilmiyoruz. Bunu bulmak için "xk" parametresini kullanacağız. Peki "xk"nın 0'dan 7'ye değişim göstermesini ekranda nasıl görmemiz lazım?
[b]
xk = 0 -> Xooooooo -> bd = %10000000 = 128 = 2^7
xk = 1 -> oXoooooo -> bd = %01000000 = 64 = 2^6
xk = 2 -> ooXooooo -> bd = %00100000 = 32 = 2^5
xk = 3 -> oooXoooo -> bd = %00010000 = 16 = 2^4
xk = 4 -> ooooXooo -> bd = %00001000 = 8 = 2^3
xk = 5 -> oooooXoo -> bd = %00000100 = 4 = 2^2
xk = 6 -> ooooooXo -> bd = %00000010 = 2 = 2^1
xk = 7 -> oooooooX -> bd = %00000001 = 1 = 2^0
[/b]
Bu değerleri tablolayabiliriz. Ama sonuç olarak bunu da formülüze etmek mümkün. Şöyle ki

[b]bd = 2 ^ (7 - xk)[/b]

Evet "bd" yani byte değerini 2'nin (7-xk). üssünü alarak bulabiliyoruz.

Uff puff. Peki başka birşey kaldı mı? Ne yazık ki evet... Ama ufak birşey. Biz bu byte'a doğrudan bir değer verdiğimizde byte'ın eski değerini silmiş oluyoruz. Bu durumda ekrana basmak istediğimiz bir nokta, aynı byte'a denk gelen diğer 7 noktayı silmiş oluyor. Bunu engellemek için OR'lamak lazım. Matematikteki "veya" ifadesini bir hatırlayalım.
[b]
%11010001
%10001010
-------------- <- OR
%11011011
[/b]
Byte'ın eski değeriyle "bd" değerini OR'ladığımız taktirde eğer o pixel daha önceden basılmışsa bir değişim olmayacak, basılmamışsa basılacak ve diğer bitler durumdan etkilenmeyecek. Örnek olarak byte'ın ilk ve son bitlerine daha önceden nokta konulmuş olduğunu varsayalım ve biz 3 numaralı bit'e (2^3) OR'layarak bir nokta koyalım.
[b]
%10000001 <- Orjinal değer
%00001000 <- Yeni basılan nokta
-------------- <- OR
%10001001 <- Sonuç değeri
[/b]
İşte bu sonuç değeri tam istediğimiz değer! Şimdi uzuuun uzun anlattığımız bunca parçalanmış formülü toparlayalım. VICHaritasi dizisine kısaca "vh" diyecek olursak;
[b]
ai = yi + xi
bd = 2 ^ (7 - xk)
vh[ai] = vh[ai] OR bd
[/b]
İşte formül bu. Şimdi yi ve xi'yi yerlerine koyalım.
[b]
ai = (ys * 320 + yk) + (xs * 8)
bd = 2 ^ (7 - xk)
vh[ai] = vh[ai] OR bd
[/b]
Şimdi de ys, yk, xs ve xk değerlerini de yerine koyalım.
[b]
ai = (int(y / 8) * 320 + (y mod 8)) + (int(x / 8) * 8)
bd = 2 ^ (7 - (x mod 8))
vh[ai] = vh[ai] OR bd
[/b]
Son hali biraz karışık gözükebilir. Bu yüzden parçalara ayırarak açıklama ihtiyacı hissettim. "nokta(x,y)" fonksiyonunun açıklanmaya başladığı yerden buraya kadar olan bölümü anlayana kadar defalarca okumanızı tavsiye ediyorum.

Şimdi de bu formülü JavaScript diline uygun hale getirelim. Öncelikle bir sayıyı 8'e böldükten sonra tam sayı kısmını almanın en basit yolu o sayıyının bitlerini 3 bit sağa kaydırmaktır. 3 bit sağa kaydırmak sayıyı 2^3'e bölmek anlamına gelir ki dışarda kalan bitler küsürattır. Küsüratı atmış oluyoruz kısacası. JavaScript C tabanlı bir dil olduğu için öperatörlerinin de birçoğu C ile aynıdır. Bit kaydırma işlemleri << ve >> operatörleriyle yapılır. Yani y >> 3 diyerek y'yi 8'e bölüp tam sayı kısmını almak mümkün.

Gelelim mod işlemine. Aslında "%" operatörüyle bu işi halledebiliriz ancak söz konusu olan sayı 2'nin üslerinden biriyse AND'lemek her zaman daha iyi ve daha hızlı bir yöntemdir. mod 8 demek sayının 7 ile AND'lenmesi demektir. 7 = %00000111 ile AND'leyerek 7'yi geçen sayının tekrar 0'a dönmesini sağlıyoruz. mod 8 de aynı işi görüyor.

Bir başka nokta ise "xi" parametresinde yaptığımız 8'e bölüp tam sayı kısmını alıp 8 ile çarpma işlemi. Bu işlem yalnızca sayının alt 3 bitin sıfır olmasını sağlıyor. Aslında alt 3 bit sıfır olacak şekilde %111111000 = 504 ($1f8) sayısıyla AND'lemek de bize aynı sonucu verecektir. Burada dikkat edilmesi gereken husus x'in 0-255 değil 0-319 aralığında değiştiğidir. Bu yüzden AND'lerken 8 değil 9 bit kullanıyoruz.

AND ve OR operatörleri JavaScript'de yine C'de olduğu gibi & ve | karakterleriyle ifade ediliyorlar. Üs alma işlemi için ise Math kütühanesinde yer alan pow(sayı, üs) fonksiyonu kullanılıyor.

Şimdi bütün bu yazılanları toparlayacak olursak formül son şeklini şu şekilde alıyor.
[b]
ai = ((y >> 3) * 320) + (y & 7) + (x & 0x1f8);
bd = Math.pow(2,7 - (x & 7));
vh[ai] = vh[ai] | bd;
[/b]
Örnekteki değişkenlere çevirecek olursak;
[b]
adres = ((y >> 3) * 320) + (y & 7) + (x & 0x1f8);
byteDegeri = Math.pow(2, 7 - (x & 7));
VICHaritasi[adres] = VICHaritasi[adres] | byteDegeri;
[/b]
İşte size plot rutininin açıklaması.

Evet Commodore 64'de ekrana nokta basmak o kadar da basit bir iş değildir. 64'ler dergisinde Barış Yalçınkaya'nın köşe yazısında bir okuyucunun sorusunu hatırlıyorum. Okuyucu "Commodore 64'de ekrana üçgen, kare gibi şekilleri nasıl çizebilirim?" diye çok mantıklı ve basit bir soru sormuştu. Eminim Barış bir hayli ter dökmüştür cevaplayana kadar. En son cevap olarak bir çizim programıyla hazırlanmış bir grafiğin nasıl ekrana basılacağını anlatmıştı. Ama Barış'a kesinlikle hak veriyorum. Ekrana nokta basmak bile gördüğünüz gibi "anlatmaya geldiğinde" oldukça zor bir iş.

[b]Commodore 64'de Ekrana Nokta Basmak[/b]

Tamam, simülatörle bastık noktaları. Ama şimdi bir de bu işin Commodore'a uyarlanması var. Genellikle Commodore 8 bitlik bir bilgisayar olduğu için ilk verilen nokta basma rutini örneğinde x koordinatı 0-255 aralığında değerler alabilecek şekilde örneklenir. Ancak ben sizlere doğrudan x: 0-319 ve y: 0-199 aralığında değerler alabilecek şekilde yani 9 bitlik bir x koordinatıyla nasıl nokta basılacağını göstereceğim. ACME ile derlenebilecek kod örneği aşağıdadır.

[b]noktakoy.a[/b]
[b]
  !to "noktakoy.prg",cbm

  * = $0801
  !byte $0c, $08, $00, $00, $9e, $32, $30, $36, $31, $00, $00, $00

KARAKTER_EKRANI = $0400
VIC_HARITASI = $2000

  * = $080d
  ;
  ; İç ve Dış Ekran Renklerini Belirle
  ;
  lda #$02
  sta $d020
  lda #$00
  sta $d021
  ;
  ; Bitmap Ekran Aç
  ;
  lda #$18
  sta $d018
  lda #$c8
  sta $d016
  lda #$3b
  sta $d011
  ;
  ; Ekranın Arkaplan ve Çizim Renklerini Belirle
  ;
  ldx #$00
  lda #$10
.ekrandongusu
  sta KARAKTER_EKRANI,x
  sta KARAKTER_EKRANI+$100,x
  sta KARAKTER_EKRANI+$200,x
  sta KARAKTER_EKRANI+$2e8,x
  inx
  bne .ekrandongusu
  ;
  ; Ana Rutin
  ;
  ldy #0   ; x coordinatı 9.bit
  lda #160  ; x coordinatı
  ldx #100  ; y coordinatı
  jsr noktakoy ; ekrana nokta bas
  jmp *   ; sonsuz döngüye gir

;
; isim : noktakoy
; aciklama : ekrandaki verilen (x,y) koordinatına nokta koyar
; girdiler : a -> x koordinatı
;   x -> y koordinatı
; kullanilan : $f0, $f1, $f2
;
noktakoy
  sty $f2
  ldy ekranLo,x
  sty $f0
  ldy ekranHi,x
  sty $f1
  ldy $f2
  beq .xhisifir
  inc $f1
.xhisifir
  tax
  and #$f8
  tay
  lda oraTablosu,x
  ora ($f0),y
  sta ($f0),y
  rts

!align 255,0,0

oraTablosu
!for i,32 {
  !byte %10000000
  !byte %01000000
  !byte %00100000
  !byte %00010000
  !byte %00001000
  !byte %00000100
  !byte %00000010
  !byte %00000001
}

!align 255,0,0

ekranLo
!for i,25 {
  !for j,8 {
    !byte (VIC_HARITASI+(320*(i-1))+(j-1))&255
  }
}

!align 255,0,0

ekranHi
!for i,25 {
  !for j,8 {
    !byte (VIC_HARITASI+(320*(i-1))+(j-1))>>8
  }
}

  * = VIC_HARITASI
  
  !fill $1f40, 0
[/b]
Programın Çıktısı:

[img = CTR data/articles/test_platformu/images/noktakoy.gif]

Bu örnekte dikkat edilmesi gereken bir nokta var. (Bakın ekranın ortasında duruyor :))
[b]
  ;
  ; Ana Rutin
  ;
  ldy #0   ; x coordinatı 9.bit
  lda #160  ; x coordinatı
  ldx #100  ; y coordinatı
  jsr noktakoy ; ekrana nokta bas
[/b]
Öncelike bu bölümde gördüğünüz register isimleri kafanızı karıştırmasın. Yani "ldx" komutu x koordinatı değerini taşır şeklinde düşünmeyin. Aksine yanlarında açıklamaları olduğu gibi ldx ile 0-199 arasındaki y koordinatı değerini y register'ına yüklüyoruz. ldy ve lda ise x koordinatı değerlerini içeriyor. Peki burada 9 biti nasıl kullandık? y registerının en sağdaki biti (0. bit) a registerının 9.biti anlamına geliyor. Yani x'e 300 gibi 255'den büyük bir değer vermemiz gerektiğinde bunu öncelikle 9 bitlik bir ifade şeklinde yazmalıyız.

[b]300 = %100101100[/b]

Daha sonra en soldaki biti y registerının en sağdaki biti olacak şekilde ayırıp geri kalan 8 biti de a registerına vermek gerekiyor. Yani;
[b]
ldy #%00000001
lda #%00101100
[/b]
Şeklinde x'e 300 değerini verebiliyoruz. Bunu daha basit görmenizi sağlamak için 300'ü 16 bit ile ifade edip ortadan ikiye böleceğim.

[b]300 = %100101100 = %0000000100101100 = %<00000001><00101100>[/b]

Soldaki parça y, sağdaki ise a register'ının değerini ifade ediyor.

Dikkat etmeniz gereken nokta y registerının 1 değerini alması durumunda x'in değerinin 319 - 256 = 63 değerini geçmemesi gerektiğidir. Yani y'nin her iki değeri için a'nın değer aralıklarını inceleyecek olursak;
[b]
y = 0 -> a [0,255]
y = 1 -> a [0,63]
[/b]
Olması gerekmektedir. Benzer şekilde y koordinatının değerlerini tutan x registerı ise 199'u geçmemelidir.

[b]x [0,199][/b]

Bu koşullara uyulmak suretiyle 320 x 200'lük alanda ekranın istediğiniz yerine nokta basabilirsiniz.

Şimdi bu örneği VIC Simülatörü'ndeki örneği yapmakta kullanalım.

Commodore 64'de Vic Simülatör'deki Örnek İle Aynı Sonucu Veren Programı Hazırlamak

Öncelikle elipsin çiziminde kullanılacak bazı sinüs tablolarını hazırlamamız gerekiyor. Bu konu bir önceki Test Platformu bölümünde detaylı olarak ele alınmıştı. Burada yine JavaScript kullanıyoruz.

[b]sinus.htm[/b]
[b]
<script>
var txtSinXLo = "";
var txtSinXHi = "";
var txtSinY = "";
var txtCikti = "";

for(i = 0; i < 256; i++)
{
  sinX = 160 + Math.floor(159.9 * Math.sin(i / 128 * Math.PI));
  sinXLo = sinX & 255;
  sinXHi = sinX >> 8;
  sinY = 100 + Math.floor(99.9 * Math.sin(i / 128 * Math.PI));

  if(i != 0)
  {
    txtSinXLo += ",";
    txtSinXHi += ",";
    txtSinY += ",";
  }
  txtSinXLo += sinXLo;
  txtSinXHi += sinXHi;
  txtSinY += sinY;
}

txtCikti += "!align 255,0,0<br><br>";
txtCikti += "sinusTablosuXLo<br>";
txtCikti += "!byte "+txtSinXLo+"<br>";
txtCikti += "!byte "+txtSinXLo+"<br>";
txtCikti += "cosinusTablosuXLo = sinusTablosuXLo + 64<br><br>";

txtCikti += "!align 255,0,0<br><br>";
txtCikti += "sinusTablosuXHi<br>";
txtCikti += "!byte "+txtSinXHi+"<br>";
txtCikti += "!byte "+txtSinXHi+"<br>";
txtCikti += "cosinusTablosuXHi = sinusTablosuXHi + 64<br><br>";

txtCikti += "!align 255,0,0<br><br>";
txtCikti += "sinusTablosuY<br>";
txtCikti += "!byte "+txtSinY+"<br>";
txtCikti += "!byte "+txtSinY+"<br>";
txtCikti += "cosinusTablosuY = sinusTablosuY + 64<br><br>";

document.write(txtCikti);
</script>
[/b]
"sinus.htm"in tarayıcıya verdiği çıktıyı kopyala&yapıştır ile "elipsciz.a" kaynak kodununun sonlarında belirtilen bölgeye yapıştırmamız gerekiyor.

[b]elipsciz.a[/b]
[b]
  !to "elipsciz.prg",cbm

  * = $0801
  !byte $0c, $08, $00, $00, $9e, $32, $30, $36, $31, $00, $00, $00

KARAKTER_EKRANI = $0400
VIC_HARITASI = $2000

  * = $080d
  ;
  ; İç ve Dış Ekran Renklerini Belirle
  ;
  lda #$02
  sta $d020
  lda #$00
  sta $d021
  ;
  ; Bitmap Ekran Aç
  ;
  lda #$18
  sta $d018
  lda #$c8
  sta $d016
  lda #$3b
  sta $d011
  ;
  ; Ekranın Arkaplan ve Çizim Renklerini Belirle
  ;
  ldx #$00
  lda #$10
.ekrandongusu
  sta KARAKTER_EKRANI,x
  sta KARAKTER_EKRANI+$100,x
  sta KARAKTER_EKRANI+$200,x
  sta KARAKTER_EKRANI+$2e8,x
  inx
  bne .ekrandongusu
  ;
  ; Ana Rutin
  ;
anarutin
  ldx sayac
  ;
  ; koordinatları al
  ;
  lda cosinusTablosuXHi,x
  sta xhi
  lda cosinusTablosuXLo,x
  sta xlo
  lda sinusTablosuY,x
  sta y

  ldy xhi   ; x coordinatı 9.bit
  lda xlo   ; x coordinatı
  ldx y   ; y coordinatı
  jsr noktakoy ; ekrana nokta bas

  inc sayac ; tablo indeks sayacını 1 arttır
  bne anarutin ; eğer hala 255'i geçmediyse ana rutin başlangıcına git

  jmp *   ; sonsuz döngüye gir

;
; isim : noktakoy
; aciklama : ekrandaki verilen (x,y) koordinatına nokta koyar
; girdiler : a ->gt; x koordinatı
;   x ->gt; y koordinatı
; kullanilan : $f0, $f1, $f2
;
noktakoy
  sty $f2
  ldy ekranLo,x
  sty $f0
  ldy ekranHi,x
  sty $f1
  ldy $f2
  beq .xhisifir
  inc $f1
.xhisifir
  tax
  and #$f8
  tay
  lda oraTablosu,x
  ora ($f0),y
  sta ($f0),y
  rts

sayac !byte 0
xlo !byte 0
xhi !byte 0
y !byte 0

!align 255,0,0

oraTablosu
!for i,32 {
  !byte %10000000
  !byte %01000000
  !byte %00100000
  !byte %00010000
  !byte %00001000
  !byte %00000100
  !byte %00000010
  !byte %00000001
}

!align 255,0,0

ekranLo
!for i,25 {
  !for j,8 {
    !byte (VIC_HARITASI+(320*(i-1))+(j-1))&255
  }
}

!align 255,0,0

ekranHi
!for i,25 {
  !for j,8 {
    !byte (VIC_HARITASI+(320*(i-1))+(j-1))>gt;>gt;8
  }
}

["sinus.a"nın çıktısı buraya gelecek]

  * = VIC_HARITASI
  
  !fill $1f40, 0
[/b]
Programın Çıktısı:

[img = CTR data/articles/test_platformu/images/elipsciz.gif]

[b]VIC Simülatör'de Yapılan İşlemin Commodore'a Aktarılmasına İlişkin Değerlendirme[/b]

Ekrana nokta basma rutini VIC Simülatör örneğinde çok detaylı anlatıldığı için Commodore 64 versiyonunun açıklamasını yapmaya gerek duymuyorum. Uyarlama olarak tıpatıp aynısı. Elbette ki bazı ek tablolar kullanılıyor, Commodore'a özel optimizasyonlar ve mecburi tasarım değişiklikleri oluyor. Ama bunun haricinde anlatılacak pek birşey yok. En başından beri bahsettiğim gibi, bu döküman 6510 ASM'yi kaba hatlarıyla bilen ve ACME ya da benzeri derleyicileri kullanmış kişilere hitap ediyor. Eğer 6510 ASM bilmiyorsanız, bu örnekleri anlayabilmek için öncelikle başlangıç seviyesindeki dökümanları okumanızı tavsiye ederim.

Gelelim elips örneğine. Burada VIC Simülatör'ündeki;
[b]
x = 160 + 160 * Math.cos(i / 128 * Math.PI);
y = 100 + 100 * Math.sin(i / 128 * Math.PI);
[/b]
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üsüratları 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üsürat kaybından önemli ölçüde kurtulmuş oluyoruz. Kaybolan küsüratlar 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
[b]
a + a * sin(x)
[/b]
Burada x ve y için a değerleri 160 ve 100 olduğuna göre;
[b]
160 + 160 * cos(x)
100 + 100 * sin(x)
[/b]
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ı?

Çü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 nisbeten 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;
[url = mailto:c64hydrogen@yahoo.com]skate <at> glance <dot> ws[/url]
[b]
Emir Akaydın
Skate / Glance / Clash
[/b]
