Add input; Add RLCA

This commit is contained in:
Kevin Hamacher 2016-05-29 11:58:35 +02:00
parent 44c8b2e7d8
commit 1ad3d47c88
4 changed files with 127 additions and 18 deletions

View File

@ -112,7 +112,7 @@ impl Cartridge {
match val {
0x0A => self.ram_rtc_enabled = true,
0x00 => self.ram_rtc_enabled = false,
_ => panic!("Unknown MBC value {:02X} for {:04X}", val, addr)
_ => println!("Unknown MBC value {:02X} for {:04X}", val, addr)
}
},
0x2000 ... 0x3FFF => self.bank_no = val & 0x7F,

View File

@ -790,7 +790,21 @@ impl CPU {
0x05 => self.reg_dec(REG_N_B),
0x06 => self.ld_r_v(REG_N_B),
0x07 => {
panic!("RLCA, not implemented");
if self.debug {
println!("RLCA");
}
let val = self.regs[REG_A];
let carry = val & 0x80 == 0x80;
self.set_clear_flag(FLAG_C, carry);
if !carry {
self.regs[REG_A] = self.regs[REG_A] << 1;
} else {
self.regs[REG_A] = self.regs[REG_A] << 1 | 1;
}
self.clear_flag(FLAG_Z);
self.clear_flag(FLAG_N);
self.clear_flag(FLAG_H);
4
}
0x08 => {
let a: u16 = to_u16(self.load_args(2));

View File

@ -1,9 +1,6 @@
extern crate sdl2;
extern crate libc;
use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
// Internal ram size
const VRAM_SIZE: usize = 0x2000;
@ -67,7 +64,7 @@ pub struct Display {
renderer: sdl2::render::Renderer<'static>,
event_pump: sdl2::EventPump,
pub event_pump: sdl2::EventPump,
vblank_fired: bool,
stat_fired: bool,
@ -242,16 +239,6 @@ impl Display {
} else {
self.status &= !(1 << 2);
}
// Make sure the window is responsive:
for event in self.event_pump.poll_iter() {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
panic!("TODO: Proper shutdown");
},
_ => {}
}
}
}
fn renderscan(&mut self) {

View File

@ -6,12 +6,35 @@ pub const INTERRUPT_TIMER_OVERFLOW: u8 = 1 << 2;
pub const INTERRUPT_DISPLAY_STAT: u8 = 1 << 1;
pub const INTERRUPT_DISPLAY_VBLANK: u8 = 1 << 0;
const KEY_SPECIAL: u8 = 1 << 5;
const KEY_REGULAR: u8 = 1 << 4;
const KEY_DOWN: u8 = 1 << 3;
const KEY_UP: u8 = 1 << 2;
const KEY_LEFT: u8 = 1 << 1;
const KEY_RIGHT: u8 = 1 << 0;
const KEY_START: u8 = 1 << 3;
const KEY_SELECT: u8 = 1 << 2;
const KEY_B: u8 = 1 << 1;
const KEY_A: u8 = 1 << 0;
use super::display;
use super::sound;
use super::timer;
use super::serial;
use super::cartridge;
extern crate sdl2;
use self::sdl2::event::Event;
use self::sdl2::keyboard::Keycode;
#[derive(Debug)]
enum Key {
UP, LEFT, DOWN, RIGHT, START, SELECT, A, B
}
pub struct Interconnect {
bios: Box<[u8]>,
cartridge: cartridge::Cartridge,
@ -31,6 +54,10 @@ pub struct Interconnect {
vram_dma_source_low: u8,
vram_dma_destination_high: u8,
vram_dma_destination_low: u8,
joy_regular_keys: u8,
joy_special_keys: u8,
joy_switch: u8,
}
impl Interconnect {
@ -55,6 +82,39 @@ impl Interconnect {
vram_dma_source_low: 0,
vram_dma_destination_high: 0,
vram_dma_destination_low: 0,
// No keys pushed by default
joy_regular_keys: 0x0F,
joy_special_keys: 0x0F,
joy_switch: 0x30,
}
}
fn press_key(&mut self, key: Key) {
println!("Press key {:?}", &key);
match key {
Key::UP => self.joy_regular_keys &= !KEY_UP,
Key::DOWN => self.joy_regular_keys &= !KEY_DOWN,
Key::RIGHT => self.joy_regular_keys &= !KEY_RIGHT,
Key::LEFT => self.joy_regular_keys &= !KEY_LEFT,
Key::START => self.joy_special_keys &= !KEY_START,
Key::SELECT => self.joy_special_keys &= !KEY_SELECT,
Key::A => self.joy_special_keys &= !KEY_A,
Key::B => self.joy_special_keys &= !KEY_B,
}
}
fn release_key(&mut self, key: Key) {
println!("Release key {:?}", &key);
match key {
Key::UP => self.joy_regular_keys |= KEY_UP,
Key::DOWN => self.joy_regular_keys |= KEY_DOWN,
Key::RIGHT => self.joy_regular_keys |= KEY_RIGHT,
Key::LEFT => self.joy_regular_keys |= KEY_LEFT,
Key::START => self.joy_special_keys |= KEY_START,
Key::SELECT => self.joy_special_keys |= KEY_SELECT,
Key::A => self.joy_special_keys |= KEY_A,
Key::B => self.joy_special_keys |= KEY_B,
}
}
@ -74,6 +134,37 @@ impl Interconnect {
if self.timer.timer_interrupt() {
self.interrupt_request_flags |= INTERRUPT_TIMER_OVERFLOW;
}
// Make sure the window is responsive:
loop {
if let Some(event) = self.display.event_pump.poll_event(){
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
panic!("TODO: Proper shutdown");
},
Event::KeyDown { keycode: Some(Keycode::Left), .. } => self.press_key(Key::LEFT),
Event::KeyDown { keycode: Some(Keycode::Down), .. } => self.press_key(Key::DOWN),
Event::KeyDown { keycode: Some(Keycode::Up), .. } => self.press_key(Key::UP),
Event::KeyDown { keycode: Some(Keycode::Right), .. } => self.press_key(Key::RIGHT),
Event::KeyDown { keycode: Some(Keycode::A), .. } => self.press_key(Key::START),
Event::KeyDown { keycode: Some(Keycode::S), .. } => self.press_key(Key::SELECT),
Event::KeyDown { keycode: Some(Keycode::Z), .. } => self.press_key(Key::A),
Event::KeyDown { keycode: Some(Keycode::X), .. } => self.press_key(Key::B),
Event::KeyUp { keycode: Some(Keycode::Left), .. } => self.release_key(Key::LEFT),
Event::KeyUp { keycode: Some(Keycode::Down), .. } => self.release_key(Key::DOWN),
Event::KeyUp { keycode: Some(Keycode::Up), .. } => self.release_key(Key::UP),
Event::KeyUp { keycode: Some(Keycode::Right), .. } => self.release_key(Key::RIGHT),
Event::KeyUp { keycode: Some(Keycode::A), .. } => self.release_key(Key::START),
Event::KeyUp { keycode: Some(Keycode::S), .. } => self.release_key(Key::SELECT),
Event::KeyUp { keycode: Some(Keycode::Z), .. } => self.release_key(Key::A),
Event::KeyUp { keycode: Some(Keycode::X), .. } => self.release_key(Key::B),
_ => {}
}
} else {
break;
}
}
}
pub fn is_boot_rom(&self) -> bool {
@ -101,7 +192,16 @@ impl Interconnect {
0xD000 ... 0xDFFF => {
self.ram[(addr - 0xD000) as usize + self.wram_bank as usize * 0x1000]
}
0xFF00 => 0xFF, // TODO: This is the input stuff
0xFF00 => {
if self.joy_switch & KEY_REGULAR == 0 {
self.joy_regular_keys
} else if self.joy_switch & KEY_SPECIAL == 0 {
self.joy_special_keys
} else {
println!("Reading none from joystick?");
0xFF
}
}
0xFF01 ... 0xFF02 => self.serial.read_byte(addr),
0xFF04 ... 0xFF07 => self.timer.read_byte(addr),
0xFF0F => {
@ -166,6 +266,10 @@ impl Interconnect {
self.ram[(addr - 0xD000) as usize + self.wram_bank as usize * 0x1000] = val;
}
0xFE00 ... 0xFE9F => self.display.write_byte(addr, val), // OAM
0xFF00 => {
// Joystick select
self.joy_switch = val;
}
0xFF01 ... 0xFF02 => self.serial.write_byte(addr, val),
0xFF04 ... 0xFF07 => self.timer.write_byte(addr, val),
0xFF0F => {
@ -213,7 +317,11 @@ impl Interconnect {
if val > 7 {
panic!("R u sure this is correct?");
}
self.wram_bank = val;
if val == 0 {
self.wram_bank = 1;
} else {
self.wram_bank = val;
}
}
0xFF80 ... 0xFFFE => {
self.hiram[(addr - 0xFF80) as usize] = val;