NightNetwork - yazılım, yazın, verim vs.

12.3. Karakterleri Kaydırmak

Bellekteki bir texti kayarak VM içinden geçirmek şimdiye kadar uğraştığımız problemlerden oldukça farklı. Çözümün çok zor olmadığını göreceksiniz. Ve bu çözümü gördükten sonra, mevcut bilgilerinizle pekçok şey yapabileceğinizi göreceksiniz. Zaten bu bölümden sonra oldukça güzel bir intro yapacağız. Ama önce scroll konusunu masaya yatırıyoruz.

      !to "out.prg"
      * = $c000

      VM_SATIR_0 = $0400 + (0 * 40)

      lda #0
      sta $d020
      sta $d021

      loop1: 

      ldx #0
      loop2: 
      lda VM_SATIR_0+1,x
      sta VM_SATIR_0,x
      inx
      cpx #39
      bne loop2


      read: 
      lda text_source
      sta VM_SATIR_0+39
      inc read+1

      ldy #$40
      ldx #0
      delay: 
      dex
      bne delay
      dey
      bne delay

      end: jmp loop1

      !align 255,0
      text_source:
      !scr "merhaba dunya... iste karsinizda yazdigim "
      !scr "ilk scroll rutini... henuz smooth degil ama "
      !scr "onemli degil. onu da bi kac gune kadar yapmis "
      !scr "olacagim zaten. greetings to ali, veli, 49, 50..."
      !scr "the new codemaster signs off..."
      !fill $2c,$20
    

Programımız yine ilk önce ekranı ve çerçeveyi siyah yapıyor. Daha sonra programın asıl döngüsüne giriyoruz. Döngü içinde programın yaptığı üç temel iş var:

  • Yazının kayacağı satırdaki adresleri 0'dan 39'a numaralandırdığımızı düşünelim. Programın yaptığı ilk iş, 1 ila 39 nolu adreslerdeki toplam 39 karakteri, 0 ila 38 nolu adreslere kopyalamak. Yani satırdaki bütün harfleri bir pozisyon sola kaydırmak. Bunun sonucu olarak en soldaki 0 nolu adresteki karakter siliniyor. Çünkü 1 nolu adresteki karakter onun üzerine yazılmış oluyor. Aynı zamanda 38 ve 39 nolu adreslerdeki karakterler birbirinin aynı oluyor. Çünkü 39 nolu adresteki karakter 38 adresine kopyalandı. Şimdi 39 nolu adrese kayan yazının yeni harfinin girmesi gerekli

  • Bu 39 karakterlik kaydırmadan sonra read etiketli kodla kayacak olan mesajın yenı harfi okunuyor ve ekranda 39 nolu adrese basılıyor. Kod donup tekrar buraya geldiğinde lda ile yazının bir sonraki harfinin okunması gerekli. Bu yüzden inc read+1 ile lda komutunun argumanı olan mutlak adresin küçük baytı bir artırılıyor. Yani program kendini değiştiriyor.

  • Bütün bunlar çok hızlı olduğu için yazının kaymasının okunabilecek bir hıza indirilmesi gerekiyor bunu da döngünün sonunda basit bir delay ile hallediyoruz. Delayin ardından jump komutu ile sonsuz döngünün başına atlyoruz.

Kayacak yazıyı belleğe text_source etiketiyle yerleştirmeden önce bir yeni acme komutu ile daha tanışıyosunuz. !align komutu kendisinden sonra gelen baytların bellekte "istediğimiz gibi" bir adresten başlamasını sağlıyor. Bunun anlamı şu: Bu programda biz, text_source'un tam bir "page" başından başlamasını istiyoruz. Peki page nedir?

C64'ün 64K'lık belleğini 256 baytlık bloklara bölerseniz 256 tane blok elde edersiniz. Bu blokların herbirinin adresi 256'nın katları olur. Bu blokların her birine page (sayfa) adı verilir. Bu pagelerin ilki $0000 - $00ff arasındaki baytları kapsar. Bi sonraki page $0100 - $01ff arasındaki baytları kapsar.

Biz kaymasını istediğimiz yazıların page başından başlamasını istiyoruz. Bunu sağlamak için !align 255,0 komutu kullanılıyor. 255 ve 0'ın ne demek olduğuna şu an takılmayın. Bilmeniz gereken tek şey kodun içinde !align gördüğünüz anda bir sonraki parcanın gerekirse arada boşluk bırakılıp en yakın page başından başlayacağı. Bu programda align satırı olmasa text_source etiketi $c02b'ye eşitlenecek ve text mesajını oluşturan karakter kodları o adresten itibaren yer alacaktı. Ama o satır sayesinde bir sonraki en yakın page başı olan $c100 adresine yerleştirildiler.

Peki biz text_source'u page başına koymak için niye uğraşıyoruz? Bunun cevabı read etiketindeki lda satırında. Bu satırdaki adres değerinin küçük baytını sürekli artırdığımızı hatırlıyorsunuz. Bu demektir ki bu bayt 255'e kadar artacak ve ardından 0'a dönüp yeniden artmaya devam edecek. Biz eğer text_source'un $c02b olmasına izin verseydik, o zaman en son c0ff deki harfi okuduktan sonra adresin küçük baytı artıtıldığında 0 olacaktı. Dolayısyla bir sonraki read işlemi lda $c000 şeklinde gerçekleşecekti. Orada ise code var mesaj yok. Biz c100 a yerleştirmekle yazının sağlıklı bir biçimde başa dönmesini sağlamış olduk. Programın şu halinde lda satırı c100 ile c1ff arasını okuyup tekrar c100'a donerek çalışıyor.

Son olarak bir acme komutu ile daha tanışıyorsunuz: !fill. Bu komut adından da tahmin edebileceğiniz gibi programınızın kapladığı bellekteki bir bölgeyi bir değerle doldurmaya yarıyor. Burada c100'dan başlayan mesaj textinin sonundan page sonuna (c1ff) kadar boşluk karakteri ile doldurmak için kullanıyoruz. !fill iki argüman alıyor. İlk argüman kaç baytlık bölgeyi dolduracağını ikinci argüman da ne ile dolduracağını belirtiyor.

NightNetwork - 2009