Add pixels-rs and winit as dependencies
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,3 @@
 | 
			
		||||
/target
 | 
			
		||||
/games
 | 
			
		||||
/games
 | 
			
		||||
/.vscode
 | 
			
		||||
							
								
								
									
										1431
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1431
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -8,3 +8,6 @@ edition = "2018"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
rand = "0.7.3"
 | 
			
		||||
pixels = "0.0.4"
 | 
			
		||||
winit = "0.22.2"
 | 
			
		||||
winit_input_helper = "0.7.0"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								src/emu.rs
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/emu.rs
									
									
									
									
									
								
							@@ -15,12 +15,12 @@ pub struct Chip8 {
 | 
			
		||||
    memory: [u8; 4096],
 | 
			
		||||
    delay: Timer,
 | 
			
		||||
    sound: Timer,
 | 
			
		||||
    display: Display,
 | 
			
		||||
    pub display: Display,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Chip8 {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Chip8 {
 | 
			
		||||
        let mut chip8 = Chip8 {
 | 
			
		||||
            opcode: 0,
 | 
			
		||||
            i: 0,
 | 
			
		||||
            pc: 0x200, // Progrm counter starts at 0x200
 | 
			
		||||
@@ -32,11 +32,33 @@ impl Default for Chip8 {
 | 
			
		||||
            delay: Default::default(),
 | 
			
		||||
            sound: Default::default(),
 | 
			
		||||
            display: Display::default(),
 | 
			
		||||
        }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        chip8.load_font_set();
 | 
			
		||||
        chip8
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Chip8 {
 | 
			
		||||
    const FONT_SET: [u8; 80] = [
 | 
			
		||||
        0xF0, 0x90, 0x90, 0x90, 0xF0, // 0
 | 
			
		||||
        0x20, 0x60, 0x20, 0x20, 0x70, // 1
 | 
			
		||||
        0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2
 | 
			
		||||
        0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3
 | 
			
		||||
        0x90, 0x90, 0xF0, 0x10, 0x10, // 4
 | 
			
		||||
        0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5
 | 
			
		||||
        0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6
 | 
			
		||||
        0xF0, 0x10, 0x20, 0x40, 0x40, // 7
 | 
			
		||||
        0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8
 | 
			
		||||
        0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9
 | 
			
		||||
        0xF0, 0x90, 0xF0, 0x90, 0x90, // A
 | 
			
		||||
        0xE0, 0x90, 0xE0, 0x90, 0xE0, // B
 | 
			
		||||
        0xF0, 0x80, 0x80, 0x80, 0xF0, // C
 | 
			
		||||
        0xE0, 0x90, 0x90, 0x90, 0xE0, // D
 | 
			
		||||
        0xF0, 0x80, 0xF0, 0x80, 0xF0, // E
 | 
			
		||||
        0xF0, 0x80, 0xF0, 0x80, 0x80, // F
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    pub fn execute_cycle(&mut self) {
 | 
			
		||||
        self.opcode = self.get_opcode();
 | 
			
		||||
        println!("{:#x}", self.opcode);
 | 
			
		||||
@@ -46,6 +68,12 @@ impl Chip8 {
 | 
			
		||||
        self.sound.tick();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn load_font_set(&mut self) {
 | 
			
		||||
        for (i, byte) in Self::FONT_SET.iter().enumerate() {
 | 
			
		||||
            self.memory[i] = *byte;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn load_rom<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
 | 
			
		||||
        let mut file = File::open(path.as_ref())?;
 | 
			
		||||
        let mut rom_buf: Vec<u8> = vec![];
 | 
			
		||||
@@ -157,6 +185,7 @@ impl Chip8 {
 | 
			
		||||
    fn jmp_addr(&mut self, n_1: u16, n_2: u16, n_3: u16) {
 | 
			
		||||
        // sets the program counter to addr (nnn)
 | 
			
		||||
        self.pc = Self::convert_to_addr(n_1, n_2, n_3);
 | 
			
		||||
        println!("{:#x}", self.pc);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ret(&mut self) {
 | 
			
		||||
@@ -203,7 +232,7 @@ impl Chip8 {
 | 
			
		||||
    fn add_vx_byte(&mut self, x: u16, k_1: u16, k_2: u16) {
 | 
			
		||||
        // calculate Vx + kk, then store it in Vx
 | 
			
		||||
        let x = x as usize;
 | 
			
		||||
        self.v[x] = self.v[x] + Self::convert_to_byte(k_1, k_2);
 | 
			
		||||
        self.v[x] = self.v[x].wrapping_add(Self::convert_to_byte(k_1, k_2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ld_vx_vy(&mut self, x: u16, y: u16) {
 | 
			
		||||
@@ -247,7 +276,7 @@ impl Chip8 {
 | 
			
		||||
        let vy = self.v[y as usize];
 | 
			
		||||
 | 
			
		||||
        self.v[0xF as usize] = if vx > vy { 1 } else { 0 };
 | 
			
		||||
        self.v[x as usize] = vx - vy;
 | 
			
		||||
        self.v[x as usize] = vx.wrapping_sub(vy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn shr_vx(&mut self, x: u16) {
 | 
			
		||||
@@ -390,8 +419,9 @@ impl Chip8 {
 | 
			
		||||
        self.i = self.i + self.v[x as usize] as u16;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ld_f_vx(&mut self, _x: u16) {
 | 
			
		||||
        todo!("Implement 0xF_29");
 | 
			
		||||
    fn ld_f_vx(&mut self, x: u16) {
 | 
			
		||||
        // set I to location of hex sprite related to Vx
 | 
			
		||||
        self.i = self.v[x as usize] as u16 * 5;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ld_b_vx(&mut self, x: u16) {
 | 
			
		||||
@@ -399,15 +429,15 @@ impl Chip8 {
 | 
			
		||||
        // take tens digit and place it at I + 1
 | 
			
		||||
        // take ones digit and place it at I + 2
 | 
			
		||||
        let i = self.i as usize;
 | 
			
		||||
        let mut iter = Self::digits(self.v[x as usize]);
 | 
			
		||||
        let mut iter = Self::digits(self.v[x as usize] as usize);
 | 
			
		||||
 | 
			
		||||
        let ones = iter.next().unwrap(); // Ther has to at least be a ones lol
 | 
			
		||||
        let tens = iter.next().unwrap_or(0);
 | 
			
		||||
        let hundreds = iter.next().unwrap_or(0);
 | 
			
		||||
 | 
			
		||||
        self.memory[i] = hundreds;
 | 
			
		||||
        self.memory[i + 1] = tens;
 | 
			
		||||
        self.memory[i + 2] = ones;
 | 
			
		||||
        self.memory[i] = hundreds as u8;
 | 
			
		||||
        self.memory[i + 1] = tens as u8;
 | 
			
		||||
        self.memory[i + 2] = ones as u8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn ld_i_vx(&mut self, x: u16) {
 | 
			
		||||
@@ -436,7 +466,7 @@ impl Chip8 {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // https://stackoverflow.com/questions/41536479/how-do-i-split-an-integer-into-individual-digits
 | 
			
		||||
    fn digits(mut num: u8) -> impl Iterator<Item = u8> {
 | 
			
		||||
    fn digits(mut num: usize) -> impl Iterator<Item = usize> {
 | 
			
		||||
        let mut divisor = 1;
 | 
			
		||||
        while num >= divisor * 10 {
 | 
			
		||||
            divisor *= 10;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -4,16 +4,78 @@
 | 
			
		||||
use chip8::emu::Chip8;
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
 | 
			
		||||
use pixels::{wgpu::Surface, Error, Pixels, SurfaceTexture};
 | 
			
		||||
use winit::dpi::LogicalSize;
 | 
			
		||||
use winit::event::{Event, VirtualKeyCode};
 | 
			
		||||
use winit::event_loop::{ControlFlow, EventLoop};
 | 
			
		||||
use winit::window::WindowBuilder;
 | 
			
		||||
use winit_input_helper::WinitInputHelper;
 | 
			
		||||
 | 
			
		||||
static WIDTH: u32 = 64;
 | 
			
		||||
static HEIGHT: u32 = 32;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let event_loop = EventLoop::new();
 | 
			
		||||
    let mut input = WinitInputHelper::new();
 | 
			
		||||
    let window = {
 | 
			
		||||
        let size = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
 | 
			
		||||
        WindowBuilder::new()
 | 
			
		||||
            .with_title("Chip8 Emulator")
 | 
			
		||||
            .with_inner_size(size)
 | 
			
		||||
            .with_min_inner_size(size)
 | 
			
		||||
            .build(&event_loop)
 | 
			
		||||
            .unwrap()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let mut hidpi_factor = window.scale_factor();
 | 
			
		||||
 | 
			
		||||
    let mut pixels = {
 | 
			
		||||
        let surface = Surface::create(&window);
 | 
			
		||||
        let surface_texture = SurfaceTexture::new(WIDTH, HEIGHT, surface);
 | 
			
		||||
        Pixels::new(WIDTH, HEIGHT, surface_texture).unwrap()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let mut chip8: Chip8 = Default::default();
 | 
			
		||||
 | 
			
		||||
    chip8
 | 
			
		||||
        .load_rom(Path::new("./games/c8games/TICTAC"))
 | 
			
		||||
        .load_rom(Path::new("./games/test_opcode.ch8"))
 | 
			
		||||
        .expect("Unable to load ROM");
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
    event_loop.run(move |event, _, control_flow| {
 | 
			
		||||
        chip8.execute_cycle();
 | 
			
		||||
 | 
			
		||||
        std::thread::sleep(Duration::from_millis(300));
 | 
			
		||||
        draw(&chip8.display.buf, pixels.get_frame());
 | 
			
		||||
        pixels.render().unwrap();
 | 
			
		||||
        window.request_redraw();
 | 
			
		||||
 | 
			
		||||
        if input.update(&event) {
 | 
			
		||||
            if let Some(factor) = input.scale_factor_changed() {
 | 
			
		||||
                hidpi_factor = factor;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
 | 
			
		||||
                *control_flow = ControlFlow::Exit;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if let Some(size) = input.window_resized() {
 | 
			
		||||
                pixels.resize(size.width, size.height);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // std::thread::sleep(Duration::from_millis(1000));
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn draw(chip8_gfx: &[u8], frame: &mut [u8]) {
 | 
			
		||||
    for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
 | 
			
		||||
        let rgba = if chip8_gfx[i] != 0 {
 | 
			
		||||
            [0xFF, 0xFF, 0xFF, 0xFF]
 | 
			
		||||
        } else {
 | 
			
		||||
            [0x00, 0x00, 0x00, 0xFF]
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        pixel.copy_from_slice(&rgba);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user