ch8_isa/data/draw_data.rs
1/*
2 * draw_data.rs
3 * Defines a struct that holds data for the DRAW instruction
4 * Created on 12/6/2019
5 * Created by Andrew Davis
6 *
7 * Copyright (C) 2019 Andrew Davis
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23//usage statements
24use super::Register;
25use super::super::codegen::CodeGen;
26
27/// Contextual data for the `DRAW` instruction
28pub struct DrawData {
29 /// The register that contains the x-coordinate of the sprite
30 vx: Register,
31
32 /// The register that contains the y-coordinate of the sprite
33 vy: Register,
34
35 /// The height of the sprite
36 h: u8
37}
38
39//implementation
40impl DrawData {
41 /// Constructs a new `DrawData` instance
42 ///
43 /// # Arguments
44 ///
45 /// * `new_vx` - The register containing the x-coordinate
46 /// * `new_vy` - The register containing the y-coordinate
47 /// * `new_h` - The height of the sprite to draw
48 ///
49 /// # Panics
50 ///
51 /// This method will panic if `new_vx` or `new_vy` refers to
52 /// the `I` register.
53 ///
54 /// # Returns
55 ///
56 /// A new `DrawData` instance with the given properties
57 pub fn new(new_vx: Register, new_vy: Register, new_h: u8)
58 -> DrawData {
59 //validate the registers
60 if (new_vx == Register::I) || (new_vy == Register::I) {
61 panic!("Cannot use index register as coordinates");
62 }
63
64 //mask the height
65 let new_h = new_h & 0x0F;
66
67 //and return the instance
68 return DrawData {
69 vx: new_vx,
70 vy: new_vy,
71 h: new_h
72 }
73 }
74}
75
76//CodeGen implementation
77impl CodeGen for DrawData {
78 /// Generates an opcode for the `DRAW` instruction
79 ///
80 /// # Returns
81 ///
82 /// The opcode generated from the data
83 fn gen_opcode(&self) -> u16 {
84 let mut code = 0xD000;
85 code |= (self.vx.to_id() as u16) << 8;
86 code |= (self.vy.to_id() as u16) << 4;
87 code |= self.h as u16;
88 return code;
89 }
90}
91
92//unit tests
93#[cfg(test)]
94mod tests {
95 //import the DrawData struct
96 use super::*;
97
98 //this test checks that the I register cannot be used as coordinates
99 #[test]
100 #[should_panic]
101 fn test_index_cannot_be_used_as_coordinate() {
102 let _b1 = DrawData::new(Register::I, Register::V0, 0xF);
103 let _b2 = DrawData::new(Register::V0, Register::I, 0xF);
104 }
105
106 //this test checks that the height field is masked
107 #[test]
108 fn test_height_is_masked() {
109 let drawd = DrawData::new(Register::V1, Register::V2, 0xFB);
110 assert_eq!(drawd.h, 0xB);
111 }
112
113 //this test checks opcode generation
114 #[test]
115 fn test_opcode_gen() {
116 let drawd = DrawData::new(Register::V1, Register::V2, 0x5);
117 assert_eq!(drawd.gen_opcode(), 0xD125);
118 }
119}
120
121//end of file