agb/save/
sram.rs

1//! Module for battery backed SRAM save media support.
2//!
3//! SRAM acts as ordinary memory mapped into the memory space, and as such
4//! is accessed using normal memory read/write commands.
5
6use crate::save::asm_utils::*;
7use crate::save::utils::Timeout;
8use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
9
10const SRAM_SIZE: usize = 32 * 1024; // 32 KiB
11
12/// Checks whether an offset is contained within the bounds of the SRAM.
13fn check_bounds(offset: usize, len: usize) -> Result<(), Error> {
14    if offset.checked_add(len).is_none() || offset + len > SRAM_SIZE {
15        return Err(Error::OutOfBounds);
16    }
17    Ok(())
18}
19
20/// The [`RawSaveAccess`] used for battery backed SRAM.
21pub struct BatteryBackedAccess;
22impl RawSaveAccess for BatteryBackedAccess {
23    fn info(&self) -> Result<&'static MediaInfo, Error> {
24        Ok(&MediaInfo {
25            media_type: MediaType::Sram32K,
26            sector_shift: 0,
27            sector_count: SRAM_SIZE,
28            uses_prepare_write: false,
29        })
30    }
31
32    fn read(&self, offset: usize, buffer: &mut [u8], _: &mut Timeout) -> Result<(), Error> {
33        check_bounds(offset, buffer.len())?;
34        unsafe {
35            read_raw_buf(buffer, 0x0E000000 + offset);
36        }
37        Ok(())
38    }
39
40    fn verify(&self, offset: usize, buffer: &[u8], _: &mut Timeout) -> Result<bool, Error> {
41        check_bounds(offset, buffer.len())?;
42        let val = unsafe { verify_raw_buf(buffer, 0x0E000000 + offset) };
43        Ok(val)
44    }
45
46    fn prepare_write(&self, _: usize, _: usize, _: &mut Timeout) -> Result<(), Error> {
47        Ok(())
48    }
49
50    fn write(&self, offset: usize, buffer: &[u8], _: &mut Timeout) -> Result<(), Error> {
51        check_bounds(offset, buffer.len())?;
52        unsafe {
53            write_raw_buf(0x0E000000 + offset, buffer);
54        }
55        Ok(())
56    }
57}