Skip to content

Commit

Permalink
fix joypad's bug
Browse files Browse the repository at this point in the history
  • Loading branch information
novoru committed Nov 1, 2020
1 parent de9ce09 commit 9d47250
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 56 deletions.
13 changes: 12 additions & 1 deletion src/core/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::core::pad::{ Pad, Key };
use crate::core::ppu::*;
use crate::core::hram::HRam;
use crate::core::apu::Apu;
use crate::core::timer::Timer;

use std::path::Path;

Expand All @@ -20,6 +21,7 @@ pub struct Bus {
apu: Apu,
interrupt: Interrupt,
pad: Pad,
pub timer: Timer,
}

impl Bus {
Expand All @@ -32,6 +34,7 @@ impl Bus {
apu: Apu::new(),
interrupt: Interrupt::new(),
pad: Pad::new(),
timer: Timer::new(),
}
}

Expand All @@ -44,6 +47,7 @@ impl Bus {
apu: Apu::new(),
interrupt: Interrupt::new(),
pad: Pad::new(),
timer: Timer::new(),
}
}

Expand Down Expand Up @@ -112,6 +116,9 @@ impl Bus {
},
_ => (),
}
if self.timer.tick() {
self.interrupt.set_irq(InterruptKind::Timer);
};
}
}

Expand All @@ -137,6 +144,8 @@ impl Io for Bus {
// I/O ports
0xFF00 => self.pad.read8(),
// 0xFF00 ..= 0xFF3B => self.ioports.read8(addr),
// Timer
0xFF04 ..= 0xFF07 => self.timer.read8(addr),
// Interrupt Flag Register
0xFF0F => self.interrupt.read8(addr),
// LCD Registers
Expand Down Expand Up @@ -170,7 +179,9 @@ impl Io for Bus {
// Empty but unusable for I/O
0xFEA0 ..= 0xFEFF => (),
// I/O ports
0xFF00 => self.pad.write8(data),
0xFF00 => self.pad.write8(data),
// Timer
0xFF04 ..= 0xFF07 => self.timer.write8(addr, data),
// Sound Channel 1 - Tone & Sweep
0xFF10 ..= 0xFF14 |
// Sound Channel 2 - Tone
Expand Down
36 changes: 17 additions & 19 deletions src/core/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct Cpu {
sp: u16,
pc: u16,
bus: Bus,
halt: bool,
debug: bool,
}

Expand All @@ -53,10 +54,11 @@ impl Cpu {
c: 0x13,
e: 0xD8,
l: 0x4D,
f: Flags::Z | Flags::N | Flags::H | Flags::C,
f: Flags::from_bits_truncate(0xB0),
sp: 0xFFFE,
pc: 0x100,
bus: Bus::no_cartridge(),
halt: false,
debug: false,
}
}
Expand All @@ -70,10 +72,11 @@ impl Cpu {
c: 0x13,
e: 0xD8,
l: 0x4D,
f: Flags::Z | Flags::N | Flags::H | Flags::C,
f: Flags::from_bits_truncate(0xB0),
sp: 0xFFFE,
pc: 0x100,
bus: Bus::from_path(path),
halt: false,
debug: false,
}
}
Expand All @@ -98,17 +101,12 @@ impl Cpu {
}

fn step(&mut self) {
// if self.pc == 0x0150 {
// println!("break");
// self.debug = true;
// }
// if self.debug {
// use std::io::stdin;
// let mut input = String::new();
// stdin().read_line(&mut input).unwrap();
// println!("{}", self);
// }

if self.halt {
if self.bus.has_irq() {
self.halt = false;
}
return;
}
if self.bus.has_irq() && self.bus.is_enabled_irq() {
self.resolve_irq();
return;
Expand All @@ -119,15 +117,15 @@ impl Cpu {
}

fn resolve_irq(&mut self) {
let pc = self.pc;
self.push((pc>>8) as u8);
self.push((pc&0xFF) as u8);

let addr = self.bus.isr_addr();
if addr == None {
return;
}

let pc = self.pc;
self.push((pc>>8) as u8);
self.push((pc&0xFF) as u8);

self.pc = addr.unwrap() as u16;
self.bus.disable_irq();
}
Expand Down Expand Up @@ -1629,8 +1627,8 @@ impl Cpu {
name: "HALT",
opcode: 0x76,
cycles: 4,
operation: |_| {
// TODO
operation: |cpu| {
cpu.halt = true;
Ok(())
},
},
Expand Down
1 change: 1 addition & 0 deletions src/core/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const TIMER_ISR_ADDR: usize = 0x0050;
const SERIAL_ISR_ADDR: usize = 0x0058;
const JOYPAD_ISR_ADDR: usize = 0x0060;

#[derive(Debug)]
pub enum InterruptKind {
Vblank,
LcdcStatus,
Expand Down
3 changes: 2 additions & 1 deletion src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ pub mod pad;
pub mod ppu;
pub mod hram;
pub mod apu;
pub mod mbc;
pub mod mbc;
pub mod timer;
72 changes: 45 additions & 27 deletions src/core/pad.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#[macro_use]
use bitflags::*;

use std::fmt;

bitflags!{
struct P1: u8 {
const P15 = 0b00100000;
Expand All @@ -11,10 +9,23 @@ bitflags!{
const P12 = 0b00000100;
const P11 = 0b00000010;
const P10 = 0b00000001;
const NONE = 0b00000000;
}
}

bitflags!{
struct KeyState: u8 {
const START = 0b10000000;
const SELECT = 0b01000000;
const B = 0b00100000;
const A = 0b00010000;
const DOWN = 0b00001000;
const UP = 0b00000100;
const LEFT = 0b00000010;
const RIGHT = 0b00000001;
}
}

#[derive(Debug)]
pub enum Key {
Right,
Left,
Expand All @@ -28,53 +39,60 @@ pub enum Key {

pub struct Pad {
register: P1,
}

impl fmt::Display for Pad {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Pad {{ 0b{:08b} }}", self.register)
}
state: KeyState,
}

impl Pad {
pub fn new() -> Self {
Pad {
register: P1::P15 | P1::P14 | P1::P13 | P1::P12 | P1::P11 | P1::P10,
register: P1::P13 | P1::P12 | P1::P11 | P1::P10,
state: KeyState::A | KeyState::B |
KeyState::SELECT | KeyState::START |
KeyState::RIGHT | KeyState::LEFT |
KeyState::UP | KeyState::DOWN,
}
}

pub fn read8(&self) -> u8 {
self.register.bits()
if !self.register.contains(P1::P15) {
return self.register.bits() & 0xF0 | (self.state.bits() >> 4) & 0x0F;
}

if !self.register.contains(P1::P14) {
return self.register.bits() & 0xF0 | self.state.bits() & 0x0F;
}

self.register.bits() & 0x0F
}

pub fn write8(&mut self, data: u8) {
self.register = P1::from_bits_truncate(data);
}

fn _update(&mut self) {
if self.register.contains(P1::P14) | self.register.contains(P1::P15) {
self.register.insert(P1::P10 | P1::P11 | P1::P12 | P1::P13);
}
}

pub fn push_key(&mut self, key: Key) {
match key {
Key::Right | Key::A => self.register.remove(P1::P10),
Key::Left | Key::B => self.register.remove(P1::P11),
Key::Up | Key::Select => self.register.remove(P1::P12),
Key::Down | Key::Start => self.register.remove(P1::P13),
Key::Right => self.state.remove(KeyState::RIGHT),
Key::A => self.state.remove(KeyState::A),
Key::Left => self.state.remove(KeyState::LEFT),
Key::B => self.state.remove(KeyState::B),
Key::Up => self.state.remove(KeyState::UP),
Key::Select => self.state.remove(KeyState::SELECT),
Key::Down => self.state.remove(KeyState::DOWN),
Key::Start => self.state.remove(KeyState::START),
}
// self.update();
}

pub fn release_key(&mut self, key: Key) {
match key {
Key::Right | Key::A => self.register.insert(P1::P10),
Key::Left | Key::B => self.register.insert(P1::P11),
Key::Up | Key::Select => self.register.insert(P1::P12),
Key::Down | Key::Start => self.register.insert(P1::P13),
Key::Right => self.state.insert(KeyState::RIGHT),
Key::A => self.state.insert(KeyState::A),
Key::Left => self.state.insert(KeyState::LEFT),
Key::B => self.state.insert(KeyState::B),
Key::Up => self.state.insert(KeyState::UP),
Key::Select => self.state.insert(KeyState::SELECT),
Key::Down => self.state.insert(KeyState::DOWN),
Key::Start => self.state.insert(KeyState::START),
}
// self.update();
}

}
8 changes: 4 additions & 4 deletions src/core/ppu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ impl Io for Ppu {
self.oam_dma_started = true;
},
0xFF47 => self.bgp = Bgp::from(data),
0xFF48 => self.obp0 = 0,
0xFF49 => self.obp1 = 0,
0xFF48 => self.obp0 = 0xFF,
0xFF49 => self.obp1 = 0xFF,
0xFF4A => self.wy = data,
0xFF4B => self.wx = data,
// ToDo: LCD Color Palettes (CGB only)
Expand Down Expand Up @@ -242,15 +242,15 @@ impl Ppu {
let mut lcdc_irq = false;

if self.clock >= CYCLE_PER_LINE {
vblank_irq = true;
if self.ly == SCREEN_HEIGHT as u8 {
vblank_irq = true;
self.build_sprite();
if self.stat.contains(Stat::INTR_LYC) {
lcdc_irq = true;
}
} else if self.ly >= SCREEN_HEIGHT as u8 + LCD_BLANK_HEIGHT {
self.ly = 0;
// self.build_bg();
self.build_bg();
} else if self.ly < SCREEN_HEIGHT as u8 {
self.build_bg();
// if self.window_enabled() {
Expand Down
Loading

0 comments on commit 9d47250

Please sign in to comment.