Skip to content

Commit

Permalink
Refactored bus API
Browse files Browse the repository at this point in the history
  • Loading branch information
velllu committed Sep 11, 2023
1 parent b44119b commit 6b7c15b
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 54 deletions.
78 changes: 56 additions & 22 deletions src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,41 +78,75 @@ impl Bus {
}
}

// TODO: Make code DRYer
impl Bus {
pub fn write_byte(&mut self, address: u16, value: u8) {
// Reading
impl core::ops::Index<u16> for Bus {
type Output = u8;
fn index(&self, address: u16) -> &Self::Output {
match address {
0x8000..=0x9FFF => self.video_ram[(address - 0x8000) as usize] = value,
0x8000..=0x9FFF => &self.video_ram[(address - 0x8000) as usize],
0xA000..=0xBFFF => todo!(), // external ram
0xC000..=0xDFFF => self.work_ram[(address - 0xC000) as usize] = value,
0xC000..=0xDFFF => &self.work_ram[(address - 0xC000) as usize],
0xE000..=0xFDFF => todo!(), // mirror ram
0xFE00..=0xFE9F => self.eom[(address - 0xFE00) as usize] = value,
0xFF00..=0xFF7F => self.io[(address - IO_START as u16) as usize] = value,
0xFF80..=0xFFFE => self.high_ram[(address - 0xFF80) as usize] = value,
0xFFFF => self.ie = value,

_ => {
println!("Invalid writing");
}
0xFE00..=0xFE9F => &self.eom[(address - 0xFE00) as usize],
0xFF00..=0xFF7F => &self.io[(address - IO_START as u16) as usize],
0xFF80..=0xFFFE => &self.high_ram[(address - 0xFF80) as usize],
0xFFFF => &self.ie,
_ => todo!(),
}
}
}

pub fn read(&self, address: u16) -> u8 {
// Writing
impl core::ops::IndexMut<u16> for Bus {
fn index_mut(&mut self, address: u16) -> &mut Self::Output {
match address {
0x8000..=0x9FFF => self.video_ram[(address - 0x8000) as usize],
0x8000..=0x9FFF => &mut self.video_ram[(address - 0x8000) as usize],
0xA000..=0xBFFF => todo!(), // external ram
0xC000..=0xDFFF => self.work_ram[(address - 0xC000) as usize],
0xC000..=0xDFFF => &mut self.work_ram[(address - 0xC000) as usize],
0xE000..=0xFDFF => todo!(), // mirror ram
0xFE00..=0xFE9F => self.eom[(address - 0xFE00) as usize],
0xFF00..=0xFF7F => self.io[(address - IO_START as u16) as usize],
0xFF80..=0xFFFE => self.high_ram[(address - 0xFF80) as usize],
0xFFFF => self.ie,

_ => 0xFF,
0xFE00..=0xFE9F => &mut self.eom[(address - 0xFE00) as usize],
0xFF00..=0xFF7F => &mut self.io[(address - IO_START as u16) as usize],
0xFF80..=0xFFFE => &mut self.high_ram[(address - 0xFF80) as usize],
0xFFFF => &mut self.ie,
_ => todo!(),
}
}
}

// impl Bus {
// // pub fn write_byte(&mut self, address: u16, value: u8) {
// // match address {
// // 0x8000..=0x9FFF => self.video_ram[(address - 0x8000) as usize] = value,
// // 0xA000..=0xBFFF => todo!(), // external ram
// // 0xC000..=0xDFFF => self.work_ram[(address - 0xC000) as usize] = value,
// // 0xE000..=0xFDFF => todo!(), // mirror ram
// // 0xFE00..=0xFE9F => self.eom[(address - 0xFE00) as usize] = value,
// // 0xFF00..=0xFF7F => self.io[(address - IO_START as u16) as usize] = value,
// // 0xFF80..=0xFFFE => self.high_ram[(address - 0xFF80) as usize] = value,
// // 0xFFFF => self.ie = value,

// // _ => {
// // println!("Invalid writing");
// // }
// // }
// // }

// pub fn read(&self, address: u16) -> u8 {
// match address {
// 0x8000..=0x9FFF => self.video_ram[(address - 0x8000) as usize],
// 0xA000..=0xBFFF => todo!(), // external ram
// 0xC000..=0xDFFF => self.work_ram[(address - 0xC000) as usize],
// 0xE000..=0xFDFF => todo!(), // mirror ram
// 0xFE00..=0xFE9F => self.eom[(address - 0xFE00) as usize],
// 0xFF00..=0xFF7F => self.io[(address - IO_START as u16) as usize],
// 0xFF80..=0xFFFE => self.high_ram[(address - 0xFF80) as usize],
// 0xFFFF => self.ie,

// _ => 0xFF,
// }
// }
// }

impl Bus {
/// Returns the opcode at specified address
pub fn read_from_rom(&self, pc: u16) -> u8 {
Expand Down
41 changes: 22 additions & 19 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@ impl GameBoy {

fn load_r_into_io(&mut self, register: OneByteRegister) {
let register = *self.registers.get_r(register);
self.bus
.write_byte((IO_START + self.next(1) as usize) as u16, register);
let i = self.next(1);

self.bus[(IO_START + i as usize) as u16] = register;
}

fn load_io_into_r(&mut self, register: OneByteRegister) {
let i = self.next(1);

let register = self.registers.get_r(register);
*register = self.bus.read((IO_START + i as usize) as u16)
*register = self.bus[(IO_START + i as usize) as u16]
}
}

Expand All @@ -85,7 +86,7 @@ impl GameBoy {
}

fn compare_ra_to_ram(&mut self, address: u16) {
let ram = self.bus.read(address);
let ram = self.bus[address];
self.flags
.update_zero_flag(self.registers.a.wrapping_sub(ram));
}
Expand Down Expand Up @@ -224,25 +225,25 @@ impl GameBoy {
0x3E => { self.load_i_into_r(OneByteRegister::A); (2, 2) },

// Load R into ram
0x02 => { self.bus.write_byte(self.registers.get_bc(), self.registers.a); (1, 2) },
0x12 => { self.bus.write_byte(self.registers.get_de(), self.registers.a); (1, 2) },
0x36 => { self.bus.write_byte(self.registers.get_hl(), self.next(1)); (2, 3) },
0x70 => { self.bus.write_byte(self.registers.get_hl(), self.registers.b); (1, 2) },
0x71 => { self.bus.write_byte(self.registers.get_hl(), self.registers.c); (1, 2) },
0x72 => { self.bus.write_byte(self.registers.get_hl(), self.registers.d); (1, 2) },
0x73 => { self.bus.write_byte(self.registers.get_hl(), self.registers.e); (1, 2) },
0x74 => { self.bus.write_byte(self.registers.get_hl(), self.registers.h); (1, 2) },
0x75 => { self.bus.write_byte(self.registers.get_hl(), self.registers.l); (1, 2) },
0x77 => { self.bus.write_byte(self.registers.get_hl(), self.registers.a); (1, 2) },
0x02 => { self.bus[self.registers.get_bc()] = self.registers.a; (1, 2) },
0x12 => { self.bus[self.registers.get_de()] = self.registers.a; (1, 2) },
0x36 => { self.bus[self.registers.get_hl()] = self.next(1); (2, 3) },
0x70 => { self.bus[self.registers.get_hl()] = self.registers.b; (1, 2) },
0x71 => { self.bus[self.registers.get_hl()] = self.registers.c; (1, 2) },
0x72 => { self.bus[self.registers.get_hl()] = self.registers.d; (1, 2) },
0x73 => { self.bus[self.registers.get_hl()] = self.registers.e; (1, 2) },
0x74 => { self.bus[self.registers.get_hl()] = self.registers.h; (1, 2) },
0x75 => { self.bus[self.registers.get_hl()] = self.registers.l; (1, 2) },
0x77 => { self.bus[self.registers.get_hl()] = self.registers.a; (1, 2) },

0x22 => {
self.bus.write_byte(self.registers.get_hl(), self.registers.a);
self.bus[self.registers.get_hl()] = self.registers.a;
self.registers.set_hl(self.registers.get_hl().wrapping_add(1));
(1, 2)
},

0x32 => {
self.bus.write_byte(self.registers.get_hl(), self.registers.a);
self.bus[self.registers.get_hl()] = self.registers.a;
self.registers.set_hl(self.registers.get_hl().wrapping_sub(1));
(1, 2)
},
Expand All @@ -254,13 +255,15 @@ impl GameBoy {
0xF0 => { self.load_io_into_r(OneByteRegister::A); (2, 3) },

// Load R into RAM, with address specified by II
0xEA => { self.bus.write_byte(self.next_two(), self.registers.a); (3, 4) },
0xEA => { let ii = self.next_two(); self.bus[ii] = self.registers.a; (3, 4) },
0x08 => {
// This is a bit different from `0xEA`, because we need to load SP in,
// which is 2 bytes long
let (s, p) = split_u16_into_two_u8s(self.registers.sp);
self.bus.write_byte(self.next_two(), s);
self.bus.write_byte(self.next_two().wrapping_add(1), p);

let ii = self.next_two();
self.bus[ii] = s;
self.bus[ii.wrapping_add(1)] = p;

(3, 5)
}
Expand Down
12 changes: 5 additions & 7 deletions src/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@ impl GameBoy {
if self.gpu.steps == 456 {
self.gpu.steps = 0;
self.gpu.already_outputted_pixel = 0;
self.bus
.write_byte(0xFF44, self.bus.read(0xFF44).wrapping_add(1));
self.bus[0xFF44] = self.bus[0xFF44_u16.wrapping_add(1)];

if self.bus.read(0xFF44) == 144 {
if self.bus[0xFF44] == 144 {
self.gpu.state = GPUState::VBlank;
} else {
self.gpu.state = GPUState::OAMSearch;
Expand All @@ -62,11 +61,10 @@ impl GameBoy {
self.gpu.state = GPUState::OAMSearch;
if self.gpu.steps == 456 {
self.gpu.steps = 0;
self.bus
.write_byte(0xFF44, self.bus.read(0xFF44).wrapping_add(1));
self.bus[0xFF44] = self.bus[0xFF44].wrapping_add(1);

if self.bus.read(0xFF44) == 153 {
self.bus.write_byte(0xFF44, 0);
if self.bus[0xFF44] == 153 {
self.bus[0xFF44] = 0;
self.gpu.state = GPUState::OAMSearch;
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ impl GameBoy {
let (p, c) = split_u16_into_two_u8s(self.registers.pc);

self.registers.sp = self.registers.sp.wrapping_sub(1);
self.bus.write_byte(self.registers.sp, p);
self.bus[self.registers.sp] = p;
self.registers.sp = self.registers.sp.wrapping_sub(1);
self.bus.write_byte(self.registers.sp, c);
self.bus[self.registers.sp] = c;

self.registers.pc = pc_location;
}
Expand All @@ -55,15 +55,15 @@ impl GameBoy {
return;
}

let is_enabled: Interrupts = self.bus.read(0xFFFF).into();
let mut value: Interrupts = self.bus.read(0xFF0F).into();
let is_enabled: Interrupts = self.bus[0xFFFF].into();
let mut value: Interrupts = self.bus[0xFF0F].into();

// TODO: Make code DRYer
if is_enabled.vblank && value.vblank {
self.interrupt(0x40);

value.vblank = false;
self.bus.write_byte(0xFF0F, value.into());
self.bus[0xFF0F] = value.into();
}
}
}
2 changes: 1 addition & 1 deletion src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ mod cpu {

gb.step();

assert_eq!(0x01, gb.bus.read(gb.registers.get_hl().wrapping_sub(1)));
assert_eq!(0x01, gb.bus[gb.registers.get_hl().wrapping_sub(1)]);
assert_eq!(0x01, gb.registers.l);
}

Expand Down

0 comments on commit 6b7c15b

Please sign in to comment.