14. Bölüm
Cenker Özkurt
C severler Amiga başına. Artık sıra sizde! Amiga'da baş döndürücü programlar yazmak için, elinizde daha fazla kaynak program olacak. Kaynaklar bizden!
Bu sayımızda, geçen sayıda verdiğimiz örneğin açıklaması dışında, Amiga'da library açma-kapama ve bununla ilgili örnekler göreceksiniz.
Şimdi sizlere Amiga Library'leri hakkında biraz bilgi vererek yazıma başlamak istiyorum. Library'ler (kütüphaneler), adından da anlaşılacağı gibi, içerisinde bilgisayar için gerekli olan sistem komutlarını içerir. Biz herhangi bir programı çalıştırdığımızda, grafik ya da müzik olsun, program kendi için gerekli olan library'i açarak içindeki program parçalarını kullanmaya başlar. Bu program parçaları (routine'ler), Amiga üreticileri tarafından bilgisayarınızın belleğine (Rom'una) yerleştirilmiştir. Tabii ki bu, biz programcılara büyük kolaylıklar sağlamaktadır. Zaten C dili de bu program parçalarını kullanmak için yazılmış en ideal dillerden biridir. Ayrıca Amiga'mn Rom'unun da, C dilinde yazıldığını belirtmeden geçemeyeceğim.
Amiga'da Library'ler, yaptıkları işe göre çeşitli isimler altında toplanmıştır. Örneğin grafik için gerekli olan program parçaları Amiga'da 'graphics.library' olarak isimlendirilmiştir. Eğer biz Amiga'da yeni bir ekran (screen) açmak istersek, 'graphics.library'yi kullanmak zorundayız. Çünkü Amiga bize bu screen'i açmak için 'graphics.library' içinde bir routine hazırlamıştır. Biz bu library'i açarak, sisteme grafik alt programlarını kullanacağımızı bildiriyoruz.
Aslında biz bu routine'leri kullanmak zorunda değiliz. Mesela ekran açma işini, biz kendimiz de bir alt routine olarak hazırlayabiliriz. Fakat bu düşünüldüğü kadar kolay bir iş değil. Çünkü böyle bir programı hazırlamak için, hem Amiga Hardware'ini (donanımını) çok iyi bilmeli, hem de bu routine'leri, hardware'e tam olarak ulaşabilmek için Assembler (en hızlı program dili: 68000MC bu dili kullanır.) ile yazmalıyız. Ayrıca şunu da belirtmek isterim ki; C dili içerisinde de Assembler programları yazıp kullanabilirsiniz. Eğer C dili içerisinde Assembler kullanmak isterseniz, biraz Assembler ve Hardware çalışmanız gerekiyor. Zaten bildiğiniz gibi dergimizde, Ömer Sinan Polat arkadaşımızın Assembler kursları yayınlamakta. Siz de bu yazılan takip ederek hem Assembler öğrenmiş, hem de daha hızlı programlar yazmış olursunuz.
Daha hızlı programlar(!) dedim. Şimdi soracaksınız, Amiga C hızlı bir dil değilse, neden Amiga'nın Rom'u C dilinde yazılmış? Aslında olay şu; Amiga C dili oldukça hızlı bir dildir. Zaten C Compiler programı da, yazdığınız programları sonuç olarak Assembler diline çevirir. Fakat C'de routinler birden fazla amaca yönelik yazılmıştır. Bu programlar çalışırken, devamlı olarak başka programlarla alışveriş içerisindedirler. Bunun amacı, programın hatasız olarak çalışmasını sağlamak; eğer varsa da, bunu kullanıcıya ya da programcıya bildirmektir. Tabii ki bu da programın hızını biraz yavaşlatmaktadır. Fakat bunun bazı avantajları da vardır. En başta gelen avantajı, hem bu routinleri kullanarak daha kısa zamanda program yazabilmemiz, hem de korkusuzca istediğimiz program parçalarım (routine'leri) kullanabilmemiz. Sadece bu oldukça yeterli bir sebep. Ama öyle program kısımları olur ki, bu kısımların hem çok kısa sürede işini bitirmesi, hem de çok iş yapması beklenir. Bu tür routinlerin oldukça hızlı olması gerekir. İşte kara gün dostunuz Assembler, böyle zamanlarda yardımınıza koşar.
Şimdi Amiga'da var olan diğer Library'leri ve yaptıkları işleri kısaca görelim; gerçi Assembler'cı Ömer Sinan arkadaşımız geçen sayılarda ayrıntılı olarak Library'lerden bahsetmişti; fakat ben de kısaca değinmek istiyorum. Amiga'nın Library'leri şunlardır:
EXEC.LIBRARY
Amiga sisteminizin çalışması için, bu Library'ye ihtiyacınız vardır. Bu Library açılmadan diğer Library'ler açılamaz. Çünkü Library'leri açmak için gerekli olan OpenLibrary() fonksiyonu, 'exec.library' içerisindedir ve hafızada hazır olarak bulunmaktadır. Unutmadan şunu da belirteyim ki; bazı Library'ler Amiga'nızın Rom'unda değil disketlerde saklıdır. Bunlar sonradan hazırlanmıştır. Bu Library'leri kullanacaksanız, disketinizde LIBS directory'si içinde bulunup bulunmadıklarına dikkat edin. Yoksa Library'niz açılamaz.
Exec Library, bunlardan başka hafıza ayıran komutları içerir. Çünkü bildiğiniz gibi, Amiga Multi-Tasking bir alettir. Birden fazla program çalışırken, hangi programın hangi hafızayı kullandığını sisteme belirtmek gerekir. Böylece programlar birbirlerine karışmamış, kısacası aletiniz **Crash** etmemiş olur. Bundan başka 'exec.library' input-output kanallarının çalışması için gerekli olan program parçalarını içerir.
GRAPHICS.LIBRARY
Bu Library grafik için gerekli olan yazı, çizim, ve buna benzer grafik routine'lerini içerir. Ayrıca ekrandaki veya hafızadaki bir bloğu taşımak için kullanılan, Amiga'nın yardımcı çipi Blitter'ı kullanır. DOS.LIBRARY Amiga'nızın disket işlemleri için gerekli olan komutları içerir. Yükleme, saklama, silme, kopyalama gibi..
INTUITION.LIBRARY
WorkBench disketinizi taktığınızda, karşınıza çıkan ilk pencere bu Library sayesinde oluşmaktadır. Menüler, ekranlar ve windowlar, bu library ile kullanılabilir hale gelir.
CLIST.LIBRARY
Amiga'nızdaki Copper çipi için gerekli, değişiklikleri yapmada kullanılır. Copper, grafik içinde kullanılan çok hızlı bir Hardware donanımıdır.
MATHFFP.LIBRARY
Basit matematiksel fonksiyonları içerir.
MATHTRANS.LIBRARY
Yüksek seviyeli matematiksel fonksiyonları içerir.
MATHIEEEDOUBBAS.LIBRARY
Integer (tamsayılar) için basit matematiksel fonksiyonları içerir.
DISKFONT.LIBRARY
Disketteki fontları kullanmamızı sağlayan routine'leri içerir. FONTS directory'si içerisindedir.
LAYERS.LIBRARY
Ekran hafızalarını kontrol eden program parçalarını içerir.
Bunlar dışında, CONSOLE.LIBRARY, POTGO.LIBRARY, ICON.LIBRARY, TRANSLATOR.LIBRARY de Amiga'nızın Rom'unda bulunuyor.
Library'ler de burada sona erdiğine göre, artık geçen sayımızda verdiğimiz örneğimizi açıklamaya başlayabiliriz. Fakat gene de bu örneği açıklarken, bazı noktaları yüzeysel olarak geçeceğim. Bunlara ileride daha derinlemesine değineceğiz.
Şimdi ilk olarak programımız başındaki INCLUDE'ların ne işe yaradıklarına bir bakalım.
Include'lardan sonra küçük ve büyük işaretleri arasındaki isimler, programımızın başlangıçta tanımlaması gereken yapıların saklandığı dosya ismini verir. Bu isimler Compiler disketinizin içerisindeki 'include' directory'si içerisinde saklıdır. Include komutundan sonra, bu dosya yüklenerek ilk tanımlamalar yapılır. Bu dosyanın da bir C dosyası olması zorunludur. Çünkü compiler bu dosyayı da derler. Ayrıca bu dosyalarda macrolar, değişkenler ve yapılar mevcuttur. Eğer biz bir grafik programı yazacaksak, içerisinde bu routine'lerin kullanacağı macroları veya yapıları saklayan <graphics/gfxbase.h> dosyasını include ile yüklemeliyiz. Aksi takdirde, grafik library'nin açıldığı adresi saklayan değişkenin (GfxBase) yapısını belirleyememiş oluruz.
Include, bir compiler komutudur. Bundan başka <> işaretleri arasındaki dosyanın uzantısının da sonunda '.h' olmasına dikkat edin. Ayrıca o işaretleri yerine "" işaretleri de kullanabilirsiniz. Aradaki fark, compiler programının, <> işaretleri arasındaki dosyayı disketteki 'include' directory'si içinde araması, "" işaretleri arasındaki dosyayı da, aktif directory içerisinde aramasıdır.
Diğer include dosyalarının hangilerinin nerelerde kullanıldığını ise, programlarımızı verirken birlikte açıklayacağız.
İşte aşağıda include'dan sonra bu dosyaların tanımlamış olduğu yapıları görüyorsunuz. Bu yapılar sistem için sabit olarak isimlendirilmiştir. Bu nedenle GfxBase yerine başka bir değişken kullanamazsınız. Aksi takdirde sistem grafik için kullanılan library adres değişkenini bulamaz.
struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase;Dikkat ederseniz burada IntuitionBase ve GfxBase değişkenleri, yapıyla aynı ismi alıyor. Satırlardan da anlaşılacağı gibi, Intuition ve Graphics library'leri için gerekli olan library başlangıç adres değişkenleri tanımlanıyor. OpenLibrary() komutu, istenilen library'yi açıp bu library için ayrılan bellek alanını alarak geri dönüyor.
struct RastPort *rp; struct Screen *screen;Bu satırlarda ise, RastPort ve Screen yapıları değişkenler aktarılıyor. RastPort, bize screen (ekran) veya window (pencere) için gerekli olan bazı adres ve bilgileri içeriyor. Mesela RastPort yapısı sayesinde, gene kendi içerisindeki BitMap yapısından ekranın bitmap adreslerini öğrenebiliyoruz. Bunun dışında RastPort, grafik komutları için bir parametre oluşturuyor. Grafik komutları, RastPort'un içeriğine bakarak kullanacakları ekranın grafik adresini, büyüklüğünü, renk sayısını öğreniyorlar.
Screen structure'ı ise, ekranın tüm özelliklerini saklayan değişkenlerin yapısını oluşturuyor. RastPort değişkeni de zaten Screen içerisinde mevcut.
Sistemin kullanmış olduğu bu yapıları ve içeriklerini daha sonra vereceğim.
main()komutundan sonra artık program işlemeye başlıyor.
IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",0);
IntuitionBase değişkenine, 'intuition.library' için atanan başlangıç alanı veriliyor, (struct IntuitionBase *) ile, OpenLibrary'den gelecek olan değerin tipi belirlenmiş oluyor.
GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",0);
IntuitionBase gibi, fakat 'graphics.library' için atanan başlangıç adresini veriyor.
screen=IntuitionBase->ActiveScreen;IntuitionBase yapısı içinden aktif olan screen'nin yapı adresi, screen değişkenine atanıyor.
rp=&(screen->RastPort);screen'in içerisinden, RastPort yapısının adresi rp değişkenine atanıyor. Buradaki & ile screen->RastPort'un adresini almış oluyoruz. Çünkü screen'in içerisindeki RastPort pointer olarak belirlenmemiş.
cls();ile kendi hazırladığımız WorkBench'i silme routine'nine sıçramış oluyoruz. Bu routine'de ise;
int y;y integer değişkenini tanımlıyoruz.
SetAPen(rp,0);komutu ile, ekrandaki kalem rengini zemin rengi olarak seçmiş oluyoruz. 0, zemin rengini belirliyor. Bu sayı WorkBench ekranında olduğumuz için maksimum 3'e kadar çıkabilir; yani toplam 4 renk.
Dikkat ettiyseniz, rp parametresi kullanıldı. Çünkü SetAPen() fonksiyonu bir grafik komutudur.
Ekranı soldan sağa çizgiler çekerek siliyoruz. Yukarıdan aşağı 200 satırlık bir döngü.
Move(rp,0,y); Draw(rp,640,y);Move() ile çizim başlangıç koordinatını Draw() ile çizilecek olan nokta koordinatını vererek çizimi bitiriyor ve döngü de bittikten sonra geri dönüyoruz.
CloseLibrary(IntuitionBase); CloseLibrary(GfxBase);Evet, bu komutlardan sonra da açmış olduğumuz 'intuition.library' ve 'graphics.library'leri kapıyor ve sistemi rahat bırakıyoruz.
Bir örnek program da burada sona eriyor. Fakat bu programımız bizim Amiga'daki ilk önemli programımız. Bu etapta anlayamadığınız bazı noktalar olacaktır. Siz de bu örnekleri geliştirerek anlamadığınız noktaları açıklığa kavuşturabilirsiniz.
Programımızın compile işlemleri hakkında biraz daha bilgi vermek istiyorum. Çünkü geçen sayıda verdiğim açıklamalar, biraz yetersiz ve eksikti.
Burada kullandığımız grafik komutları, aslında parametrelerini Long türü değişken olarak istemektedir. Fakat biz programımızda int türü değişkenler kullandık. Bu da programın aksak çalışmasına neden olur ya da program çalışmayabilir. Bu nedenle, ya program içerisindeki değişkenleri long yapmalı ya da compile işlemi sırasında bunu compiler'a bildirmeliyiz. Fakat program içerisinden int'leri long yapmak da yetmeyebilir. Çünkü bazı sabitler bulunabilir. Mesela bizim programımızda olduğu gibi;
SetAPen(rp,0);0 sabittir ve compiler, bu değişkeni int olarak alacaktır. Fakat biz bu sabiti;
SetAPen(rp,0L);olarak yani yanına 'L' koyarak long olduğunu belirtebiliriz. Fakat eğer bu sabitler fazla ise, biraz uğraştırır. Bu nedenle, en iyisi bizim Compiler'a bunu bildirmemiz. Yani compile ederken;
CC +L program.cLink ederken;
LN program.o -LC32yazmalıyız. Compiler'daki +L opsiyonu değişkenleri long olarak çevirir. Link işlemindeki -LC32 ise, kullanılacak olan komutların 32 bitlik olduğunu belirtir. Bu işlemler Aztec C V3.6 için geçerlidir. Daha fazla bilgi için Aztec C manuel kitabına bakabilirsiniz.
Şimdilik bu kadar diyorum. Gelecek ay yeni ve daha gelişmiş programlarla görüşmek üzere hepinize iyi çalışmalar ve bol sistem komutlu günler dilerim!