maikor_vm_file/
game_file.rs1use crate::constants::mem::*;
2use crate::file_utils::{convert_vec, read_sized_blocks, ReaderExt};
3use crate::read_write_impl::{Readable, Writeable};
4use crate::GameFileError::FileAccessError;
5use crate::{GameFile, GameFileError, GameFileHeader};
6
7impl GameFile {
8 pub fn new(
9 header: GameFileHeader,
10 main_code: [u8; MAIN_CODE],
11 code_banks: Vec<[u8; CODE_BANK]>,
12 atlases: Vec<[u8; ATLAS_BANK]>,
13 ) -> Self {
14 Self {
15 header,
16 main_code,
17 code_banks,
18 atlases,
19 }
20 }
21}
22
23impl Readable for GameFile {
24 fn from_reader<R: ReaderExt>(reader: &mut R) -> Result<GameFile, GameFileError> {
25 let header = GameFileHeader::from_reader(reader)?;
26 let main_code = reader
27 .read_block(CODE_BANK)
28 .map_err(|e| FileAccessError(e, "reading main code"))?;
29 let code_banks = read_sized_blocks(reader, header.code_bank_count as usize)?;
30 let atlas_banks = read_sized_blocks(reader, header.atlas_bank_count as usize)?;
31 Ok(GameFile::new(
32 header,
33 convert_vec(main_code),
34 code_banks,
35 atlas_banks,
36 ))
37 }
38}
39
40impl Writeable for GameFile {
41 fn as_bytes(&self) -> Result<Vec<u8>, GameFileError> {
42 let mut output = self.header.as_bytes()?;
43 output.extend_from_slice(&self.main_code);
44 for bank in &self.code_banks {
45 output.extend_from_slice(bank);
46 }
47 for bank in &self.atlases {
48 output.extend_from_slice(bank);
49 }
50
51 Ok(output)
52 }
53}
54
55#[cfg(test)]
56mod test {
57 use crate::read_write_impl::Writeable;
58 use crate::{GameFile, GameFileHeader, ATLAS_BANK, CODE_BANK, MAIN_CODE};
59
60 #[test]
61 #[rustfmt::skip]
62 fn test_write() {
63 let header = GameFileHeader::new(String::from("1"), 1, 1, 1,0, String::from("a"), String::from("b"), String::from("c"), 1, 1);
64 let file = GameFile::new(header, [1; MAIN_CODE], vec![[2; CODE_BANK]], vec![[3; ATLAS_BANK]]);
65
66 let bytes = file.as_bytes().unwrap();
67 assert_eq!(bytes.len(), MAIN_CODE + CODE_BANK + ATLAS_BANK + 22);
68 }
69}