From 1ad3d47c880d6e2aae712d626497df022084e934 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Sun, 29 May 2016 11:58:35 +0200 Subject: [PATCH] Add input; Add RLCA --- src/cartridge.rs | 2 +- src/cpu.rs | 16 ++++++- src/display.rs | 15 +----- src/interconnect.rs | 112 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/cartridge.rs b/src/cartridge.rs index 9b7bd9e..35c3bd7 100644 --- a/src/cartridge.rs +++ b/src/cartridge.rs @@ -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, diff --git a/src/cpu.rs b/src/cpu.rs index 93cb73d..4236af8 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -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)); diff --git a/src/display.rs b/src/display.rs index fe859b2..2588ad6 100644 --- a/src/display.rs +++ b/src/display.rs @@ -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) { diff --git a/src/interconnect.rs b/src/interconnect.rs index 1c725be..791d8af 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -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;