Crate kerbalobjects
source ·Expand description
KerbalObjects
The kerbalobjects
crate provides an interface for creating object files for
Kerbal Operating System (kOS), It supports reading and writing
Kerbal Object files, and Kerbal Machine Code (kOS executable) files.
Documentation for both file formats can be found here:
- For Kerbal Object files.
- For Kerbal Machine code files.
Kerbal Object files are used by the Kerbal Assembler and Kerbal Linker toolchain, and eventually are linked into Kerbal Machine Code files, which are loadable and executable by kOS.
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.");
Re-exports
pub use errors::*;
Modules
- Generic errors while reading KSM or KO files
- Kerbal Object files
- Kerbal Machine Code files
Structs
- A struct to iterate over the bytes of a buffer, and keep track of the current position for better error messages
Enums
- The type of an internal value within Kerbal Operating System.
- An internal value within Kerbal Operating System.
- The opcode of a kOS machine code instruction.
Traits
- Allows a type to be converted from bytes from a BufferIterator to itself.
- Allows a type to be converted to bytes and appended to a WriteableBuffer
- Allows a type to allow a Kerbal Machine Code or Kerbal Object file to be written into it