diff --git a/src/bus.rs b/src/bus.rs index 411699b..d79f395 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -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 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 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 { diff --git a/src/cpu.rs b/src/cpu.rs index e92cdff..25e531b 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -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] } } @@ -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)); } @@ -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) }, @@ -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) } diff --git a/src/gpu.rs b/src/gpu.rs index 005dadd..e076912 100644 --- a/src/gpu.rs +++ b/src/gpu.rs @@ -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; @@ -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; } } diff --git a/src/interrupts.rs b/src/interrupts.rs index 97f6672..9b09e82 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -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; } @@ -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(); } } } diff --git a/src/tests.rs b/src/tests.rs index 7d0d8d0..3982495 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -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); }