feat: add pixels-rs and winit as dependencies
This commit is contained in:
		
							
								
								
									
										1670
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1670
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -7,3 +7,7 @@ edition = "2018"
 | 
			
		||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
anyhow = "1.0.38"
 | 
			
		||||
pixels = "0.2.0"
 | 
			
		||||
winit = "0.24.0"
 | 
			
		||||
winit_input_helper = "0.9.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ use super::work_ram::{VariableWorkRAM, WorkRAM};
 | 
			
		||||
pub struct Bus {
 | 
			
		||||
    boot: Option<[u8; 256]>, // Boot ROM is 256b long
 | 
			
		||||
    cartridge: Option<Cartridge>,
 | 
			
		||||
    ppu: PPU,
 | 
			
		||||
    pub ppu: PPU,
 | 
			
		||||
    wram: WorkRAM,
 | 
			
		||||
    vwram: VariableWorkRAM,
 | 
			
		||||
    timer: Timer,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								src/cpu.rs
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/cpu.rs
									
									
									
									
									
								
							@@ -1,10 +1,11 @@
 | 
			
		||||
use super::bus::Bus;
 | 
			
		||||
use super::instruction::Instruction;
 | 
			
		||||
use super::instruction::{Cycles, Instruction};
 | 
			
		||||
use super::ppu::PPU;
 | 
			
		||||
use std::fmt::{Display, Formatter, Result as FmtResult};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Default)]
 | 
			
		||||
pub struct Cpu {
 | 
			
		||||
    bus: Bus,
 | 
			
		||||
    pub bus: Bus,
 | 
			
		||||
    reg: Registers,
 | 
			
		||||
    flags: Flags,
 | 
			
		||||
    ime: bool,
 | 
			
		||||
@@ -61,32 +62,11 @@ impl Cpu {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn decode(&mut self, opcode: u8) -> Instruction {
 | 
			
		||||
        let tmp = Instruction::from_byte(self, opcode);
 | 
			
		||||
 | 
			
		||||
        let a = self.register(Register::A);
 | 
			
		||||
        let flag: Flags = self.register(Register::Flag).into();
 | 
			
		||||
        let bc = self.register_pair(RegisterPair::BC);
 | 
			
		||||
        let de = self.register_pair(RegisterPair::DE);
 | 
			
		||||
        let hl = self.register_pair(RegisterPair::HL);
 | 
			
		||||
        let sp = self.register_pair(RegisterPair::SP);
 | 
			
		||||
 | 
			
		||||
        // println!(
 | 
			
		||||
        //     "A: {:#04X} | BC: {:#06X} | DE: {:#06X} | HL: {:#06X} | SP: {:#06X} | {}",
 | 
			
		||||
        //     a, bc, de, hl, sp, flag
 | 
			
		||||
        // );
 | 
			
		||||
 | 
			
		||||
        // Get info from serial port
 | 
			
		||||
        // if self.bus.read_byte(0xFF02) == 0x81 {
 | 
			
		||||
        //     let c = self.bus.read_byte(0xFF01) as char;
 | 
			
		||||
        //     self.bus.write_byte(0xFF02, 0x00);
 | 
			
		||||
        //     print!("TEST RESULT!: {}", c);
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        tmp
 | 
			
		||||
        Instruction::from_byte(self, opcode)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn execute(&mut self, instruction: Instruction) {
 | 
			
		||||
        Instruction::execute(self, instruction);
 | 
			
		||||
    pub fn execute(&mut self, instruction: Instruction) -> Cycles {
 | 
			
		||||
        Instruction::execute(self, instruction)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -119,6 +99,12 @@ impl Cpu {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Cpu {
 | 
			
		||||
    pub fn get_ppu(&mut self) -> &mut PPU {
 | 
			
		||||
        &mut self.bus.ppu
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Copy, Clone)]
 | 
			
		||||
enum State {
 | 
			
		||||
    Execute,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										102
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,20 +1,98 @@
 | 
			
		||||
use anyhow::{anyhow, Result};
 | 
			
		||||
use gb::cpu::Cpu as LR35902;
 | 
			
		||||
use pixels::{Pixels, SurfaceTexture};
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use winit::{
 | 
			
		||||
    dpi::LogicalSize,
 | 
			
		||||
    event::{Event, VirtualKeyCode},
 | 
			
		||||
    event_loop::{ControlFlow, EventLoop},
 | 
			
		||||
    window::Window,
 | 
			
		||||
    window::WindowBuilder,
 | 
			
		||||
};
 | 
			
		||||
use winit_input_helper::WinitInputHelper;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
// 160 x 144
 | 
			
		||||
const GB_WIDTH: u32 = 160;
 | 
			
		||||
const GB_HEIGHT: u32 = 144;
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
    let event_loop = EventLoop::new();
 | 
			
		||||
    let mut input = WinitInputHelper::new();
 | 
			
		||||
    let window = create_window(&event_loop)?;
 | 
			
		||||
    let mut pixels = create_pixels(&window)?;
 | 
			
		||||
 | 
			
		||||
    let out = Box::leak(Box::new(std::io::stdout()));
 | 
			
		||||
    let mut out_handle = out.lock();
 | 
			
		||||
    let mut game_boy = LR35902::new();
 | 
			
		||||
 | 
			
		||||
    game_boy.load_cartridge("bin/cpu_instrs.gb");
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        let pc = game_boy.register_pair(gb::cpu::RegisterPair::PC);
 | 
			
		||||
        let opcode = game_boy.fetch();
 | 
			
		||||
        let instruction = game_boy.decode(opcode);
 | 
			
		||||
    event_loop.run(move |event, _, control_flow| {
 | 
			
		||||
        if let Event::RedrawRequested(_) = event {
 | 
			
		||||
            let ppu = game_boy.get_ppu();
 | 
			
		||||
            let frame = pixels.get_frame();
 | 
			
		||||
 | 
			
		||||
        println!(
 | 
			
		||||
            "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}",
 | 
			
		||||
            pc, opcode, instruction
 | 
			
		||||
        );
 | 
			
		||||
            ppu.draw(frame);
 | 
			
		||||
 | 
			
		||||
        game_boy.execute(instruction);
 | 
			
		||||
    }
 | 
			
		||||
            if pixels
 | 
			
		||||
                .render()
 | 
			
		||||
                .map_err(|e| anyhow!("pixels.render() failed: {}", e))
 | 
			
		||||
                .is_err()
 | 
			
		||||
            {
 | 
			
		||||
                *control_flow = ControlFlow::Exit;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if input.update(&event) {
 | 
			
		||||
            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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Emulation
 | 
			
		||||
            let addr = game_boy.register_pair(gb::cpu::RegisterPair::PC);
 | 
			
		||||
 | 
			
		||||
            let opcode = game_boy.fetch();
 | 
			
		||||
            let instruction = game_boy.decode(opcode);
 | 
			
		||||
            let _cycles = game_boy.execute(instruction);
 | 
			
		||||
            window.request_redraw();
 | 
			
		||||
 | 
			
		||||
            write!(
 | 
			
		||||
                out_handle,
 | 
			
		||||
                "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}\n",
 | 
			
		||||
                addr, opcode, instruction
 | 
			
		||||
            )
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // loop {
 | 
			
		||||
    //     let pc = game_boy.register_pair(gb::cpu::RegisterPair::PC);
 | 
			
		||||
    //     let opcode = game_boy.fetch();
 | 
			
		||||
    //     let instruction = game_boy.decode(opcode);
 | 
			
		||||
 | 
			
		||||
    //     let _cycles = game_boy.execute(instruction);
 | 
			
		||||
 | 
			
		||||
    //     let ppu = game_boy.get_ppu();
 | 
			
		||||
    //     ppu.step();
 | 
			
		||||
    // }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn create_window(event_loop: &EventLoop<()>) -> Result<Window> {
 | 
			
		||||
    let size = LogicalSize::new(GB_WIDTH as f64, GB_HEIGHT as f64);
 | 
			
		||||
    Ok(WindowBuilder::new()
 | 
			
		||||
        .with_title("DMG-1 Game Boy")
 | 
			
		||||
        .with_inner_size(size)
 | 
			
		||||
        .with_min_inner_size(size)
 | 
			
		||||
        .build(&event_loop)?)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn create_pixels(window: &Window) -> Result<Pixels<Window>> {
 | 
			
		||||
    let window_size = window.inner_size();
 | 
			
		||||
    let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, window);
 | 
			
		||||
    Ok(Pixels::new(GB_WIDTH, GB_HEIGHT, surface_texture)?)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								src/ppu.rs
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/ppu.rs
									
									
									
									
									
								
							@@ -7,6 +7,17 @@ pub struct PPU {
 | 
			
		||||
    pub stat: LCDStatus,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PPU {
 | 
			
		||||
    pub fn step(&mut self) {}
 | 
			
		||||
 | 
			
		||||
    pub fn draw(&self, frame: &mut [u8]) {
 | 
			
		||||
        for (_i, pixel) in frame.chunks_exact_mut(4).enumerate() {
 | 
			
		||||
            let rgba: [u8; 4] = [0xFF, 0xFF, 0xFF, 0xFF];
 | 
			
		||||
            pixel.copy_from_slice(&rgba);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for PPU {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user