1#![no_std]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![deny(clippy::unwrap_used)]
4#![warn(missing_docs)]
5#![warn(clippy::pedantic)]
7#![allow(clippy::missing_errors_doc)]
8#![allow(clippy::module_name_repetitions)]
9
10#[cfg(feature = "alloc")]
64extern crate alloc;
65
66mod borrowed_or_owned;
67mod cartridge;
68mod cartridge_type;
69mod chip;
70mod chip_type;
71mod data;
72mod error;
73mod iter;
74mod parser;
75mod position;
76
77pub use crate::cartridge::{Cartridge, RawCartridge};
78pub use crate::cartridge_type::CartridgeType;
79pub use crate::chip::{Chip, Chip8K, RawChip};
80pub use crate::chip_type::ChipType;
81pub use crate::data::{Data, Data8K};
82pub use crate::error::ParseError;
83pub use crate::iter::{Iter, Iter8K};
84pub use crate::parser::{parse_crt, parse_crt_aligned};
85pub use crate::position::Position;
86
87#[cfg(feature = "alloc")]
88#[cfg(test)]
89mod test {
90 use crate::{parse_crt, parse_crt_aligned, Cartridge, CartridgeType, ChipType, Data, Position};
91 use alloc::vec;
92 use alloc::vec::Vec;
93
94 const EXAMPLE_HEAD: [u8; 80] = [
95 0x43, 0x36, 0x34, 0x20, 0x43, 0x41, 0x52, 0x54, 0x52, 0x49, 0x44, 0x47, 0x45, 0x20, 0x20,
96 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x41, 0x54, 0x54, 0x41, 0x43, 0x4B, 0x20, 0x4F, 0x46, 0x20, 0x54, 0x48, 0x45,
98 0x20, 0x4D, 0x55, 0x54, 0x41, 0x4E, 0x54, 0x20, 0x43, 0x41, 0x4D, 0x45, 0x4C, 0x53, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x43, 0x48, 0x49, 0x50, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00,
100 0x00, 0x80, 0x00, 0x20, 0x00,
101 ];
102 const BUFFER_SIZE: usize = EXAMPLE_HEAD.len() + 8192;
103
104 #[test]
105 fn test() {
106 let mut crt = vec![0u8; BUFFER_SIZE + 2 * align_of::<u32>()];
108 let crt = crt.as_mut_slice();
109 let offset = crt.as_ptr().align_offset(align_of::<u32>());
110 assert!(
111 offset <= align_of::<u32>(),
112 "crt not alignable, this shouldn't happen"
113 );
114 let crt = &mut crt[offset..offset + BUFFER_SIZE];
115
116 crt[0..EXAMPLE_HEAD.len()].copy_from_slice(&EXAMPLE_HEAD);
118
119 #[allow(clippy::useless_asref)]
121 let crt = crt.as_ref();
122
123 check(parse_crt(crt).unwrap_or_else(|_| panic!("unable to parse crt")));
125 check(unsafe { parse_crt_aligned(crt) }.unwrap_or_else(|_| panic!("unable to parse crt")));
126 }
127
128 fn check<const A: bool>(input: (Cartridge, Data<A>)) {
129 let (cartridge, data) = input;
130 assert_eq!(cartridge.cartridge_hardware_type, CartridgeType::Generic);
131 assert!(!cartridge.exrom_line);
132 assert!(cartridge.game_line);
133 assert_eq!(cartridge.name(), b"ATTACK OF THE MUTANT CAMELS");
134
135 let Some(data) = data.into_8k_baking() else {
136 panic!("crt contains RAM and/or not the usual 8 KiB ROM banking")
137 };
138
139 let data = data.iter().collect::<Vec<_>>();
140 assert_eq!(data.len(), 1);
141 let (chip, rom) = &data[0];
142 assert_eq!(chip.chip_type, ChipType::Rom);
143 assert_eq!(chip.bank_number, 0);
144 assert_eq!(chip.position, Position::Low);
145 assert_eq!(rom.len(), 8192);
146 }
147}