pub(crate) fn drw_vx_vy_nibble(&mut self, optcode: u16) {
        debug!("DRWNibble => {:#X}", optcode);
        let (_x, _y) = vx_vy!(optcode);
        let _vx = self.v[_x];
        let _vy = self.v[_y];
        let n = optcode & 0x000F;
        self.v[0xF] &= 0;
        for y in 0..n as u8 {
            let pixel = self.memory[self.i + y as usize];
            for x in 0..8 as u8 {
                if pixel & (0x80 >> x) >= 1 {
                    let address =
                        (add!(x, _vx) as u32 % SCREEN_WIDTH) as usize +
                        (add!(y, _vy) as u32 % SCREEN_HEIGHT) as usize *
                        SCREEN_WIDTH as usize;
                    
                    if address >= self.display.len() {
                        error!("address({}) hits display outbounds({})", address, self.display.len() - 1);
                        error!("x:{} _x:{} x+_x:{}", x, _vx, add!(x, _vx));
                        error!("y:{} _y:{} y+_y:{}", y, _vy, add!(y, _vy));
                        error!("x+y*screen_width:{}", add!(x, _vx) as usize + add!(y, _vy) as usize * SCREEN_WIDTH as usize);                        
                        self.quit = true;
                        return;
                    }
                    self.v[0xF] |= self.display[address];
                    self.display[address] ^= 1;
                }
            }
        }
        self.display_redraw = true;
        self.pc += 2;
    }
/// Dxyn - DRW Vx, Vy, nibble
/// Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
/// The interpreter reads n bytes from memory, starting at the address stored in I. These bytes are then displayed as sprites on screen at coordinates (Vx, Vy).
/// Sprites are XORed onto the existing screen. If this causes any pixels to be erased, VF is set to 1, otherwise it is set to 0. If the sprite is positioned so
/// part of it is outside the coordinates of the display, it wraps around to the opposite side of the screen. See instruction 8xy3 for more information on XOR,
/// and section 2.4, Display, for more information on the Chip-8 screen and sprites.
DRW Vx, Vy, nibble
Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
The interpreter reads n bytes from memory, starting at the address stored in I. These bytes are then displayed as sprites on screen at coordinates (Vx, Vy).
Sprites are XORed onto the existing screen. If this causes any pixels to be erased, VF is set to 1, otherwise it is set to 0. If the sprite is positioned so
part of it is outside the coordinates of the display, it wraps around to the opposite side of the screen. See instruction 8xy3 for more information on XOR,
and section 2.4, Display, for more information on the Chip-8 screen and sprites.
DRW Vx Vy nibble Display n - byte sprite starting at memory location I at ( Vx Vy ) set VF = collision . The interpreter reads n bytes from memory starting at the address stored in I . These bytes are then displayed as sprites on screen at coordinates ( Vx Vy ) . Sprites are XORed onto the existing screen . If this causes any pixels to be erased VF is set to 1 otherwise it is set to 0 . If the sprite is positioned so part of it is outside the coordinates of the display it wraps around to the opposite side of the screen . See instruction 8xy3 for more information on XOR and section 2 . 4 Display for more information on the Chip - 8 screen and sprites .
pub(crate) fn drw_vx_vy_nibble(&mut self, optcode: u16) {
        debug!("DRWNibble => {:#X}", optcode);
        let (_x, _y) = vx_vy!(optcode);
        let _vx = self.v[_x];
        let _vy = self.v[_y];
        let n = optcode & 0x000F;
        self.v[0xF] &= 0;
        for y in 0..n as u8 {
            let pixel = self.memory[self.i + y as usize];
            for x in 0..8 as u8 {
                if pixel & (0x80 >> x) >= 1 {
                    let address =
                        (add!(x, _vx) as u32 % SCREEN_WIDTH) as usize +
                        (add!(y, _vy) as u32 % SCREEN_HEIGHT) as usize *
                        SCREEN_WIDTH as usize;
                    if address >= self.display.len() {
                        error!("address({}) hits display outbounds({})", address, self.display.len() - 1);
                        error!("x:{} _x:{} x+_x:{}", x, _vx, add!(x, _vx));
                        error!("y:{} _y:{} y+_y:{}", y, _vy, add!(y, _vy));
                        error!("x+y*screen_width:{}", add!(x, _vx) as usize + add!(y, _vy) as usize * SCREEN_WIDTH as usize);                        
                        self.quit = true;
                        return;
                    }
                    self.v[0xF] |= self.display[address];
                    self.display[address] ^= 1;
                }
            }
        }
        self.display_redraw = true;
        self.pc += 2;
    }
pub ( crate ) fn drw_vx_vy_nibble ( & mut self , optcode : u16 ) { debug ! ( " " optcode ) ; let ( _x , _y ) = vx_vy ! ( optcode ) ; let _vx = self . v [ _x ] ; let _vy = self . v [ _y ] ; let n = optcode & 0x000F ; self . v [ 0xF ] &= 0 ; for y in 0 .. n as u8 { let pixel = self . memory [ self . i + y as usize ] ; for x in 0 .. 8 as u8 { if pixel & ( 0x80 >> x ) >= 1 { let address = ( add ! ( x _vx ) as u32 % SCREEN_WIDTH ) as usize + ( add ! ( y _vy ) as u32 % SCREEN_HEIGHT ) as usize * SCREEN_WIDTH as usize ; if address >= self . display . len ( ) { error ! ( " " address self display len ( ) 1 ) ; error ! ( " " x _vx add ( x _vx ) ) ; error ! ( " " y _vy add ( y _vy ) ) ; error ! ( " " add ( x _vx ) as usize add ( y _vy ) as usize SCREEN_WIDTH as usize ) ; self . quit = true ; return ; } self . v [ 0xF ] |= self . display [ address ] ; self . display [ address ] ^= 1 ; } } } self . display_redraw = true ; self . pc += 2 ; }
Dxyn - DRW Vx, Vy, nibble
Display n-byte sprite starting at memory location I at (Vx, Vy), set VF = collision.
Dxyn - DRW Vx Vy nibble Display n - byte sprite starting at memory location I at ( Vx Vy ) set VF = collision .
&mut self
optcode
u16
&mut self
optcode
u16