~maddie/STT-implementation

ref: 9303aa07fb512637391518873f206ef142ecca29 STT-implementation/src/lib.rs -rw-r--r-- 4.5 KiB
9303aa07 — kn0000 Rewrote lib.rs to fix numerous mistakes and tidy up with constants 6 months ago
                                                                                
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
const STACK_SIZE: usize = 1024;
pub const MEMORY_SIZE: usize = 1<<20;
pub const SCREEN_WIDTH: usize = 512;
pub const SCREEN_HEIGHT: usize = 512;
pub const SCREEN_UPDATE_ADDRESS: usize = 0x7FFFF

#[derive(Debug)]
pub struct Stack {
    buffer: [u16;STACK_SIZE],
    index: usize
}

impl Stack {
    fn push(&mut self, value: u16) {
        self.buffer[self.index] = value;
        self.index = (self.index + 1) % STACK_SIZE;
    }

    fn pop(&mut self) -> u16 {
        self.index = (self.index + STACK_SIZE - 1) % STACK_SIZE;
        self.buffer[self.index]
    }
}

pub fn new_stack() -> Stack {
    Stack{
        buffer: [0u16;STACK_SIZE],
        index: 0
    }
}

pub struct Processor {
    pub stack_a: Stack,
    pub stack_b: Stack,
    pub memory: [u16;MEMORY_SIZE],
    pub carry: bool,
    pub pc: usize
}

impl Processor {
    pub fn run(&mut self) -> bool {
        let instruction = self.memory[self.pc] & 0x3FF;
        let (mut stack, off_stack)  = {
            if (instruction & 0x200) == 0 {
                (&mut self.stack_a, &mut self.stack_b)
            }
            else {(&mut self.stack_b, &mut self.stack_a)}
        };
        let mut is_jump = false;

        if instruction & 0x100 == 0 { //calculation
            self.carry = calc(&mut stack, instruction, self.carry);
        }
        else if instruction & 0x80 == 0 { //jump
            let push_pc = (instruction & 0x40) != 0;
            let conditional = (instruction & 0x20) != 0;
            if !conditional || self.carry {
                let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                is_jump = true;
                if push_pc {
                    let a = self.pc + 1;
                    let upper = a & 0b11111111110000000000 >> 10;
                    let lower = a & 0b1111111111;
                    stack.push(upper as u16);
                    stack.push(lower as u16);
                }
                self.pc = address;
            }
        }
        else {
            match instruction & 0x7F {
                0 => { //immediate value
                    self.pc += 1;
                    stack.push(self.memory[self.pc] & 0x3FF);
                }
                1 => {
                    let upper = self.pc & 0b11111111110000000000 >> 10;
                    let lower = self.pc & 0b1111111111;
                    stack.push(upper as u16);
                    stack.push(lower as u16);
                }
                2 => { //swap
                    let a = stack.pop();
                    let b = stack.pop();
                    stack.push(a);
                    stack.push(b);
                }
                3 => off_stack.push(stack.pop()), //move between stacks
                4 => { //push from memory
                    let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                    stack.push(self.memory[address]);
                }
                5 => { //pop to memory
                    let address = (stack.pop() as usize) | ((stack.pop() as usize) << 10);
                    self.memory[address] = stack.pop();
                }
                6 => { //dup
                    let a = stack.pop();
                    stack.push(a);
                    stack.push(a);
                }
                7 => { //over
                    let a = stack.pop();
                    let b = stack.pop();
                    stack.push(b);
                    stack.push(a);
                    stack.push(b);
                }
                0x7F => return false,
                _ => ()
            }
        }
        if !is_jump {self.pc += 1};
        true
    }
}

fn calc(stack: &mut Stack, instruction: u16, carry_in: bool) -> bool {
    let operand_a = stack.pop();
    let operand_b = stack.pop();
    let mut carry = carry_in;
    let mut result = 0;
    for i in 0..10 {
        let count = ((operand_a >> i) & 1) + ((operand_b >> i) & 1) + (carry as u16);
        result += ((instruction >> (count+4)) & 1) << i;
        carry = ((instruction >> count) & 1) != 0;
    }
    stack.push(result);
    carry
}

pub fn mem_to_buf(memory: &[u16]) -> [u32;SCREEN_WIDTH*SCREEN_HEIGHT] {
    let mut result = [0u32;SCREEN_WIDTH*SCREEN_HEIGHT];
    let mut i = 0;
    for byte in &memory[(MEMORY_SIZE-SCREEN_WIDTH*SCREEN_HEIGHT)..MEMORY_SIZE] {
        result[i] = (((byte & 0b111000000) as u32) << 15) | (((byte & 0b111000) as u32) << 10) | (((byte & 0b111) as u32) << 5); //shifts 3 bits of each 10 bit value into the rgb channels of the buffer, from the last region of memory
        i += 1;
    }
    result
}