AMIGA ve C
Retro bilgisayarAMIĞA
CENKER ÖZKURT Amiga C'de örnek programlarımız devam ediyor. Bu ay iki yeni örneğimiz var. İlk örnek program, disketinizin herhangi bir track ve sector'ündeki bilgileri, bir sector uzunluğunda (512:
byte) okumanızı sağlıyor. Elinizdeki birçok disket utility programlarında olduğu gibi. Tabii ki bizim örneğimiz bu olayı daha basite indirerek anlamanızı kolaylaştırıyor. İkinci örneğimiz ise, bir hafıza bölgesini görüntülememizi sağlayan kısa bir program. Bu program ile yumuşak hardware scroll'lar ile daha büyük ekranlar üzerinde gezebiliriz. Sanıyorum, şu ana kadar vermiş olduğum kısa veya uzun örnek programları, yazarak veya üzerinde oynayarak deneyim kazanmışsınızdır. Bu ayki örneğimiz de aynı amacı taşıyor. Bundan sonra ise C'de yeni bir konu üzerinde düracağız! Konumuzu kısaca açıklayayım; Bildiğiniz gibi Amiga'nın işletim sistemi oldukça gelişmiş (PC'lere göre!). Açılan screen'ler, window'lar ve gadget'ler bu sistemin bir parçası. Böylece bir mouse aracılığı ile bile program kullanmak oldukça kolaylaşıyor. Bu sistemin tamamı, “intuition.library' içerisindeki program parçaları ile yönetiliyor. İşte bu sistemi tanımak ve benzeri programları yazabilmek için, “intuition.library” içerisine gireceğiz. Bu konuyu kısaca "intuition" olarak tanımlayabiliriz. Buradan da anlaşılıyor ki, gelecek ayki ve sonraki aylardaki konumuz, "intuition". Bu konuyu iyi kavradığınızda artık birşeyleri aşmış sayılırız! Evet, bu ayki ilk örneğimize geçebiliriz. Önceden de belirttiğim gibi, ilk örnek ile disketteki herhangi bir track ve sector'deki bilgileri, bir sector uzunluğunca (512 byte'lık) okuyabiliyoruz. Program çalıştırıldığında bizden bir track, sector ve kafa (head) numarası istiyor. Burada track O ile 79 arasında, sector O ile 11, kafa ise O ya da 1 olabiliyor. Daha sonra program, disketinizin vermiş olduğunuz bölgesindeki 512 byte'lik kısmı hem ASCII hem de HEX olarak, hafızasına yükleyerek ekrana yansıtıyor. Bu sayede o bölgeyi incelememiz mümkün olabiliyor. Şimdi aşağıdaki programımızı bir deneyin!.
/* (c) ShowDisk by Cenker Ozkurt */
#include "exec/types.h"
#include "exec/devices.h"
#include "devices/trackdisk.h"
ra
#define TD READCMD READ
#define BLOCKSIZE TD SECTOR
#define NUMHEADS 2
struct MsgPort *diskport;
struct IOExtTD *diskreg;
BYTE
BYTE *diskdata;
ULONG diskChangeCount;
main(argc,argv)
int arge;
char *argv(1;
int ij;
printf("ShowDisk by Cenker Ozkurün");
if(arge!—4) |
printf("Usage : ShowDisk (Cylinder) (Sector) (Headn");
return(0);
|
TnitDisk();
diskdata — &diskbuffer|0);
ReadC
FreeDisk(;
for(i-0;i<512;i4-8) |
: " i);
for(j-0;j<8;j44) |
printf("9002x ",(UBYTE) *(diskdata*i4j));
printf("
|
if(*(diskdata*i4j)>32) |
printf("9oc",*(diskdata*i4j));
) else print£(".");
diskreg->iotd Reg.io Length > BLOCKSIZE;
diskreg->iotd Reg.io Data — (APTR)diskdata;
diskreg->iotd Reg.io Command - TD READ;
diskreg->iotd Count — diskChangeCount;
offset TD SECTOR * (sec * NUMSECS * hd * NUMS
ECS * NUMHEADS * eyl);
diskreg->iotd Reg.io Offset — offset;
return(DolO(diskreg));
|
sec, hd)
SHORT eyl, sec, hd;
LONG offset;
MotorOn()
diskreg->iotd Reg.io Length -
diskreg->iotd Reg.io Command - TD MOTOR;
return(0);
MotorOffO
diskreg->iotd Reg.io Length — 0;
diskreg->iotd Reg.io Command - TD MOTOR;
DolOldiskreg);
return(0);
TnitDisk()
(
diskport — CreatePort(0,0);
if(diskpol 0) exit(100); j
i ruct IOExtTD *)CreateExtlO(diskport,sizeof(str-
uct
if(diskreg —— 0) ( DeletePort(diskport); exit(200); )
DİLLER
OpenDevice(TD
diskreg->iotd Reg.io Command > TD CHANGENUM;
DolOldiskreg);
diskChangeCount — diskreg->iotd Reg.io Actual;
)
FreeDisk()
(
MotorOffO;
CloseDevice(diskreg);
DeleteExtlO(diskreg, sizeof(struct
DeletePort(diskport);
|
Program buraya kadar. Programı yazdıktan sonra CHIP memory'de çalışacak şekilde compile etmemiz gerekiyor. Aksi takdirde programımız doğru çalışmaz. Bunun sebebi, geçen aylarda anlattığım copper olayında olduğu gibi, disk işlemlerinin de kontrol register'larının DMA tarafından kontrol edilmesi. Bu da bizim yapı değişkenlerimizin CHIP hafıza bölgesinde bulunmasını gerektiriyor. Compile işlemini, CC *L Prog.c; link İşlemini ise LN *C prog.o -LC32 olarak yazın. Programı ilk olarak örnek parametrelerle bir deneyelim. Programımızın ismini ShowDisk olarak verdim. Buna göre *“ShowDisk 0 0 0' yazdığımızda, program bize sıfırıncı track ve sector olan bootblock bölgesini görüntüleyecektir. Aynı şekilde root bloğu görmek istediğimizde; *ShowDisk 40 0 yazmamız yeterli olacaktır. Dikkat ettiyseniz, program parametrelerini Main içerisinden alıyor. Bu nedenle programın istediği parametreleri program isminden hemen sonra vermemiz gerekiyor. Program listesini ise rutinler haline getirerek daha anlaşılır yapmaya çalıştım. Bu nedenle şimdilik rutin seviyesinde programımızı inceleyeceğiz.
İlk olarak programımız, içerisinden alarak, eğer bir hata yoksa InitDisk(); rutinine sıçrıyor. Bu rutinde *df0;' device'ını bizim kullanabilmemiz için bir *Port' yaratılıyor (CreatePort();). Daha sonra bu port'u kumanda edebilmemiz için *diskreg' yapı değişkeni tanımlanıyor. (CreateExtlO();). Artık bu işlemlerden sonra device'ımızı açıp kullanabiliriz (Open- Device();). Tabii ki bu işi komutu ile gerçekleştiriyoruz. Bu komut sayesinde 'diskreg' yapı değişkeninde hazırlamış olduğumuz isteklerimiz gerçekleştiriliyor. Daha sonra program TnitDisk(); rutininden çıkıp ReadCyISeci(); rutinine sıçrıyor. Bu rutinde ise istenen track, sector ve head parametreleri verilerek diskten track yükleme gerçekleştiriliyor. Bu rutin içerisinde yine *diskreg' yapı değişkeni vasıtasıyla disket için yapmak istediğimiz işlemi belirtiyoruz. Burada bu isteğimizi 'command' struct değişkenine TD READ olarak verdik. Bu macro değişkeni ile “TrackDisk Read' komutunu vermiş oluyoruz. Burada TD WRITE macro değişkenini verdiğimiz de ise, bir yazma işlemini gerçekleştirmiş oluyoruz. Bu sayede disketinizin istediğiniz bir bölgesine bilgi yazabilirsiniz. Bu arada disketten okuma işleminde, okunacak bilgilerin *diskdata' değişkenine yüklendiğini ve BLOCKSIZE (512 sector) uzunluğunda olduğuna dikkat edin. Rutinden geri döndüğümüzde ise, artık gerekli bilgi *“diskdata” değişkenine yüklenmiş olacaktır. Bundan sonra kendimize ayırdığımız Port'umuzu FreeDisk(); rutini ile rahat bırakabiliriz. Programın sonrası ise artık bilgilerin ekrana Text ve yazılmasını sağlamaktadır. Bir noktayı unutmadan belirteyim; her disketten yükleme ya da yazma işleminden önce MotorOn(); sonra Moto- TOffO; rutinlerine sıçramamız gerekir. İşte, Amiga'da Track-Track yükleme ya da yazma işlemleri bunlardan ibarettir. *diskreg' yapı değişkenine verilen diğer trackdisk macro komutlarını, include dosyaları içerisinden trackdisk.h dosyası içerisinden bulabilirsiniz. Sıra geldi ikinci örneğimize. Programımıza bir gözatarak açıklamamıza geçelim.
#include <stdio.h>
#include <exec/types.h>
#include <graphics/gfx.h>
#include <hardware/dmabits.h>
#include <hardware/custom.h>
#include <hardware/blit.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/rastport.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <graphics/clip.h>
#include <exec/exec.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>
#include <functions.h>
#define DEPTH 3L
#define WİDTH 1020L
#define 1020L
#define VPWIDTH 320L
#define VPHEIGHT 200L
#define NOT ENOUGH MEMORY -1000
struct View view,
struct ViewPort viewport;
struct ColorMap *cm;
struct RasInfo rasinfo;
struct BitMap bitmap;
struçt RastPort rastport;
extern struct ColorMap *GetColorMap(;
struct GfxBase *GfxBase;
USHORT colortable(|—|
0x000, Oxfb0, Oxcce, Oxf15, OxaS0, Ox0c5, 0x777, Ox77f,
0x000, 0x55f, 0x000, Oxc57,
0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
UWORD *colorpalette;
mainlargc, argv)
int argc;
char
LONG i, n;
SHORT nmax>5;
SHORT pfl xmove, pfi ymove;
UBYTE *displaymem;
GfxBase — (struct GfxBase *)OpenLibrary("graphics.library"
OL);
if (GfxBase -— NULL) exit(100);
oldview — GfxBase->Acti View;
InitBitMap(&bitmap, DEPTH, WIDTH, HEIGHT);
InitRastPort(&rastport);
rastport.BitMap — &bitmap;
rasinfo.BitMap — &bitmap;
rasinfo.RxOffset
rasinfo.RyOffset
rasinfo.Next — NULL;
view, ViewPort - &viewport;
view.Modes -PFBA;
viewport.DWidth - VPWIDTH;
viewport.DHeight - VPHEIGHT;
viewport.RasInfo - &rasinfo;
cm — GetColorMap(32L);
if (cm -— NULL) |
exit(100);
colorpalette - (UWORD *)cm->ColorTable;
for(i-0; i<32; |
*colorpalettet-4 — colortableli);
viewport.ColorMap — em;
i<DEPTH; i4-4-) (
bitmap.Planesli) - (PLANEPTR) AllocRaster(WIDTH,
if(bitmap.Planesli) -— NULL) (
printf("Memory?");
exit(NOT ENOUGH MEMORY);
BiCkear(bimap Plaks (i), RASSIZE(WIDTH, HEIGHT), IL):
Draw(&rastport,640,400);
&viewport);
MrgCop(&view);
LoadView(&view);
xmove — 1; pfl ymove — 1;
for( n<-nmax; ) |
rasinfo.RxOffset — rasinfo.RxOffset * pfl xmove;
Tasinfo.RyOffset — rasinfo.RyOffset * pfi ymove;
if (rasinfo.RxOffset <— O Il rasinfo.RxOffset >- 31 9) 1
pfl xmove — -pfl xmove;
)
if (rasinfo.RyOffset <— O Il rasinfo.RyOffset 199) |
pri y o+ - 9. ove.
&viewport);
MrgCop(&view);
LoadView(&view);
WaitTOFO;
FreeMemory0O;
)
FreeMemory()
LONG i;
; i<DEPTH; i4--4-) |
if (bitmap.Planes|i| !— NULL) |
for (i—
WIDTH, HEIGHT);
)
li
FreeColorMap(cm);
LoadView(oldview);
FreeVPortCopLists(&viewport);
FreeCprList(view.LOFCprList);
CloseLibrary(GfxBase);
|
İkinci örneğimiz oldukça yararlı. Bu örnekte köşeden köşeye bir çizgi çekilerek yumuşak hardware scroll gerçekleştiriliyor. Yapılan işlemi kısaca şöyle anlatalım. İlk olarak, kullanacağımız plane bilgilerini tutan *bitmap' ve *rastport' yapı değişkenleri yaratılıyor. Bu yapı değişkenleri bir *rasinfo' yapı değişkenine bildiriliyor. Bu sayede scroll, rasinfo içerisinden offset değişkenlerle kontrol edilebiliyor. Rasinfo değişkeni, ViewPort yapı değişkeni için görüntü alanını saklama görevi görüyor. Bu sayede MakeVPort0; fonksiyonu ile görüntü yapısal olarak sisteme bildiriliyor. Fakat bu işlem görüntünün gelmesine yetersiz kalıyor. Bu görüntüyü copper listesine eklememiz gerekiyor. Bu işlemi de MrgCop0; fonksiyonu ile gerçekleştiriyor ve Load View(; ile ekrana gelmesini sağlıyoruz. Ekranda yaptığımız her işlemden sonra (mesela çizgi çekmek ya da ekran o! le oynayarak kaydırma işlemini yapmak) aynı şekilde görüntüyü sisteme belirtmek ve tazelemek için MakeVPort(), MrgCop() ve LoadView() fonksiyon üçlüsünü kullanmamız gerekmektedir. Bundan sonrası ise Amiga'ya kalmış. Programımızın yapmış olduğu iş ana hatlarıyla bu kadar. Diğer kısımları anlayabileceğinizi tahmin ederek bu ayki yazımızı burada noktalıyorum. Yazımın başında da belirttiğim gibi bundan sonraki konumuz 'intuition'lar. Gelecek ay buluşmak üzere hepinize mutlu günler dilerim!....