1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use clap::ArgMatches;
use std::{error::Error, fs};
use termcolor::{Color, ColorSpec};

mod argument;
pub use argument::{Argument, Value};

mod instruction;
pub use instruction::Instr;

mod fio;
use fio::{determine_file_type, FileType};

mod ksm_reader;
pub use ksm_reader::{ArgumentSection, CodeSection, DebugSection, DebugEntry, KSMFile, KSMFileReader, SectionType};

mod coloredout;
pub use coloredout::Terminal;

pub static NO_COLOR: Color = Color::Rgb(255, 255, 255);

pub static VERSION: &'static str = "1.1.4";

pub static LINE_COLOR: Color = Color::Rgb(201, 155, 87);
pub static ADDRESS_COLOR: Color = Color::Rgb(133, 80, 179);
pub static MNEMONIC_COLOR: Color = Color::Rgb(201, 87, 87);
pub static VARIABLE_COLOR: Color = Color::Rgb(255, 147, 147);
pub static TYPE_COLOR: Color = Color::Rgb(129, 181, 154);

pub fn run(config: &CLIConfig) -> Result<(), Box<dyn Error>> {
    let no_color = ColorSpec::new();

    let mut term = Terminal::new(no_color);

    term.writeln(&format!("kDump version {}", VERSION))?;

    let filename = config.file_path.to_string();
    let raw_contents = fs::read(filename)?;

    let file_type = determine_file_type(&raw_contents)?;

    match file_type {
        FileType::KSM => {
            let mut ksm_reader = KSMFileReader::new(raw_contents)?;

            let ksm_file = KSMFile::read(&mut ksm_reader)?;

            ksm_file.dump(&config)?;

            Ok(())
        }
        FileType::KO => {
            return Err("KerbalObject file dumping has not yet been implemented.".into());
        }
        FileType::UNKNOWN => {
            return Err("File type not recognized.".into());
        }
    }
}

pub struct CLIConfig {
    pub file_path: String,
    pub disassemble: bool,
    pub disassemble_symbol: bool,
    pub disassemble_symbol_value: String,
    pub file_headers: bool,
    pub argument_section: bool,
    pub line_numbers: bool,
    pub section_headers: bool,
    pub full_contents: bool,
    pub stabs: bool,
    pub syms: bool,
    pub all_headers: bool,
    pub info: bool,
    pub demangle: bool,
    pub show_no_raw_insn: bool,
    pub show_no_labels: bool,
}

impl CLIConfig {
    pub fn new(matches: ArgMatches) -> CLIConfig {
        CLIConfig {
            file_path: String::from(matches.value_of("INPUT").unwrap()),
            disassemble: matches.is_present("disassemble"),
            disassemble_symbol: matches.is_present("disassemble_symbol"),
            disassemble_symbol_value: if matches.is_present("disassemble_symbol") {
                String::from(matches.value_of("disassemble_symbol").unwrap())
            } else {
                String::new()
            },
            file_headers: matches.is_present("file_headers"),
            argument_section: matches.is_present("argument_section"),
            line_numbers: matches.is_present("line_numbers"),
            section_headers: matches.is_present("section_headers"),
            full_contents: matches.is_present("full_contents"),
            stabs: matches.is_present("stabs"),
            syms: matches.is_present("syms"),
            all_headers: matches.is_present("all_headers"),
            info: matches.is_present("info"),
            demangle: matches.is_present("demangle"),
            show_no_raw_insn: matches.is_present("show_no_raw_insn"),
            show_no_labels: matches.is_present("show_no_labels"),
        }
    }
}