Skip to content
Snippets Groups Projects
Verified Commit 12497caa authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: initial game pad support

parent 57b8041a
Branches
Tags
No related merge requests found
Pipeline #870 passed
...@@ -28,7 +28,7 @@ pub struct Cpu { ...@@ -28,7 +28,7 @@ pub struct Cpu {
} }
impl Cpu { impl Cpu {
pub fn new(mmu: Mmu) -> Cpu { pub fn new(mmu: Mmu) -> Self {
let mut implemented = 0; let mut implemented = 0;
let mut implemented_ext = 0; let mut implemented_ext = 0;
...@@ -55,7 +55,7 @@ impl Cpu { ...@@ -55,7 +55,7 @@ impl Cpu {
EXTENDED.len() EXTENDED.len()
); );
Cpu { Self {
pc: 0x0, pc: 0x0,
sp: 0x0, sp: 0x0,
a: 0x0, a: 0x0,
......
...@@ -2,6 +2,7 @@ use crate::{ ...@@ -2,6 +2,7 @@ use crate::{
cpu::Cpu, cpu::Cpu,
data::{DMG_BOOT, SGB_BOOT}, data::{DMG_BOOT, SGB_BOOT},
mmu::Mmu, mmu::Mmu,
pad::Pad,
ppu::{Ppu, FRAME_BUFFER_SIZE}, ppu::{Ppu, FRAME_BUFFER_SIZE},
util::read_file, util::read_file,
}; };
...@@ -20,11 +21,12 @@ pub struct GameBoy { ...@@ -20,11 +21,12 @@ pub struct GameBoy {
#[cfg_attr(feature = "wasm", wasm_bindgen)] #[cfg_attr(feature = "wasm", wasm_bindgen)]
impl GameBoy { impl GameBoy {
#[cfg_attr(feature = "wasm", wasm_bindgen(constructor))] #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
pub fn new() -> GameBoy { pub fn new() -> Self {
let pad = Pad::new();
let ppu = Ppu::new(); let ppu = Ppu::new();
let mmu = Mmu::new(ppu); let mmu = Mmu::new(ppu, pad);
let cpu = Cpu::new(mmu); let cpu = Cpu::new(mmu);
GameBoy { cpu: cpu } Self { cpu: cpu }
} }
pub fn pc(&self) -> u16 { pub fn pc(&self) -> u16 {
......
...@@ -3,5 +3,6 @@ pub mod data; ...@@ -3,5 +3,6 @@ pub mod data;
pub mod gb; pub mod gb;
pub mod inst; pub mod inst;
pub mod mmu; pub mod mmu;
pub mod pad;
pub mod ppu; pub mod ppu;
pub mod util; pub mod util;
use crate::ppu::Ppu; use crate::{pad::Pad, ppu::Ppu};
pub const BIOS_SIZE: usize = 256; pub const BIOS_SIZE: usize = 256;
pub const ROM_SIZE: usize = 32768; pub const ROM_SIZE: usize = 32768;
...@@ -7,6 +7,7 @@ pub const ERAM_SIZE: usize = 8192; ...@@ -7,6 +7,7 @@ pub const ERAM_SIZE: usize = 8192;
pub struct Mmu { pub struct Mmu {
ppu: Ppu, ppu: Ppu,
pad: Pad,
boot_active: bool, boot_active: bool,
boot: [u8; BIOS_SIZE], boot: [u8; BIOS_SIZE],
rom: [u8; ROM_SIZE], rom: [u8; ROM_SIZE],
...@@ -15,9 +16,10 @@ pub struct Mmu { ...@@ -15,9 +16,10 @@ pub struct Mmu {
} }
impl Mmu { impl Mmu {
pub fn new(ppu: Ppu) -> Mmu { pub fn new(ppu: Ppu, pad: Pad) -> Self {
Mmu { Self {
ppu: ppu, ppu: ppu,
pad: pad,
boot_active: true, boot_active: true,
boot: [0u8; BIOS_SIZE], boot: [0u8; BIOS_SIZE],
rom: [0u8; ROM_SIZE], rom: [0u8; ROM_SIZE],
...@@ -76,11 +78,14 @@ impl Mmu { ...@@ -76,11 +78,14 @@ impl Mmu {
self.ppu.hram[(addr & 0x007f) as usize] self.ppu.hram[(addr & 0x007f) as usize]
} else { } else {
match addr & 0x00f0 { match addr & 0x00f0 {
0x00 => match addr & 0x00ff {
0x00 => self.pad.read(addr),
_ => {
println!("Reading from unknown IO control 0x{:04x}", addr);
0x00
}
},
0x40 | 0x50 | 0x60 | 0x70 => self.ppu.read(addr), 0x40 | 0x50 | 0x60 | 0x70 => self.ppu.read(addr),
0x00 => {
println!("Reading from Game Pad control 0x{:04x}", addr);
0x00
}
_ => { _ => {
println!("Reading from unknown IO control 0x{:04x}", addr); println!("Reading from unknown IO control 0x{:04x}", addr);
0x00 0x00
...@@ -129,41 +134,36 @@ impl Mmu { ...@@ -129,41 +134,36 @@ impl Mmu {
self.ram[(addr & 0x1fff) as usize] = value; self.ram[(addr & 0x1fff) as usize] = value;
} }
// Working RAM Shadow, I/O, Zero-page RAM // Working RAM Shadow, I/O, Zero-page RAM
0xf000 => { 0xf000 => match addr & 0x0f00 {
match addr & 0x0f00 { 0x000 | 0x100 | 0x200 | 0x300 | 0x400 | 0x500 | 0x600 | 0x700 | 0x800 | 0x900
0x000 | 0x100 | 0x200 | 0x300 | 0x400 | 0x500 | 0x600 | 0x700 | 0x800 | 0xa00 | 0xb00 | 0xc00 | 0xd00 => {
| 0x900 | 0xa00 | 0xb00 | 0xc00 | 0xd00 => { self.ram[(addr & 0x1fff) as usize] = value;
self.ram[(addr & 0x1fff) as usize] = value; }
} 0xe00 => {
0xe00 => { println!("Writing to PPU OAM at 0x{:04x}", addr);
println!("Writing to PPU OAM at 0x{:04x}", addr); }
} 0xf00 => {
0xf00 => { if addr >= 0xff80 {
if addr >= 0xff80 { self.ppu.hram[(addr & 0x007f) as usize] = value;
self.ppu.hram[(addr & 0x007f) as usize] = value; } else {
} else { match addr & 0x00f0 {
match addr & 0x00f0 { 0x00 => match addr & 0x00ff {
0x40 | 0x60 | 0x70 => { 0x00 => self.pad.write(addr, value),
self.ppu.write(addr, value); _ => println!("Writing to unknown IO control 0x{:04x}", addr),
} },
0x00 => { 0x40 | 0x60 | 0x70 => {
println!("Writing to Game Pad, timer, etc. control 0x{:04x} := 0x{:02x}", addr, value); self.ppu.write(addr, value);
}
0x50 => match addr & 0x00ff {
0x50 => self.boot_active = false,
_ => {
println!("Writing to unknown IO control 0x{:04x}", addr);
}
},
_ => {
println!("Writing to unknown IO control 0x{:04x}", addr);
}
} }
0x50 => match addr & 0x00ff {
0x50 => self.boot_active = false,
_ => println!("Writing to unknown IO control 0x{:04x}", addr),
},
_ => println!("Writing to unknown IO control 0x{:04x}", addr),
} }
} }
addr => panic!("Writing in unknown location 0x{:04x}", addr),
} }
} addr => panic!("Writing in unknown location 0x{:04x}", addr),
},
addr => panic!("Writing in unknown location 0x{:04x}", addr), addr => panic!("Writing in unknown location 0x{:04x}", addr),
} }
} }
......
pub struct Pad {
down: bool,
up: bool,
left: bool,
right: bool,
start: bool,
select: bool,
b: bool,
a: bool,
selection: PadSelection,
}
#[derive(Clone, Copy, PartialEq)]
pub enum PadSelection {
Action,
Direction,
}
impl Pad {
pub fn new() -> Self {
Self {
down: false,
up: false,
left: false,
right: false,
start: false,
select: false,
b: false,
a: false,
selection: PadSelection::Action,
}
}
pub fn read(&mut self, addr: u16) -> u8 {
match addr & 0x00ff {
0x0000 => {
let mut value;
match self.selection {
PadSelection::Action => {
value = if self.a { 0x01 } else { 0x00 }
| if self.b { 0x02 } else { 0x00 }
| if self.select { 0x04 } else { 0x00 }
| if self.start { 0x08 } else { 0x00 }
}
PadSelection::Direction => {
value = if self.right { 0x01 } else { 0x00 }
| if self.left { 0x02 } else { 0x00 }
| if self.up { 0x04 } else { 0x00 }
| if self.down { 0x08 } else { 0x00 }
}
}
value |= if self.selection == PadSelection::Direction {
0x00
} else {
0x10
} | if self.selection == PadSelection::Action {
0x00
} else {
0x20
};
value
}
addr => panic!("Reading from unknown Pad location 0x{:04x}", addr),
}
}
pub fn write(&mut self, addr: u16, value: u8) {
match addr & 0x00ff {
0x0000 => {
self.selection = if value & 0x10 == 0x00 {
PadSelection::Direction
} else {
PadSelection::Action
}
}
addr => panic!("Reading from unknown Pad location 0x{:04x}", addr),
}
}
}
...@@ -95,8 +95,8 @@ pub enum PpuMode { ...@@ -95,8 +95,8 @@ pub enum PpuMode {
} }
impl Ppu { impl Ppu {
pub fn new() -> Ppu { pub fn new() -> Self {
Ppu { Self {
frame_buffer: Box::new([0u8; DISPLAY_WIDTH * DISPLAY_HEIGHT * RGB_SIZE]), frame_buffer: Box::new([0u8; DISPLAY_WIDTH * DISPLAY_HEIGHT * RGB_SIZE]),
vram: [0u8; VRAM_SIZE], vram: [0u8; VRAM_SIZE],
hram: [0u8; HRAM_SIZE], hram: [0u8; HRAM_SIZE],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment