From 3f643b961cc54aa5b198c7edfc354ffec0b28a67 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Wed, 22 Jan 2025 16:05:24 +0100 Subject: Remove dependency on TOML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When I introduced this dependency it looked like a good idea to have a better-looking replacement to cl65's cfg format. That being said, the end result wasn't *much* prettier either, and the end result could be even bigger and equally confusing. Since 5f48de69f46d ("Add support for cfg files") there is quite the framework in order to support regular cl65's cfg files. Hence, this commit takes another approach: let's tune this format to a more compressed and simplified one. This is now the current "nasm cfg" format, and it allowed us to re-use a lot of code while also being more to the point for NES/Famicom development than the original cfg format. With this new format, we can now remove the dependency on TOML and all of the inner dependencies which were quite a lot. Signed-off-by: Miquel Sabaté Solà --- lib/xixanta/src/cfg.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) (limited to 'lib/xixanta/src/cfg.rs') diff --git a/lib/xixanta/src/cfg.rs b/lib/xixanta/src/cfg.rs index a6127b9..be3a9c1 100644 --- a/lib/xixanta/src/cfg.rs +++ b/lib/xixanta/src/cfg.rs @@ -18,6 +18,7 @@ struct RawMapping { fill: Option, ignore: bool, line_num: usize, + segments: String, } // Fetch a line of values in the format of "Name: key1=value1, key2=value2, @@ -87,6 +88,7 @@ fn fetch_memory_definition(line: &str, line_num: usize) -> Result Result res.fill = Some(val.to_string()), "start" => res.start = val.to_string(), "size" => res.size = val.to_string(), + "segments" => res.segments = val.to_string(), _ => {} } } @@ -150,8 +153,8 @@ fn find_value(key: &str, values: &str, line_num: usize) -> Result Result, String> { let mut values = vec![]; let mut raw_segments = vec![]; @@ -265,7 +268,7 @@ pub fn parse_cfg_file(text: &str) -> Result, String> { // realized it's CHR ROM. if header { header = false; - } else if start == 0x00 { + } else if start == 0x0000 { section_type = SectionType::ChrRom; } else if section_type != SectionType::ChrRom { section_type = SectionType::PrgRom; @@ -294,6 +297,83 @@ pub fn parse_cfg_file(text: &str) -> Result, String> { Ok(res) } +fn get_segments_from(value: &str, line: usize) -> Result, String> { + if !value.starts_with('[') || !value.ends_with(']') { + return Err(format!("should be enclosed inside of [] (line {})", line)); + } + + let mut res = vec![]; + for name in value[1..value.len() - 1].split(' ') { + let trimmed_name = name.trim(); + res.push(Segment::from(trimmed_name)); + } + + Ok(res) +} + +/// Parse the given blob of `text` as a simplified .cfg file. +pub fn parse_nasm_cfg_file(text: &str) -> Result, String> { + let mut mappings = vec![]; + let symbols = HashMap::new(); + let mut header = true; + let mut section_type = SectionType::Header; + + for (idx, line) in text.lines().enumerate() { + // Skip empty lines and comments. + let l = line.trim(); + if l.is_empty() || l.starts_with('#') { + continue; + } + + let real_line = match l.find(';') { + Some(idx) => &l[0..idx], + None => { + return Err(format!( + "line does not end with a semicolon (line {})", + idx + 1 + )) + } + }; + + // Parse the mapping definition. + let mapping = fetch_memory_definition(real_line, idx + 1)?; + + // Parse hexadecimal values from start, size and fill. + let start = get_hex_from(&mapping.start, mapping.line_num, &symbols)? as u16; + let size = get_hex_from(&mapping.size, mapping.line_num, &symbols)?; + let fill = match &mapping.fill { + Some(f) => Some(get_hex_from(f, mapping.line_num, &symbols)? as u8), + None => None, + }; + + // As with 'parse_cfg_file', the section type: + // 1. If it's the first mapping we see, then it's the header. + // 2. If after the header it claims to start at 0x00, then from now on + // it's CHR ROM. + // 3. Otherwise it's PRG ROM unless in a previous iteration we + // realized it's CHR ROM. + if header { + header = false; + } else if start == 0x0000 { + section_type = SectionType::ChrRom; + } else if section_type != SectionType::ChrRom { + section_type = SectionType::PrgRom; + }; + + mappings.push(Mapping { + name: mapping.name, + offset: 0, + start, + size, + fill, + section_type: section_type.clone(), + segments: get_segments_from(&mapping.segments, idx + 1)?, + }); + } + + Ok(mappings) +} + #[cfg(test)] mod tests { use super::*; -- cgit v1.2.3