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