From 4628873cfc53d3bdc7a0834b3edbb02b0b9cf4a7 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Sun, 22 Dec 2024 22:40:11 +0100 Subject: Transform mapping configurations into toml files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow the creation of configuration files that can live outside of this tree, so developers can fine tune configuration files of their own without having to pick up whatever is currently available. Signed-off-by: Miquel Sabaté Solà --- lib/xixanta/src/assembler.rs | 58 ++-- lib/xixanta/src/mapping.rs | 530 ++++++++++++----------------------- lib/xixanta/src/mappings/empty.toml | 12 + lib/xixanta/src/mappings/nrom.toml | 27 ++ lib/xixanta/src/mappings/nrom65.toml | 27 ++ lib/xixanta/src/mappings/unrom.toml | 69 +++++ 6 files changed, 348 insertions(+), 375 deletions(-) create mode 100644 lib/xixanta/src/mappings/empty.toml create mode 100644 lib/xixanta/src/mappings/nrom.toml create mode 100644 lib/xixanta/src/mappings/nrom65.toml create mode 100644 lib/xixanta/src/mappings/unrom.toml (limited to 'lib/xixanta/src') diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs index e6f3396..d24a555 100644 --- a/lib/xixanta/src/assembler.rs +++ b/lib/xixanta/src/assembler.rs @@ -82,8 +82,6 @@ pub struct Assembler { impl Assembler { pub fn new(mappings: Vec) -> Self { - crate::mapping::assert(&mappings); - Self { context: Context::new(), literal_mode: None, @@ -1557,7 +1555,7 @@ impl Assembler { #[cfg(test)] mod tests { use super::*; - use crate::mapping::{SectionType, Segment, EMPTY}; + use crate::mapping::{get_mapping_configuration, SectionType, Segment}; fn one_two() -> Vec { vec![ @@ -1600,6 +1598,10 @@ mod tests { ] } + fn empty() -> Vec { + get_mapping_configuration("empty").unwrap() + } + fn minimal_header() -> Vec { vec![ Bundle::fill(0x4E), // N @@ -1615,7 +1617,7 @@ mod tests { // Set up the empty mapper, but we have to push a minimal header // (otherwise an early assertion will fail), and we need to point to the // "CODE" segment (which is in the mapping indexed by 1). - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1636,7 +1638,7 @@ mod tests { } fn assert_error(line: &str, line_num: usize, global: bool, message: &str) { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1668,7 +1670,7 @@ mod tests { #[test] fn empty_line() { for line in vec!["", " ", ";; Comment", " ;; Comment"].into_iter() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1771,7 +1773,7 @@ adc $Four #[test] fn scoped_variable() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1811,7 +1813,7 @@ adc #Another::Variable #[test] fn bare_variables() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1836,7 +1838,7 @@ adc Variable #[test] fn reference_outer_variables() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1930,7 +1932,7 @@ lda #Scope::Variable #[test] fn operations_with_variables() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -1970,7 +1972,7 @@ ldx #~Value #[test] fn signed_with_variables() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2003,7 +2005,7 @@ ldx #+Value #[test] fn divide_by_zero() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2025,7 +2027,7 @@ ldx #(2 / Value) #[test] fn bad_shift() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2343,7 +2345,7 @@ ldx #(2 << Value) #[test] fn same_segment_labels() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2379,7 +2381,7 @@ nop #[test] fn anonymous_relative_jumps() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2448,7 +2450,7 @@ nop #[test] fn anonymous_relative_branches() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2513,7 +2515,7 @@ nop #[test] fn conditional_branch_to_labels() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2547,7 +2549,7 @@ nop #[test] fn jsr_to_proc() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2584,7 +2586,7 @@ nop #[test] fn label_in_instruction_addressing() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2624,7 +2626,7 @@ palettes: #[test] fn byte_literals() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2663,7 +2665,7 @@ palettes: #[test] fn hi_lo_byte() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2695,7 +2697,7 @@ lda #>Var #[test] fn macro_no_arguments() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2728,7 +2730,7 @@ MACRO #[test] fn macro_not_enough_arguments() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2757,7 +2759,7 @@ MACRO #[test] fn macro_too_many_arguments() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2786,7 +2788,7 @@ MACRO(1, 2) #[test] fn macro_with_one_argument() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2819,7 +2821,7 @@ MACRO(2) #[test] fn macro_unknown_arguments() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -2849,7 +2851,7 @@ MACRO(1) #[test] fn macro_multiple_arguments() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; @@ -3132,7 +3134,7 @@ code: #[test] fn cannot_switch_to_segment_inside_of_scope() { - let mut asm = Assembler::new(EMPTY.to_vec()); + let mut asm = Assembler::new(empty()); asm.mappings[0].segments[0].bundles = minimal_header(); asm.mappings[0].offset = 6; asm.current_mapping = 1; diff --git a/lib/xixanta/src/mapping.rs b/lib/xixanta/src/mapping.rs index 8cf752d..a196c8e 100644 --- a/lib/xixanta/src/mapping.rs +++ b/lib/xixanta/src/mapping.rs @@ -1,327 +1,11 @@ use crate::errors::EvalError; use crate::object::Bundle; +use toml::{Table, Value}; -lazy_static! { - /// An empty mapper used for testing purposes. - pub static ref EMPTY: Vec = vec![ - Mapping { - name: String::from("HEADER"), - start: 0x0000, - size: 0x0010, - offset: 0, - fill: Some(0x00), - section_type: SectionType::Header, - segments: vec![Segment { - name: String::from("HEADER"), - len: 0, - offset: 0, - bundles: vec![], - }] - }, - Mapping { - name: String::from("ROM0"), - start: 0x8000, - size: 0x8000, - offset: 0, - fill: None, - section_type: SectionType::PrgRom, - segments: vec![Segment { - name: String::from("CODE"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - ]; - - // Mapper for a simple NROM setup (e.g. Super Mario Bros). - pub static ref NROM: Vec = vec![ - Mapping { - name: String::from("HEADER"), - start: 0x0000, - size: 0x0010, - offset: 0, - fill: Some(0x00), - section_type: SectionType::Header, - segments: vec![Segment { - name: String::from("HEADER"), - len: 0, - offset: 0, - bundles: vec![], - }] - }, - Mapping { - name: String::from("ROM0"), - start: 0x8000, - size: 0x7FFA, - offset: 0, - fill: Some(0x00), - section_type: SectionType::PrgRom, - segments: vec![Segment { - name: String::from("CODE"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - Mapping { - name: String::from("ROMV"), - start: 0xFFFA, - size: 0x0006, - offset: 0, - fill: Some(0x00), - section_type: SectionType::PrgRom, - segments: vec![Segment { - name: String::from("VECTORS"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - Mapping { - name: String::from("ROM2"), - start: 0x0000, - size: 0x2000, - offset: 0, - fill: Some(0x00), - section_type: SectionType::ChrRom, - segments: vec![Segment { - name: String::from("CHARS"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - ]; - - // Mapper for UxROM boards (UxROM (NES-UNROM, NES-UOROM, HVC-UN1ROM their - // HVC counterparts, and clone boards). - pub static ref UXROM: Vec = vec![ - Mapping { - name: String::from("HEADER"), - start: 0x0000, - size: 0x0010, - offset: 0, - fill: Some(0x00), - section_type: SectionType::Header, - segments: vec![Segment { - name: String::from("HEADER"), - len: 0, - offset: 0, - bundles: vec![], - }] - }, - Mapping { - name: String::from("PRG0"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xF8), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK0"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG1"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xF9), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK1"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG2"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xFA), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK2"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG3"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xFB), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK3"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG4"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xFC), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK4"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG5"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xFD), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK5"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG6"), - start: 0x8000, - size: 0x4000, - offset: 0, - fill: Some(0xFE), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("BANK6"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("PRG"), - start: 0xC000, - size: 0x3FFA, - offset: 0, - fill: Some(0xFF), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("FIXED"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("ROMV"), - start: 0xFFFA, - size: 0x0006, - offset: 0, - fill: Some(0x00), - section_type: SectionType::PrgRom, - segments: vec![Segment { - name: String::from("VECTORS"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - ]; - - pub static ref NROM65: Vec = vec![ - Mapping { - name: String::from("HEADER"), - start: 0x0000, - size: 0x0010, - offset: 0, - fill: Some(0x00), - section_type: SectionType::Header, - segments: vec![Segment { - name: String::from("HEADER"), - len: 0, - offset: 0, - bundles: vec![], - }] - }, - Mapping { - name: String::from("ROM0"), - start: 0x8000, - size: 0x7FFA, - offset: 0, - fill: Some(0x00), - section_type: SectionType::PrgRom, - segments: vec![ - Segment { - name: String::from("STARTUP"), - len: 0, - offset: 0, - bundles: vec![], - }, - Segment { - name: String::from("CODE"), - len: 0, - offset: 0, - bundles: vec![], - }, - ] - }, - Mapping { - name: String::from("ROMV"), - start: 0xFFFA, - size: 0x0006, - offset: 0, - fill: Some(0x00), - section_type: SectionType::PrgRom, - segments: vec![Segment { - name: String::from("VECTORS"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - Mapping { - name: String::from("ROM2"), - start: 0x0000, - size: 0x2000, - offset: 0, - fill: Some(0x00), - section_type: SectionType::ChrRom, - segments: vec![Segment { - name: String::from("CHARS"), - len: 0, - offset: 0, - bundles: vec![], - },] - }, - ]; -} +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"); /// The type of section that a Mapping represents. #[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)] @@ -353,6 +37,17 @@ pub struct Segment { pub bundles: Vec, } +impl From<&str> for Segment { + fn from(name: &str) -> Self { + Segment { + name: name.to_string(), + offset: 0, + len: 0, + bundles: vec![], + } + } +} + impl Segment { /// Returns the length of the segment by counting the bundles that have been // pushed so far into the segment. @@ -401,39 +96,180 @@ pub struct Mapping { pub section_type: SectionType, } -/// Assert that the given mappings conform to a minimum standard. -pub fn assert(mappings: &[Mapping]) { - assert!( - !mappings.is_empty(), - "We need at least one segment defined, the header" - ); - assert!( - !mappings.first().unwrap().segments.is_empty(), - "We need at least one segment defined, the header" - ); - assert_eq!( - mappings.first().unwrap().section_type, - SectionType::Header, - "First mapping section must be the header" - ); - assert_eq!( - mappings.first().unwrap().size, - 0x10, - "The header must be exactly 16 bytes long" - ); +/// Returns a vector corresponding to the configuration of mappings that is +/// expected for the given `name`. Returns an error if the configuration cannot +/// be parsed or there's something wrong about it. +pub fn get_mapping_configuration(name: &str) -> Result, String> { + let text = match name.to_lowercase().as_str() { + "empty" => EMPTY_CONFIG, + "nrom" => NROM_CONFIG, + "nrom65" => NROM65_CONFIG, + "uxrom" | "unrom" => UXROM_CONFIG, + _ => return Err("mapper configuration is not known".to_string()), + }; + + let configuration = load_configuration_for(text)?; + validate_configuration(&configuration)?; + + 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 { + 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 { + 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, 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, String> { + // Obtain the raw data by parsing the given text as a toml::Table. + let table = match text.parse::() { + 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() { + return Err("We need at least one segment defined, the header".to_string()); + } + if mappings.first().unwrap().segments.is_empty() { + return Err("We need at least one segment defined, the header".to_string()); + } + if mappings.first().unwrap().section_type != SectionType::Header { + return Err("First mapping section must be the header".to_string()); + } + if mappings.first().unwrap().size != 0x10 { + return Err("The header must be exactly 16 bytes long".to_string()); + } let prg_rom_len = mappings .iter() .filter(|m| m.section_type == SectionType::PrgRom) .fold(0, |acc, x| acc + x.size); - assert!(prg_rom_len >= 0x4000, "PRG ROM must be at least 8KB long"); - assert!( - prg_rom_len % 0x4000 == 0, - "PRG ROM must be formed by banks of exactly 8KB" - ); + + if prg_rom_len < 0x4000 { + return Err("PRG ROM must be at least 8KB long".to_string()); + } + if prg_rom_len % 0x4000 != 0 { + return Err("PRG ROM must be formed by banks of exactly 8KB".to_string()); + } + + Ok(()) } -/// Validate some sanity checks on the given `mappings`. Only call this function +/// Perform some sanity checks on the given `mappings`. Only call this function /// after all bundles have been produced. pub fn validate(mappings: &[Mapping]) -> Result<(), EvalError> { // Guaranteed by `crate::mapping::assert` to be the header. diff --git a/lib/xixanta/src/mappings/empty.toml b/lib/xixanta/src/mappings/empty.toml new file mode 100644 index 0000000..ae6312c --- /dev/null +++ b/lib/xixanta/src/mappings/empty.toml @@ -0,0 +1,12 @@ +[HEADER] +start = 0x0000 +size = 0x0010 +fill = 0x00 +section_type = "Header" +segments = ["HEADER"] + +[ROM0] +start = 0x8000 +size = 0x8000 +section_type = "PRGROM" +segments = ["CODE"] diff --git a/lib/xixanta/src/mappings/nrom.toml b/lib/xixanta/src/mappings/nrom.toml new file mode 100644 index 0000000..18711a6 --- /dev/null +++ b/lib/xixanta/src/mappings/nrom.toml @@ -0,0 +1,27 @@ +[HEADER] +start = 0x0000 +size = 0x0010 +fill = 0x00 +section_type = "Header" +segments = ["HEADER"] + +[ROM0] +start = 0x8000 +size = 0x7FFA +fill = 0x00 +section_type = "PRGROM" +segments = ["CODE"] + +[ROMV] +start = 0xFFFA +size = 0x0006 +fill = 0x00 +section_type = "PRGROM" +segments = ["VECTORS"] + +[ROM2] +start = 0x0000 +size = 0x2000 +fill = 0x00 +section_type = "CHRROM" +segments = ["CHARS"] diff --git a/lib/xixanta/src/mappings/nrom65.toml b/lib/xixanta/src/mappings/nrom65.toml new file mode 100644 index 0000000..d4775e4 --- /dev/null +++ b/lib/xixanta/src/mappings/nrom65.toml @@ -0,0 +1,27 @@ +[HEADER] +start = 0x0000 +size = 0x0010 +fill = 0x00 +section_type = "Header" +segments = ["HEADER"] + +[ROM0] +start = 0x8000 +size = 0x7FFA +fill = 0x00 +section_type = "PRGROM" +segments = ["STARTUP", "CODE"] + +[ROMV] +start = 0xFFFA +size = 0x0006 +fill = 0x00 +section_type = "PRGROM" +segments = ["VECTORS"] + +[ROM2] +start = 0x0000 +size = 0x2000 +fill = 0x00 +section_type = "CHRROM" +segments = ["CHARS"] diff --git a/lib/xixanta/src/mappings/unrom.toml b/lib/xixanta/src/mappings/unrom.toml new file mode 100644 index 0000000..070cfd1 --- /dev/null +++ b/lib/xixanta/src/mappings/unrom.toml @@ -0,0 +1,69 @@ +[HEADER] +start = 0x0000 +size = 0x0010 +fill = 0x00 +section_type = "Header" +segments = ["HEADER"] + +[PRG0] +start = 0x8000 +size = 0x4000 +fill = 0xF8 +section_type = "PRGROM" +segments = ["BANK0"] + +[PRG1] +start = 0x8000 +size = 0x4000 +fill = 0xF9 +section_type = "PRGROM" +segments = ["BANK1"] + +[PRG2] +start = 0x8000 +size = 0x4000 +fill = 0xFA +section_type = "PRGROM" +segments = ["BANK2"] + +[PRG3] +start = 0x8000 +size = 0x4000 +fill = 0xFB +section_type = "PRGROM" +segments = ["BANK3"] + +[PRG4] +start = 0x8000 +size = 0x4000 +fill = 0xFC +section_type = "PRGROM" +segments = ["BANK4"] + +[PRG5] +start = 0x8000 +size = 0x4000 +fill = 0xFD +section_type = "PRGROM" +segments = ["BANK5"] + +[PRG6] +start = 0x8000 +size = 0x4000 +fill = 0xFE +section_type = "PRGROM" +segments = ["BANK6"] + +[PRG] +start = 0xC000 +size = 0x3FFA +fill = 0xFF +section_type = "PRGROM" +segments = ["FIXED"] + +[ROMV] +start = 0xFFFA +size = 0x0006 +fill = 0x00 +section_type = "PRGROM" +segments = ["VECTORS"] -- cgit v1.2.3