“SPRITE”LAR
SPRITE NEDİR?
SPRITE ekrandaki yazılardan, şekillerden bağımsız donanım kaynaklı programlanabilir grafiklerdir. Kullanımı tamamen kullanıcıya kalmıştır. Yani ekranın istediğiniz yerinde gösterebilir, renklerini değiştirebilir, X ve Y eksenlerinde genişletebilir, istediğiniz şekle sokabilir, karakterlerin arkasında veya önünde gösterebilir ve animasyon yapabilirsiniz. Bütün bunları yapabilmeniz için ise bir sürü POKE komutuna ihtiyacınız olacaktır. Eğer BASIC kullanıyorsanız işiniz biraz kolay sayılır. Gerektiğinde içinde sprite komutları bulunan “basic extension” –mesela HADES BASIC– programlarını kullanabilirsiniz. Ama böyle bir programınız yoksa veya BASIC yerine assembler kullanıyorsanız bütün adresleri ezbere bilmeniz gerekecektir. C64’te fabrika çıkışı olarak 8 tane sprite olsa bile bazı demolarda onlarca hatta yüzlerce sprite’ı görebilirsiniz. Şu an için ekranda gösterilen en son sprite sayısı kaç bilmiyorum. Öylesine yazdığım bir code ile 96 tane sprite gösterdiğimi hatırlıyorum.
Bu arada not düşelim. Ekranda 8’den fazla sprite gösterme tekniğine MULTIPLEX denmektedir ve zamanı gelince “intro teknikleri” bölümünde açıklayacağım. Ayrıca sprite’ların “renkli raster şeritleri” efektiyle arası pek iyi değildir. Daha doğrusu ekranda raster şeritleri varken, şeritlerin üzerinde bir sprite göstermek isterseniz bütün zamanlamalarınız altüst olur. Bu kısa bilgilerden sonra devam edelim.
SPRITE DATALARI NEREDE BULUNUR?
Sprite’ların programlanabilir grafikler olduğunu biliyoruz. Dolayısıyla bu grafiklerin hafızada bir yerlerde bulunması gerekmektedir. Derginin 4. sayısında hatırlarsanız programlama bölümünde karakter setini anlatırken “BANK”lardan bahsetmiştik. Normalde C64 açıldığında $0000-$3FFF adresleri arasında bulunan BANK 0’ı kullanır. Bu nedenle sprite’ların grafikleri de bu adresler arasında bulunması gerekir. Sprite’lar 24 pixel genişliğinde ve 21 pixel yüksekliğindedir. Yatay eksende 8 pixel hafızada 1 byte’a karşılık gelmektedir. Dolayısıyla 24 pixel=3 byte olmaktadır. Bir sprite hafızada 21 satır*3 byte yani 63 byte’lık bir bölge kullanmaktadır. Hesaplama yaparken 64 byte olarak alınır. Fakat siz bu 64 byte’lık bölgeleri kafanıza göre belirleyemezsiniz. Bu bölgeler belli adreslerden başlamaktadır.
Bir BANK 16384 byte’tan oluşmaktadır ve bir bank içinde en fazla 16384/64=256 adet sprite bulunabilir. Bu duruma göre siz sprite’larınızın datalarını 64’ün katları şeklinde olan adreslerde tutmanız gerekecektir. Her ne kadar durum böyle olsa da BANK 0’da kullanamayacağınız adresler vardır ($0000-$03FF arası). Buralarda işletim sistemi tarafından kullanılan adresler, vektörler, yığın ve ekran belleği bulunmaktadır. Eğer çok fazla sprite kullanmayacaksanız veya sprite datalarınızın biraz dağınık olması önemli değilse bahsettiğimiz bölgelerde bazı boşluklar vardır ve buralara 4 adet sprite’a ait dataları yerleştirebilirsiniz.
Aslında $0000-$03FF arasını dilediğiniz gibi kullanabilirsiniz. $0000-$03FF arasındaki bölge 16 sprite’lık bir yer demektir (1024/64=16) ve biz bunun 13 sprite’lık bölümünü rahatça kullanabiliriz. Şimdi bu iş nasıl olacak açıklayalım. Demo veya intro yapacağımız için dolayısıyla assembler –ve interrupt– kullanacağımız için sistem değişkenlerinin çoğu işimize yaramayacaktır. Ama siz yine de bu adresleri kullanmamaya özen gösterin.
$0000-$003F : Kullanmayın, çünkü 1 numaralı adres hafızayı düzenlemek için kullanılıyor. Fakat 2 ve daha sonraki adresleri başka işlemler için rahatça kullanabilirsiniz.
$0040-$00FF : Kasete/diskete erişim yapmayacaksanız veya kursör kullanan işlemler yapmayacaksanız buraları sizindir. Üç sprite için kullanılabilir ama tavsiye etmem.
$0100-$01BF : Burası yığına ait olduğu için kullanılamaz gibi gözükse bile üç sprite için kullanabilirsiniz. Eğer programınızda arka arkaya çok fazla JSR –20 kadar– veya PHA –60 kadar– komutları kullanırsanız bu bölgeye girmeye başlarsınız. Fakat arka arkaya JSR komutu kullanmak programın anlaşılmasını zorlaştırır. Gerekirse kullanabilirsiniz.
$01C0-$01FF : Kesinlikle kullanmayın. Aksi takdirde C64’ünüz kilitlenebilir. $0200-$02BF : Kullanabilirsiniz. Üç sprite için kullanabilirsiniz. $02C0-$0300 : Burası her zaman boştur. Güle güle kullanın. Bir sprite içindir.
$0300-$033F : Kullanmayın. Çünkü burada işletim sistemi tarafından kullanılan vektörler vardır. Eğer kullanırsanız istenmeyen sonuçlar çıkacaktır.
$0340-$03FF : Kullanabilirsiniz. Üç sprite için yeterlidir. $0400-$07FF : Ekran belleği ve sprite göstergeçleri vardır. Kullanamazsınız. $0800-$3FFF : İstediğiniz gibi kullanın. Kod, müzik, grafik, text, sprite data vs..
Yukarıdaki adreslerden $02C0-$0300 ve $0340-$03FF aralarını her zaman kullanabilirsiniz.
SPRITE OLUŞTURMA
Bir sprite için 63 byte gerekli demiştik. Bir byte 8 bitten oluştuğu için 63*8=504 tane bitten hangilerinin açık hangilerinin kapalı olacağını belirleyerek sprite’ımıza istediğimiz şekli verebiliriz. Daha sonra bu bitlerin durumuna göre her byte’ın değerini hafızadaki ilgili adreslere yazdığımızda sprite’ımız kullanılabilir hale gelmiş olacaktır.
Çizdiğiniz sprite’ın datalarını hesaplamak için işaretlediğiniz noktalar için “1”, işaretlemedikleriniz için ise “0” değerini, tablodaki “değer” satırındaki değerlerle çarpmanız ve sonuçları toplamanız gerekmektedir. Yani bir byte’ın değerini bulmak için (bit numarası * değer) çarpımlarını toplayacaksınız. Aslında yaptığınız işlem ikiliden onlu sayıya çevirme işlemidir. Bu çevirme işlemi derginin 1. sayısında anlatılmıştır. Bir sprite için 63 adet sayı elde etmeniz lazımdır.
Bitler
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Değer 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1 128 64 32 16 8 4 2 1
Satır
0. Satır
1. Satır
2. Satır
3. Satır
4. Satır
5. Satır
6. Satır
7. Satır
8. Satır
9. Satır
10. Satır
11. Satır
12. Satır
13. Satır
14. Satır
15. Satır
16. Satır
17. Satır
18 Satır
19 Satır
20
Sprite tasarlama tablosu. Fotokopi çektirin ve kullanmaya başlayın.
SPRITE GÖSTERGEÇLERİ
Sprite’larımızın hafızada hazır olduğunu varsayıyoruz. Bir sprite’ı ekranda göstermeden önce VIC’e sprite’ın hafızada bulunduğu yeri bildirmemiz gerekiyor. Bunun için ekran belleğinin ($0400-$07FF) son sekiz adresini ($07F8-$07FF) kullanacağız. Her sprite için bir adres ayrılmıştır. 8 tane sprite’ımız var ve bunları 0, 1, 2, 3, 4, 5, 6, 7 olarak numaralandıracağız. Bu durumda 0. sprite için $07F8, 1. sprite için $07F9 ..... 7. sprite için $07FF adresini kullanacağız. Eğer VIC bank’ını ve/veya ekran belleğinin yerini değiştirirseniz bu pointer adresleri de değişecektir.
Daha önce sprite datalarının hafızada 64’ün katları şeklinde olan adreslerde bulunması gerektiğini yazmıştık. Bir sprite datasının bulunduğu adresi 64’e bölüp sonucu o sprite’a ait pointer adresine yazarsak datayı VIC’e göstermiş oluruz.
SPRITE’LARI GÖRÜNTÜLEMEK
VIC’in $D015 (53269) numaralı registeri sprite’ların ekranda görünmesini veya kaybolmasını sağlar. Registerin her biti bir sprite için kullanılır. Bir sprite’a ait bit “1” yapılırsa ve koordinat değerleri görülebilen ekran sınırları içindeyse sprite ekranda gözükecektir. Eğer ilgili biti “0” yaparsanız sprite görünmez hale gelecektir. Hangi sprite’ı göstermek istiyorsanız o sprite’a ait bitin değerini $D015’e yerleştirilmelidir.
Bit 7 6 5 4 3 2 1 0 Değer 128 64 32 16 8 4 2 1
Diğer sprite’lara zarar vermeden istenilen bir sprite’ı göstermek için, göstermek istediğiniz sprite’ın bit değerini EOR komutu ile kullanın ve $D015 adresine yazın.
lda
$d015
eor
#$değer
sta
$d015
“EOR #$DEĞER” komutu bir tür anahtar gibi çalışır. Sprite açıksa kapatır, kapalı ise açar. Bu yöntem açma için “ORA” kapatma için “AND” komutu kullanmaktan çok daha iyidir, çünkü “ORA” ve “AND” komutları için kullanılan parametreler birbirinden farklıdır. Mesela 5. sprite’ı açmak için ORA #$20, kapatmak için “AND #$DF” komutunu kullanmanız gerekir.
Kontrol etmek istediğiniz sprite birden fazlaysa, bit değerlerinin toplamını EOR komutu için kullanırsınız.
SPRITE RENKLERİ
Her sprite için bir renk registeri ayrılmıştır ve bu adresler $D027-$D02E (dahil) (53287-53294) arasındadır. Sprite’ı tasarlarken işaretlenen bitler sprite renginde, işaretlenmeyen bitler ise saydam olup arkasında ne varsa o görüntülenecektir.
ÇOK RENKLİ SPRITE’LAR
Çok renkli modunda bir sprite kullanmak istiyorsanız $D01C (53276) adresini kullanabilirsiniz. Kullanılışı aynı $D015 adresi gibidir. Her sprite için bir bit ayrılmıştır. Çok renkli modda bir sprite göstermek istiyorsanız ilgili biti “1” yapmalısınız.
lda
$d01c
eor
#$değer
sta
$d01c
ÇOK RENKLİ MOD
Çok renkli modda bir sprite için 4 renk kullanma imkanı vardır. Fakat çok renkli moda geçtiğinizde yatay çözünürlük yarıya düşer. Artık yatayda 24 bit değil 12 bit çifti kullanabilirsiniz. Sprite’ı renklendirirken bu bit çiftlerinin durumuna göre renkler belirlenir.
BİT ÇİFTİ AÇIKLAMA 0 0 Saydam, ekran rengi 0 1 0 numaralı çok renkli mod sprite registeri ($D025-53285) 1 0 Sprite renk registeri 1 1 1 numaralı çok renkli mod sprite registeri ($D026-53286)
SPRİTE’LARIN GENİŞLEMESİ
Sprite’ların X ve Y eksenlerinde 2 kat büyüme özelliği vardır. Bir sprite’ı X ekseninde 2 kat büyütmek için $D01D (53277), Y ekseninde 2 kat büyütmek için ise $D017 (53271) adresleri kullanılır. Her sprite için bir bit ayrılmıştır. Eğer bit “1” ise o sprite geniş olarak görüntülenir.
lda
$d01d
eor
#$değer
sta
$d01d
lda
$d017
eor
#$değer
sta
$d017
SPRITE KOORDİNATLARI
Sprite’ları ekranda göstermek için iki koordinata ihtiyacımız vardır: X ve Y koordinatları. VIC’in ilk 16 registeri X, Y sırasında olmak üzere 8 sprite’ın X ve Y koordinat değerlerini tutar. X koordinatlarıyla ilgili olarak bir registerimiz daha vardır. Bu registerin her biti bir sprite için ayrılmıştır ve “EXB” (Extra X Bit) olarak bilinir.
C64’ün ekran çözünürlüğü 320x200 olup, bir sprite’ın X koordinat değeri 255’ten büyük olabilir. Oysa X ve Y koordinatlarını tutan registerler en fazla 255 olabilir. 255’ten büyük X koordinat değerleri için $D010 adresinde her sprite için bir bit ayrılmıştır. Böylece X koordinat değeri 0-511 arasında olabilir. Y koordinat değeri ise 0-255 arasında olabilir. Aslında genişletilmemiş sprite’lar için ekranda tam olarak görüntülenebildiği koordinatlar minimum X,Y ($18-24, $32-50), maksimum X,Y ($140-320, $E5-229)’dur. Genişletilmiş sprite’lar için minimum X,Y ($18, $32) maksimum X,Y ($128-296, $D0-208)’dir.
$D000 – 0. Sprite için X koordinatı $D001 – 0. Sprite için Y koordinatı $D002 – 1. Sprite için X koordinatı $D003 – 1. Sprite için Y koordinatı $D004 – 2. Sprite için X koordinatı $D005 – 2. Sprite için Y koordinatı $D006 – 3. Sprite için X koordinatı $D007 – 3. Sprite için Y koordinatı $D008 – 4. Sprite için X koordinatı $D009 – 4. Sprite için Y koordinatı $D00A – 5. Sprite için X koordinatı $D00B – 5. Sprite için Y koordinatı $D00C – 6. Sprite için X koordinatı $D00D – 6. Sprite için Y koordinatı $D00E – 7. Sprite için X koordinatı $D00F – 7. Sprite için Y koordinatı
$D010 – Sprite’lar için EXB adresi
SPRITE ÖNCELİKLERİ
Sprite’ların birbirlerine göre öncelikleri vardır. Aynı koordinatlarda bulunan iki sprite’dan numarası küçük olan önde gözükecektir. Yani mesela 0 ve 4 numaralı sprite’lar aynı koordinatlarda bulunuyorsa 0 numaralı sprite önde gözükecektir.
Aynı şekilde sprite’ların arka plandaki karakterlerle, grafiklerle olan önceliği $D01B adresindeki sprite-background öncelik registeri tarafından belirlenir. Adresin her biti bir sprite için ayrılmıştır. Eğer bir bitin değeri “0” ise sprite arka plandaki karakterlerin, grafiklerin önünde gözükecektir. Eğer “1” ise sprite karakterlerin, grafiklerin arkasında gözükecektir.
SPRITE’LARIN ÇARPIŞMASI
VIC’in en ilginç özelliklerinden birisi de sprite-sprite ve sprite-background çarpışmalarını kontrol edebilmesidir. Bir çarpışmanın olabilmesi için bir sprite’ın “1” olan kısmı ile başka bir sprite’ın veya karakterin “1” olan kısmının çakışması gerekir.
VIC’in $D01E adresi sprite-sprite çarpışmasını, $D01F adresi sprite-background çarpışmasını kontrol eder. Eğer bir bit “1” ise çarpışma olmuş demektir.
SPRITE DEMO PROGRAM
Buraya kadar teorik olarak sprite’lar hakkında bilgi sahibi olduk. Şimdi bir program ile bu öğrendiklerimizi pratik olarak gerçekleştireceğiz. Fakat bu programda çarpışma kontrolünü ve çok renkli sprite’lar için renk değiştirme işlemlerini yapmayacağız. Sprite’larımız içi kapalı kare şeklinde olacaktır. Ekrandaki sprite’lar 1’den 8’e kadar numaralandırılmıştır. Önce seçmek istediğiniz sprite’ın numarasına basın. Sonra sprite özelliklerini değiştirin. Sprite background önceliğini sprite’ı hareket ettirmeden değiştirin. “D” tuşu ile sprite eski yerine yerleştirilir. Özellikler eski değerlerine gelir.
TUŞ ÖZELLİK
X X yönünde genişletir/normale döndürür. Y Y yönünde genişletir/normale döndürür. C Sprite rengini değiştirir. P Sprite-background önceliğini belirler. D Default değerleri geri yükler. O Sprite on/off kontrolü. E EXB’yi açar/kapatır. CURSOR SAĞ X ekseninde koordinat değerini 1 arttırır. Sprite sağa hareket eder. CURSOR SOL X ekseninde koordinat değerini 1 azaltır. Sprite sola hareket eder. CURSOR AŞAĞI Y ekseninde koordinat değerini 1 arttırır. Sprite aşağı hareket eder. CURSOR YUKARI Y ekseninde koordinat değerini 1 azaltır. Sprite yukarı hareket eder.
*=$0801
.word nextline
.word 2004
; 2004
.byte $9e
; SYS
.text "2061"
; 2061
.byte 0
; komutu
nextline
.word 0
lda
#$0c
jsr
$e536
ldx
#$00
stx
$d020
stx
$d021
lda
#$ff
ldata
sta
sdata,x
inx
cpx
#$3f
bne
ldata
ldx
#$00
lkoor
lda
koor,x
sta
$d000,x
inx
cpx
#$10
bne
lkoor
ldx
#$00
ldy
#$01
lcolor
lda
select,x
sta
$d027,x
sta
$0400,y
sta
$0450,y
lda
#(sdata/$40)
sta
$07f8,x
iny
iny
iny
inx
cpx
#$08
bne
lcolor
lda
#$ff
sta
$d015
key
jsr
$ffe4
ldx
#$00
compare
cmp
select,x
beq
change
inx
cpx
#$08
bne
compare
jmp
key
change
stx
sprnum
sta
$d020
set
jsr
$ffe4
on_off
ldx
sprnum
cmp
#$4f
;"O" tuşu
bne
colch
lda
$d015
eor
eorcode,x
sta
$d015
jmp
set
colch
cmp
#$43
;"C" tuşu
bne
x_pand
inc
$d027,x
jmp
set
x_pand
cmp
#$58
;"X" tuşu
bne
y_pand
lda
$d01d
eor
eorcode,x
sta
$d01d
jmp
set
y_pand
cmp
#$59
;"Y" tuşu
bne
prior
lda
$d017
eor
eorcode,x
sta
$d017
jmp
set
prior
cmp
#$50
;"P" tuşu
bne
default
lda
$d01b
eor
eorcode,x
sta
$d01b
jmp
set
default
cmp
#$44
;"D" tuşu
bne
inc_x
lda
select,x
sta
$d027,x
lda
$d015
ora
eorcode,x
sta
$d015
lda
$d01d
and
off,x
sta
$d01d
sta
$d017
sta
$d010
sta
$d01b
lda
#$00
sta
$d020
txa
asl
tax
lda
koor,x
sta
$d000,x
lda
koor+1,x
sta
$d000+1,x
jmp
key
inc_x
cmp
#$1d
;"RIGHT" tuşu
bne
dec_x
txa
asl
tax
inc
$d000,x
bne
noexb
setx
ldx
sprnum
lda
$d010
eor
eorcode,x
sta
$d010
noexb
jmp
set
dec_x
cmp
#$9d
;"LEFT" tuşu
bne
inc_y
txa
asl
tax
dec
$d000,x
bne
noexb
jmp
setx
inc_y
cmp
#$11
;"DOWN" tuşu
bne
dec_y
txa
asl
tax
inc
$d001,x
jmp
set
dec_y
cmp
#$91
;"UP" tuşu
bne
exb
txa
asl
tax
dec
$d001,x
jmp
set
exb
cmp
#$45
;"E" tuşu
bne
tekrar
lda
$d010
eor
eorcode,x
sta
$d010
tekrar
jmp
set
rts
koor
.byte $18,$3a,$30,$3a,$48,$3a,$60,$3a
.byte $78,$3a,$90,$3a,$a8,$3a,$c0,$3a
select
.byte $31,$32,$33,$34,$35,$36,$37,$38
sprnum
.byte 0
eorcode
.byte 1,2,4,8,16,32,64,128
off
.byte 254,253,251,247,239,223,191,127
sdata
=$02c0
.end