diff options
Diffstat (limited to 'src/metadata.rs')
-rw-r--r-- | src/metadata.rs | 127 |
1 files changed, 0 insertions, 127 deletions
diff --git a/src/metadata.rs b/src/metadata.rs deleted file mode 100644 index 7692434..0000000 --- a/src/metadata.rs +++ /dev/null @@ -1,127 +0,0 @@ -use phosphor::Colour; - - -pub fn parse_metadata(bytecode: &[u8]) -> Option<ProgramMetadata> { - MetadataParser::from_bytecode(bytecode).parse() -} - - -struct MetadataParser<'a> { - bytecode: &'a [u8], -} - -impl<'a> MetadataParser<'a> { - pub fn from_bytecode(bytecode: &'a [u8]) -> Self { - Self { bytecode } - } - - pub fn parse(self) -> Option<ProgramMetadata> { - macro_rules! array { - ($len:expr, $slice:expr) => {{ - let mut array = [0; $len]; - for i in 0..$len { array[i] = *$slice.get(i).unwrap_or(&0); } - array - }}; - } - - if self.range(0x00, 3) != &[0x41, 0x00, 0x20] { - return None; - } - - let (name, version) = split_name_version(self.string(self.double(0x10))); - let authors = self.string(self.double(0x12)).map(|string| { - string.lines().map(|line| line.to_string()).collect() - }); - - Some( ProgramMetadata { - bedrock_string: array!(7, self.range(0x03, 7)), - program_memory_size: match self.double(0x0a) { - 0 => 65536, double => double as usize }, - working_stack_size: match self.byte(0x0c) { - 0 => 256, byte => byte as usize }, - return_stack_size: match self.byte(0x0d) { - 0 => 256, byte => byte as usize }, - required_devices: self.double(0x0e), - name, - version, - authors, - description: self.string(self.double(0x14)), - path_buffer: match self.double(0x16) { - 0 => None, addr => Some(addr as usize) }, - small_icon: match self.double(0x18) { - 0 => None, addr => Some(array!(72, self.range(addr, 72))) }, - large_icon: match self.double(0x1a) { - 0 => None, addr => Some(array!(512, self.range(addr, 512))) }, - bg_colour: parse_colour(self.double(0x1c)), - fg_colour: parse_colour(self.double(0x1e)), - } ) - } - - fn byte(&self, address: u16) -> u8 { - *self.bytecode.get(address as usize).unwrap_or(&0) - } - - fn double(&self, address: u16) -> u16 { - u16::from_be_bytes([ - *self.bytecode.get(address as usize).unwrap_or(&0), - *self.bytecode.get(address as usize + 1).unwrap_or(&0), - ]) - } - - fn range(&self, address: u16, length: usize) -> &[u8] { - let start = address as usize; - let end = start + length; - self.bytecode.get(start..end).unwrap_or(&[]) - } - - fn string(&self, address: u16) -> Option<String> { - if address == 0 { return None; } - let start = address as usize; - let mut end = start; - while let Some(byte) = self.bytecode.get(end) { - match byte { 0 => break, _ => end += 1 } - } - let range = self.bytecode.get(start..end)?; - Some( String::from_utf8_lossy(range).to_string() ) - } -} - -fn split_name_version(string: Option<String>) -> (Option<String>, Option<String>) { - if let Some(string) = string { - match string.split_once('/') { - Some((left, right)) => (Some(left.to_string()), Some(right.to_string())), - None => (Some(string), None), - } - } else { - (None, None) - } -} - -fn parse_colour(double: u16) -> Option<Colour> { - let i = (double >> 12 ) as usize; - let r = (double >> 8 & 0xf) as u8 * 17; - let g = (double >> 4 & 0xf) as u8 * 17; - let b = (double & 0xf) as u8 * 17; - match i { - 0 => Some(Colour::from_rgb(r, g, b)), - _ => None, - } -} - - -pub struct ProgramMetadata { - pub bedrock_string: [u8; 7], - pub program_memory_size: usize, - pub working_stack_size: usize, - pub return_stack_size: usize, - pub required_devices: u16, - pub name: Option<String>, - pub version: Option<String>, - pub authors: Option<Vec<String>>, - pub description: Option<String>, - pub path_buffer: Option<usize>, - pub small_icon: Option<[u8; 72]>, - pub large_icon: Option<[u8; 512]>, - pub bg_colour: Option<Colour>, - pub fg_colour: Option<Colour>, -} |