1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use *;
use VM;
/// 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>,
/// }
///
/// # fn main() {}
///
/// 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 = "__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.
///