A Rust crate that allows anyone to read or write a Kerbal Machine Code file or Kerbal Object file.
toml
[dependencies]
kerbalobjects = "4.0"
```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 argsection = ArgumentSection::new(); let mut maincode = CodeSection::new(CodeType::Main);
let one = argsection.addchecked(KOSValue::Int16(1));
// Corresponds to the KerbalScript code: // PRINT("Hello, world!").
maincode.add(Instr::OneOp(Opcode::Push, argsection.addchecked(KOSValue::String("@0001".into())))); maincode.add(Instr::TwoOp(Opcode::Bscp, one, argsection.addchecked(KOSValue::Int16(0)))); maincode.add(Instr::ZeroOp(Opcode::Argb)); maincode.add(Instr::OneOp(Opcode::Push, argsection.addchecked(KOSValue::ArgMarker))); maincode.add(Instr::OneOp(Opcode::Push, argsection.addchecked(KOSValue::StringValue("Hello, world!".into())))); maincode.add(Instr::TwoOp(Opcode::Call, argsection.addchecked(KOSValue::String("".into())), argsection.addchecked(KOSValue::String("print()".into())))); maincode.add(Instr::ZeroOp(Opcode::Pop)); maincode.add(Instr::OneOp(Opcode::Escp, one));
let codesections = vec![ CodeSection::new(CodeType::Function), CodeSection::new(CodeType::Initialization), maincode ];
// A completely wrong and useless debug section, but we NEED to have one let mut debugentry = DebugEntry::new(1).withrange(DebugRange::new(0x06, 0x13));
let debugsection = DebugSection::new(debugentry);
let mut filebuffer = Vec::withcapacity(2048);
let ksmfile = KSMFile::newfromparts(argsection, codesections, debugsection);
ksmfile.write(&mut filebuffer);
let mut file = std::fs::File::create("hello.ksm").expect("Couldn't open output file");
file.writeall(filebuffer.as_slice()).expect("Failed to write to output file"); ```
```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 datasection = ko.newdatasection(".data"); let mut start = ko.newfuncsection("start"); let mut symtab = ko.newsymtab(".symtab"); let mut symstrtab = ko.newstrtab(".symstrtab");
// Set up the main code function section let one = datasection.addchecked(KOSValue::Int16(1));
start.add(Instr::TwoOp( Opcode::Bscp, one, datasection.addchecked(KOSValue::Int16(0)), )); start.add(Instr::ZeroOp(Opcode::Argb)); start.add(Instr::OneOp( Opcode::Push, datasection.addchecked(KOSValue::ArgMarker), )); start.add(Instr::OneOp( Opcode::Push, datasection.addchecked(KOSValue::StringValue("Hello, world!".into())), )); start.add(Instr::TwoOp( Opcode::Call, datasection.addchecked(KOSValue::String("".into())), datasection.addchecked(KOSValue::String("print()".into())), )); start.add(Instr::ZeroOp(Opcode::Pop)); start.add(Instr::OneOp(Opcode::Escp, one));
// Set up our symbols let filesymbol = KOSymbol::new( symstrtab.add("test.kasm"), DataIdx::PLACEHOLDER, 0, SymBind::Global, SymType::File, SectionIdx::NULL, ); let startsymbol = KOSymbol::new( symstrtab.add("start"), DataIdx::PLACEHOLDER, start.size() as u16, SymBind::Global, SymType::Func, start.sectionindex(), );
symtab.add(filesymbol); symtab.add(startsymbol);
ko.adddatasection(datasection); ko.addfuncsection(start); ko.addstrtab(symstrtab); ko.addsym_tab(symtab);
// Write the file out to disk let mut filebuffer = Vec::withcapacity(2048);
let ko = ko.validate().expect("Could not update KO headers properly"); ko.write(&mut file_buffer);
let filepath = PathBuf::from("test.ko"); let mut file = std::fs::File::create(filepath).expect("Output file could not be created: test.ko");
file.writeall(filebuffer.as_slice()) .expect("File test.ko could not be written to."); ```
See the kerbalobjects docs.rs for information on how to use this library.
Documentation on kOS instructions and what they do.
Besides the documentation, support can be found by the library author in this Discord server.
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 and KO file formats and how to create or read them.