Emulatör Yapısı

CHIP-8'in tüm sistem özelliklerini biliyoruz. Bunların hepsini emulator.rs içerisinde yeni bir yapı içerisinde tanımlayalım, bu sefer yapımızı tanımlarken içerisinde elemanları olan bir yapı tanımlayacağız:

pub struct Emulator {
    /// Bellek 4KB
    memory: [u8; 4096],

    /// Genel amaçlı registerlar
    v: [u8; 16],

    /// Bellek adresini tutmaya yarayan register
    i: u16,

    /// Program sayacı (program counter)
    pc: u16,

    /// Stack
    stack: [u16; 16],

    /// Stack'ın en üstünü tutan stack pointeri
    sp: u8,

    /// Gecikme zamanlayıcısı
    delay_timer: u8,

    /// Ses zamanlayıcısı
    sound_timer: u8,

    /// Görüntü yapısı
    display: Display,

    /// Klavye yapısı
    keyboard: Keyboard,
}

Rust static ve strong yazılımlı bir dil olduğundan, tüm alanların tipleri de tanımlanmak zorundadır. Diğer dillerin aksine tip tanımlamaları sağ tarafta yer alır.

Yeni Bir Emulator Instance'ı Oluşturulması

Öncelikle Emulator yapımızı, varsayılan değerleriyle bir instance'ını oluşturan yeni bir fonksiyon tanımlayalım.

impl Emulator {
    pub fn new() -> Emulator {
        let mut emulator = Emulator {
            memory: [0; 4096],
            v: [0; 16],
            i: 0x200,
            pc: 0x200,
            stack: [0; 16],
            sp: 0,
            delay_timer: 0,
            sound_timer: 0,
            display: Display::new(),
            keyboard: Keyboard::new(),
        };

        for (i, font) in FONTSET.iter().enumerate() {
            emulator.memory[i] = *font;
        }

        emulator
    }
}

Değişken tanımlamaları let anahtar kelimesi ile yapılır. Rust'ta her değişken varsayılan olarak immutable (içeriği değiştirilemez) haldedir. Biz fonksiyonumuzun devamında, emülatör belleğine font setini yükleyeceğimizden içeriği değiştirilebilir bir değişkene ihtiyacımız var. Bu nedenle let tanımlamamızın ardından mut anahtar kelimesini kullanıyoruz. mut anahtar kelimesi o değişkeni mutable (içeriği değiştirilebilir) duruma getirmektedir. CHIP-8 programları belleğin 0x200 alanından başlayacağından, I ve PC registerları 0x200 yapılır. Onun dışında her alan 0 olacak şekilde bir Emulator instance'ı oluşturulur.

Şu an için Display ve Keyboard yapılarını görmezden gelin. Görüntü ve klavye işlemlerinin yapıldığı bu yapılar ileride anlatılacaktır.

        for (i, font) in FONTSET.iter().enumerate() {
            emulator.memory[i] = *font;
        }

CHIP-8: 0 dan F'e olmak üzere 5 byte uzunluğunda sprite gösterme özelliğine sahiptir (16*5=80). Bu font bilgisi daha önce tanımlanmış bir değişken üzerinden emülatör belleğine yüklenir. FONTSET array'ının içeriğini kaynak kodlarında görebilirsiniz. Rust'ta arraylar Iterator özelliğine sahip olduğundan iter() metodu yardımıyla kolayca iterator'e dönüştürülebilir. enumerate metodu ise aynı Python'da olduğu gibi item ile birlikte iterasyon sayacını döner. Bu metod sayaç ve item değerlerini dönen bir tuple olduğundan, for döngüsü tuple değişken tanımlamalarıyla kullanılır.

Son olarak fonksiyonumuz içerisinde yer alan emulator satırı, fonksiyonumuzdan emulator değişkenimizin dönmesine yarar.