51 stable releases
4.0.3 | Jun 21, 2023 |
---|---|
4.0.2 | Nov 11, 2022 |
4.0.1 | Oct 27, 2022 |
3.1.13 | Dec 5, 2021 |
1.0.4 | Nov 17, 2020 |
#546 in Parser implementations
196 downloads per month
Used in 3 crates
335KB
4K
SLoC
KerbalObjects
A Rust crate that allows anyone to read or write a Kerbal Machine Code file or Kerbal Object file.
[dependencies]
kerbalobjects = "4.0"
Examples
Example for Kerbal Machine Code hello world program
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
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 for information on how to use this library.
Documentation on kOS instructions and what they do.
Support
Besides the documentation, support can be found by the library author in this Discord server.
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 and KO file formats and how to create or read them.
Dependencies
~0.5–1MB
~22K SLoC