[title = Test Platformu - Blm 3]
Yeni bir sayda tekrar merhaba sevgili Plazma okurlar. Plazma'nn ilk saysndan beri sre gelen "Test Platformu" bu sayda artk daha da detayl bir biimde devam ediyor. nceki saylar okumam balang seviyesindeki programclar bu sayda zorlanabilirler. Her say birbirinin devam niteliinde olduu iin bu blm okumadan nce blm 1 ve blm 2'yi okumanz tavsiye ediyorum.

[b]Bu Blmde Neler Anlatlacak?[/b]

 Bu yaz dizisinin misyonu Commodore 64 iin PC destekli yazlm gelitirmeyle ilgili yntemler sunmak olduu iin bu sayda ncelikle JavaScript'den bir "VIC Simlatr" nasl hazrlanr onu greceiz. Bu VIC Simlatr, Commodore 64'n ekran ipi olan VIC'in hafzadaki byte diziliini ekrana nasl yansttyla ilgili bir simlasyon yapacak. Bu sayede bir efekti Commodore 64'de programlamaya balamadan JavaScript'den eitli testler yapabileceiz.

 VIC Simlatrn kullanarak bir nokta basma rutini hazrlayacaz. Bu rutin ekranda verilen x ve y koordinatna nokta koyacak.

 Ayn rnek iersinde basit bir sins, cosins hesabyla ekrana tam snrlarna denk gelecek ekilde bir elips izdireceiz.

 Daha sonra Commodore 64 zerinde grafik ekran ap ekrana nokta basma ileminin nasl yapldn kod rnekleriyle greceiz.

 Sonraki admda VIC Simlatrnden denediimiz elips izdirme rutininin nasl Commodore 64'e aktarlabileceini inceleyeceiz.

 En son olarak da bu son yaptmz ilemin Commodore 64'e aktarma ileminin eksik, zayf ynlerini ve alternatiflerini tartacaz. Ancak dier yntemleri sonraki blmlere saklayacaz.

[b]VIC Simlatr[/b]

ok uzun bir zamandr VIC simlatr tr bireyi JavaScript'den yapmak istiyordum. Aslnda C++ ve .NET'den hazrladm benzer birok program olmasna ramen, JavaScript'in scripting dili olmas ve dolaysyla derlenmeden alabilmesi, gittiim heryerde herkesin PC'sinde kolaylkla alabiliyor olmam salamas gibi avantajlarndan dolay JavaScript'de de benzer bireyler yapmay hedeflemitim. Ancak JavaScript'den VIC simlatr yapmak o kadar da kolay deil. Gelin ne olduunu ve nasl yapldn inceleyelim.

[b]VIC simlasyonu tam olarak nedir?[/b]

Commodore 64'n tek renk grafik modu 320x200 znrlkten, yani toplam 64000 pixelden oluur. Ancak PC'de 13h (320x200 256 renk) gibi modlarda almaya alm insanlara commodoredaki hafza yaps balangta epey bir ters gelecektir. nk 13h modunda her bir pixel bir byte'a denk gelirken ve byte deerleri renkleri simgelerken, Commodore'da 1 byte'n her biti 1 pixeli sembolize edecek ekilde 1 byte = 8 pixel'e denk gelir. rnein 197 byte deerini ele alalm:

[b]197 = %11000101[/b]

Yani bunun ekrandaki grnts X'ler dolu o'lar bo pixelleri sembolize edecek olursa;

[b]XXoooXoX[/b]

eklinde olacaktr. Ekrana rnek olarak ard arda bir dolu bir bo pixel izmek istediimiz durumda ise tersten bir hesap yaparak byte deerine ulaabiliriz.

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

Bir dier konu bytelarn nasl dizilecei konusu. Yani her 8 pixellik alan hangi srayla ekrana baslyor. Bu da commodoreda programlama ile yeni tanan insanlarn genelde skntya dt bir baka konu.

Dizilim ncelikle aaya doru balar. Yani 8 pixeli temsil eden bir byte, dierinin altna yerleir. Ancak bu tm ekran iin deil yalnzca 8x8 pixellik bir alan iin geerlidir.

Commodore'un 320x200 znrlndeki ekran aadaki resimde de grnd gibi 8x8 pixellik karakter alanlar halinde 40x25'lik 1000 adet paraya blnmtr.

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

Paralardan her biri ise 8x8 pixelden olumaktadr. te bu her 8x8'lik alan hafzada pe pee gelen 8 byte ile ifade edilir. rnek olarak ekrana yazlan bir A harfi u ekilde bytelara evrilebilir.

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

Grld zere 8x8lik bir alan bu ekilde pe pee 8 byte ile ifade edebiliyoruz. Peki hafzada bundan sonra yazlacak 9. byte ekranda nereye denk gelecek? Bu karakterin bitiiindeki karakter alannn en st 8 pixeline denk gelecek. Yani biz pe pee iki kez ekildeki saylar 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 gsterecektir. Bu durumun tek bir istisnas olabilir. O da bu bytelarn satr sonuna, yani 40. karaktere denk gelmeleri durumudur. Bu durumda ise bir alttaki karakter satrndan devam eder byte dizilimi. Eer bytelarn 320x200lk alandaki koordinatlarn idafe edecek olursak aadaki gibi bir sonula karlarz. Buradaki parantez iindeki deerler srasyla pixel cinsinden x ve y deerleridir. Unutulmamas gereken ey, her bir byten verilen x koordinat deerinden itibaren 8 pixeli kapsaddr.
[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]
Eer yukardaki tablo kafanz kartrdysa size daha rahat anlalr bir model ile aklayaym. rnein karnzda raflar var ve her rafn stnde yan yana duran bir sr su kab var. Siz ayn rafta duran su kaplarnn hepsini hortumarla birbirlerine balyorsunuz. Ksacas biri dolduktan sonra fazla gelen suyu yanndakine aktaryor. Her rafn en sandaki kap bir alttaki rafn en solundaki kaba hortumla bal.

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

Siz en st rafn en solunda duran kaba su doldurmaya baladka 8 birimlik kap dolduunda yanndaki kaba, o da yanndakine aktaryor.

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

En son bir raftaki tm kaplar dolunca ise alt rafn en solundaki kaptan devam ediyor.

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

Burdaki her kap 8x8'lik bir karakter alanna denk geliyor ve 8 byte alabiliyor. Eer her rafta toplam 40 kap olur ve 25 tane de rafmz olursa aln size Commodore'un ekrannn hafza dizilimi. Tek fark bardaklar Commodore'da tersten doluyor. Yani yukardan aaya.

VIC simlatr ise bu hafza dizilimini PC'de simle ederek bize hi Commodore ya da Commodore emlasyonu kullanmadan test ortam salayacak bir ara olacak.

[b]"VIC Simlatr"n JavaScript'den yapmann zor olan yan ve zm nedir?[/b]

Aslnda flash, java ve benzeri tarayc teknolojilerini kullanmaksnz basit bir yntemle JavaScript'den 320x200'lk alann tamamn simle etmek hemen hemen imkanszdr. nk bu 64000 pixellik bir alan demektir ve HTML yap itibariyle 64000 nesne ya da 64000 paraya blnm bir tabloyu kolay kolay kaldramaz. Kaldrsa da ok ama ok yava olur. Peki ne yapmak lazm? Hadi bu yukardaki raf, bardak modelini ele alalm. Biz eer her bir barda birer resim olarak kullanacak olursak bu yalnzca 40x25 = 1000 resim eder ki bu HTML iin olduka makul bir say. Peki ka farkl resim oluturmamz gerekir bu durumda? 2^64 = 18,446,744,073,709,551,616 adet resim oluturmamz gerekir. Hmmm... O zaman bu olay birazck optimize etmemiz gerekecek. Taraycya 1000 resim yerine 8000 resim yklemek onu yaklak 8 kat yavalatacaktr. Peki bu resim saysnda yeterli bir fark yaratacak m? Bu durumda her 1 byte 1 resme denk gelecek yani 2^8 = 256 adet resim oluturmamz yeterli olacak. 8 kat hz kaybederek resim saysn 72,057,594,037,927,936'de 1'e drdk. Fena saylmaz.

Yukardaki paragraf elbette ki biraz espiri ieriyor. Bu "niye her bir byte bir resme karlk geliyor?" sorusuna yant olsun diye yazdm, benim dnce metodumu anlatan bir paragraf. Ancak sonu olarak her 8 pixel, yani her 1 byte' 1 resime denk getirmemiz lazm. Peki bu resimleri nasl oluturacaz? 256 her ne kadar ar byk bir say deilse de inann oturup tek tek photoshopda 256 resmi pixellemek istemezsiniz. Bunun iin ben PHP kullandm. nk PHP'nin grafik ktphanesi olan GD2 ok basit bir kullanma sahip. Sizler de PHP kurup, php.ini'nin iersinden ";extension=php_gd2.dll" satrnn bandaki noktalvirgl kaldracak olursanz aadaki scripti altrarak ihtiyacmz olan 256 resmi oluturabilirsiniz.

Not: Php klasrnn iinde "extensions" isminde bir klasr ve altnda "php_gd2.dll" olmas gerekiyor. Eer bu dll yoksa php.net sitesinden en son srmn installern deil, zipli paketini indirecek olursanz 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 dosyasn altrmak iin bir web server kurulu olmas art deil. sterseniz dorudan konsol penceresinden de scripti tetikleyebilirsiniz. rnek olarak "VicSimulator" klasrnn "D" sabit diskinde kk dizinde durduunu varsayalm.

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

Bu ekilde bir kt almanz gerekir. Eer "php" komutunu bulamaz ve hata verirse bu durumda php.exe'yi yer ald klasrle birlikte ift trnak iareti iine alarak verirseniz sorun kalmayacaktr. rnek:

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

Ancak her zaman "gifolustur.php" dosyasnn bulunduu klasrde olmaya dikkat edin. nk bu script altrld dizine "i" isimli bir klasr ap iersine 0'dan 255'e kadar numerik olarak isimlendirilmi gif dosyalar yaratr.

Peki neden daha aklayc olan "images" yerine yalnzca "i" setik klasr ismi olarak? nk birazdan oluturacamz HTML dosyasnda resimler bu klasrden okunacak ve klasr ismi 8000 kez tekrar edecei iin oluturulacak HTML'in toplam uzunluunu azaltmak ve kty hzlandrmak iin tek harf kullanmay tercih ettik. Bu tr ufak ayrntlar sonucu olduka etkiler. Aslnda en hzls resimleri dorudan kk dizine koymak olacaktr ama dzen iin bu kadar taviz verilebilir.

PHP'ye ok uzaksanz, bir trl yukardaki scripti altramadysanz, Windows'un security ayarlar scripte engel oluyor ve nasl dzelticeinizi bilmiyorsanz ya da yalnzca PHP kurmaya/kullanmaya eniyorsanz bu durumda derginin iersinde yer alan hazr gifleri kullanabilirsiniz.

VIC Simlatr'nn JavaScript Kodlar

Srada i VIC Simlatr'n yazmaya geldi. Kolaylkla kullanlabilmesi ve kopyala&yaptr ileriyle uratrmamak iin kodlar ayr bir JS uzantl dosyada tutacaz. JS uzantl dosyalar kolaylkla HTML'lere linklenebilir ve kullanlabilirler.

[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 haritasnn oluturulmas biraz zaman alabilir.
\nHarita oluturulurken sabrl 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 simlatr yapmak bu kadar kolay. Bu kodu aklamaya ihtiya duymuyorum. Sonu olarak ne yaptn bilmeniz nemli. Kodun en banda global olarak tanmlanan "VICHaritasi" dizisi 8000 bytelk bir dizi. ekraniTemizle() fonksiyonu bu diziyi 0 deerleriyle dolduruyor ve ekraniCiz ise bu deerleri VIC'in alma prensibine uygun bir ekilde simle ederek uygun gif paralar ile bir tablo halinde ekrana basyor. ekraniTemizle() fonksiyonu bu scriptin sonunda arlrken ekraniCiz() fonksiyonu bu scriptin linklendii HTML dosyasndan kullanlmak zere hazrland.

imdi bu yukardaki scripti kullanan bir HTML rnei grelim.

[b]vicsim.htm[/b]
[b]
<html>
<head>
<title>VIC Simlatr</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 kts:[/b]

ncelikle ekrana aadaki 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 yaptk? Standart HTML yapsn karacak olursak iki blge bizi ilgilendiriyor. Birincisi

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

satr. Bu satrda az nce oluturduumuz "vicsim.js" dosyasn HTML'e ekliyoruz. Dier nemli blge 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 tanmlyoruz. Bunlardan birincisi verilen (x,y) koordinatna nokta basan bir rutin. Elbette ki bu rutin VICHaritasi dizisini kullanyor. Yani aslnda bu fonksiyonu ararak ekrana henz birey izmiyoruz. Bunun yerine noktay VICHaritasi dizisindeki ilgili bytelar deitirerek koyuyoruz.

Dier fonksiyonumuz ise ekraniOlustur() fonksiyonu. Bu fonksiyon ise ekrana izilecek eyin belirlendii ksm. Bu rnekte ekrana tam snrlarna denk gelecek bir elips izdiriyoruz. ncelikle sins, cosins fonksiyonlar yardmyla elipsin evresini oluturan (x,y) deerleri elde ediliyor, daha sonra az ncesinde yaratlm nokta(x,y) fonksiyonu arllarak noktalar VICHaritasi dizisindeki yerlerini alyorlar.

Son olarak ekraniOlustur() fonksiyonu arldktan sonra nceki JS dosyasnda bulunan ekraniCiz() arlarak sonucu HTML iersinde grntlyoruz.

in zet bu. Burada sins, cosins kullanlarak ember ya da elips nasl izdirilir bunu aklamay yersiz buluyorum. Forml olarak zaten ak bir ekilde duruyor. 160 ve 100 nerden geldi diyecek olursanz 320 ve 200'n yars yani ekrann orta koordinatlar. 256 adm says ve 128 ise bu adm saysnn yars. Aslnda 128 yerine 256'y olduu ekilde kullanmak gerekir ancak derece -> radyan dnmnde kullanlan bir ksaltma ile (i / 256 * 2 * pi) yerine (i / 128 * pi) eklinde ksalttmz iin 128 deerini kullandk.

Gelelim en can alc noktaya. nokta(x,y) fonksiyonu. Buradaki adres ve byteDegeri'ni nasl hesaplyoruz? Gelin birlikte buna kafa yoralm.

Elimizde bir x ve bir y deeri var. Bizim ulamak istediimiz 8000'lik dizinin kanc elemanna denk geldii ve bu elemann deerini nasl etkilediini (hangi bitini set ettiini) bulmak. ncelikle unu biliyoruz. Ekrann en sol stnden yani dizinin ilk elemanndan itibaren bytelar birer birer arttka y'de 8'lik alanda birer birer artp her 8'den sonra yeniden 0'a dnyor. Bunu yine bardak, raf rneini inceyerek anlayabilirsiniz. lk byte'da y koordinat 0, ikincide 1, ncde 2....sekizincide 7 ve dokuzuncuda yine 0... Peki bu nereye kadar byle devam ediyor? 40. karaktere kadar yani 40x8=320. byte'a kadar. 320. byteda y koordinat 8 atlayarak 8 ile 15 aras deerler almaya balyor. 640'da 16-23, 960'da 24-31 eklinde devam ediyor bu. Peki bunu nasl formlze edeceiz? Madem "her 8'de bir" diyoruz ncelikle bu 8'deki krlma noktasn ilk okuldan kalma yntemle blme ilemi yaparak inceleyelim.

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

Buradaki s sonu ve k kalan' temsil ediyor. Peki bu iki parametreyi nasl formlize edeceiz? Elbette ki aadaki ekilde.
[b]
ys = int(y / 8)
yk = y mod 8
[/b]
Yani "ys", y / 8 ileminden kan sonucun tam say ksm ve "yk" ise 8 ile blmden kalan yani matematiksel ifadesiyle "mod 8". Peki bu "ys" ve "yk" bize neyi veriyor. Hadi bir tablo yaparak grelim sonucu.
[b]
ilem: 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, ite bu tablodaki deerler bireyleri ortaya karyor. Dkmann en banda verdiim tabloya bakarsanz ve az nce bahsettiim gibi 320'de bir y'de 8'lik bir art olduunu dnecek olursak hafzadaki doru adresi bulmak iin "ys" parametresini 320 ile arpmak ve "yk" ile toplamak gerekiyor. Bu durumda formlmz;

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

Haline dnyor. Burdaki "yi" bize dizinin y koordinatna bal indeksini veriyor. Ne yazk ki iimiz bitmedi. Bir de x koordinatmz var. Ama x koordinatnda iimiz biraz daha kolay. Tek bir noktay unutmamak kouluyla! x koordinatndaki 1 pixellik ilerleme y koordinatnda olduu gibi hafzada 1 byte'lk ilerlemeye denk gelmiyor. 8 pixel ayn byte zerinde yer alyor. Yani x = 0 ve x = 7 deerleri aslnda bize ayn byte' veriyor. Ancak bu byte'da deitirmemiz gereken bit deerleri deiiyor. imdilik yalnzca hafza adresini bulmaya altmza gre x = 0 ve x = 7 bizim iin ayn ey ifade ediyor. Bu ne demektir? x'i 8'e blebiliriz. Bylece;
[b]
xs = int(x / 8)
xk = x mod 8

ilem: 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 deerlerini elde ediyoruz. Ekran adreslerinde bir srada toplam 40 byte var. Ancak unutmamamz gereken hafzada bu bytelarn pe pee gelmedii 8'er aralklarla dizildii. nk aralarda ayn karakter alannda yer alan dier y koordinatlarna ait deerler duruyor. Peki 8'er 8'er gittiine gre ne yapmak lazm? Tabii ki bu "xs" deerini 8 ile arpmak lazm.

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

Hadi artk bu kadar uzun ilemden sonra u adres indeksini bulalm.

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

te bu kadar. Artk dizinin kanc elemanna erimemiz gerektiini biliyoruz. Ama hala ona hangi deeri vermemiz gerektiini bilmiyoruz. Bunu bulmak iin "xk" parametresini kullanacaz. Peki "xk"nn 0'dan 7'ye deiim gstermesini ekranda nasl grmemiz lazm?
[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 deerleri tablolayabiliriz. Ama sonu olarak bunu da formlze etmek mmkn. yle ki

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

Evet "bd" yani byte deerini 2'nin (7-xk). ssn alarak bulabiliyoruz.

Uff puff. Peki baka birey kald m? Ne yazk ki evet... Ama ufak birey. Biz bu byte'a dorudan bir deer verdiimizde byte'n eski deerini silmi oluyoruz. Bu durumda ekrana basmak istediimiz bir nokta, ayn byte'a denk gelen dier 7 noktay silmi oluyor. Bunu engellemek iin OR'lamak lazm. Matematikteki "veya" ifadesini bir hatrlayalm.
[b]
%11010001
%10001010
-------------- <- OR
%11011011
[/b]
Byte'n eski deeriyle "bd" deerini OR'ladmz taktirde eer o pixel daha nceden baslmsa bir deiim olmayacak, baslmamsa baslacak ve dier bitler durumdan etkilenmeyecek. rnek olarak byte'n ilk ve son bitlerine daha nceden nokta konulmu olduunu varsayalm ve biz 3 numaral bit'e (2^3) OR'layarak bir nokta koyalm.
[b]
%10000001 <- Orjinal deer
%00001000 <- Yeni baslan nokta
-------------- <- OR
%10001001 <- Sonu deeri
[/b]
te bu sonu deeri tam istediimiz deer! imdi uzuuun uzun anlattmz bunca paralanm forml toparlayalm. VICHaritasi dizisine ksaca "vh" diyecek olursak;
[b]
ai = yi + xi
bd = 2 ^ (7 - xk)
vh[ai] = vh[ai] OR bd
[/b]
te forml bu. imdi yi ve xi'yi yerlerine koyalm.
[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 deerlerini de yerine koyalm.
[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 kark gzkebilir. Bu yzden paralara ayrarak aklama ihtiyac hissettim. "nokta(x,y)" fonksiyonunun aklanmaya balad yerden buraya kadar olan blm anlayana kadar defalarca okumanz tavsiye ediyorum.

imdi de bu forml JavaScript diline uygun hale getirelim. ncelikle bir sayy 8'e bldkten sonra tam say ksmn almann en basit yolu o sayynn bitlerini 3 bit saa kaydrmaktr. 3 bit saa kaydrmak sayy 2^3'e blmek anlamna gelir ki darda kalan bitler ksrattr. Ksrat atm oluyoruz ksacas. JavaScript C tabanl bir dil olduu iin peratrlerinin de birou C ile ayndr. Bit kaydrma ilemleri << ve >> operatrleriyle yaplr. Yani y >> 3 diyerek y'yi 8'e blp tam say ksmn almak mmkn.

Gelelim mod ilemine. Aslnda "%" operatryle bu ii halledebiliriz ancak sz konusu olan say 2'nin slerinden biriyse AND'lemek her zaman daha iyi ve daha hzl bir yntemdir. mod 8 demek saynn 7 ile AND'lenmesi demektir. 7 = %00000111 ile AND'leyerek 7'yi geen saynn tekrar 0'a dnmesini salyoruz. mod 8 de ayn ii gryor.

Bir baka nokta ise "xi" parametresinde yaptmz 8'e blp tam say ksmn alp 8 ile arpma ilemi. Bu ilem yalnzca saynn alt 3 bitin sfr olmasn salyor. Aslnda alt 3 bit sfr olacak ekilde %111111000 = 504 ($1f8) saysyla AND'lemek de bize ayn sonucu verecektir. Burada dikkat edilmesi gereken husus x'in 0-255 deil 0-319 aralnda deitiidir. Bu yzden AND'lerken 8 deil 9 bit kullanyoruz.

AND ve OR operatrleri JavaScript'de yine C'de olduu gibi & ve | karakterleriyle ifade ediliyorlar. s alma ilemi iin ise Math kthanesinde yer alan pow(say, s) fonksiyonu kullanlyor.

imdi btn bu yazlanlar toparlayacak olursak forml son eklini u ekilde alyor.
[b]
ai = ((y >> 3) * 320) + (y & 7) + (x & 0x1f8);
bd = Math.pow(2,7 - (x & 7));
vh[ai] = vh[ai] | bd;
[/b]
rnekteki deikenlere 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 aklamas.

Evet Commodore 64'de ekrana nokta basmak o kadar da basit bir i deildir. 64'ler dergisinde Bar Yalnkaya'nn ke yazsnda bir okuyucunun sorusunu hatrlyorum. Okuyucu "Commodore 64'de ekrana gen, kare gibi ekilleri nasl izebilirim?" diye ok mantkl ve basit bir soru sormutu. Eminim Bar bir hayli ter dkmtr cevaplayana kadar. En son cevap olarak bir izim programyla hazrlanm bir grafiin nasl ekrana baslacan anlatmt. Ama Bar'a kesinlikle hak veriyorum. Ekrana nokta basmak bile grdnz gibi "anlatmaya geldiinde" olduka zor bir i.

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

Tamam, simlatrle bastk noktalar. Ama imdi bir de bu iin Commodore'a uyarlanmas var. Genellikle Commodore 8 bitlik bir bilgisayar olduu iin ilk verilen nokta basma rutini rneinde x koordinat 0-255 aralnda deerler alabilecek ekilde rneklenir. Ancak ben sizlere dorudan x: 0-319 ve y: 0-199 aralnda deerler alabilecek ekilde yani 9 bitlik bir x koordinatyla nasl nokta baslacan gstereceim. ACME ile derlenebilecek kod rnei aadadr.

[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
  ;
  ; Ekrann 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 dngye gir

;
; isim : noktakoy
; aciklama : ekrandaki verilen (x,y) koordinatna 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]
Programn kts:

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

Bu rnekte dikkat edilmesi gereken bir nokta var. (Bakn ekrann ortasnda 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 blmde grdnz register isimleri kafanz kartrmasn. Yani "ldx" komutu x koordinat deerini tar eklinde dnmeyin. Aksine yanlarnda aklamalar olduu gibi ldx ile 0-199 arasndaki y koordinat deerini y register'na yklyoruz. ldy ve lda ise x koordinat deerlerini ieriyor. Peki burada 9 biti nasl kullandk? y registernn en sadaki biti (0. bit) a registernn 9.biti anlamna geliyor. Yani x'e 300 gibi 255'den byk bir deer vermemiz gerektiinde bunu ncelikle 9 bitlik bir ifade eklinde yazmalyz.

[b]300 = %100101100[/b]

Daha sonra en soldaki biti y registernn en sadaki biti olacak ekilde ayrp geri kalan 8 biti de a registerna vermek gerekiyor. Yani;
[b]
ldy #%00000001
lda #%00101100
[/b]
eklinde x'e 300 deerini verebiliyoruz. Bunu daha basit grmenizi salamak iin 300' 16 bit ile ifade edip ortadan ikiye bleceim.

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

Soldaki para y, sadaki ise a register'nn deerini ifade ediyor.

Dikkat etmeniz gereken nokta y registernn 1 deerini almas durumunda x'in deerinin 319 - 256 = 63 deerini gememesi gerektiidir. Yani y'nin her iki deeri iin a'nn deer aralklarn inceleyecek olursak;
[b]
y = 0 -> a [0,255]
y = 1 -> a [0,63]
[/b]
Olmas gerekmektedir. Benzer ekilde y koordinatnn deerlerini tutan x register ise 199'u gememelidir.

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

Bu koullara uyulmak suretiyle 320 x 200'lk alanda ekrann istediiniz yerine nokta basabilirsiniz.

imdi bu rnei VIC Simlatr'ndeki rnei yapmakta kullanalm.

Commodore 64'de Vic Simlatr'deki rnek le Ayn Sonucu Veren Program Hazrlamak

ncelikle elipsin iziminde kullanlacak baz sins tablolarn hazrlamamz gerekiyor. Bu konu bir nceki Test Platformu blmnde detayl olarak ele alnmt. Burada yine JavaScript kullanyoruz.

[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 taraycya verdii kty kopyala&yaptr ile "elipsciz.a" kaynak kodununun sonlarnda belirtilen blgeye yaptrmamz 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
  ;
  ; Ekrann 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 sayacn 1 arttr
  bne anarutin ; eer hala 255'i gemediyse ana rutin balangcna git

  jmp *   ; sonsuz dngye gir

;
; isim : noktakoy
; aciklama : ekrandaki verilen (x,y) koordinatna 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"nn kts buraya gelecek]

  * = VIC_HARITASI
  
  !fill $1f40, 0
[/b]
Programn kts:

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

[b]VIC Simlatr'de Yaplan lemin Commodore'a Aktarlmasna likin Deerlendirme[/b]

Ekrana nokta basma rutini VIC Simlatr rneinde ok detayl anlatld iin Commodore 64 versiyonunun aklamasn yapmaya gerek duymuyorum. Uyarlama olarak tpatp ayns. Elbette ki baz ek tablolar kullanlyor, Commodore'a zel optimizasyonlar ve mecburi tasarm deiiklikleri oluyor. Ama bunun haricinde anlatlacak pek birey yok. En bandan beri bahsettiim gibi, bu dkman 6510 ASM'yi kaba hatlaryla bilen ve ACME ya da benzeri derleyicileri kullanm kiilere hitap ediyor. Eer 6510 ASM bilmiyorsanz, bu rnekleri anlayabilmek iin ncelikle balang seviyesindeki dkmanlar okumanz tavsiye ederim.

Gelelim elips rneine. Burada VIC Simlatr'ndeki;
[b]
x = 160 + 160 * Math.cos(i / 128 * Math.PI);
y = 100 + 100 * Math.sin(i / 128 * Math.PI);
[/b]
satrlarn nasl uyarladk? Aslnda tay iyice ykseltmemek iin kt bir yntem kullandk. yle ki bu izdiimiz elipsin aplarndan birini bile deitirmek istesek "sinus.htm" dosyasn deitirip, yeni sins tablolar elde edip, ktlar "elipsciz.a" kaynak koduna yaptrdktan sonra program yeniden derlememiz gerekecek. Peki neden?

Sorunu yle ele alalm. Commodore 64'de sins fonksiyonu yok. Peki sins fonksiyonunu nasl uyarlayabiliriz? Aslnda matematiksel olarak bunun yntemleri var, hatta hatta ok ksa assembler kodlaryla bile sins hesaplatlabiliyor. Ancak en hzl yntem nceden hazrlanm bir tablo. Peki bu tabloyu hafzada nasl tutacaz?

Sins fonksiyonu ne yazk ki yalnzca ondalkl sonular vermekle kalmyor, hatta hatta yalnzca -1 ile 1 aras sonular veriyor. Bu durumda byte deerleri tam say olduu iin ksratlar atacak olursak, tabloda yalnzca -1, 0 ve 1 deerleri bulunur. Bytelar negatif deerler de alamayaca iin muhtemelen -1 yerine 7 bit kullanarak (en soldaki bit pozitif negatif iareti belirtecek ekilde) 255 ya da 128 benzeri bir deer kullanmamz gerekecektir. En mantkl yntem sin(x) deil de a*sin(x)'i tablolamak. Bu durumda ksrat kaybndan nemli lde kurtulmu oluyoruz. Kaybolan ksratlar ise bu tr bir rnekte hi nemli deil. Ancak negatif saylarla ilgili problemimiz hala devam etmekte. Bu durumda JavaScript'deki rnein birebir aynsn tablolayarak bu ii zyoruz yani
[b]
a + a * sin(x)
[/b]
Burada x ve y iin a deerleri 160 ve 100 olduuna gre;
[b]
160 + 160 * cos(x)
100 + 100 * sin(x)
[/b]
hesaplamamz gerekiyor. Cosins fonksiyonu sins tablosunu biraz ilerden okumaya balayarak elde edilebildii iin cosins ayrca tablolanmyor yalnzca sins tablosu pe pee iki kez hafzaya konuluyor.

Burada yaanan son sorun x koordinatlarnda kyor. x 255 deerini getii ve tek byte ile ifade edilemedii iin iki tabloya blnmek zorunda kalyor. Bir tablo alt 8 bitini 1 byte ile ifade ederken dier tablo ise 9. bitini bir byte ile ifade ediyor. Bu hesaplama ileri "sinus.htm" dosyasnda halledildikten sonra kaynak koda yerletiriliyor ve basit bir dngyle tablodaki hazr deerler okunarak ekrana pixeller yerletiriliyor. Peki buradaki yntem ne derece yanl?

Aslnda yntem hemen hemen doru. Tek eksik tablolarn sabit deerlerle arplarak hazrlandktan sonra olduu gibi kullanlmas. Olmas gereken tablolarn mmkn olan en geni deerlerle hesaplandktan sonra bir katsayyla arplarak kullanlmasdr. Mmkn olan en geni katsayya rnek vermek gerekirse buradaki formlde 8 bitlik bir tablo iin en geni "a" deeri 128'dir. Yani 128 + 128 * sin(x) eklinde 0 - 255 arasndaki deerler elde edilebilir. 256'ya tama nlenmek amacyla 128 + 127.9 * sin(x) haline getirilmesi gerekebilir. Neden bu yntem kullanlmad?

nk bu yntem arpma ilemi gerektiriyor ve Commodore'da arpma ilemi yapmak da bal bana bir meseledir. Ayrca 8 bitlik bir sayyla 8 bitlik bir sayy arpp 16 bit sonu elde etmek nisbeten aklamas kolay bir durumdur. Ancak x koordinat 9 bit olduu iin 16 bitlik bir sayyla 8 bitlik bir sayy arpan ve 24 bit sonu veren bir rutine ihtiya vardr ve bu noktada iler gittike zorlayor. Elbette ki 9 bitlik koordinat sisteminin hassasiyeti bir miktar bozularak bu ii sahte yntemlerle zmek mmkn. Ama u seviyede bu tr konulara girmeyi uygun grmediim iin sabit tablolardan okunan deerleri olduu gibi kullanmay tercih ettim.

ler giderek detaylanyor ve bu sayda da burada brakyoruz. Sizlere iyi beyin jimnastikleri diliyorum.

Benimle irtibata gemek isteyenler iin e-mail adresim;
[url = mailto:c64hydrogen@yahoo.com]skate <at> glance <dot> ws[/url]
[b]
Emir Akaydn
Skate / Glance / Clash
[/b]
