Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

psx_mc/
ram.rs

1// SPDX-License-Identifier: GPL-2.0-or-later
2//! An in-memory [`Block`] device: a full 128 KiB card image in RAM.
3//!
4//! Used by the host test-suite (the whole filesystem is exercised against it)
5//! and usable on-device as a virtual/scratch card or a staging buffer before a
6//! single bulk flush to hardware.
7
8use crate::{Block, Error, Result, CARD_SIZE, FRAME_COUNT, FRAME_SIZE};
9
10/// A 128 KiB card held entirely in memory.
11///
12/// The struct owns the full image inline (128 KiB), so place it in a `static`
13/// or box it on the heap rather than passing it around by value on the small
14/// PS1 stack.
15#[repr(C)]
16pub struct RamCard {
17    bytes: [u8; CARD_SIZE],
18}
19
20impl RamCard {
21    /// A blank (all-zero, unformatted) card. Call [`crate::Card::format`] to lay
22    /// down a valid directory.
23    pub const fn new() -> Self {
24        RamCard {
25            bytes: [0u8; CARD_SIZE],
26        }
27    }
28
29    /// Build from an existing 128 KiB image (e.g. a `.mcd` file loaded on a host).
30    pub fn from_image(image: &[u8]) -> Result<Self> {
31        if image.len() != CARD_SIZE {
32            return Err(Error::OutOfRange);
33        }
34        let mut c = RamCard::new();
35        c.bytes.copy_from_slice(image);
36        Ok(c)
37    }
38
39    /// Borrow the raw 128 KiB image (for persisting to a host file).
40    pub fn image(&self) -> &[u8; CARD_SIZE] {
41        &self.bytes
42    }
43}
44
45impl Default for RamCard {
46    fn default() -> Self {
47        Self::new()
48    }
49}
50
51impl Block for RamCard {
52    fn read_frame(&mut self, frame: u16, out: &mut [u8; FRAME_SIZE]) -> Result<()> {
53        let f = frame as usize;
54        if f >= FRAME_COUNT {
55            return Err(Error::OutOfRange);
56        }
57        let base = f * FRAME_SIZE;
58        out.copy_from_slice(&self.bytes[base..base + FRAME_SIZE]);
59        Ok(())
60    }
61
62    fn write_frame(&mut self, frame: u16, data: &[u8; FRAME_SIZE]) -> Result<()> {
63        let f = frame as usize;
64        if f >= FRAME_COUNT {
65            return Err(Error::OutOfRange);
66        }
67        let base = f * FRAME_SIZE;
68        self.bytes[base..base + FRAME_SIZE].copy_from_slice(data);
69        Ok(())
70    }
71}