Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Initial commit and basic project files

  • Loading branch information...
sphinxc0re committed Dec 7, 2016
1 parent 64587f8 commit f419a84988830316fcf949e4263cab2f77b2a5f4
Showing with 250 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +99 −0 Cargo.lock
  3. +7 −0 Cargo.toml
  4. +8 −0 src/instruction.rs
  5. +22 −0 src/main.rs
  6. +48 −0 src/program.rs
  7. +65 −0 src/vm.rs
@@ -0,0 +1 @@
target

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,7 @@
[package]
name = "bakervm"
version = "0.1.0"
authors = ["Julian Laubstein <contact@julianlaubstein.de>"]

[dependencies]
clap = "2.19.1"
@@ -0,0 +1,8 @@
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Instruction {
HALT,
IADD,
ISUB,
PRINT,
PUSH(i64),
}
@@ -0,0 +1,22 @@
extern crate clap;

mod vm;
mod program;
mod instruction;

use clap::{Arg, App};

fn main() {
let matches = App::new("bakerVM")
.version("0.0.1")
.author("Julian Laubstein <contact@julianlaubstein.de>")
.about("A virtual machine for classic point-and-click adventure games")
.arg(Arg::with_name("input")
.index(1)
.help("Sets the input file to use"))
.arg(Arg::with_name("verbose")
.short("v")
.multiple(true)
.help("Sets the level of verbosity"))
.get_matches();
}
@@ -0,0 +1,48 @@
use instruction::Instruction;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

pub type Program = Vec<Instruction>;

pub fn decode<P: AsRef<Path>>(path: P) -> Program {
let mut f = File::open(path).unwrap();
let mut s = String::new();
f.read_to_string(&mut s).unwrap();

let mut program = Program::new();

let mut byte_iter = s.bytes();
let mut byte = byte_iter.next();
while byte != None {
let res = match byte {
Some(byte) => {
match byte {
1 => Instruction::HALT,
2 => Instruction::IADD,
3 => Instruction::ISUB,
4 => Instruction::PRINT,
5 => {
let mut res: i64 = byte_iter.next().unwrap() as i64;
res << 8;
res = res & byte_iter.next().unwrap() as i64;
res << 8;
res = res & byte_iter.next().unwrap() as i64;
res << 8;
res = res & byte_iter.next().unwrap() as i64;

Instruction::PUSH(res)
}
_ => panic!("Unexpected opcode"),
}
}
None => panic!("Unexpected end of file"),
};

program.push(res);

byte = byte_iter.next();
}

program
}
@@ -0,0 +1,65 @@
use instruction::Instruction;
use program::Program;

pub struct VM {
ip: usize,
sp: i64,
code: Program,
globals: Vec<i64>,
stack: Vec<i64>,
}

impl VM {
pub fn new(code: Program, startip: usize) -> VM {
VM {
ip: startip,
sp: -1,
code: code,
globals: Vec::new(),
stack: Vec::new(),
}
}

pub fn exec(&mut self) {
let mut bytecode = self.code[self.ip].clone();
while (bytecode != Instruction::HALT) && self.ip < self.code.len() {
self.ip += 1;
match bytecode {
Instruction::PUSH(num) => self.push(num),
Instruction::IADD => self.iadd(),
Instruction::ISUB => self.isub(),
Instruction::PRINT => self.print(),
_ => panic!("Unknown instruction: {:#?}", bytecode),
}
bytecode = self.code[self.ip].clone();
}
}

fn push(&mut self, value: i64) {
self.stack.push(value);
self.sp += 1;
}

fn pop(&mut self) -> i64 {
assert!(self.sp >= 0, "Unable to pop value off an empty Stack");
let res = self.stack.remove(self.sp as usize);
self.sp -= 1;
res
}

fn iadd(&mut self) {
let b = self.pop();
let a = self.pop();
self.push(a + b);
}

fn isub(&mut self) {
let b = self.pop();
let a = self.pop();
self.push(a - b);
}

fn print(&mut self) {
println!("{:?}", self.stack[self.sp as usize]);
}
}

0 comments on commit f419a84

Please sign in to comment.
You can’t perform that action at this time.