rgy 0.1.0

No-std Rust GameBoy emulator library
Documentation
use crate::{
    device::IoHandler,
    mmu::{MemRead, MemWrite, Mmu},
};
use alloc::{vec, vec::Vec};
use log::*;

pub struct Cgb {
    double_speed: bool,
    speed_switch: bool,
    wram_select: usize,
    wram_bank: Vec<Vec<u8>>,
}

#[allow(unused)]
impl Cgb {
    pub fn new() -> Self {
        Self {
            double_speed: false,
            speed_switch: false,
            wram_select: 1,
            wram_bank: (0..8).map(|_| vec![0; 0x1000]).collect(),
        }
    }

    pub fn try_switch_speed(&mut self) {
        if self.speed_switch {
            self.double_speed = !self.double_speed;
            self.speed_switch = false;
        }
    }

    pub fn double_speed(&self) -> bool {
        self.double_speed
    }
}

impl IoHandler for Cgb {
    fn on_read(&mut self, _mmu: &Mmu, addr: u16) -> MemRead {
        if addr >= 0xc000 && addr <= 0xcfff {
            let off = addr as usize - 0xc000;
            MemRead::Replace(self.wram_bank[0][off])
        } else if addr >= 0xd000 && addr <= 0xdfff {
            let off = addr as usize - 0xd000;
            MemRead::Replace(self.wram_bank[self.wram_select][off])
        } else if addr == 0xff4d {
            let mut v = 0;
            v |= if self.double_speed { 0x80 } else { 0x00 };
            v |= if self.speed_switch { 0x01 } else { 0x00 };
            MemRead::Replace(v)
        } else if addr == 0xff56 {
            warn!("Infrared read");
            MemRead::PassThrough
        } else if addr == 0xff70 {
            MemRead::Replace(self.wram_select as u8)
        } else {
            MemRead::PassThrough
        }
    }

    fn on_write(&mut self, _mmu: &Mmu, addr: u16, value: u8) -> MemWrite {
        if addr >= 0xc000 && addr <= 0xcfff {
            let off = addr as usize - 0xc000;
            self.wram_bank[0][off] = value;
        } else if addr >= 0xd000 && addr <= 0xdfff {
            let off = addr as usize - 0xd000;
            self.wram_bank[self.wram_select][off] = value;
        } else if addr == 0xff4d {
            self.speed_switch = value & 0x01 != 0;
        } else if addr == 0xff56 {
            warn!("Infrared read");
        } else if addr == 0xff70 {
            self.wram_select = (value as usize & 0xf).max(1);
        }

        MemWrite::PassThrough
    }
}