plazma - amatör bilgisayar kültürü

Amiga Assembly Kursu 3

Şemseddin 'Endo' Moldibi

Amiga Assembly kursumuzun 3. bölümünde artık yavaş yavaş görsel sonuçları olan konulara gireceğiz. Geçen sayımızda dallanma komutları ve donanım yazmaçlarını (hardware registerları) görmüştük. Amiga’nın görüntü ile ilgili konularına girmeden önce öğrenmemiz gereken son bir konu daha var:

1. Adresleme Modları

Önceki sayılarımızda 68000 komutları hakkında bilgi edinmiştik, bu komutların çoğu için 12 farklı adresleme modu vardır, 68020 ve üst modellerinde 6 mod daha vardır. 68000’de kod yazmanın kolaylığı bu adresleme modlarının çokluğundan gelir.

1.1. 68000 Adresleme Modları (Addressing Modes)

  1. Data Register Direct, Dn

  2. Address Register Direct, An

  3. Address Register Indirect, (An)

  4. Address Register Indirect with Post-Increment, (An)+

  5. Address Register Indirect with Pre-Decrement, -(An)

  6. Address Register Indirect with Displacement, w(An)

  7. Address Register Indirect with Index, b(An,Rx)

  8. Absolute Short, w

  9. Absolute Long, l

  10. Program Counter with Displacement, w(PC)

  11. Program Counter with Index, b(PC,Rx)

  12. Immediate, #x

Burada kullanılan sembollerin anlamları aşağıdaki gibidir:

  1. Dn Data Register (n = 0 - 7)

  2. An Address Register (n = 0 - 7)

  3. b 08-bit sabit

  4. w 16-bit sabit

  5. l 32-bit sabit

  6. x 8-, 16-, 32-bit sabit

  7. Rx Index Register (Dn veya An)

Şimdi bu adresleme modlarının her birini örneklerle inceleyelim:

Data Register Direct:

CLR.W    D3
MOVE.B   D0,D1
SUB.L    D2,D1

Address Register Direct:

Bu mod Data Register Direct ile aynı yazım şekline sahiptir, ancak adres yazmacı kullanıldığında .B (byte) eki kullanılamaz.

MOVE.L   A0,D0
CLR.W    A5

Address Register Indirect:

Bu mod ile bir adres yazmacının gösterdiği (point ettiği) adresteki değeri okunur.

MOVE.L   (A0),D0

Burada dikkat edilmesi gereken en önemli nokta, .L veya .W ile yalnızca bir çift adresten okuma yapabilirsiniz. Örneğin aşağıdaki kodu çalıştırdığınızda, eğer <label> bir çift adres değilse bilgisayarınız kilitlenecektir.

LEA      LABEL,A0
MOVE.B   (A0),D0
RTS

LABEL:
         DC.B $01,$02,$03

Bu durumu önlemek için EVEN veya ALIGN assembler direktiflerini kullanmak gerekir.

LEA      LABEL,A0
MOVE.B   (A0),D0
RTS

EVEN     ;Gerekirse 1 byte atlayarak
         ;sonraki adresi cift yapar
LABEL:
         DC.B $01,$02,$03

Address Register Indirect with Post-Increment/Pre-Decrement:

Bu mod bir önceki ile aynıdır, ancak adresi okuma işlemini yaptıktan sonra kullanılan adres yazmacının değerini işlem boyutu kadar (.B, .W, .L için sırasıyla 1, 2, 4) arttırır/azaltır.

;A0daki degeri oku ve A0i 4 arttır
MOVE.L   (A0)+,D0
;A1daki degeri oku ve A1i 2 azalt
MOVE.W   -(A1),D0

Address Register Indirect with Displacement:

Verilen adres yazmacına istenen değer eklenir ve yeni adresteki değer okunur. Yeni adres compile-time’da hesaplanır, yani adres yazmacının değeri değişmez.

;A1in degerine 4 ekle
;adresteki degeri D0a al
MOVE.L   4(A1),D0

Burada eklenen değer 16 bit işaretli bir sayıdır, yani $7FFF’den büyük olması durumunda çıkarma işlemi yapılacaktır. MOVE.W -30(A5),D0 şeklinde de kullanabilirsiniz.

Address Register Indirect with Index:

Yukarıdaki mod ile aynıdır, ancak okunacak adresi hesaplarken baksa bir adres yazmacının değeri de eklenir.

MOVE.L   4(A0,A1.L),D0

D0’ın değer A1+A2+4 adresinden okunan longword değer olacaktır.

Burada ilk verilen değer 8 bitlik işaretli bir sayıdır, sondaki yazmaç ise (data veya adres yazmacı olabilir) 16 veya 32 bitliktir. Aşağıdaki örnekleri inceleyin.

MOVE.L   4(A0,D1.W),D0
MOVE.L   20(A0,D2.L),D7
MOVE.W   4(A0,A1.W),A0
MOVE.B   -50(A0,A2.L),D0
CLR.L    8(A3,D4.L)

Absolute Short / Long:

Mutlak adres modunda verilen adresteki değer okunur. Absolute Short’ta verilen adres 16 bitlik (işaretli/signed) bir adrestir. Normalde 68000’de adresler için 32 bit kullanırız, örneğin $00752000 gibi. Ancak eğer kullanacağımız adres 16 bit ile ifade edilebiliyorsa biraz yer biraz da hız sağlamak amacıyla $00004560 yerine $4560.W kullanabiliriz.

;Short mod (hepsi aynidir)
MOVE.L   4.W,A6
MOVE.L   $4.W,A6
MOVE.L   $0004.W,A6
MOVE.L   $00000004.W,A6
;Long mod (hepsi aynidir)
MOVE.L   $4.L,A6
MOVE.L   $00000004.L,A6
MOVE.L   $4,A6

Short modda kullanılan değerler signed olduklarından hafızanın ilk 32KB’lık bölümünü adreslemek için kullanılabilirler ($7FFF’e kadar), bu nedenle bu modu pek fazla kullanmayız.

Program Counter with Displacement:

Bu modda o an bulunulan adrese bir değer (16 bit signed) eklenerek elde edilen adresteki değer okunur.

MOVE.L   8(PC), D0

Aşağıdaki örnekte ilk satır <label> adresindeki değeri D0’a yükler, derlendiğinde komut 2 byte, adres 4 byte yer kaplar. Ancak ikinci satırda MOVE komutu kendi bulunduğu yerden relatif olarak label kadar ilerideki adresin değerini okur. Derlendiğinde MOVE komutu yine 2 byte ancak komut parametresi bu defa 4 yerine 2 byte olur.

MOVE.L   label,D0
MOVE.L   label(PC),D0
RTS

label
         DC.W $AA55,$7788

Bu mod yine biraz hız ve yer sağladığı gibi aslında daha önemli bir kullanım amacı vardır. Bu mod sayesinde Relocatable kod yazabilirsiniz. Yani hafızanın neresine konursa konsun aynı şekilde çalışabilecek, yüklendikten sonra da yeri değiştirilebilecek kodlar. Normalde AmigaDOS programlarınızı yüklerken zaten bir relocate işlemi yapar ve programınız hafızanın boş herhangi bir yerine yüklenir. Ancak yüklendikten sonra yerini değiştiremezsiniz. Eğer tüm lokal label işlemlerinizde PC relatif mod kullandıysanız programınızın yerini yüklendikten sonra da değiştirebilirsiniz. (Örneğin bir virüs yazıyorsanız bu çok kullanışlı bir özelliktir.)

NOT: Bu mod read-only’dir, yani PC relatif bir yazma işlemi yapamazsınız. Örneğin MOVE.L #0,4(PC) veya CLR.W 8(PC) gibi bir komutu derleyemezsiniz.

Program Counter with Index:

Bu mod da öncekinin aynısıdır, ek olarak bir register’ın değeri de (.W veya .L olarak) işleme katılır. Ayrıca burada verilen pozisyon öncekinden farklı olarak 16 bit değil 8 bittir.

;D0a PC+A1+$10 adresindeki
MOVE.L   $10(PC,A1.L),D0

Her ne kadar tavsiye etmesem de buradaki pozisyon değerini kod içinden değiştirerek (self-modifying) bir tablo üzerinde okuma gibi işlemleri de yapabilirsiniz.

Immediate:

MOVE.L   #556,D0
SUB.W    #2,A0

Böylece adresleme modlarının sonuna gelmiş olduk. Bu modların isimleri ezbere bilmenize tabii ki gerek yok, sadece aklınızda bulunsunlar, gerektiğinde elinizdeki araçları ve nasıl kullanıldıklarını bilin yeterli. Burada verdiğim örneklerin çoğunda MOVE komutunu kullandım ancak bu modlar neredeyse tüm komutlar için geçerlidir (ADD, SUB, BTST, NOT, EOR vb.)

Şimdi sırada Amiga’nın belki de en can alıcı konularından biri olan Copper var.

2. Copper

Copper, Amiga’nın Custom chip’lerinden biridir, çoğunlukla grafik işlemleriyle ilgili kullanılmasına karşın genel amaçlı olarak da kullanılabilir; ses, blitter ve sprite’ları kontrol edebilir; blitter aracılığıyla hafızada blok kopyalama işlemi yapabilir. Amiga’nın multitasking yapısında çok önemli bir yeri vardır, çünkü copper 68000’den bağımsız çalışır, kendi komutlarını işlerken CPU’ya yük olmaz. Bu sayıda copper komutlarını, bir copper listesini nasıl aktif edebileceğimizi, copper ile ilgili adresleri ve son olarak da bazı örnek copper uygulamalarını göreceğiz.

2.1. Copper Komutları

Copper bu kadar çok işi sadece 3 komut ile gerçekleştirir. Bu komutlar WAIT, MOVE ve SKIP’tir. Copper komutları program içinde bir liste halinde verilir. Pek çok Amiga programında uzun listeler halinde bu komutları görebilirsiniz. Bu listeler aslında copper’ın belirli raster satırlarını bekleyip belirli adreslere istenen değerleri yazmasını sağlayan komut listeleridir. Bu listelere “Copper List” denir.

Bir copper komutu 2 word’den oluşur. Basit bir copper listesi aşağıdaki gibi görünür:

DC.W $A001,$FF00
DC.W $0180,$0BBB
DC.W $A101,$FF00
DC.W $0180,$0CCC
DC.W $A201,$FF00
DC.W $0180,$0AAA
DC.W $FFFF,$FFFE

Bu listeyi şöyle özetleyebiliriz, $A0’ncı raster pozisyonunu bekle, arkaplan rengini gri $0BBB) yap, $A1’i bekle, rengi $0CCC yap, $A2’yi bekle, rengi $0AAA yap, listeyi bitir.

Şimdi sırasıyla copper komutlarını inceleyelim.

2.1.1. WAIT

Bu komut istenen x,y raster pozisyonunun beklenmesini sağlar. Evet, copper dikey tarama pozisyonu (vertical blanking) bekleyebildiği gibi yatay tarama pozisyonunu da (horizontal beam position) bekleyebilir. WAIT komutu aşağıdaki gibidir:

DC.W $YYXX,$AABB

Burada YY beklenecek dikey raster pozisyonu, XX yatayda beklenecek raster pozisyonudur. AA ve BB ise dikey ve yatay karşılaştırma bitleridir. XX ve YY’nin sadece istenen bitleri raster pozisyonu ile karşılaştırılır. Şimdilik bu aklınızı çok karıştırmasın. AA olarak $FF verdiğinizde tam olarak belirttiğiniz raster satırı beklenir. Benzer şekilde BB olarak $FE verdiğinizde de belirttiğiniz yatay pozisyon beklenir.

Burada ayrıca ilk word’ün ilk biti 1, ikinci word’ün ilk biti 0 olmalıdır. Bu, komutun WAIT olduğunu belirler.

;50.raster satirini bekle
;X pozisyonunu dikkate alma
DC.W $5001,$FF00
;255.raster satirini bekle
;X pozisyonunu dikkate alma
DC.W $FF01,$FF00
;160.Y pozisyonu ve
;129.X pozisyonunu bekle
DC.W $A081,$FFFE

Burada masking bitlerini interrupt ile birlikte kullanarak, örneğin her 16 satırda bir işlem yapılmasını sağlayabiliriz. Bu konuyu daha ileride göreceğiz.

Aklınıza aşağıdaki copper listesinin çalışmayacağını düşünebilirsiniz:

DC.W $A001,$FF00
DC.W $9001,$FF00

Burada önce $A0 daha sonra ise $90. raster pozisyonunu beklemeye çalışıyoruz. $A0’dan sonra $90’ı beklemek (zaten geçmiş olan bir pozisyonu beklemek) tüm tarama zamanını alacaktır. Ancak WAIT komutunun çalışma şekline baktığımızda durum düşündüğümüz gibi değildir. WAIT komutu raster pozisyonu (raster beam position) verilen pozisyondan büyük veya ona eşit olduğunda devam eder. Yani yukarıdaki iki satırın ilki çalıştıktan sonra ikinci satır hemen geçilecektir. ($90. satır zaten geçilmiş olduğundan dolayı.)

Amiga’da PAL ekran için raster pozisyonu (0,0)’dan (312,226), yani toplam 312 dikey raster satırı ve 226 yatay pozisyon vardır. Bu nedenle copper yatayda 226’dan ($E2) sonrasını bekleyemez. Ayrıca WAIT komutunun yatay/dikey pozisyon parametreleri 8 bit olduğunda 255. raster pozisyonuna kadar bekleyebilir. 255’ten sonraki raster satırlarını nasıl bekleyeceğimiz daha ileride göreceğiz.

WAIT komutunun bitleri aşağıdaki gibidir:

İlk word

Açıklama

Bit 0

Daima 1

Bit 15 – 8

Dikey pozisyon, Vertical beam position (VP)

Bit 7 – 1

Yatay pozisyon, Horizontal beam position (HP)

İkinci word

Açıklama

Bit 0

Daima 0

Bit 15

Bu bit 1 olduğunda WAIT komutu pozisyon ile birlikte aynı zamanda blitter’ın işini bitirmesini de bekler. (Blitter-finished-disable bit)

Bit 14 - 8

Dikey karşılaştırma bitleri, Vertical position compare enable bits (VE)

Bit 7 - 1

Yatay karşılaştırma bitleri, Horizontal position compare enable bits (called HE).

Burada dikkat ettiyseniz ilk word’ün ilk biti 1, ikinci word’ün ilk biti ise 0. Bu, komutun WAIT komutu olduğu anlamına gelir. İlk word’ün 0’ncı biti 0 olduğunda ise komut MOVE komutu olarak yorumlanır.

2.1.2. MOVE

MOVE komutu bir hardware register’ına yazma işlemi yapabilmemizi sağlar. Bu sayede sistemin birçok bileşenini kontrol edebiliriz. Hardware register’larının $DFF000-$DFF1FE arasında olduğunu biliyoruz. Ancak MOVE komutunun bazı kısıtlamaları vardır:

  1. MOVE komutu $000-$010 arasındaki register’lara ($DFF000-$DFF010) yazma işlemi yapamaz!

  2. $010 ile $020 arasında registerlara yazma yapabilmesi ancak COPCON (Copper Control, $02E) register’ının Copper Danger bitinin (0’ncı bit) 1 olmasıyla mümkündür.

  3. $020’den büyük tüm registerlara yazma işlemi yapabilir.

MOVE komutunun bitleri aşağıdaki gibidir:

İlk word

Açıklama

Bit 0

Daima 0

Bit 8 – 1

Hardware register adresi

Bit 15 – 9

Kullanılmıyor, 0 yapın

İkinci word

Açıklama

Bit 0-15

Yazılacak değer

Aşağıdaki örnek copper listesi BPLCON0 ($0100) adresine $1200 değerini yazar, bu, tek bitplane’lik (2 renkli) bir ekran açılmasını sağlar. 2 ve 3. satırlarda BPL1PTH ($0E0) ve BPL1PTL ($0E2) adreslerine $0002 ve $0000 değerleri yazılır. Bu register’lar bitplane’in hafıza adreslerini tutar. Örnekte bu adres $00020000 olarak verilmiştir. Hemen ardından COLOR00 ($0180) adresine $0222 (koyu gri renk) değeri yazılır, COLOR01 ($0182) renk register’ına $0FFF değeri (beyaz) yazılır ve liste sona erdirilir.

DC.W $0100,$1200
DC.W $00E0,$0002
DC.W $00E2,$0000
DC.W $0180,$0222
DC.W $0182,$0FFF
DC.W $FFFF,$FFFE

2.1.3. SKIP

SKIP komutunun bitleri WAIT komutu ile aynıdır, tek fark her iki 0’ncı bitin de 1 olmasıdır:

İlk word

Açıklama

Bit 0

Daima 1

Bit 15 – 8

Dikey pozisyon, Vertical beam position (VP)

Bit 7 – 1

Yatay pozisyon, Horizontal beam position (HP)

İkinci word

Açıklama

Bit 0

Daima 1

Bit 15

Bu bit 1 olduğunda verilen pozisyon ile birlikte aynı zamanda blitter’ın işini bitirmesi de beklenir. (Blitter-finished-disable bit)

Bit 14 - 8

Dikey karşılaştırma bitleri, Vertical position compare enable bits (VE)

Bit 7 - 1

Yatay karşılaştırma bitleri, Horizontal position compare enable bits (HE).

SKIP komutu raster pozisyonu, verilen değere eşit veya büyük olduğunda bir sonraki komutun işlenmeden geçilmesini sağlar. Normalde bu komuta çok fazla ihtiyaç duymayız. Aşağıdaki örnek satır, dikey raster pozisyonu 100’ü ($64) geçtiyse bir sonra gelen komutun atlanmasını sağlar.

DC.W   $6401,$FF01

2.2. Copper Listesini Durdurmak

Bir copper listesini nasıl hazırlayacağımızı, istediğimiz pozisyonu nasıl bekleyeceğimizi biliyoruz. Peki bir copper listesini nasıl durduracağız. Aslında gayet basit; copper listesi asla ulaşamayacağı bir pozisyonu bekletildiğinde sona erer ve bir sonraki taramada başa döner. Aslında copper listesi her tarama da baştan yüklenir, yani oluşturduğunuz liste bir taramayı aşıyorsa eğer yarım kalacak ve yeni taramada liste başa alınacaktır. Aşağıdaki WAIT komutu copper listesini sona erdirir.

DC.W $FFFF,$FFFE

Burada X ve Y pozisyonu olarak $FF ve $FF’i bekletiyoruz, ancak biliyoruz ki yatayda copper en fazla $E2’ye kadar bekleyebilir. Bu şekilde sistem copper listesinin sona geldiğini anlar ve sonraki tarama başlangıcında listeyi baştan başlatır.

2.3. Copper Listesini Çalıştırmak

Bir copper listesini oluşturduktan sonra çalışmasını sağlamak için aşağıdaki 2 yöntemden birini kullanmalıyız.

Doğrudan hardware yazmaçlarına copper listesinin adresini yazmak ve copper’ı tetiklemek veya graphics.library aracılığıyla copper’ı aktive etmek.

Bir copper listesi oluşturduktan sonra aşağıdaki şekilde aktif hale getirebiliriz:

LEA      $DFF000,A0
LEA      MYCOPPERLIST,A1
MOVE.L   A1,$80(A0)
MOVE.W   #0,$88(A0)

Burada ilk olarak $DFF000 (custom chip base address) A0 register’ına alınıyor. İkinci satırda MYCOPPERLIST isimli label adresi (bizim oluşturduğumuz copper listesi) A1’e alınıyor. A1’deki değer (copper listemizin adresi) A0’daki adresin $80 ilerisine, $DFF080 (COP1LC) adresine yazılıyor. Son olarak $DFF088 (COPJMP1) adresine herhangi bir değer yazılarak copper listesinin tetiklenmesi sağlanıyor. (Bu adres bir strobe adrestir, yani herhangi bir yazma işlemi yapıldığında bir işlemi tetikler)

COP1LC ve COPJMP1 adresleri istediğimiz zaman yazabilir ve copper’ın farklı bir listeyi göstermesini sağlayabiliriz, hatta bu adreslere copper kendisi de yazma işlemi yapabilir, bu şekilde copper’ı kendi içinde bir döngüye sokabiliriz.

İkinci yöntem ise graphics.library’yi kullanmaktır.

;Grafik kutuphanesini ac
MOVE.L   $4,A6
MOVE.L   #GFXNAME,A0
JSR      OpenLibrary(A6)
;Hata varsa D0=0 olur
TST.L    D0
BEQ      ERROR
;Gfx librarynin ofset
;adresini A6ya al
MOVE.L   D0,A6
;Copper listesini calistir
LEA      MYCOPPERLIST,A0
MOVE.L   A0,$32(A6)

Burada “OpenLibrary” ifadesini kullanabilmek için elbette kodun başında graphics.i’yi include etmek gerekir. Veya “JSR OpenLibrary(A6)” yerine “JSR -408(A6)” da yazabilirsiniz.

Bir demo, intro veya oyun yazdığımız zaman açtığımız tüm kütüphaneleri kodun sonunda kapamalı ve eski copper adresini geri yazmalıyız. Bu, temiz bir çıkış için gereklidir. Örneklerde bunun nasıl yapıldığını görebilirsiniz.

2.4. Copper ile neler yapılabilir

Bir copper listesi ile aslında makinenin neredeyse tüm kaynaklarına ulaşabilirsiniz. Tüm hardware register’larına yazabilir, blitter ile veri transferi yapabilir, ses veya spritelari kullanabilirsiniz.

Ancak en yaygın kullanım şekilleri şunlardır: ekranda çeşitli renk efektleri oluşturmak (raster barlar ya da Amiga’da daha yaygın söylenişiyle copper bar), sprite multiplexer (aynı numaralı spriteların belirli bir raster pozisyonundan sonra tekrar kullanılması), ekran/bitmap/sprite renklerinin veya data göstergeçlerinin istenen rasterlarda değiştirilmesi (2 renkli bir ekran açıp yüzlerce renk kullanabilirsiniz), hatta ekranın üst yarısı 320x256 çözünürlükte iken alt yarısını 640x256 yapabilirsiniz veya bitmap pointer’larını her satırda değiştirerek bir resmi ters gösterebilir, daraltıp uzatabilir, flood efekti yapabilirsiniz.

3. Örnekler

3.1. Sıralama (Sorting)

Aşağıdaki kod parçası <table>’da verilen tablodaki değerleri büyükten küçüğe doğru sıralamaktadır.

D0’da sıralanacak sayıların adedinden geriye doğru sayan değer, A0’da tablo adresi bulunmaktadır. D7 geçici (temporary) olarak kullanılmış, D6’da ise sıralama işlemini gerekiyorsa tekrarlamak için bir flag tutulmaktadır. Kodu derleyip çalıştırdıktan sonra Asmpro’da “H table” yazarak tablonun son halini görebilirsiniz.

sort:
   lea      table(pc),a0
   moveq    #8-2,d0
   moveq    #0,d6
loop:
;A0daki deger ile
;A0+2deki degeri
;karsilastir
   move.w   (a0),d1
   cmp.w    2(a0),d1
   bgt.s    pass
swap:
;A0 ile A0+2nin
;degerlerini degistir
   move.w   (a0),d7
   move.w   2(a0),(a0)
   move.w   d7,2(a0)
   moveq    #1,d6
pass:
;tabloda ilerle
;tablodaki degerler word
;oldugundan 2 arttiriyoruz
   addq.l   #2,a0
   dbf      d0,loop
;herhangi bir degisiklik
;olduysa sort islemini
;tekrarla
   tst      d6
   bne.s    sort
   rts

table:
   dc.w  $0056,$0134,$0012,$0072
   dc.w  $0145,$0001,$000C,$0025

3.2. Copper #1

Aşağıdaki örnek 320x256 tek bitplane (2 renkli) bir ekran açar. COLOR00 ($0180) renk register’ının değerini 225 raster satırı boyunca her satırda değiştirerek güzel bir copper bar oluşturuyor.

size    =   320*256/8
bars    =   225*2

start
;ekran adresini copper
;listesine yaz
    move.l  #myscreen,d0
    move.w  d0,sl
    swap    d0
    move.w  d0,sh

;ekranin tamamini temizle
    lea     myscreen,a0
    move.l  #size-1,d0
loop
    move.b  #$00,(a0)+
    dbf     d0,loop

;copper listesinin icine
;sirasiyla wait ve move komutlarini
;yaz, toplam 225 adet move
    lea     cp,a0
    move.l  #bars/2-1,d0
    move.l  #$0001ff00,d1
    move.l  #$01800000,d2
loop2
    move.l  d1,(a0)+
    move.l  d2,(a0)+
;wait komutundaki raster
;pozisyonunu 1 artir
    add.l   #$01000000,d1
;move komutundaki renk degerini
;bir artir
    add.w   #$00000001,d2
    dbf     d0,loop2

;custom chip base adresini al
;ve duzgun bir bitmap ekran
;acmak icin gerekli degerleri
;yaz, 1 bitplane lo-res
    lea     $dff000,a0
    move.w  #$0000,$102(a0)
    move.w  #$0000,$108(a0)
    move.w  #$0038,$092(a0)
    move.w  #$00d0,$094(a0)
    move.w  #$2c81,$08e(a0)
    move.w  #$2cc1,$090(a0)
;copper list adresini $080e yaz
;copperi tetikle ($088e yaz)
;copper dmasini ac
    lea     mylist,a1
    move.l  a1,$80(a0)
    move.w  #0,$88(a0)
    move.w  #$8380,$96(a0)
mouse
    btst    #6,$bfe001
    bne.s   mouse
out rts

;copper listesi ve bitmap ekran
;verilerini daima chip rame koy
    section data,data_c

mylist
;1 bitplane lo-res ekran ac
;bu degerin her taramada set 
;edilmesi gerekir, aksi halde
;bos veya bozuk bir ekran
;gorursunuz
    dc.w    $0100,$1200
;bitmap pointlerlari
;$0e0 ve $0e2 adreslerinde
;hiword, loword olarak durur
    dc.w    $00e0
sh  dc.w    $0000
    dc.w    $00e2
sl  dc.w    $0000
;wait ve move komutlari icin
;yer ayir (450 long word) 
cp  ds.l    bars
    dc.w    $ffff,$fffe

;ekran icin yer ayir
myscreen
    dcb.b   size,$00

Evet işte basit bir copper örneği. Bu örnekte geçen bitmap ekran açma, ekran pointer’larını set etme gibi işlemleri önümüzdeki sayıda detaylıca göreceğiz. Şimdilik copper listesinin dinamik olarak nasıl oluşturulduğu ve nasıl aktif hale getirildiğini inceleyiniz.

Örnek kodlar hakkında anlayamadıklarınızı mail ile sorabilirsiniz. Son olarak copper’ı aktif hale getirmek için bahsettiğimiz ikinci yöntemi görelim. Yukarıdaki kodda

    lea     mylist,a1
    move.l  a1,$80(a0)
    move.w  #0,$88(a0)
    move.w  #$8380,$96(a0)

ifadeleri yerine aşağıdakileri yazarak da copper listemizi aktive edebiliriz:

   move.l   $4,a6
   lea      gfxname,a1
   moveq    #0,d0
   jsr      -408(a6)
   tst.l    d0
   beq.s    out
   move.l   d0,a1
   move.l   #mylist,$32(a1)
;kodun sonuna
gfxname
   dc.b     'graphics.library',0

Burada grafik kütüphanesi açılıyor ve kütüphanenin base adresinin $32 ilerisine copper listemizin başlangıç adresi yazılıyor. Bu işlem listemizi aktif hale getirecektir. Elbette açtığımız bir library’yi programın sonunda kapatmamız gerekir:

   move.l   $4,a6
   ;A1de graphics librarynin
   ;base adresi olmali
   jsr      -414(a6)

Library’lerle ilgili daha detaylı bilgili ileriki sayılarda göreceğiz. Ayrıca -408, -414 gibi ofset değerlerini ezberlemek yerine include dosyaları ile çalışarak OpenLibrary, CloseLibrary şeklinde nasıl kullanacağımızı göreceğiz.

Bu sayıdaki yazımızın sonuna geldik, ekte “sources” klasörünün içinde örneklerin kaynak kodlarını bulabilirsiniz. Ayrıca iki tane daha copper örneğini incelemeniz için koydum. Eğer kaynak kodları Windows üzerinde editlemek isterseniz satır sonu formatını unix olarak kaydetmeyi unutmayın. Aksi halde AsmPro’dan yüklerken problem yaşayabilirsiniz.

Sonraki sayıda yine copper kadar can alıcı olan “Görüntü Alanları (Display Fields)” konusuna bakacağız. Sorularınızı ve isteklerinizi bana iletebilirsiniz. Görüşmek üzere.

Kaynaklar:

  1. HowToCode (Amiga Demo Coders Reference Manual)

  2. Amiga Hardware Guide

  3. Amiga Machine Language (Abacus Books)

  4. Programmer’s Reference Manual (Motorola)

plazma - (2006 - 2011)