# KerbalObjects [github](https://github.com/newcomb-luke/kerbalobjects.rs) [github](https://crates.io/crates/kerbalobjects) [github](https://docs.rs/kerbalobjects/latest/kerbalobjects/) [License]() [Crates.io Downloads]() [GitHub Workflow Status]() [Libraries.io dependency status for GitHub repo](https://deps.rs/repo/github/newcomb-luke/kerbalobjects.rs) A Rust crate that allows anyone to read or write a Kerbal Machine Code file or Kerbal Object file. ```toml [dependencies] kerbalobjects = "4.0" ``` ## Examples ### Example for Kerbal Machine Code hello world program ```rust use std::io::Write; use kerbalobjects::ksm::sections::{ArgumentSection, CodeSection, CodeType, DebugEntry, DebugRange, DebugSection}; use kerbalobjects::ksm::{Instr, KSMFile}; use kerbalobjects::{Opcode, KOSValue, ToBytes}; let mut arg_section = ArgumentSection::new(); let mut main_code = CodeSection::new(CodeType::Main); let one = arg_section.add_checked(KOSValue::Int16(1)); // Corresponds to the KerbalScript code: // PRINT("Hello, world!"). main_code.add(Instr::OneOp(Opcode::Push, arg_section.add_checked(KOSValue::String("@0001".into())))); main_code.add(Instr::TwoOp(Opcode::Bscp, one, arg_section.add_checked(KOSValue::Int16(0)))); main_code.add(Instr::ZeroOp(Opcode::Argb)); main_code.add(Instr::OneOp(Opcode::Push, arg_section.add_checked(KOSValue::ArgMarker))); main_code.add(Instr::OneOp(Opcode::Push, arg_section.add_checked(KOSValue::StringValue("Hello, world!".into())))); main_code.add(Instr::TwoOp(Opcode::Call, arg_section.add_checked(KOSValue::String("".into())), arg_section.add_checked(KOSValue::String("print()".into())))); main_code.add(Instr::ZeroOp(Opcode::Pop)); main_code.add(Instr::OneOp(Opcode::Escp, one)); let code_sections = vec![ CodeSection::new(CodeType::Function), CodeSection::new(CodeType::Initialization), main_code ]; // A completely wrong and useless debug section, but we NEED to have one let mut debug_entry = DebugEntry::new(1).with_range(DebugRange::new(0x06, 0x13)); let debug_section = DebugSection::new(debug_entry); let mut file_buffer = Vec::with_capacity(2048); let ksm_file = KSMFile::new_from_parts(arg_section, code_sections, debug_section); ksm_file.write(&mut file_buffer); let mut file = std::fs::File::create("hello.ksm").expect("Couldn't open output file"); file.write_all(file_buffer.as_slice()).expect("Failed to write to output file"); ``` ### Example for Kerbal Object hello world program ```rust use kerbalobjects::ko::symbols::{KOSymbol, SymBind, SymType}; use kerbalobjects::ko::{Instr, KOFile}; use kerbalobjects::{KOSValue, Opcode}; use kerbalobjects::ko::SectionIdx; use kerbalobjects::ko::sections::DataIdx; use std::io::Write; use std::path::PathBuf; let mut ko = KOFile::new(); let mut data_section = ko.new_data_section(".data"); let mut start = ko.new_func_section("_start"); let mut symtab = ko.new_symtab(".symtab"); let mut symstrtab = ko.new_strtab(".symstrtab"); // Set up the main code function section let one = data_section.add_checked(KOSValue::Int16(1)); start.add(Instr::TwoOp( Opcode::Bscp, one, data_section.add_checked(KOSValue::Int16(0)), )); start.add(Instr::ZeroOp(Opcode::Argb)); start.add(Instr::OneOp( Opcode::Push, data_section.add_checked(KOSValue::ArgMarker), )); start.add(Instr::OneOp( Opcode::Push, data_section.add_checked(KOSValue::StringValue("Hello, world!".into())), )); start.add(Instr::TwoOp( Opcode::Call, data_section.add_checked(KOSValue::String("".into())), data_section.add_checked(KOSValue::String("print()".into())), )); start.add(Instr::ZeroOp(Opcode::Pop)); start.add(Instr::OneOp(Opcode::Escp, one)); // Set up our symbols let file_symbol = KOSymbol::new( symstrtab.add("test.kasm"), DataIdx::PLACEHOLDER, 0, SymBind::Global, SymType::File, SectionIdx::NULL, ); let start_symbol = KOSymbol::new( symstrtab.add("_start"), DataIdx::PLACEHOLDER, start.size() as u16, SymBind::Global, SymType::Func, start.section_index(), ); symtab.add(file_symbol); symtab.add(start_symbol); ko.add_data_section(data_section); ko.add_func_section(start); ko.add_str_tab(symstrtab); ko.add_sym_tab(symtab); // Write the file out to disk let mut file_buffer = Vec::with_capacity(2048); let ko = ko.validate().expect("Could not update KO headers properly"); ko.write(&mut file_buffer); let file_path = PathBuf::from("test.ko"); let mut file = std::fs::File::create(file_path).expect("Output file could not be created: test.ko"); file.write_all(file_buffer.as_slice()) .expect("File test.ko could not be written to."); ``` ## Documentation See the kerbalobjects [docs.rs](https://docs.rs/kerbalobjects/latest/kerbalobjects/) for information on how to use this library. Documentation on kOS [instructions](https://github.com/newcomb-luke/kerbalobjects.rs/blob/main/docs/Instruction-docs.md) and what they do. ## Support Besides the documentation, support can be found by the library author in this [Discord server](https://discord.gg/APETM2ceVZ). ## If this doesn't fit your use case If this library doesn't implement a specific feature that your program needs, then please create a new issue or contact the developer. If that cannot be resolved, see docs/ for examples and explanations of the [KSM](https://github.com/newcomb-luke/kerbalobjects.rs/blob/main/docs/KSM-file-format.md) and [KO](https://github.com/newcomb-luke/kerbalobjects.rs/blob/main/docs/KO-file-format.md) file formats and how to create or read them.