Refactor several opcodes + remove opcode property
This commit is contained in:
		
							
								
								
									
										77
									
								
								src/emu.rs
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								src/emu.rs
									
									
									
									
									
								
							@@ -5,7 +5,6 @@ use std::path::Path;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[derive(Copy, Clone)]
 | 
					#[derive(Copy, Clone)]
 | 
				
			||||||
pub struct Chip8 {
 | 
					pub struct Chip8 {
 | 
				
			||||||
    opcode: u16,
 | 
					 | 
				
			||||||
    i: u16,
 | 
					    i: u16,
 | 
				
			||||||
    pc: u16,
 | 
					    pc: u16,
 | 
				
			||||||
    sp: u8,
 | 
					    sp: u8,
 | 
				
			||||||
@@ -21,7 +20,6 @@ pub struct Chip8 {
 | 
				
			|||||||
impl Default for Chip8 {
 | 
					impl Default for Chip8 {
 | 
				
			||||||
    fn default() -> Self {
 | 
					    fn default() -> Self {
 | 
				
			||||||
        let mut chip8 = Chip8 {
 | 
					        let mut chip8 = Chip8 {
 | 
				
			||||||
            opcode: 0,
 | 
					 | 
				
			||||||
            i: 0,
 | 
					            i: 0,
 | 
				
			||||||
            pc: 0x200, // Progrm counter starts at 0x200
 | 
					            pc: 0x200, // Progrm counter starts at 0x200
 | 
				
			||||||
            sp: 0,
 | 
					            sp: 0,
 | 
				
			||||||
@@ -60,16 +58,16 @@ impl Chip8 {
 | 
				
			|||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn execute_cycle(&mut self) {
 | 
					    pub fn execute_cycle(&mut self) {
 | 
				
			||||||
        self.opcode = self.get_opcode();
 | 
					        let opcode = self.get_opcode();
 | 
				
			||||||
        println!("{:#x}", self.opcode);
 | 
					        // println!("{:#x}", self.opcode);
 | 
				
			||||||
        self.execute_opcode();
 | 
					        self.execute_opcode(opcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.delay.tick();
 | 
					        self.delay.tick();
 | 
				
			||||||
        self.sound.tick();
 | 
					        self.sound.tick();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn load_font_set(&mut self) {
 | 
					    pub fn load_font_set(&mut self) {
 | 
				
			||||||
        self.memory[0..0x50].copy_from_slice(&Self::FONT_SET);
 | 
					        self.memory[0x50..0xA0].copy_from_slice(&Self::FONT_SET);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn load_rom<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
 | 
					    pub fn load_rom<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
 | 
				
			||||||
@@ -98,11 +96,11 @@ impl Chip8 {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn execute_opcode(&mut self) {
 | 
					    fn execute_opcode(&mut self, opcode: u16) {
 | 
				
			||||||
        let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(self.opcode);
 | 
					        let (nib_1, nib_2, nib_3, nib_4) = Self::get_nibs(opcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let nnn: u16 = self.opcode & 0x0FFF;
 | 
					        let nnn: u16 = opcode & 0x0FFF;
 | 
				
			||||||
        let kk: u8 = (self.opcode & 0x00FF) as u8;
 | 
					        let kk: u8 = (opcode & 0x00FF) as u8;
 | 
				
			||||||
        let x = nib_2;
 | 
					        let x = nib_2;
 | 
				
			||||||
        let y = nib_3;
 | 
					        let y = nib_3;
 | 
				
			||||||
        let n = nib_4;
 | 
					        let n = nib_4;
 | 
				
			||||||
@@ -114,6 +112,8 @@ impl Chip8 {
 | 
				
			|||||||
            (0x0, 0x0, 0xE, 0x0) => self.cls(),
 | 
					            (0x0, 0x0, 0xE, 0x0) => self.cls(),
 | 
				
			||||||
            // 00EE
 | 
					            // 00EE
 | 
				
			||||||
            (0x0, 0x0, 0xE, 0xE) => self.ret(),
 | 
					            (0x0, 0x0, 0xE, 0xE) => self.ret(),
 | 
				
			||||||
 | 
					            // 0NNN
 | 
				
			||||||
 | 
					            (0x0, _, _, _) => { /* Nothing to see here */ }
 | 
				
			||||||
            // 1NNN
 | 
					            // 1NNN
 | 
				
			||||||
            (0x1, _, _, _) => self.jmp_addr(nnn),
 | 
					            (0x1, _, _, _) => self.jmp_addr(nnn),
 | 
				
			||||||
            // 2NNN
 | 
					            // 2NNN
 | 
				
			||||||
@@ -179,7 +179,7 @@ impl Chip8 {
 | 
				
			|||||||
            // Fx65
 | 
					            // Fx65
 | 
				
			||||||
            (0xF, _, 0x6, 0x5) => self.load_into_vx_from_i(x),
 | 
					            (0xF, _, 0x6, 0x5) => self.load_into_vx_from_i(x),
 | 
				
			||||||
            // Otherwise...
 | 
					            // Otherwise...
 | 
				
			||||||
            _ => panic!("UNIMPLEMENTED OPCODE: {:#x}", self.opcode),
 | 
					            _ => panic!("UNIMPLEMENTED OPCODE: {:#x}", opcode),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -197,7 +197,7 @@ impl Chip8 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn jmp_addr(&mut self, nnn: u16) {
 | 
					    fn jmp_addr(&mut self, nnn: u16) {
 | 
				
			||||||
        // sets the program counter to addr (nnn)
 | 
					        // sets the program counter to addr (nnn)
 | 
				
			||||||
        self.pc = nnn;
 | 
					        self.pc = nnn - 2; // We want to execute nnn so decrement pc by 2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn call_addr(&mut self, nnn: u16) {
 | 
					    fn call_addr(&mut self, nnn: u16) {
 | 
				
			||||||
@@ -205,7 +205,7 @@ impl Chip8 {
 | 
				
			|||||||
        // pc is then set to addr
 | 
					        // pc is then set to addr
 | 
				
			||||||
        self.sp += 1;
 | 
					        self.sp += 1;
 | 
				
			||||||
        self.stack[self.sp as usize] = self.pc;
 | 
					        self.stack[self.sp as usize] = self.pc;
 | 
				
			||||||
        self.pc = nnn;
 | 
					        self.pc = nnn - 2; // see Chip8#jmp_addr()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn se_vx_byte(&mut self, x: u8, kk: u8) {
 | 
					    fn se_vx_byte(&mut self, x: u8, kk: u8) {
 | 
				
			||||||
@@ -236,6 +236,7 @@ impl Chip8 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn add_vx_byte(&mut self, x: u8, kk: u8) {
 | 
					    fn add_vx_byte(&mut self, x: u8, kk: u8) {
 | 
				
			||||||
        // calculate Vx + kk, then store it in Vx
 | 
					        // calculate Vx + kk, then store it in Vx
 | 
				
			||||||
 | 
					        // This does indeed overflow without setting VF
 | 
				
			||||||
        self.v[x as usize] = self.v[x as usize].wrapping_add(kk);
 | 
					        self.v[x as usize] = self.v[x as usize].wrapping_add(kk);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -265,22 +266,19 @@ impl Chip8 {
 | 
				
			|||||||
        // only the lowest 8 bits of result are stored in Vx
 | 
					        // only the lowest 8 bits of result are stored in Vx
 | 
				
			||||||
        let x = x as usize;
 | 
					        let x = x as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (res, did_overflow) = self.v[x].overflowing_add(self.v[y as usize]);
 | 
					        let (sum, did_overflow) = self.v[x].overflowing_add(self.v[y as usize]);
 | 
				
			||||||
 | 
					        self.v[x] = sum;
 | 
				
			||||||
        self.v[0xF] = if did_overflow { 1 } else { 0 };
 | 
					        self.v[0xF] = if did_overflow { 1 } else { 0 };
 | 
				
			||||||
        self.v[x] = res;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn sub_vx_vy(&mut self, x: u8, y: u8) {
 | 
					    fn sub_vx_vy(&mut self, x: u8, y: u8) {
 | 
				
			||||||
        // TODO: Confirm that the default behaviour
 | 
					 | 
				
			||||||
        // for this opcode includes a wrapping subtraction
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // subtract Vx and Vy, if Vx > Vy VF is set to 1, otherwise 0
 | 
					        // subtract Vx and Vy, if Vx > Vy VF is set to 1, otherwise 0
 | 
				
			||||||
        // then set Vx to Vx - Vy
 | 
					        // then set Vx to Vx - Vy
 | 
				
			||||||
        let vx = self.v[x as usize];
 | 
					        let x = x as usize;
 | 
				
			||||||
        let vy = self.v[y as usize];
 | 
					        let y = y as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.v[0xF] = if vx > vy { 1 } else { 0 };
 | 
					        self.v[0xF] = if self.v[x] > self.v[y] { 1 } else { 0 };
 | 
				
			||||||
        self.v[x as usize] = vx.wrapping_sub(vy);
 | 
					        self.v[x] = self.v[x].wrapping_sub(self.v[y]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn shr(&mut self, x: u8) {
 | 
					    fn shr(&mut self, x: u8) {
 | 
				
			||||||
@@ -288,18 +286,18 @@ impl Chip8 {
 | 
				
			|||||||
        // then shift Vx one to the right
 | 
					        // then shift Vx one to the right
 | 
				
			||||||
        let x = x as usize;
 | 
					        let x = x as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.v[0xF] = if (self.v[x] & 1) == 1 { 1 } else { 0 };
 | 
					        self.v[0xF] = if (self.v[x] & 0x01) == 0x01 { 1 } else { 0 };
 | 
				
			||||||
        self.v[x] >>= 1;
 | 
					        self.v[x] >>= 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn subn_vx_vy(&mut self, x: u8, y: u8) {
 | 
					    fn subn_vx_vy(&mut self, x: u8, y: u8) {
 | 
				
			||||||
        // subtract Vy and Vx, if Vy > Vx VF is set to 1, otherwise 0
 | 
					        // subtract Vy and Vx, if Vy > Vx VF is set to 1, otherwise 0
 | 
				
			||||||
        // then set Vx = Vy - Vx
 | 
					        // then set Vx = Vy - Vx
 | 
				
			||||||
        let vx = self.v[x as usize];
 | 
					        let x = x as usize;
 | 
				
			||||||
        let vy = self.v[y as usize];
 | 
					        let y = y as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.v[0xF] = if vy > vx { 1 } else { 0 };
 | 
					        self.v[0xF] = if self.v[y] > self.v[x] { 1 } else { 0 };
 | 
				
			||||||
        self.v[x as usize] = vy.wrapping_sub(vx);
 | 
					        self.v[x as usize] = self.v[y].wrapping_sub(self.v[x]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn shl(&mut self, x: u8) {
 | 
					    fn shl(&mut self, x: u8) {
 | 
				
			||||||
@@ -325,7 +323,7 @@ impl Chip8 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn jmp_addr_with_offset(&mut self, nnn: u16) {
 | 
					    fn jmp_addr_with_offset(&mut self, nnn: u16) {
 | 
				
			||||||
        // set program counter to addr + V0
 | 
					        // set program counter to addr + V0
 | 
				
			||||||
        self.pc = nnn + self.v[0] as u16;
 | 
					        self.pc = nnn + self.v[0] as u16 - 2; // see Chip8#jmp_addr
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn rand(&mut self, x: u8, kk: u8) {
 | 
					    fn rand(&mut self, x: u8, kk: u8) {
 | 
				
			||||||
@@ -347,7 +345,6 @@ impl Chip8 {
 | 
				
			|||||||
    fn skip_on_press(&mut self, x: u8) {
 | 
					    fn skip_on_press(&mut self, x: u8) {
 | 
				
			||||||
        // if current key is the same as the on in Vx
 | 
					        // if current key is the same as the on in Vx
 | 
				
			||||||
        // program counter is increased by 2
 | 
					        // program counter is increased by 2
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.key.is_pressed(self.v[x as usize]) {
 | 
					        if self.key.is_pressed(self.v[x as usize]) {
 | 
				
			||||||
            self.pc += 2;
 | 
					            self.pc += 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -356,7 +353,6 @@ impl Chip8 {
 | 
				
			|||||||
    fn skip_not_pressed(&mut self, x: u8) {
 | 
					    fn skip_not_pressed(&mut self, x: u8) {
 | 
				
			||||||
        // if current key is not the sameas the one in Vx
 | 
					        // if current key is not the sameas the one in Vx
 | 
				
			||||||
        // increment the program counter by 2
 | 
					        // increment the program counter by 2
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if !self.key.is_pressed(self.v[x as usize]) {
 | 
					        if !self.key.is_pressed(self.v[x as usize]) {
 | 
				
			||||||
            self.pc += 2;
 | 
					            self.pc += 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -389,12 +385,16 @@ impl Chip8 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn add_vx_to_i(&mut self, x: u8) {
 | 
					    fn add_vx_to_i(&mut self, x: u8) {
 | 
				
			||||||
        // set I to be I + Vx
 | 
					        // set I to be I + Vx
 | 
				
			||||||
        self.i += self.v[x as usize] as u16;
 | 
					        // Althought not standard, we check for overflow as well here
 | 
				
			||||||
 | 
					        // Memory is 4KB (12-bits) so anything mor than that "overflows"
 | 
				
			||||||
 | 
					        let sum = self.i + self.v[x as usize] as u16;
 | 
				
			||||||
 | 
					        self.v[0xF] = if sum > 0x0FFF { 1 } else { 0 };
 | 
				
			||||||
 | 
					        self.i = sum & 0x0FFF;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn set_i_to_hex_sprite_loc(&mut self, x: u8) {
 | 
					    fn set_i_to_hex_sprite_loc(&mut self, x: u8) {
 | 
				
			||||||
        // set I to location of hex sprite related to Vx
 | 
					        // set I to location of hex sprite related to Vx
 | 
				
			||||||
        self.i = self.v[x as usize] as u16 * 5;
 | 
					        self.i = 0x50 + (5 * self.v[x as usize] as u16);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn copy_digits_to_i(&mut self, x: u8) {
 | 
					    fn copy_digits_to_i(&mut self, x: u8) {
 | 
				
			||||||
@@ -402,11 +402,11 @@ impl Chip8 {
 | 
				
			|||||||
        // take tens digit and place it at I + 1
 | 
					        // take tens digit and place it at I + 1
 | 
				
			||||||
        // take ones digit and place it at I + 2
 | 
					        // take ones digit and place it at I + 2
 | 
				
			||||||
        let i = self.i as usize;
 | 
					        let i = self.i as usize;
 | 
				
			||||||
        let mut iter = Self::digits(self.v[x as usize] as usize);
 | 
					        let mut digit = Self::digits(self.v[x as usize] as usize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let ones = iter.next().unwrap(); // Ther has to at least be a ones lol
 | 
					        let ones = digit.next().unwrap(); // Ther has to at least be a ones lol
 | 
				
			||||||
        let tens = iter.next().unwrap_or(0);
 | 
					        let tens = digit.next().unwrap_or(0);
 | 
				
			||||||
        let hundreds = iter.next().unwrap_or(0);
 | 
					        let hundreds = digit.next().unwrap_or(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.memory[i] = hundreds as u8;
 | 
					        self.memory[i] = hundreds as u8;
 | 
				
			||||||
        self.memory[i + 1] = tens as u8;
 | 
					        self.memory[i + 1] = tens as u8;
 | 
				
			||||||
@@ -415,7 +415,6 @@ impl Chip8 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn copy_from_vx_to_memory(&mut self, x: u8) {
 | 
					    fn copy_from_vx_to_memory(&mut self, x: u8) {
 | 
				
			||||||
        // copy values v0 -> Vx to memory starting at i
 | 
					        // copy values v0 -> Vx to memory starting at i
 | 
				
			||||||
 | 
					 | 
				
			||||||
        for n in 0..=(x as usize) {
 | 
					        for n in 0..=(x as usize) {
 | 
				
			||||||
            self.memory[self.i as usize + n] = self.v[n];
 | 
					            self.memory[self.i as usize + n] = self.v[n];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -423,9 +422,7 @@ impl Chip8 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn load_into_vx_from_i(&mut self, x: u8) {
 | 
					    fn load_into_vx_from_i(&mut self, x: u8) {
 | 
				
			||||||
        // read what will be values of v0 -> vx from memory starting at i
 | 
					        // read what will be values of v0 -> vx from memory starting at i
 | 
				
			||||||
        let x = x as usize;
 | 
					        for n in 0..=(x as usize) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        for n in 0..=x {
 | 
					 | 
				
			||||||
            self.v[n] = self.memory[self.i as usize + n];
 | 
					            self.v[n] = self.memory[self.i as usize + n];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user