sfc_cart 0.2.0

SNES/SFC ROM header library and utilities.
Documentation
// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR MPL-2.0
// SPDX-FileCopyrightText: 2024 Gabriel Marcano <gabemarcano@yahoo.com>

use sfc_cart::Cart;

use std::env;
use std::fs::File;

pub fn main() {
    let args: Vec<String> = env::args().collect();

    println!("[");
    for (i, filepath) in args[1..].iter().enumerate() {
        let f = File::open(filepath).unwrap();
        let mut cart = match Cart::new(f) {
            Ok(cart) => cart,
            Err(err) => {
                eprintln!("Error with file \"{filepath}\": {err}");
                continue;
            }
        };
        let computed_checksum = cart.compute_checksum().unwrap();
        let header = &cart.header;

        println!("\t{{");

        println!("\t\t\"title\": \"{}\",", header.title);
        println!("\t\t\"ROM speed\": \"{}\",", header.speed);
        println!("\t\t\"ROM mode\": \"{}\",", header.mode);
        println!("\t\t\"Coprocessor\": \"{}\",", header.coprocessor);
        println!("\t\t\"chipset\": \"{}\",", header.chipset);
        println!("\t\t\"ROM size\": \"{} KiB\",", header.rom_size);
        println!("\t\t\"RAM size\": \"{} KiB\",", header.ram_size);
        println!("\t\t\"region\": \"{}\",", header.region);
        println!("\t\t\"developer id\": {},", header.dev_id);
        println!("\t\t\"ROM version\": {},", header.version);
        if let Some(expanded_header) = &header.expanded_header {
            println!("\t\t\"expanded header\": {{");
            println!("\t\t\t\"maker coder\": \"{}\",", expanded_header.maker_code);
            println!("\t\t\t\"game coder\": \"{}\",", expanded_header.game_code);
            println!(
                "\t\t\t\"expansion flash size\": \"{}\",",
                expanded_header.expansion_flash_size
            );
            println!(
                "\t\t\t\"expansion RAM size\": \"{}\",",
                expanded_header.expansion_ram_size
            );
            println!(
                "\t\t\t\"special version\": \"{}\",",
                expanded_header.special_version
            );
            println!(
                "\t\t\t\"chipset subtype\": \"{}\"",
                expanded_header.chipset_subtype
            );
            println!("\t\t}},");
        }
        println!("\t\t\"checksum\": \"0x{:04X}\",", header.checksum);
        println!("\t\t\"computed checksum\": \"0x{computed_checksum:04X}\",");
        println!("\t\t\"vectors\": {{");
        println!("\t\t\t\"native\": {{");
        println!("\t\t\t\t\"COP\": \"0x{:04X}\",", header.vectors.native.cop);
        println!("\t\t\t\t\"BRK\": \"0x{:04X}\",", header.vectors.native.brk);
        println!(
            "\t\t\t\t\"ABORT\": \"0x{:04X}\",",
            header.vectors.native.abort
        );
        println!("\t\t\t\t\"NMI\": \"0x{:04X}\",", header.vectors.native.nmi);
        println!("\t\t\t\t\"IRQ\": \"0x{:04X}\"", header.vectors.native.irq);
        println!("\t\t\t}},");
        println!("\t\t\t\"emulation\": {{");
        println!(
            "\t\t\t\t\"COP\": \"0x{:04X}\",",
            header.vectors.emulation.cop
        );
        println!(
            "\t\t\t\t\"ABORT\": \"0x{:04X}\",",
            header.vectors.emulation.abort
        );
        println!(
            "\t\t\t\t\"NMI\": \"0x{:04X}\",",
            header.vectors.emulation.nmi
        );
        println!(
            "\t\t\t\t\"RESET\": \"0x{:04X}\",",
            header.vectors.emulation.reset
        );
        println!(
            "\t\t\t\t\"IRQ_BRK\": \"0x{:04X}\"",
            header.vectors.emulation.irq_brk
        );
        println!("\t\t\t}}");
        println!("\t\t}}");

        if i == (args.len() - 2) {
            println!("\t}}");
        } else {
            println!("\t}},");
        }
    }
    println!("]");
}