AMIGA ASSEMBLER
Retro bilgisayarMerhaba Assemblercılar... Bu sayıda geçen sayıda verdiğimiz intuition text rutininin açıklamaları ile devam edeceğiz ve bu işlemi iyice öğreneceğiz. Text rutini açıklamaları ardından window'a intuition'ın verdiği özellikleri kazandıracağız.
Geçen sayıdaki programı çalıştırdığınızda, gördüğünüz gibi window'un sol üst köşesinde bir yazı bulunmaktaydı. Şimdi gelelim bu yazının nasıl oluştuğuna. İlk önce size programdan window'un içinde yazı yazımına ait makine kodu rutinini tek başına göstereyim.
1
move.l
INTBASE,a6
2
move.l
WINBASE,a0
3
move.l
50(a0),a0
4
move.l
#TEXT,al
5
move.l
#0,d0
6
move.l
#0,dl
7
jsr
-$d8(a6)
Şimdi, IntuiText rutininin açıklamasına geçelim.
Bu rutinin yaptığı işi gördünüz, Window içerisine yazı yazmaktan ibaret. Rutinin dört parametresi bulunmakta.
İlk parametresi, örneğin 2. satırında gördüğünüz gibi A0 registerine atanan WINDOW RASTPORT adresini içermektedir. Tabii bu rastport'un yazının yazılmasını istediğimiz window rastport'u olduğunu söylemeye gerek yok herhalde. Bu rastport'un nerede olduğuna gelince, o da window structure'ın 50. byte'ından itibaren bir longword değerde saklıdır. Bu uygulamayı 3. satırda görebilirsiniz.
İkinci parametre olarak, Text structure'ınızın adresini A1 registerine bildirmemiz gerekiyor (4. satır).
Üçüncü ve dördüncü parametre ise, yazılacak satırın X ve Y koordinatlarını içermelidir. Sizin isteğinize göre bu değer, window'un boyutlarını geçmemek şartı ile kullanılabilir.
IntuiText rutinin bir parçası olan text structure'ını aşağıda ayrı olarak tek tek açıklayalım.
TEXT: dc.b 3,2
dc.b 1
even
dew 2,10
del
0
del
TEXTST
del
0
dc.b 3,2
ÖMER SİNAN POLAT Bu iki byte değer yazımızın renklerini belirliyor. İlk değer yazının rengi, ikinci değer ise yazının arka plan rengi olmakta.
dc.b 1 Bu byte değer ise, ilk iki değer ile kombine bir halde. Görevi, yazının dört çeşit yazı modundan hangisi olacağına karar vermek. Bu değerler 0, 1, 2, 4 olabilir. 1 değeri, ilk satırda verdiğimiz iki değer aynen kullanılacak anlamına gelir. Burada 0 kullanırsak, sadece yazı rengi dikkate alınıyor ve 4 kullanırsak Text'imiz yazı renginin negatifi olarak beliriyor, even
Bu kullanım, Seka'ya aittir. Görevi, bir üst satırda tek byte kullanıldığından ve Seka'da kodu word değerler üzerinden oluşturduğundan oluşabilecek bir hatayı önlemek.
dc.w 2,10 Bu iki word değer rutindeki gibi yazı satırının X ve Y koordinatlarını belirtirler. Buraya yazdığınız değerler, rutindeki ile toplanıp sonuca göre yer tespiti yapılır. Ben burada 2 ve 10 değerlerini kullandım; nedeni, rutindeki X, Y koordinat değerlerine 0 girilse dahi yazı satırı window'un tam sol üst köşesine eşit gelecektir.
dc.l 0
Bu değer, herhangi bir karakter setinin pointer adresini içermelidir. Tabii bu karakter seti de yazının yazımında kullanılacak karakterleri belirtir. Eğer standart karakter setini kullanıyorsak, buraya 0 değeri girmeliyiz.
dc.l TEXTST İşte burada yazımızın bulunduğu hafıza adresini giriyoruz.
del 0
Bu adres 0 olduğunda, başka yazı çıkışı olmayacağı anlamına gelmektedir.
TEXTST: dc.b "IntuitionText",0
Bu satır, yukarıda da anlattığımız gibi yazılacak karakterleri içeriyor, dc.b formatında girdiğimiz bu kısa yazının son karakteri daima Null yani 0 olmalıdır.
Evet. Artık window içerisine yazı yazımını öğrenmiş bulunuyoruz.
Şimdi yeni bir örnekle yazı dizimize devam ediyoruz.
Bu arada dikkatinizi son iki örneğimizde de aynı olan bir şey çekmiştir. İki programda da programdan çıkmak için mouse'un sağ tuşunu kullandık. Acaba Workbench'teki window'larda olduğu gibi, window'u kapama kutucuğuna basarak bizim window'umuzu da kapatamaz mıyız?
Bunu biz de yapabiliriz. Tabii biraz karmaşık bir yapısı var. Şimdi örneğimizin bu halini görelim.
**** AMIGA DÜNYASI **** AMIGA INTUITION LIBRARY **** WINDOW EXAMPLE **** ASSEMBLER KURSU **** ÖRNEK 14.1
start: move.l
4,a6
lea
INTNAME,al
jsr
-$228(a6)
move.l
d0,INTBASE
beq
EXIT3
move.l
INTBASE,a6
lea
WINDOW,a0
jsr
-$cc(a6)
move.l
dO,WINBASE
beq
EXIT2
LOOP: move.l
WINBASE,a0
move.l
86(a0),a0
move.l
4,a6
jsr
-$174(a6)
move.l
d0.a0
move.l
20(a0),d6
tst.l
d0
beq.s
LOOP
cmp.l #$200,d6
bne.s LOOP
move.l
4,a6
move.l
WINBASE,a0
move.l
86(a0),a0
move.l
d0,al
jsr
-$16e(a6)
EXIT1: move.l,INTBASE,A6
move.l
WINBASE,a0
jsr
-$48(a6)
EXIT2: move.l
4,a6

move.l
INTBASE.al
jsr
-$19e(a6)
EXIT3: rts
*..........................................................
INTNAME:dc.b
"intuition. library",0
WINNAME:dc.b "Benim Window".0
WINDOW: dew 20,20
dew 300.100
dc.b 0.1
dc.l
S80000+S200+$2
dc.l
SI+S2+S4+$8
dc.l
0.0
dc.l
WINNAME
dc.l
0,0
dc.w 200,50
dc.w 400,200
dc.w I
INTBASE: dc.l
0
WINBASE:dc.l
0
Tabii söylememe gerek yok. Hemen oturup Seka'ya yeni örneği yazın. Veya eski source listesini yükleyip, üzerinde değişiklikler yapıp yeni halini oluşturun.
Yazımı bitirip hemen compile işlemini yapın. Eğer herhangi bir yazım veya sistem hatası meydana gelmezse, programı JSTART ile çağırabilirsiniz.
Artık mouse'un sağ tuşuna basmanız gerekmiyor. Window'u Workbench'teki gibi sol üst kısımdaki window kapama kutucuğuna mouse'un sol tuşu ile basarak window kapama ve çıkış işlemini gerçekleştiriyoruz.
Şimdi gelelim bu işin nasıl yapıldığına. Dikkat ederseniz, programımız 10. sayımızdaki örnekten biraz farklı gelişiyor. 10. sayıdaki programın ana parçası yani mouse'un sağ tuşu ile programdan çıkmayı bekleme bölümü yerine, 14 satırlık bir rutin ile değiştirdik.
İşte bu rutin bizim window'umuzun özelliklerini gerçekten kullanmamıza yarayacak.
Amiga'yı dizayn edenler, window'u kapamak, boyutlarını değiştirmek, window'u diğer window'ların arkasına göndermek, seçili window üzerinden bir tuşa basmak, seçili window'a bağlı olarak disk işlemleri gibi olayları sistemde kolayca kontrol etmek için, exec library'de mesaj okuyucu rutinler yazmışlar. Bu rutinler vasıtası ile biz bu olayları çok rahat tespit edip, programımızda herbiri için ayrı yönlendirme yapabiliyoruz.
Bu olayları sistemden okumak için, exec library'deki GetMsg($174) isimli rutini kullanacağız. Bu rutin bizden tek parametre isteyecektir. Bu parametre, Userport diye adlandırılan yine Amiga'yı dizayn edenlerin geliştirdikleri bir parametre olmaktadır.
Userport'u nerede bulacağımıza gelince; her window structure'ındaki 86. byte'dan itibaren bir longword değer olduğunu söyleyebiliriz. Onu okumak için kullandığımız komutlar ise şunlar: move.l WINDBASE,A0 move.l 86(A0),A0 Tabii sizin bu iki komutta anlayamadığınız bir kısım bulunmadığını tahmin ediyorum. Yine de bir hatırlatma gerekirse; Winbase'deki window structure adresinin değerini A0 registerine alıp, bir alt satırdaki komut ile bu değerin 86 byte fazlasındaki değeri tekrar A0'a gönderiyoruz, move.l 4,a6
Son olarak biliyorsunuz: A6 registerinde intuition library değeri vardı, onu exec library'nin tablo adresi olan 4 ile değiştiriyoruz.
jsr -$174(a6) Ve rutini çağırıyoruz. Rutinden çıktıktan sonra, D0 adresinde varsa bir mesaj onun hafızada yerleştiği değer kaydediliyor.
Şimdi buradan itibaren programın söz konusu kısmını yakından inceleyelim.
1
move.l
d0.a0
2
move.l
20(a0).d6
3
tst.I
dO
4
beq.S
LOOP
5
cmp.l
#$200.d6
6
bne.s
LOOP
1. satırda D0'daki message adresini A0'a taşıyoruz. Bu işlemin nedeni, 2. satırdaki komutta gördüğünüz gibi message adresindeki 20. byte'daki longword değeri D6 registerine taşımak içindir.
Daha sonra 3. ve 4. satırlardaki işlem, message'ın gerçekten var olup olmadığıdır. Nasıl mı? Eğer GetMsg library rutininden çıkıldığında, D0 registerindeki message adresi değeri 0 değeri ise, message yok demektir. Eğer 0'dan farklı bir değer ise message var demektir. 4. satırdaki komutun tepkisi, message yok ise, LOOP label'ına atla; var ise, bir alt komut ile devam et olur.
5. ve altıncı satırlar, oldukça anlamlı satırlardır. 2. satırdaki işlemi merak etmişsinizdir. Neden message adresindeki 20. longword'u alıp D6'da sakladık? Açıklayalım.
Bu değer, message ile meydana gelen olayın sistem kodunu teşkil etmektedir. Değerin sistemdeki adı IDCMP'dir. Tabii hemen kavradığınızı tahmin ediyorum; $200 değeri de, window'un kapama kutucuğunu temsil eden IDCMP flag'ıdır. Tablo'da bu flag'lar toplu halde görülmektedir.
Gördüğünüz gibi, istenen olayın kodunu D6'daki değer ile karşılaştırarak o olayın gerçekleşip gerçekleşmediğini anlayabiliriz.
Siz de buradaki değerleri kullanarak, programda istediğiniz kontrolleri koyabilirsiniz.
Son olarak söylenecek bir şey kaldı. Aldığınız her message hafızada bir yer işgal etmektedir. Bu yüzden alınan her message'ı geri bırakmak gereklidir. Bu işi yapmazsak, hafızada devamlı arka arkaya birikeceklerdir. Bu işlem için yine exec'deki Putmsg($16e) rutinini kullanacağız. Bu kısım ise programda şöyle ayrılabilir.
move.l
4,a6
move.l
WINBASE.a0
move.l
86(a0),a0
move.l
d0,al
jsr
-$16e(a6)
Bu rutin iki parametreye ihtiyaç duyar. Birinci olarak window'un userport adresi, ikinci olarak ise message adresi. Ardından rutinin çağrılması yeterlidir.
Daha sonra normal çıkış işlemleri yapılabilir.
Yazı dizimizi burada noktalıyoruz. Gelecek sayıda görüşmek üzere hoşça kalın.
Bit Değer İsmi Anlamı
0 $0000001 SIZEVERIFY 1 $0000002 NEWSIZE WİNDOW BOYUTLARI DEĞİŞMİŞ 2 $0000004 REFRESHWINDOW 3 $0000008 MOUSEBUTTONS MOUSE TUŞLARINA BASILMIŞ 4 $0000010 MOUSEMOVE MOUSE KOORDİNATLARI DEĞİŞMİŞ 5 $0000020 GADGETDOWN 6 $0000040 GADGETUP 7 $0000080 REQSET 8 $0000100 MENUPICK BİR MENÜ SEÇİLMİŞ 9 $0000200 CLOSEWINDOW WİNDOW KAPAMA İKONUNA BASILMIŞ 10 $0000400 RAWKEY BİR TUŞA BASILMIŞ 11 $0000800 REQVERIFY 12 $0001000 REQCLEAR 13 $0002000 MENUVERIFY 14 $0004000 NEWPREFS PREFERENCES DEĞİŞTİRİLMİŞ 15 $0008000 DISKINSERTED SÜRÜCÜYE DİSK SOKULMUŞ 16 $0010000 DISKREMOVED SÜRÜCÜDEN DİSK ÇIKARILMIŞ 17 $0020000 WBENCHMESSAGE 18 $0040000 ACTIVEWINDOW WINDOW ACTIVE HALE GELMİŞ 19 $0080000 INACTIVEWINDOW WINDOW DEACTIVE HALDE 20 $0100000 DELTAMOVE