~maddie/STT-implementation

ref: 0bfb3b7427952b9de9d495ea23a3f630ac1cf889 STT-implementation/src/lib.rs -rw-r--r-- 4.5 KiB
0bfb3b74 — kn0000 fix a stupid 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
}