diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-01-22 16:05:24 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-01-22 16:05:24 +0100 |
| commit | 3f643b961cc54aa5b198c7edfc354ffec0b28a67 (patch) | |
| tree | 1b4ddc8115bb5987353423956ec2fba0bc7fb65f /lib/xixanta/src/mapping.rs | |
| parent | 61ef02df2c128cd86efcddd3fa53870bc8d575c4 (diff) | |
| download | tools.nes-3f643b961cc54aa5b198c7edfc354ffec0b28a67.tar.gz tools.nes-3f643b961cc54aa5b198c7edfc354ffec0b28a67.zip | |
Remove dependency on TOML
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à <mikisabate@gmail.com>
Diffstat (limited to 'lib/xixanta/src/mapping.rs')
| -rw-r--r-- | lib/xixanta/src/mapping.rs | 147 |
1 files changed, 10 insertions, 137 deletions
diff --git a/lib/xixanta/src/mapping.rs b/lib/xixanta/src/mapping.rs index 49683ab..b3d22c7 100644 --- a/lib/xixanta/src/mapping.rs +++ b/lib/xixanta/src/mapping.rs @@ -1,11 +1,10 @@ -use crate::cfg::parse_cfg_file; +use crate::cfg::{parse_cfg_file, parse_nasm_cfg_file}; use crate::object::Bundle; -use toml::{Table, Value}; -const EMPTY_CONFIG: &str = include_str!("mappings/empty.toml"); -const NROM_CONFIG: &str = include_str!("mappings/nrom.toml"); -const NROM65_CONFIG: &str = include_str!("mappings/nrom65.toml"); -const UXROM_CONFIG: &str = include_str!("mappings/unrom.toml"); +const EMPTY_CONFIG: &str = include_str!("mappings/empty.cfg"); +const NROM_CONFIG: &str = include_str!("mappings/nrom.cfg"); +const NROM65_CONFIG: &str = include_str!("mappings/nrom65.cfg"); +const UXROM_CONFIG: &str = include_str!("mappings/unrom.cfg"); /// The type of section that a Mapping represents. #[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)] @@ -104,12 +103,11 @@ pub fn get_mapping_configuration(name: &str) -> Result<Vec<Mapping>, String> { let configuration = if std::fs::exists(name).unwrap_or(false) { match std::fs::read_to_string(name) { Ok(contents) => { - // If this is a file, then it might not be a TOML one, but a - // .cfg as used by cc65. - if name.ends_with(".cfg") { - parse_cfg_file(contents.as_str())? + // Call the right parse function. + if contents.starts_with("#!nasmcfg") { + parse_nasm_cfg_file(contents.as_str())? } else { - load_configuration_for(contents.as_str())? + parse_cfg_file(contents.as_str())? } } Err(_) => return Err(format!("could not read '{}'", name)), @@ -122,7 +120,7 @@ pub fn get_mapping_configuration(name: &str) -> Result<Vec<Mapping>, String> { "uxrom" | "unrom" => UXROM_CONFIG, _ => return Err("mapper configuration is not known".to_string()), }; - load_configuration_for(text)? + parse_nasm_cfg_file(text)? }; validate_configuration(&configuration)?; @@ -130,131 +128,6 @@ pub fn get_mapping_configuration(name: &str) -> Result<Vec<Mapping>, String> { Ok(configuration) } -// Returns the integer value for the mandatory integer contained in `value` that -// is named `prop_name` under the `section_name` section. This integer has to be -// lesser or equal to the `max` value. -fn get_integer( - section_name: &String, - prop_name: &str, - value: Option<&Value>, - max: usize, -) -> Result<usize, String> { - if value.is_none() { - return Err(format!( - "you have to define a value for '{}' in '{}'", - section_name, prop_name - )); - } - if !value.unwrap().is_integer() { - return Err(format!( - "value for '{}' in '{}' has to be an integer value", - section_name, prop_name - )); - } - - let val = value.unwrap().as_integer().unwrap() as usize; - if val > max { - return Err(format!( - "value for '{}' in '{}' is too big", - prop_name, section_name - )); - } - Ok(val) -} - -// Get a `SectionType` out of the given mandatory `value` which is under the -// `section_name`. -fn parse_section_type(section_name: &String, value: Option<&Value>) -> Result<SectionType, String> { - match value { - Some(v) => { - if !v.is_str() { - return Err(format!( - "'section_type' in '{}' has to be a string", - section_name - )); - } - match v.as_str().unwrap().to_lowercase().as_str() { - "header" => Ok(SectionType::Header), - "prgrom" => Ok(SectionType::PrgRom), - "chrrom" => Ok(SectionType::ChrRom), - _ => Err(format!( - "bad value for 'section_type' in '{}'", - section_name - )), - } - } - None => Err(format!( - "you have to define 'section_type' in '{}'", - section_name - )), - } -} - -// Returns a vector of segments which are contained inside of the mandatory -// `value`. -fn get_segments(section_name: &String, value: Option<&Value>) -> Result<Vec<Segment>, String> { - if value.is_none() { - return Err(format!( - "you have to define a value for 'segments' in '{}'", - section_name - )); - } - if !value.unwrap().is_array() { - return Err(format!( - "value for 'segments' in '{}' has to be an array value", - section_name - )); - } - - let mut res = vec![]; - for item in value.unwrap().as_array().unwrap() { - if !item.is_str() { - return Err(format!( - "every item in 'segments' has to be a string ({})", - section_name - )); - } - res.push(Segment::from(item.as_str().unwrap())); - } - - Ok(res) -} - -// Returns a vector of mappings that is retrieved by parsing the given text. -fn load_configuration_for(text: &str) -> Result<Vec<Mapping>, String> { - // Obtain the raw data by parsing the given text as a toml::Table. - let table = match text.parse::<Table>() { - Ok(t) => t, - Err(e) => return Err(format!("could not parse configuration file: {}", e)), - }; - - // Each section of the configuration file is a mapping, where the title is - // simply the name of it. - let mut mappings = vec![]; - for (name, value) in table { - let start = get_integer(&name, "start", value.get("start"), u16::MAX as usize)? as u16; - let size = get_integer(&name, "size", value.get("size"), u16::MAX as usize)?; - let fill = match value.get("fill") { - Some(_) => Some(get_integer(&name, "fill", value.get("fill"), u8::MAX as usize)? as u8), - None => None, - }; - let section_type = parse_section_type(&name, value.get("section_type"))?; - let segments = get_segments(&name, value.get("segments"))?; - - mappings.push(Mapping { - name, - start, - size, - offset: 0, - fill, - section_type, - segments, - }); - } - - Ok(mappings) -} - // Ensure that the given mappings conform to a minimum standard. fn validate_configuration(mappings: &[Mapping]) -> Result<(), String> { if mappings.is_empty() { |
