feat: add pixels-rs and winit as dependencies

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-01-18 20:47:09 -06:00
parent 207bcfea30
commit 2fc7ac3833
6 changed files with 1788 additions and 39 deletions

1670
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -7,3 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anyhow = "1.0.38"
pixels = "0.2.0"
winit = "0.24.0"
winit_input_helper = "0.9.0"

View File

@ -10,7 +10,7 @@ use super::work_ram::{VariableWorkRAM, WorkRAM};
pub struct Bus { pub struct Bus {
boot: Option<[u8; 256]>, // Boot ROM is 256b long boot: Option<[u8; 256]>, // Boot ROM is 256b long
cartridge: Option<Cartridge>, cartridge: Option<Cartridge>,
ppu: PPU, pub ppu: PPU,
wram: WorkRAM, wram: WorkRAM,
vwram: VariableWorkRAM, vwram: VariableWorkRAM,
timer: Timer, timer: Timer,

View File

@ -1,10 +1,11 @@
use super::bus::Bus; 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}; use std::fmt::{Display, Formatter, Result as FmtResult};
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct Cpu { pub struct Cpu {
bus: Bus, pub bus: Bus,
reg: Registers, reg: Registers,
flags: Flags, flags: Flags,
ime: bool, ime: bool,
@ -61,32 +62,11 @@ impl Cpu {
} }
pub fn decode(&mut self, opcode: u8) -> Instruction { pub fn decode(&mut self, opcode: u8) -> Instruction {
let tmp = Instruction::from_byte(self, opcode); 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
} }
pub fn execute(&mut self, instruction: Instruction) { pub fn execute(&mut self, instruction: Instruction) -> Cycles {
Instruction::execute(self, instruction); 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)] #[derive(Debug, Copy, Clone)]
enum State { enum State {
Execute, Execute,

View File

@ -1,20 +1,98 @@
use anyhow::{anyhow, Result};
use gb::cpu::Cpu as LR35902; 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(); let mut game_boy = LR35902::new();
game_boy.load_cartridge("bin/cpu_instrs.gb"); game_boy.load_cartridge("bin/cpu_instrs.gb");
loop { event_loop.run(move |event, _, control_flow| {
let pc = game_boy.register_pair(gb::cpu::RegisterPair::PC); if let Event::RedrawRequested(_) = event {
let ppu = game_boy.get_ppu();
let frame = pixels.get_frame();
ppu.draw(frame);
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 opcode = game_boy.fetch();
let instruction = game_boy.decode(opcode); let instruction = game_boy.decode(opcode);
let _cycles = game_boy.execute(instruction);
window.request_redraw();
println!( write!(
"Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}", out_handle,
pc, opcode, instruction "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}\n",
); addr, opcode, instruction
)
game_boy.execute(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)?)
} }

View File

@ -7,6 +7,17 @@ pub struct PPU {
pub stat: LCDStatus, 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 { impl Default for PPU {
fn default() -> Self { fn default() -> Self {
Self { Self {