A simple 6502 assembler written in Rust
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.4 KiB

/*
nyasm, a simple 6502 assembler written in Rust
Copyright (C) 2021 tromino <trominode@pm.me>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::fs;
use std::io;
use std::collections::HashMap;
use crate::util;
pub fn process_op_dot(
op: [&str; 2],
org: &mut Box<u16>,
labels: &mut HashMap<String, u16>,
label_requests: &mut Vec<(u16, String, bool)>,
counter: u16,
did_error: &mut bool
) -> Vec<u8> {
let op_bin: Vec<u8>;
match op[0] {
".incbin" => {
op_bin = handle_binary_input_error(fs::read(op[1]), op[1], did_error);
},
".org" => {
let new_org = util::parse_number(op[1], false, false, label_requests, org, counter, did_error);
if new_org.0 == "address" {
if !new_org.3 {
**org = new_org.1 as u16 + ((new_org.2 as u16) << 8);
} else {
util::assembler_error("Using label as argument is not allowed for .org", op[1], did_error);
}
} else if new_org.0 != "" {
util::assembler_error("Argument type not valid for .org", new_org.0, did_error);
}
op_bin = vec![];
},
".pad" => {
let mut to_op_bin: Vec<u8> = vec![];
let op_str_split = op[1].split(",").collect::<Vec<&str>>();
let parsed_end_address = util::parse_number(op_str_split[0], false, false, label_requests, org, counter, did_error);
let parsed_end_address_as_number = parsed_end_address.1 as u16 + ((parsed_end_address.2 as u16) << 8);
if parsed_end_address.0 == "address" {
if !parsed_end_address.3 {
if op_str_split.len() > 1 {
let parsed_pad_value = util::parse_number(op_str_split[1], false, true, label_requests, org, counter, did_error);
if parsed_pad_value.0 == "zero" {
for _ in counter .. parsed_end_address_as_number {
to_op_bin.push(parsed_pad_value.1);
}
} else if parsed_pad_value.0 != "" {
util::assembler_error("Argument type not valid for .pad (second value)", parsed_pad_value.0, did_error);
}
} else {
for _ in counter .. parsed_end_address_as_number {
to_op_bin.push(00u8);
}
}
} else {
util::assembler_error("Using label as argument is not allowed for .pad (first value)", op_str_split[0], did_error);
}
} else if parsed_end_address.0 != "" {
util::assembler_error("Argument type not valid for .pad (first value)", parsed_end_address.0, did_error);
}
op_bin = to_op_bin;
},
".label" => {
labels.insert(String::from(op[1]), counter);
op_bin = vec![];
},
".byte" => {
let mut to_op_bin: Vec<u8> = vec![];
let op_str_split = op[1].split(",");
for number in op_str_split {
let to_push = util::parse_number(number, false, true, label_requests, org, counter + (to_op_bin.len() as u16), did_error);
if to_push.0 == "zero" {
to_op_bin.push(to_push.1);
} else if to_push.0 != "" {
util::assembler_error("Argument type not valid for .byte", to_push.0, did_error);
}
}
op_bin = to_op_bin;
},
".addr" => {
let mut to_op_bin: Vec<u8> = vec![];
let op_str_split = op[1].split(",");
for number in op_str_split {
let to_push = util::parse_number(number, false, true, label_requests, org, counter + (to_op_bin.len() as u16), did_error);
if to_push.0 == "address" {
to_op_bin.push(to_push.1);
to_op_bin.push(to_push.2);
} else if to_push.0 != "" {
util::assembler_error("Argument type not valid for .addr", to_push.0, did_error);
}
}
op_bin = to_op_bin;
},
_ => {
op_bin = vec![];
util::assembler_error("Unknown assembler directive", op[0], did_error);
}
}
return op_bin;
}
fn handle_binary_input_error(res: Result<Vec<u8>, io::Error>, input_filename: &str, did_error: &mut bool) -> Vec<u8> {
if res.is_ok() {
return res.unwrap();
} else {
util::assembler_error("Failed to read from file", input_filename, did_error);
return vec![];
}
}