Skip to main content

System

Trait System 

Source
pub trait System {
    const ID: &'static str;
    const MEM_PAGES: u8;

    // Provided methods
    fn pre_cycle(&mut self, vm: &mut VM) -> Result<()> { ... }
    fn post_cycle(&mut self, vm: &mut VM) -> Result<()> { ... }
    fn prepare(&mut self, vm: &mut VM) -> Result<()> { ... }
    fn finish(&mut self, vm: &mut VM) -> Result<()> { ... }
    fn system_call(&mut self, vm: &mut VM, signal: u16) -> Result<()> { ... }
}
Expand description

An interface to communicate with the VM

§Example

If you wanted to implement a text based system you could write something like this:

extern crate melon;

use melon::typedef::*;
use melon::{System, VM};
use std::sync::mpsc::Receiver;


pub const MAX_CHARACTERS_PER_LINE: usize = 100;

pub struct TextSystem {
    current_output_line: String,
    current_input_line: String,
    recv: Receiver<u8>,
}


impl TextSystem {
    /// The receiver allows you to safely inject characters from another thread
    pub fn new(recv: Receiver<u8>) -> TextSystem {
        TextSystem {
            current_output_line: Default::default(),
            current_input_line: Default::default(),
            recv: recv,
        }
    }
}

impl System for TextSystem {
    const ID: &'static str = "com.example.text-system";

    const MEM_PAGES: u8 = 1;

    fn system_call(&mut self, vm: &mut VM, signal: u16) -> Result<()> {
        match signal {
            // This is pretty much like `write_line`
            1 => {
                // Read the memory of the vm until you reach the terminal `0x00` but only to a
                // maximum of 100 characters
                let line = vm.mem
                    .iter()
                    .take(MAX_CHARACTERS_PER_LINE)
                    .map(|x| *x)
                    .take_while(|x| x != &0_u8)
                    .collect::<Vec<u8>>();

                self.current_output_line = String::from_utf8(line)?;

                println!("{}", self.current_output_line);
            }
            // This is pretty much like `read_line`
            2 => {
                // Receive single characters until you reach the terminal `0x00` but only to a
                // maximum of 100 characters
                let mut line = self.recv
                    .iter()
                    .take(MAX_CHARACTERS_PER_LINE)
                    .take_while(|x| x != &0_u8)
                    .collect::<Vec<u8>>();

                line.push(0); // Push terminal `0x00`

                self.current_input_line = String::from_utf8(line.clone())?;

                // Copy characters to vm memory
                for i in 0..line.len() {
                    let vm_index = (MAX_CHARACTERS_PER_LINE + 1) + i;
                    vm.mem[vm_index] = line[i];
                }
            }
            _ => unreachable!(),
        }

        Ok(())
    }
}

Following the basic principles in this example, you are able to build any retro style computing system you want.

Required Associated Constants§

Source

const ID: &'static str

A unique ID to identify the System

Source

const MEM_PAGES: u8

The minimum number of memory pages required for this system

Provided Methods§

Source

fn pre_cycle(&mut self, vm: &mut VM) -> Result<()>

Hook into the state before each cycle

Source

fn post_cycle(&mut self, vm: &mut VM) -> Result<()>

Hook into the state after each cycle

Source

fn prepare(&mut self, vm: &mut VM) -> Result<()>

Prepare the state of the VM

Source

fn finish(&mut self, vm: &mut VM) -> Result<()>

Make finalizing manipulations to the state before the VM’s shutdown

Source

fn system_call(&mut self, vm: &mut VM, signal: u16) -> Result<()>

React to the SysCall instruction and process the given signal

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§