Skip to main content

nes_sim/
savestate.rs

1use std::error::Error;
2use std::fmt::{Display, Formatter};
3
4const SAVE_STATE_MAGIC: &[u8; 8] = b"NESSTAT\0";
5const SAVE_STATE_VERSION: u32 = 1;
6
7#[derive(Debug, PartialEq, Eq)]
8pub enum SaveStateError {
9    InvalidMagic,
10    UnsupportedVersion(u32),
11    UnexpectedEof,
12    TrailingData,
13    NoCartridge,
14    MapperMismatch { expected: u16, actual: u16 },
15    InvalidData(&'static str),
16}
17
18impl Display for SaveStateError {
19    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
20        match self {
21            Self::InvalidMagic => f.write_str("save state header is invalid"),
22            Self::UnsupportedVersion(version) => {
23                write!(f, "save state version {} is not supported", version)
24            }
25            Self::UnexpectedEof => f.write_str("save state ended unexpectedly"),
26            Self::TrailingData => f.write_str("save state contains trailing bytes"),
27            Self::NoCartridge => f.write_str("save state requires an inserted cartridge"),
28            Self::MapperMismatch { expected, actual } => write!(
29                f,
30                "save state mapper mismatch: expected mapper {}, got mapper {}",
31                expected, actual
32            ),
33            Self::InvalidData(message) => f.write_str(message),
34        }
35    }
36}
37
38impl Error for SaveStateError {}
39
40pub(crate) struct StateWriter {
41    bytes: Vec<u8>,
42}
43
44impl StateWriter {
45    pub(crate) fn new() -> Self {
46        let mut writer = Self { bytes: Vec::new() };
47        writer.write_bytes(SAVE_STATE_MAGIC);
48        writer.write_u32(SAVE_STATE_VERSION);
49        writer
50    }
51
52    pub(crate) fn finish(self) -> Vec<u8> {
53        self.bytes
54    }
55
56    pub(crate) fn write_u8(&mut self, value: u8) {
57        self.bytes.push(value);
58    }
59
60    pub(crate) fn write_bool(&mut self, value: bool) {
61        self.write_u8(u8::from(value));
62    }
63
64    pub(crate) fn write_u16(&mut self, value: u16) {
65        self.bytes.extend_from_slice(&value.to_le_bytes());
66    }
67
68    pub(crate) fn write_u32(&mut self, value: u32) {
69        self.bytes.extend_from_slice(&value.to_le_bytes());
70    }
71
72    pub(crate) fn write_u64(&mut self, value: u64) {
73        self.bytes.extend_from_slice(&value.to_le_bytes());
74    }
75
76    pub(crate) fn write_i16(&mut self, value: i16) {
77        self.bytes.extend_from_slice(&value.to_le_bytes());
78    }
79
80    pub(crate) fn write_bytes(&mut self, bytes: &[u8]) {
81        self.bytes.extend_from_slice(bytes);
82    }
83}
84
85pub(crate) struct StateReader<'a> {
86    bytes: &'a [u8],
87    offset: usize,
88}
89
90impl<'a> StateReader<'a> {
91    pub(crate) fn new(bytes: &'a [u8]) -> Result<Self, SaveStateError> {
92        let mut reader = Self { bytes, offset: 0 };
93        let mut magic = [0; SAVE_STATE_MAGIC.len()];
94        reader.read_exact(&mut magic)?;
95        if &magic != SAVE_STATE_MAGIC {
96            return Err(SaveStateError::InvalidMagic);
97        }
98
99        let version = reader.read_u32()?;
100        if version != SAVE_STATE_VERSION {
101            return Err(SaveStateError::UnsupportedVersion(version));
102        }
103
104        Ok(reader)
105    }
106
107    pub(crate) fn finish(self) -> Result<(), SaveStateError> {
108        if self.offset == self.bytes.len() {
109            Ok(())
110        } else {
111            Err(SaveStateError::TrailingData)
112        }
113    }
114
115    pub(crate) fn read_u8(&mut self) -> Result<u8, SaveStateError> {
116        let mut buf = [0];
117        self.read_exact(&mut buf)?;
118        Ok(buf[0])
119    }
120
121    pub(crate) fn read_bool(&mut self) -> Result<bool, SaveStateError> {
122        match self.read_u8()? {
123            0 => Ok(false),
124            1 => Ok(true),
125            _ => Err(SaveStateError::InvalidData("boolean field must be 0 or 1")),
126        }
127    }
128
129    pub(crate) fn read_u16(&mut self) -> Result<u16, SaveStateError> {
130        let mut buf = [0; 2];
131        self.read_exact(&mut buf)?;
132        Ok(u16::from_le_bytes(buf))
133    }
134
135    pub(crate) fn read_u32(&mut self) -> Result<u32, SaveStateError> {
136        let mut buf = [0; 4];
137        self.read_exact(&mut buf)?;
138        Ok(u32::from_le_bytes(buf))
139    }
140
141    pub(crate) fn read_u64(&mut self) -> Result<u64, SaveStateError> {
142        let mut buf = [0; 8];
143        self.read_exact(&mut buf)?;
144        Ok(u64::from_le_bytes(buf))
145    }
146
147    pub(crate) fn read_i16(&mut self) -> Result<i16, SaveStateError> {
148        let mut buf = [0; 2];
149        self.read_exact(&mut buf)?;
150        Ok(i16::from_le_bytes(buf))
151    }
152
153    pub(crate) fn read_bytes_into(&mut self, bytes: &mut [u8]) -> Result<(), SaveStateError> {
154        self.read_exact(bytes)
155    }
156
157    fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), SaveStateError> {
158        let end = self.offset.saturating_add(buf.len());
159        if end > self.bytes.len() {
160            return Err(SaveStateError::UnexpectedEof);
161        }
162        buf.copy_from_slice(&self.bytes[self.offset..end]);
163        self.offset = end;
164        Ok(())
165    }
166}