<commit_before>mod gamepak;
pub mod io;
mod sram;

use arm::{AccessType, Memory, Waitstates};
use byteorder::{ByteOrder as _, LittleEndian as LE};
use log::debug;
use util::array;

use self::io::IoRegisters;

pub const REGION_BIOS: u32 = 0x0;
pub const REGION_UNUSED_1: u32 = 0x1;
pub const REGION_EWRAM: u32 = 0x2;
pub const REGION_IWRAM: u32 = 0x3;
pub const REGION_IOREGS: u32 = 0x4;
pub const REGION_PAL: u32 = 0x5;
pub const REGION_VRAM: u32 = 0x6;
pub const REGION_OAM: u32 = 0x7;
pub const REGION_GAMEPAK0_LO: u32 = 0x8;
pub const REGION_GAMEPAK0_HI: u32 = 0x9;
pub const REGION_GAMEPAK1_LO: u32 = 0xA;
pub const REGION_GAMEPAK1_HI: u32 = 0xB;
pub const REGION_GAMEPAK2_LO: u32 = 0xC;
pub const REGION_GAMEPAK2_HI: u32 = 0xD;
pub const REGION_SRAM: u32 = 0xE;

pub const BIOS_SIZE: u32 = 0x4000;
pub const EWRAM_SIZE: u32 = 0x40000;
pub const IWRAM_SIZE: u32 = 0x8000;
pub const PAL_SIZE: u32 = 0x400;
pub const VRAM_SIZE: u32 = 0x18000;
pub const OAM_SIZE: u32 = 0x400;
pub const IOREGS_SIZE: u32 = 0x20A;

pub const EWRAM_MASK: u32 = 0x3FFFF;
pub const IWRAM_MASK: u32 = 0x7FFF;
pub const PAL_MASK: u32 = 0x3FF;
pub const OAM_MASK: u32 = 0x3FF;
pub const ROM_MAX_MASK: u32 = 0xFFFFFF;

pub struct GbaMemory {
    pub(crate) bios: Box<[u8; BIOS_SIZE as usize]>,
    pub(crate) ewram: Box<[u8; EWRAM_SIZE as usize]>,
    pub(crate) iwram: Box<[u8; IWRAM_SIZE as usize]>,
    pub(crate) palette: Box<[u8; PAL_SIZE as usize]>,
    pub(crate) vram: Box<[u8; VRAM_SIZE as usize]>,
    pub(crate) oam: Box<[u8; OAM_SIZE as usize]>,
    pub(crate) ioregs: Box<IoRegisters>,

    rom: Vec<u8>,

    allow_bios_access: bool,
    last_opcode: u32,

    prefetch_enabled: bool,
    gamepak_waitstates: [Waitstates; 6],
    ewram_waitstates: Waitstates,
    sram_waitstates: Waitstates,
}

impl GbaMemory {
    pub fn new() -> Self {
        GbaMemory {
            bios: array::boxed_copied(0),
            ewram: array::boxed_copied(0),
            iwram: array::boxed_copied(0),
            palette: array::boxed_copied(0),
            vram: array::boxed_copied(0),
            oam: array::boxed_copied(0),
            rom: Vec::new(),
            ioregs: Box::new(IoRegisters::default()),

            allow_bios_access: false,
            last_opcode: 0,

            prefetch_enabled: false,
            gamepak_waitstates: [0u8.into(); 6],
            ewram_waitstates: 2u8.into(),
            sram_waitstates: 8u8.into(),
        }
    }

    pub(crate) fn init(&mut self) {
        self.store16_io(io::WAITCNT, 0x4317);
        self.ewram_waitstates = 2.into();
    }

    pub fn set_gamepak(&mut self, gamepak: Vec<u8>) {
        self.rom = gamepak;
    }

    pub fn ioregs(&self) -> &IoRegisters {
        &self.ioregs
    }

    pub fn ioregs_mut(&mut self) -> &mut IoRegisters {
        &mut self.ioregs
    }

    pub fn view8(&mut self, address: u32) -> u8 {
        match address >> 24 {
            REGION_BIOS => self.bios.get(address as usize).copied().unwrap_or(0),
            REGION_UNUSED_1 => 0,
            REGION_EWRAM => self.ewram[(address & EWRAM_MASK) as usize],
            REGION_IWRAM => self.iwram[(address & IWRAM_MASK) as usize],
            REGION_IOREGS => {
                if address < IOREGS_SIZE {
                    self.view8_io(address)
                } else {
                    0
                }
            }
            REGION_PAL => self.palette[(address & PAL_MASK) as usize],<commit_msg>Add function for loading BIOS.<commit_after>mod gamepak;
pub mod io;
mod sram;

use arm::{AccessType, Memory, Waitstates};
use byteorder::{ByteOrder as _, LittleEndian as LE};
use log::debug;
use util::array;

use self::io::IoRegisters;

pub const REGION_BIOS: u32 = 0x0;
pub const REGION_UNUSED_1: u32 = 0x1;
pub const REGION_EWRAM: u32 = 0x2;
pub const REGION_IWRAM: u32 = 0x3;
pub const REGION_IOREGS: u32 = 0x4;
pub const REGION_PAL: u32 = 0x5;
pub const REGION_VRAM: u32 = 0x6;
pub const REGION_OAM: u32 = 0x7;
pub const REGION_GAMEPAK0_LO: u32 = 0x8;
pub const REGION_GAMEPAK0_HI: u32 = 0x9;
pub const REGION_GAMEPAK1_LO: u32 = 0xA;
pub const REGION_GAMEPAK1_HI: u32 = 0xB;
pub const REGION_GAMEPAK2_LO: u32 = 0xC;
pub const REGION_GAMEPAK2_HI: u32 = 0xD;
pub const REGION_SRAM: u32 = 0xE;

pub const BIOS_SIZE: u32 = 0x4000;
pub const EWRAM_SIZE: u32 = 0x40000;
pub const IWRAM_SIZE: u32 = 0x8000;
pub const PAL_SIZE: u32 = 0x400;
pub const VRAM_SIZE: u32 = 0x18000;
pub const OAM_SIZE: u32 = 0x400;
pub const IOREGS_SIZE: u32 = 0x20A;

pub const EWRAM_MASK: u32 = 0x3FFFF;
pub const IWRAM_MASK: u32 = 0x7FFF;
pub const PAL_MASK: u32 = 0x3FF;
pub const OAM_MASK: u32 = 0x3FF;
pub const ROM_MAX_MASK: u32 = 0xFFFFFF;

pub struct GbaMemory {
    pub(crate) bios: Box<[u8; BIOS_SIZE as usize]>,
    pub(crate) ewram: Box<[u8; EWRAM_SIZE as usize]>,
    pub(crate) iwram: Box<[u8; IWRAM_SIZE as usize]>,
    pub(crate) palette: Box<[u8; PAL_SIZE as usize]>,
    pub(crate) vram: Box<[u8; VRAM_SIZE as usize]>,
    pub(crate) oam: Box<[u8; OAM_SIZE as usize]>,
    pub(crate) ioregs: Box<IoRegisters>,

    rom: Vec<u8>,

    allow_bios_access: bool,
    last_opcode: u32,

    prefetch_enabled: bool,
    gamepak_waitstates: [Waitstates; 6],
    ewram_waitstates: Waitstates,
    sram_waitstates: Waitstates,
}

impl GbaMemory {
    pub fn new() -> Self {
        GbaMemory {
            bios: array::boxed_copied(0),
            ewram: array::boxed_copied(0),
            iwram: array::boxed_copied(0),
            palette: array::boxed_copied(0),
            vram: array::boxed_copied(0),
            oam: array::boxed_copied(0),
            rom: Vec::new(),
            ioregs: Box::new(IoRegisters::default()),

            allow_bios_access: false,
            last_opcode: 0,

            prefetch_enabled: false,
            gamepak_waitstates: [0u8.into(); 6],
            ewram_waitstates: 2u8.into(),
            sram_waitstates: 8u8.into(),
        }
    }

    pub(crate) fn init(&mut self) {
        self.store16_io(io::WAITCNT, 0x4317);
        self.ewram_waitstates = 2.into();
    }

    pub fn set_gamepak(&mut self, gamepak: Vec<u8>) {
        self.rom = gamepak;
    }

    pub fn set_bios(&mut self, mut bios: Vec<u8>) {
        bios.resize(BIOS_SIZE as usize, 0);
        self.bios = bios.into_boxed_slice().try_into().unwrap();
    }

    pub fn ioregs(&self) -> &IoRegisters {
        &self.ioregs
    }

    pub fn ioregs_mut(&mut self) -> &mut IoRegisters {
        &mut self.ioregs
    }

    pub fn view8(&mut self, address: u32) -> u8 {
        match address >> 24 {
            REGION_BIOS => self.bios.get(address as usize).copied().unwrap_or(0),
            REGION_UNUSED_1 => 0,
            REGION_EWRAM => self.ewram[(address & EWRAM_MASK) as usize],
            REGION_IWRAM => self.iwram[(address & IWRAM_MASK) as usize],
            REGION_IOREGS => {
                if address < IOREGS_SIZE {
                    self.view8_io(address)
                } else {
                    0
                }
            }
            REGION_PAL => self.palette[(address & PAL_MASK) as usize],
{'fraction_non_alphanumeric': 0.11560775435120985, 'fraction_numerical': 0.04895995471911702, 'mean_word_length': 2.708289611752361, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5902754', 'n_tokens_mistral': 2945, 'n_tokens_neox': 2761, 'n_words': 652}