Geçen bölümde karakter setlerini değiştirmekten ve kayan yazılardan bahsetmiştik. Fakat kayan yazı örneğimiz bir cümlenin sağa sola kayması şeklinde idi. Bu bölümde klasik anlamda uzun bir mesaj içeren ve ekrana sağdan girip sürekli sola devam eden kayan yazı örneği ile başlayacağız.
Aslında bu örnek birazdan göreceğiniz gibi kayan_yazı2 örneğinden daha basit. Geçen bölümün sonunda bu işi nasıl yapacağımızdan biraz bahsetmiştik. Hatırlarsanız, ana algoritmamız şöyleydi:
d016 değerini bir azaltarak bir piksellik kayma yap
eğer d016 0 olmuş ise karakter slotlarında kayma yap
Aslında bu algoritmayı biraz detaylandırmamız gerekiyor. Düşünürseniz d016'ya 0 değerini yazmamızdan hemen sonra eğer karakter slotlarında kaydırma yaparsak bir problemimiz var. Problemi anlamak için şu senaryoyu düşünelim.
Diyelim ki kayan satır en üst satır (yani $0400 - $0408). Diyelim ki yazı kaymış kaymış ve yazımızın ilk harfi tam 0401 adresindeki karakter slotuna gelmiş. Şimdi tam 0401 adresinde olan karakteri düşünün. Yani soldan 2. karakter. Ve diyelim ki d016'ya geçen sayfada 1 yazılmıştı. IRQ'muzun olacağı raster satırını ilk karakter satırının başına yakın ve ondan önceki bir raster satırına ayarlayacağız. Böylece d016'ya yapacağımız bir yazma işlemi kayan satırın çizilmesini etkileyecek.
Şimdi IRQ rutinine girdik. IRQ'ya girer girmez piksel kayması yapmak üzere d016'ya 0 yazdık. Normalde istediğimiz şey bu sayfa çizilirken 0401'deki karakterin (yani mesajımızın ilk harfinin) yine 0401'de kalması ve bu satırın d016'da 0 değeri ile çizilmesi. Geçen sefer 1 ile çizilip bu sefer 0 ile çizilmesi halinde geçen sayfadan bir piksel sola kaymış olacak yani ve zaten istediğimiz de bu.
Fakat biz IRQ rutininde d016'ya 0 yazdıktan hemen sonra d016'ya yazdığımız değerin 0 olduğunu görüp karakter slotlarını kaydırmaya başlarsak problemimiz var. Çünkü düşünürseniz henüz raster, satırımızın başında veya belki de öncesinde. Daha IRQ rutinine yeni girdik ve fazla bir zaman harcamadık (sadece d016'daki değeri manipule ettik). Dolayısıyla, eğer şu anda karakterleri slotların içinde kaydırırsak, ekranın bu çiziminde $0401'deki mesajımızın ilk harfini $0400'a kaydırmış olacağız. Yani bu ekranda $0401 de görünmesi gereken harf olması gerekenden 8 piksel solda görünecek. Bir sonraki ekranda d016'ya yeniden 7 yazdığımızda da 7 piksel sağa kayacak. yani bü ilk harfin çerçeveden piksel olarak uzaklığını düşünürsek ekranın 3 çiziminde olması gereken ve olan durumlar şöyle olacak:
olması gereken sıra: 9, 8, 7
olan sıra: 9, 0, 7
Bunun olmaması için basit bir önlem almamız gerekiyor. Karakter slotlarındaki kaydırmayı yapmak için ekranın kayan bölümünün raster satırlarının geçmesini beklemek. Yani algoritmamızı şöyle değiştiriyoruz:
d016 değerini bir azaltarak bir piksellik kayma yap
ekranda kayan bölümün sonuna gelmeyi bekle
eğer d016 0 olmuş ise karakter slotlarında kayma yap
Şimdi son adımı biraz daha detaylı düşünelim. Yapmamız gereken işlem kayan satırdaki bütün karakterleri bir slot yana kaydırmak. Bu işlem hakkında düşünürken, satırın ilk ve son karakter slotlarında ne işlemler yapılması gerektiğine dikkat edelim. En soldaki slota (yani 0. slota) bir sağındaki slottaki (yani 1. slottaki) karakter kopyalanacak. Çünkü bütün karakterler bir slot sola kayıyor. Peki en sağdaki slot? Bu slottaki (yani 39.slottaki) karakter bir soldaki slota (yani 38. slota) kopyalanacak. Peki 39. slota sonra ne yapmalıyız. Düşünürseniz kayan mesajımızdaki bir sonraki harfi (yani ekrana sağdan yeni giren harfi) 39.slota koymamız gerekiyor. Böylece ekrandaki bütün harfler bir slot sola kaydırılıp, sıradaki harf için en sağdaki slotta yer açılıyor.
Bunun dışında 1'den 39'a kadarki 39 slottaki karakterin 0'dan 38'e kadarki slotlara kopyalanması işlemini nasıl yapmalıyız? Elbette bir döngüyle yapacağız. Fakat döngümüz harfleri hangi sırayla kopyalayacak?
İlk aklınıza gelen cevap once en sağdan yani 39. slottan başlayarak her slottaki harfi bir sola kaydırmak olabilir. Fakat biraz dikkatli düşünürseniz bu yaklaşımda problem olduğunu görürsünüz. Eğer döngümüzde;
39'dan 38'e kopyala
38'den 37'ye kopyala
37'den 36'ya kopyala
...
diye ilerlersek aslında yaptığımız şey 39. slottaki karakter neyse bütün satırı o karakter ile doldurmak olacaktır. Çünkü birinci adımdan sonra 39 ve 38'de aynı karakter olacak. İkinci adımdan sonra 39 ve 38'de olan aynı değeri 37'ye kopyalamış olacağız. Üçüncü adımda 39, 38, ve 37'deki değeri 36'ya kopyalayacağız. Problemi görüyorsunuz.
Bunun yerine yapmamız gereken şey kopyalamaya diğer uçtan başlamak. Yani önce 1. slottan 0. slota, ardından 2. slottan 1. slota, ardından 3. slottan 2. slota şeklinde ilerlemeliyiz. Bu şekilde tam istediğimiz şeyi yapmış olacağız.
Şimdi bu noktaların ışığında algoritmamıza biraz daha detay ekleyelim:
d016 değerini bir azaltarak bir piksellik kayma yap
ekranda kayan bölümün sonuna gelmeyi bekle
eğer d016 0 olmuş ise karakter slotlarında kayma yap
1'den 39'a kadarki toplam 39 slottaki karakterleri 0'dan 38'e kadarki slotlara kopyala
39. slota kayan mesajın bir sonraki karakterini yerleştir.
Artık kodu incelemeye hazırız. kayan_yazı2 örneğini IRQRutini bölümünden itibaren değiştiriyoruz. Tam kaynak kodu kayan_yazı3.a64 dosyasında bulacaksınız.
IRQRutini:
inc $d019
jsr bir_pixel_kayma
KayanBolgeninSonunuBekle:
lda $d012
cmp #$3c
bmi KayanBolgeninSonunuBekle
lda #$0
sta $d016
jsr karakter_slotlarinda_kayma
jmp $ea8
Burada algoritmanın ana iskeletini IRQ rutinine yerleştirilmiş halde görüyorsunuz. Ayrıca algoritmada belirtmediğimiz bir detay olan kayan bölgenin dışında $d016'nın 0 değerine sabitlenmesini de burada görüyorsunuz.
;; ------------------------------------------------
kayan_satir = $0400 + (0 * 40)
bir_pixel_kayma:
lda bizim_d016
sec
sbc #$01
and #$07 ; %00000111
sta bizim_d016
sta $d016
rts
İşte burada bir piksellik kaymaları yapan kodumuzu görüyorsunuz. Buradaki bizim_d016 adresini (veya değişkenini de diyebiliriz) niçin kullandığımızı açıklayalım. Burada d016'daki değeri her defasında 0 ile 7 değerleri arasında bir azaltmak istiyoruz. Ve daha sonra 0 olduğu zaman ileriki bölümlerde slot kaydırmasını yapmamız gerekecek. Bu durumda ilk aklınıza gelen çözüm şöyle olabilir.
lda $d016
sec
sbc #$01
and #$07
sta $d016
rts
Fakat IRQ rutininin iskeletine bakarsanız, orada tam karakter slotlarında kayma zamanı gelmiş mi diye kontrol etmeden önce $d016'yı sıfırlıyoruz (ekranın geri kalanı kaymasın diye). Bu yüzden o rutinde d016 0 olmuş mu diye bakarsak her zaman 0 göreceğiz. Bu problemi aşmak için şöyle bir yol takip ediyoruz. d016 registerindeki değeri kontrol için kullanmak yerine kayan bölgede d016'ya yazdığımız değerin bir kopyasını da bizim_d016'ya yazıyoruz. Bir nevi d016'nın bir kopyasını tutuyoruz elimizde (sadece kayan bölgede geçerli olan değeri). Bu sayede ekranın başka bölümlerinde registere başka değerler yazsak bile kayan yazı rutini kendi en son yazdığı değeri hatırlıyor ve kendi sırası geldiğinde o değeri kullanarak işlemlerine devam edebiliyor.
karakter_slotlarinda_kayma:
lda bizim_d016
beq slotlari_kaydirma_vakti
rts
Demin açıkladığımız gibi bu bölüm bizim_d016'daki değerin sıfır olup olmadığını kontrol ederek slotları kaydırma zamanı gelip gelmediğine karar veriyor. Hatırlarsanız bu kaydırma sadece 8 ekranda bir oluyor. Yani d016 7'den 1'e kadar değerleri alırken bu işlem yapılmayıp sadece 0 değerini aldıktan sonra yapılıyor.
slotlari_kaydirma_vakti:
ldx #0
skv_dongu:
lda kayan_satir+1,x
sta kayan_satir,x
inx
cpx #39
bne skv_dongu
Ve burada da 39 karakteri bir sol slota kaydıran döngüyü görüyorsunuz. Bu döngüyü algoritma esnasında detaylı şekilde açıkladık.
ldx sonraki_karakter
lda yazi,x
sta kayan_satir+39
inx
stx sonraki_karakter
rts
Burada da son olarak satırın en sağındaki slota sıradaki karakterin konuşunu görüyorsunuz. Mesajın hangi karakterini koymamız gerektiğini takip etmek için sonraki karakter diye bir indeks değeri tutuyoruz. Bu değer bir bayt olduğu için 0 ile 255 arası değerler alabilir. Dolayısıyla bu rutinde kullandığımız mesaj en fazla 256 karakter olabilir.
Bu konuyu kapatmadan önce bir konuya daha değineceğiz. d016 registerinin kayma konusundan sorumlu bölümünün ilk 3 biti (0, 1, ve 2 nolu bitler) olduğunu söylemiştik. Bu konuyla alakalı bir bit daha var. 3 nolu bit. Bu bit ekranın görünen bölgesindeki genişliğini kontrol eder. Normalde bitin değeri birdir. Böyleyken ekran 40 karakter genişliğindedir. Eğer bu biti 0 yaparsanız, ekranın etrafındaki çerçeve biraz büyür. En soldaki karakter slotu çerçevenin arkasında kalır ve ekran 39 kararkter slotu genişliğinde görülür. Bizim örneğimizde de d016'ya hep 0 - 7 arası değerler yazdığımıza göre dikkat ederseniz bu biti 0 yaparak ekran kalınlığını 39 karaktere daraltıyoruz.
Peki bunu neden yapıyoruz. Bu sayede ekran sola kayarken en soldaki kararkter yok olmadan önce ekrandan çıkıyor. Yani örneğimizde, 0400 slotuna gelen bir karakteri d016'da 7 değeri varken düşünün. Bu karakterin 8x8 pikselinden en sol sütunu çerçeve arkasına giriyor. ardından birer piksellil kaymalarla d016 en son 0 değerini aldığında 0400'daki kararkterimiz tamamen çerçevanin arkasında kalmış oluyor. Biz de tam bu esnada 0401deki kararkteri onun üzerine kopyalıyoruz ve ertesi ekran çiziminde d016'yı tekrar 7 yapıyoruz. Bu sayede harfler yumuşak bir şekilde ekranın solundan dışarı çıkıyor. Bunu yapmasak ne olacağını görmek için bir piksel kayma rutinini şöyle değiştirin
bir_pixel_kayma:
lda bizim_d016
sec
sbc #$01
and #$07 ; %00000111
sta bizim_d016
ora #$08 ; 3 nolu biti 1 yap
sta $d016
rts