diff options
Diffstat (limited to 'crates/nasm')
| -rw-r--r-- | crates/nasm/Cargo.toml | 9 | ||||
| -rw-r--r-- | crates/nasm/src/main.rs | 80 |
2 files changed, 89 insertions, 0 deletions
diff --git a/crates/nasm/Cargo.toml b/crates/nasm/Cargo.toml new file mode 100644 index 0000000..e1f3e88 --- /dev/null +++ b/crates/nasm/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "nasm" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.82" +clap = { version = "4.5.4", features = ["derive"] } +xixanta.workspace = true diff --git a/crates/nasm/src/main.rs b/crates/nasm/src/main.rs new file mode 100644 index 0000000..9f26417 --- /dev/null +++ b/crates/nasm/src/main.rs @@ -0,0 +1,80 @@ +use anyhow::Result; +use clap::Parser as ClapParser; +use std::fs::File; +use std::io::{self, Read, Write}; +use xixanta::assembler::Assembler; + +/// Assembler for the 6502 microprocessor that targets the NES. +#[derive(ClapParser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + /// Assemble the instructions given on this file. The standard input is used + /// when this argument is not given. + file: Option<String>, + + /// Disassemble instead of assembling. Disabled by default. + #[arg(short, long, default_value_t = false)] + disassemble: bool, + + /// Place the output into the given <OUT> file. Ignored if the `stdout` flag + /// is provided. Defaults to `out.nes` when assembling, and to `out.s` when + /// disassembling. + #[arg(short = 'o', long)] + out: Option<String>, + + /// Spit the output into the standard output instead. This ignores any given + /// `out` flag. Disabled by default. + #[arg(long, default_value_t = false)] + stdout: bool, +} + +fn main() -> Result<()> { + let args = Args::parse(); + let mut assembler = Assembler::new(); + + // Select the input stream. + let input: Box<dyn Read> = match args.file { + Some(file) => Box::new(File::open(file)?), + None => Box::new(std::io::stdin()), + }; + + // Select the output stream. + let mut output: Box<dyn Write> = if args.stdout { + Box::new(io::stdout()) + } else { + match args.out { + Some(file) => Box::new(File::create(file)?), + None => Box::new(File::create(if args.disassemble { + "out.s" + } else { + "out.nes" + })?), + } + }; + + // After the parse operation, just print the results. + if args.disassemble { + let instructions = assembler.disassemble(input)?; + + for instr in instructions { + output.write_all(instr.to_human().as_bytes())?; + output.write_all("\n".as_bytes())?; + } + } else { + let instructions = assembler.assemble(input)?; + + for instr in instructions { + let bs = instr.to_bytes(); + + if instr.size() == 1 { + output.write_all(&[bs[0]])?; + } else if instr.size() == 2 { + output.write_all(&[bs[0], bs[1]])?; + } else { + output.write_all(&[bs[0], bs[1], bs[2]])?; + } + } + } + + Ok(()) +} |
