Instruction'ların Alınması
ROM'umuzu emülatör belleğine yüklediğimize göre, artık OPCODE'ları okumaya ve onları çalıştırmaya başlayabiliriz.
CHIP-8 OPCODE'ları 2 byte uzunluğundadır. Belleğimizde her bir alan 1 byte uzunluğunda olduğundan, 2 byte okuyup bunları birleştirmemiz gerekli. Örnek olarak bellek üzerinde şu iki byte düşünüldüğünde:
memory[pc] == 0xA2
memory[pc + 1] == 0xF0
Bu iki byte'ı 16-bit'lik bir sayı yapmak için, öncelikle 0xA2
değeri
16-bitlik bir sayıya çevrilir ve ardından 8-bit sol tarafa kaydırılır (left
shift). Ardından bitwise OR ile bir sonraki byte yeni değere eklenir:
0xA2 10100010 // 8-bitlik değer 16-bit'e çevrilir
0x00A2 0000000010100010 << 8 // Ardından 8-bit sola kaydırılır
0xA200 1010001000000000 | 0x00F0 // Ardından sonraki byte (0xF0) XOR ile eklenir
0xA2F0 1010001011110000
Bu işlemi Rust ile impl Emulator
bloğu içine tanımladığımız metodla
şu şekilde yapabiliriz:
fn instruction_oku(&self) -> Option<Instruction> {
let opcode = (self.memory[self.pc as usize] as u16) << 8
| (self.memory[(self.pc + 1) as usize] as u16);
Instruction::new(opcode)
}
Bu şekilde program counter'da tutulan bellek alanından 2 byte'lık OPCODE okunur
bitwise OR işlemi ile birbirine eklenir ve tanımladığımız Instruction
tipine
dönüştürülür. Daha önce Instruction
'a eklediğimiz From<u16>
özelliği
sayesinde, opcode
değişkenine herhangi bir işlem yapmadan Instruction::new
metodunda kullanabiliriz.