From 701448be2c3c58e30960d46f090bf08adfc02832 Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Thu, 3 Jul 2025 14:53:16 +1200 Subject: Initial commit --- src/components/metadata.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/components/metadata.rs (limited to 'src/components/metadata.rs') diff --git a/src/components/metadata.rs b/src/components/metadata.rs new file mode 100644 index 0000000..5c2361b --- /dev/null +++ b/src/components/metadata.rs @@ -0,0 +1,104 @@ +pub struct Metadata<'a> { + program: &'a [u8], +} + +impl<'a> Metadata<'a> { + pub fn from(program: &'a [u8]) -> Option { + if program.len() < 10 { + return None; + } + let identifier = [0xE8,0x00,0x18,0x42,0x45,0x44,0x52,0x4F,0x43,0x4B]; + match program[0..10] == identifier { + true => Some(Self { program }), + false => None, + } + } + + pub fn name(&self) -> Option { + let pointer = self.get_pointer(0x000A)?; + self.get_string(pointer) + } + + pub fn authors(&self) -> Option> { + let pointer = self.get_pointer(0x000C)?; + let string = self.get_string(pointer)?; + Some(string.lines().map(String::from).collect()) + } + + pub fn description(&self) -> Option { + let pointer = self.get_pointer(0x000E)?; + self.get_string(pointer) + } + + pub fn bg_colour(&self) -> Option { + let pointer = self.get_pointer(0x0010)?; + let colour = self.get_pointer(pointer)?; + Some(MetadataColour::from_double(colour)) + } + + pub fn fg_colour(&self) -> Option { + let pointer = self.get_pointer(0x0012)?; + let colour = self.get_pointer(pointer)?; + Some(MetadataColour::from_double(colour)) + } + + pub fn small_icon(&self) -> Option> { + let pointer = self.get_pointer(0x0014)?; + self.get_icon(pointer, 72) + } + + pub fn large_icon(&self) -> Option> { + let pointer = self.get_pointer(0x0016)?; + self.get_icon(pointer, 512) + } + + fn get_byte(&self, address: u16) -> Option { + self.program.get(address as usize).copied() + } + + fn get_pointer(&self, address: u16) -> Option { + let high = self.get_byte(address)?; + let low = self.get_byte(address.checked_add(1)?)?; + let pointer = u16::from_be_bytes([high, low]); + if pointer != 0 { Some(pointer) } else { None } + } + + fn get_string(&self, address: u16) -> Option { + let start = address as usize; + let mut end = address as usize; + loop { + match self.program.get(end) { + Some(0) => break, + Some(_) => end += 1, + None => return None, + } + } + let vec = self.program[start..end].to_vec(); + String::from_utf8(vec).ok() + } + + fn get_icon(&self, address: u16, length: usize) -> Option> { + let address = address as usize; + let data = &self.program[address..address+length]; + match data.len() == length { + true => Some(data.to_vec()), + false => None, + } + } +} + + +pub struct MetadataColour { + pub red: u8, + pub green: u8, + pub blue: u8, +} + +impl MetadataColour { + pub fn from_double(colour: u16) -> Self { + let red = (colour & 0x0F00 >> 8) as u8 * 17; + let green = (colour & 0x00F0 >> 4) as u8 * 17; + let blue = (colour & 0x000F >> 0) as u8 * 17; + Self { red, green, blue } + } +} -- cgit v1.2.3-70-g09d2