mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
Basic joypad implementation
This commit is contained in:
parent
b5bb582c54
commit
292c7d1507
21
src/bus.rs
21
src/bus.rs
@ -8,6 +8,7 @@ use crate::rom::ROM;
|
||||
use crate::ppu::{PPU, LCDStatus, LCDStatusModeFlag, LCD_STATUS_ADDRESS, LCD_CONTROL_ADDRESS, LCD_Y_ADDRESS};
|
||||
use crate::cpu::{Interrupt};
|
||||
use crate::timer::{TIMER_DIVIDER_REGISTER_ADDRESS};
|
||||
use crate::joypad::{Joypad, JOYPAD_ADDRESS};
|
||||
|
||||
pub struct AddressRange {
|
||||
begin: u16,
|
||||
@ -50,7 +51,7 @@ pub struct Bus {
|
||||
|
||||
impl Bus {
|
||||
pub fn new() -> Self {
|
||||
let game_rom = match ROM::load_file("ignore/dr-mario.gb".to_string()) {
|
||||
let game_rom = match ROM::load_file("ignore/tetris.gb".to_string()) {
|
||||
// let game_rom = match ROM::load_file("roms/cpu_instrs.gb".to_string()) {
|
||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/01-special.gb".to_string()) {
|
||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/02-interrupts.gb".to_string()) {
|
||||
@ -67,19 +68,21 @@ impl Bus {
|
||||
// _ => ROM::from_bytes(&[0; 0xFFFF])
|
||||
_ => panic!("Could not read ROM"),
|
||||
};
|
||||
let mut data = [0x00; 0x10000];
|
||||
data[JOYPAD_ADDRESS as usize] = 0b11001111;
|
||||
Self {
|
||||
data: [0x00; 0x10000],
|
||||
data,
|
||||
game_rom,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, address: u16) -> u8 {
|
||||
if address == 0xFF00 {
|
||||
return 0xFF;
|
||||
}
|
||||
if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) {
|
||||
return self.game_rom.read(address);
|
||||
}
|
||||
if address == JOYPAD_ADDRESS {
|
||||
println!("Joypad read {:08b}", self.data[address as usize]);
|
||||
}
|
||||
self.data[address as usize]
|
||||
}
|
||||
|
||||
@ -112,11 +115,19 @@ impl Bus {
|
||||
} else if address == LCD_CONTROL_ADDRESS && get_bit(data, BitIndex::I7) {
|
||||
self.data[address as usize] = data;
|
||||
self.data[LCD_Y_ADDRESS as usize] = 0x00;
|
||||
} else if address == JOYPAD_ADDRESS {
|
||||
println!("Joypad write: {:08b}", data);
|
||||
let byte = self.data[JOYPAD_ADDRESS as usize];
|
||||
self.data[JOYPAD_ADDRESS as usize] = (data & 0b00110000) | 0b11000000 | (byte & 0b00001111);
|
||||
} else {
|
||||
self.data[address as usize] = data;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn force_write(&mut self, address: u16, data: u8) {
|
||||
self.data[address as usize] = data;
|
||||
}
|
||||
|
||||
pub fn write_16bit(&mut self, address: u16, data: u16) {
|
||||
let bytes = data.to_le_bytes();
|
||||
self.write(address, bytes[0]);
|
||||
|
@ -1,24 +1,103 @@
|
||||
use std::{thread, time};
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
use winit::event::{VirtualKeyCode};
|
||||
|
||||
use crate::cpu::{CPU, Cycles};
|
||||
use crate::cpu::{CPU, Cycles, Interrupt};
|
||||
use crate::ppu::PPU;
|
||||
use crate::bus::Bus;
|
||||
use crate::timer::Timer;
|
||||
use crate::joypad::{Joypad, Button, JOYPAD_ADDRESS};
|
||||
|
||||
pub struct Emulator {
|
||||
cpu: CPU,
|
||||
ppu: PPU,
|
||||
bus: Bus,
|
||||
timer: Timer,
|
||||
joypad: Joypad,
|
||||
}
|
||||
|
||||
impl Emulator {
|
||||
pub fn new() -> Self {
|
||||
let mut joypad: Joypad = Joypad::new();
|
||||
Self {
|
||||
cpu: CPU::new(),
|
||||
ppu: PPU::new(),
|
||||
bus: Bus::new(),
|
||||
timer: Timer::new(),
|
||||
joypad: Joypad::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_input(&mut self, input: &WinitInputHelper) {
|
||||
let mut change = false;
|
||||
if input.key_pressed(VirtualKeyCode::K) {
|
||||
change = true;
|
||||
self.joypad.press(Button::A);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::J) {
|
||||
change = true;
|
||||
self.joypad.press(Button::B);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::W) {
|
||||
change = true;
|
||||
self.joypad.press(Button::Up);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::S) {
|
||||
change = true;
|
||||
self.joypad.press(Button::Down);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::A) {
|
||||
change = true;
|
||||
self.joypad.press(Button::Left);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::D) {
|
||||
change = true;
|
||||
self.joypad.press(Button::Right);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::N) {
|
||||
change = true;
|
||||
self.joypad.press(Button::Start);
|
||||
}
|
||||
if input.key_pressed(VirtualKeyCode::B) {
|
||||
change = true;
|
||||
self.joypad.press(Button::Select);
|
||||
}
|
||||
|
||||
if input.key_released(VirtualKeyCode::K) {
|
||||
change = true;
|
||||
self.joypad.release(Button::A);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::J) {
|
||||
change = true;
|
||||
self.joypad.release(Button::B);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::W) {
|
||||
change = true;
|
||||
self.joypad.release(Button::Up);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::S) {
|
||||
change = true;
|
||||
self.joypad.release(Button::Down);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::A) {
|
||||
change = true;
|
||||
self.joypad.release(Button::Left);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::D) {
|
||||
change = true;
|
||||
self.joypad.release(Button::Right);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::N) {
|
||||
change = true;
|
||||
self.joypad.release(Button::Start);
|
||||
}
|
||||
if input.key_released(VirtualKeyCode::B) {
|
||||
change = true;
|
||||
self.joypad.release(Button::Select);
|
||||
}
|
||||
if change {
|
||||
self.bus.force_write(JOYPAD_ADDRESS, self.joypad.get(&self.bus));
|
||||
self.bus.set_interrupt_flag(Interrupt::Joypad, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
91
src/joypad.rs
Normal file
91
src/joypad.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use crate::bus::{Bus};
|
||||
use crate::utils::{BitIndex, get_bit};
|
||||
|
||||
pub const JOYPAD_ADDRESS: u16 = 0xFF00;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Button {
|
||||
A,
|
||||
B,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Start,
|
||||
Select
|
||||
}
|
||||
|
||||
pub struct Joypad {
|
||||
a: bool,
|
||||
b: bool,
|
||||
up: bool,
|
||||
down: bool,
|
||||
left: bool,
|
||||
right: bool,
|
||||
start: bool,
|
||||
select: bool,
|
||||
}
|
||||
|
||||
impl Joypad {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
a: false,
|
||||
b: false,
|
||||
up: false,
|
||||
down: false,
|
||||
left: false,
|
||||
right: false,
|
||||
start: false,
|
||||
select: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn press(&mut self, button: Button) {
|
||||
println!("{:?} pressed", button);
|
||||
match button {
|
||||
Button::A => self.a = true,
|
||||
Button::B => self.b = true,
|
||||
Button::Up => self.up = true,
|
||||
Button::Down => self.down = true,
|
||||
Button::Left => self.left = true,
|
||||
Button::Right => self.right = true,
|
||||
Button::Start => self.start = true,
|
||||
Button::Select => self.select = true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn release(&mut self, button: Button) {
|
||||
println!("{:?} released", button);
|
||||
match button {
|
||||
Button::A => self.a = false,
|
||||
Button::B => self.b = false,
|
||||
Button::Up => self.up = false,
|
||||
Button::Down => self.down = false,
|
||||
Button::Left => self.left = false,
|
||||
Button::Right => self.right = false,
|
||||
Button::Start => self.start = false,
|
||||
Button::Select => self.select = false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get(&self, bus: &Bus) -> u8 {
|
||||
let byte = bus.read(JOYPAD_ADDRESS);
|
||||
let direction = !get_bit(byte, BitIndex::I4);
|
||||
let action = !get_bit(byte, BitIndex::I5);
|
||||
|
||||
let action = true;
|
||||
let direction = true;
|
||||
|
||||
0b11000000 |
|
||||
(byte & 0b00110000) |
|
||||
(
|
||||
(!((direction && self.down) || (action && self.start)) as u8) << 3
|
||||
) | (
|
||||
(!((direction && self.up) || (action && self.select)) as u8) << 2
|
||||
) | (
|
||||
(!((direction && self.left) || (action && self.b)) as u8) << 1
|
||||
) | (
|
||||
(!((direction && self.right) || (action && self.a)) as u8)
|
||||
)
|
||||
}
|
||||
}
|
@ -4,5 +4,6 @@ pub mod ppu;
|
||||
pub mod timer;
|
||||
pub mod rom;
|
||||
pub mod bus;
|
||||
pub mod joypad;
|
||||
pub mod emulator;
|
||||
pub mod render;
|
||||
|
@ -47,6 +47,8 @@ pub fn start_eventloop() {
|
||||
return;
|
||||
}
|
||||
|
||||
emulator.handle_input(&input);
|
||||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
|
Loading…
Reference in New Issue
Block a user