begin VM
This commit is contained in:
parent
2894780124
commit
3188361158
2 changed files with 210 additions and 1 deletions
205
src/virtualmachine.rs
Normal file
205
src/virtualmachine.rs
Normal file
|
@ -0,0 +1,205 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
const ASXVERSION: [u8; 3] = [0,1,0];
|
||||
|
||||
enum VMMemory {
|
||||
String(VMMemoryString),
|
||||
Number(VMMemoryNumber),
|
||||
Boolean(VMMemoryBoolean),
|
||||
Null,
|
||||
}
|
||||
|
||||
struct VMMemoryString {
|
||||
value: String,
|
||||
variable_id: u32,
|
||||
}
|
||||
struct VMMemoryNumber {
|
||||
value: i64,
|
||||
variable_id: u32,
|
||||
}
|
||||
struct VMMemoryBoolean {
|
||||
value: bool,
|
||||
variable_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DecompiledFile {
|
||||
name: String,
|
||||
functions: Vec<DecompiledFunction>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct DecompiledFunction {
|
||||
name: String,
|
||||
body: Vec<DecompiledOperation>,
|
||||
var_ids: HashMap<String, u32>,
|
||||
strings: HashMap<u32, String>,
|
||||
functions: HashMap<u32, u32>
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct DecompiledOperation {
|
||||
opcode: u8,
|
||||
arg1: u8,
|
||||
arg2: i64,
|
||||
arg3: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Register {
|
||||
id: u8,
|
||||
pointer: usize
|
||||
}
|
||||
|
||||
pub struct Machine {
|
||||
memory: Vec<VMMemory>,
|
||||
files: Vec<DecompiledFile>,
|
||||
stack: Vec<VMMemory>,
|
||||
registers: Vec<Register>,
|
||||
pc: usize,
|
||||
}
|
||||
|
||||
fn read_be_num(input: &[u8]) -> usize {
|
||||
let mut result: usize = 0;
|
||||
for i in 0..input.len() {
|
||||
result <<= 8;
|
||||
result |= input[i] as usize;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn read_str(input: &[u8]) -> String {
|
||||
let mut result = String::new();
|
||||
for &byte in input {
|
||||
result.push(byte as char);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn read_bin(input: &[u8]) -> String {
|
||||
let mut result = String::new();
|
||||
for &byte in input {
|
||||
result.push_str(&format!("{:08b}", byte));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn bin_to_num(bin: String) -> usize {
|
||||
let mut result: usize = 0;
|
||||
for (i, c) in bin.chars().rev().enumerate() {
|
||||
if c == '1' {
|
||||
result += 1 << i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn bin_to_snum(bin: String) -> i64 {
|
||||
let mut result: i64 = 0;
|
||||
let mut is_negative = false;
|
||||
for (i, c) in bin.chars().rev().enumerate() {
|
||||
if c == '1' {
|
||||
if i == bin.len() - 1 {
|
||||
is_negative = true;
|
||||
} else {
|
||||
result += 1 << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if is_negative {
|
||||
result = -result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
pub fn new() -> Self {
|
||||
let mut registers = Vec::new();
|
||||
for i in 1..17 {
|
||||
registers.push(Register {
|
||||
id: i,
|
||||
pointer: 0,
|
||||
});
|
||||
}
|
||||
return Machine {
|
||||
memory: Vec::new(),
|
||||
files: Vec::new(),
|
||||
stack: Vec::new(),
|
||||
registers: registers,
|
||||
pc: 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn load(&mut self, data: Vec<u8>) {
|
||||
if data[0..3] != *"ASX".as_bytes() {
|
||||
panic!("Invalid ASX file header");
|
||||
}
|
||||
if data[3..6] != ASXVERSION {
|
||||
panic!("Unsupported ASX version");
|
||||
}
|
||||
let filename_len = read_be_num(&data[6..10]);
|
||||
let filename = read_str(&data[10..10 + filename_len]);
|
||||
let mut offset = 10 + filename_len;
|
||||
let func_name_len = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
let func_name = read_str(&data[offset..offset + func_name_len]);
|
||||
offset += func_name_len;
|
||||
let var_id_len = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
let mut var_ids: HashMap<String, u32> = HashMap::new();
|
||||
for _ in 0..var_id_len {
|
||||
let name_len = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
let name = read_str(&data[offset..offset + name_len]);
|
||||
offset += name_len;
|
||||
let var_id = read_be_num(&data[offset..offset + 3]) as u32;
|
||||
offset += 3;
|
||||
var_ids.insert(name, var_id);
|
||||
}
|
||||
let mut strings: HashMap<u32, String> = HashMap::new();
|
||||
let string_count = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
for _ in 0..string_count {
|
||||
let str_id = read_be_num(&data[offset..offset + 3]) as u32;
|
||||
offset += 3;
|
||||
let str_len = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
let str_value = read_str(&data[offset..offset + str_len]);
|
||||
offset += str_len;
|
||||
strings.insert(str_id, str_value);
|
||||
}
|
||||
let mut functions: HashMap<u32, u32> = HashMap::new();
|
||||
let _function_count = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
for _ in 0.._function_count {
|
||||
let func_id = read_be_num(&data[offset..offset + 3]) as u32;
|
||||
offset += 3;
|
||||
let func_pos = read_be_num(&data[offset..offset + 4]) as u32;
|
||||
offset += 4;
|
||||
functions.insert(func_id, func_pos);
|
||||
}
|
||||
let mut body: Vec<DecompiledOperation> = Vec::new();
|
||||
let instr_len: usize = read_be_num(&data[offset..offset + 4]);
|
||||
offset += 4;
|
||||
for _ in 0..instr_len {
|
||||
let op = read_bin(&data[offset..offset + 10]);
|
||||
offset += 10;
|
||||
println!("{}", op);
|
||||
let op_code = bin_to_num(op[0..5].to_string());
|
||||
let arg1 = bin_to_num(op[5..9].to_string());
|
||||
let arg2 = bin_to_snum(op[9..73].to_string());
|
||||
let arg3 = bin_to_num(op[73..77].to_string());
|
||||
body.push(DecompiledOperation {
|
||||
opcode: op_code as u8,
|
||||
arg1: arg1 as u8,
|
||||
arg2: arg2,
|
||||
arg3: arg3 as u8,
|
||||
});
|
||||
}
|
||||
let mut file_functions: Vec<DecompiledFunction> = Vec::new();
|
||||
file_functions.push(DecompiledFunction { name: func_name, body: body, var_ids: var_ids, strings: strings, functions: functions });
|
||||
self.files.push(DecompiledFile {
|
||||
name: filename,
|
||||
functions: file_functions
|
||||
});
|
||||
println!("Decompiled: {:?}", self.files[0]);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue