mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
Reduce get_tile_bytes calls
This commit is contained in:
parent
a67c7d5bb6
commit
66182da336
@ -58,7 +58,9 @@ pub struct Bus {
|
|||||||
impl Bus {
|
impl Bus {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let game_rom = match ROM::load_file("/home/fran/Development/Personal/Rust/rmg-001/ignore/mario-land.gb".to_string()) {
|
let game_rom = match ROM::load_file("/home/fran/Development/Personal/Rust/rmg-001/ignore/mario-land.gb".to_string()) {
|
||||||
|
// let game_rom = match ROM::load_file("ignore/dmg-acid2.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("ignore/mario-land.gb".to_string()) {
|
// let game_rom = match ROM::load_file("ignore/mario-land.gb".to_string()) {
|
||||||
|
// let game_rom = match ROM::load_file("ignore/tetris.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("ignore/mooneye/emulator-only/mbc1/bits_bank1.gb".to_string()) {
|
// let game_rom = match ROM::load_file("ignore/mooneye/emulator-only/mbc1/bits_bank1.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.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/01-special.gb".to_string()) {
|
||||||
|
137
src/ppu.rs
137
src/ppu.rs
@ -93,11 +93,12 @@ struct Sprite {
|
|||||||
x: u8,
|
x: u8,
|
||||||
y: u8,
|
y: u8,
|
||||||
tile_number: u8,
|
tile_number: u8,
|
||||||
|
palette: u8,
|
||||||
x_flip: bool,
|
x_flip: bool,
|
||||||
y_flip: bool,
|
y_flip: bool,
|
||||||
over_bg: bool,
|
over_bg: bool,
|
||||||
palette_one: bool,
|
|
||||||
is_long: bool,
|
is_long: bool,
|
||||||
|
bit_pixels: Option<[u8; 8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sprite {
|
impl Sprite {
|
||||||
@ -105,7 +106,7 @@ impl Sprite {
|
|||||||
self.x
|
self.x
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pixel(&self, lcd_x: u8, lcd_y: u8, bus: &Bus, last_bg_index: u8) -> Option<Pixel> {
|
pub fn get_pixel(&mut self, lcd_x: u8, lcd_y: u8, bus: &Bus, last_bg_index: u8) -> Option<Pixel> {
|
||||||
if lcd_x < self.x.saturating_sub(8) || lcd_x >= self.x {
|
if lcd_x < self.x.saturating_sub(8) || lcd_x >= self.x {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -118,10 +119,8 @@ impl Sprite {
|
|||||||
true => 16,
|
true => 16,
|
||||||
false => 8,
|
false => 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
let x = lcd_x.saturating_sub(self.x.saturating_sub(8));
|
let x = lcd_x.saturating_sub(self.x.saturating_sub(8));
|
||||||
let y = lcd_y.saturating_sub(self.y .saturating_sub(16));
|
let y = lcd_y.saturating_sub(self.y .saturating_sub(16));
|
||||||
|
|
||||||
let x = match self.x_flip {
|
let x = match self.x_flip {
|
||||||
true => 7 - x,
|
true => 7 - x,
|
||||||
false => x,
|
false => x,
|
||||||
@ -131,33 +130,38 @@ impl Sprite {
|
|||||||
false => y,
|
false => y,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut tile_number = self.tile_number;
|
let bit_pixel_index = (x as usize).rem_euclid(8);
|
||||||
|
|
||||||
if self.is_long && x <= 7 {
|
let bit_pixel = match self.bit_pixels {
|
||||||
tile_number = tile_number & 0xFE;
|
Some(bit_pixels_array) => {
|
||||||
} else if self.is_long && x > 7 {
|
bit_pixels_array[bit_pixel_index]
|
||||||
tile_number = tile_number | 0x01;
|
},
|
||||||
}
|
None => {
|
||||||
|
let mut tile_number = self.tile_number;
|
||||||
|
|
||||||
let tile_line = y.rem_euclid(height) * 2;
|
if self.is_long && x <= 7 {
|
||||||
let addr = 0x8000 + (tile_number as u16 * 16) + tile_line as u16;
|
tile_number = tile_number & 0xFE;
|
||||||
|
} else if self.is_long && x > 7 {
|
||||||
|
tile_number = tile_number | 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
let tile_byte_1 = bus.read(addr);
|
let tile_line = y.rem_euclid(height) * 2;
|
||||||
let tile_byte_2 = bus.read(addr + 1);
|
let addr = 0x8000 + (tile_number as u16 * 16) + tile_line as u16;
|
||||||
|
|
||||||
let pixels = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
let tile_byte_1 = bus.read(addr);
|
||||||
|
let tile_byte_2 = bus.read(addr + 1);
|
||||||
|
let bit_pixels_array = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
||||||
|
self.bit_pixels = Some(bit_pixels_array);
|
||||||
|
|
||||||
let index = (x as usize).rem_euclid(8);
|
bit_pixels_array[bit_pixel_index]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if pixels[index] == 0 {
|
if bit_pixel == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let palette = match self.palette_one {
|
Some(PPU::get_pixel(PPU::get_palette(bit_pixel, self.palette)))
|
||||||
true => bus.read(OBJECT_PALETTE_1_ADDRESS),
|
|
||||||
false => bus.read(OBJECT_PALETTE_0_ADDRESS),
|
|
||||||
};
|
|
||||||
Some(PPU::get_pixel(PPU::get_palette(pixels[index], palette)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +171,10 @@ pub struct PPU {
|
|||||||
sprite_buffer: Vec<Sprite>,
|
sprite_buffer: Vec<Sprite>,
|
||||||
window_y_counter: u8,
|
window_y_counter: u8,
|
||||||
last_bg_index: u8,
|
last_bg_index: u8,
|
||||||
|
bg_palette: u8,
|
||||||
lcd_control_cache: Option<u8>,
|
lcd_control_cache: Option<u8>,
|
||||||
|
current_background_pixels: Option<[u8; 8]>,
|
||||||
|
current_window_pixels: Option<[u8; 8]>,
|
||||||
lcd_y: u8,
|
lcd_y: u8,
|
||||||
scroll_x: u8,
|
scroll_x: u8,
|
||||||
scroll_y: u8,
|
scroll_y: u8,
|
||||||
@ -183,7 +190,10 @@ impl PPU {
|
|||||||
sprite_buffer: Vec::new(),
|
sprite_buffer: Vec::new(),
|
||||||
window_y_counter: 0,
|
window_y_counter: 0,
|
||||||
last_bg_index: 0,
|
last_bg_index: 0,
|
||||||
|
bg_palette: 0,
|
||||||
lcd_control_cache: None,
|
lcd_control_cache: None,
|
||||||
|
current_background_pixels: None,
|
||||||
|
current_window_pixels: None,
|
||||||
lcd_y: 0,
|
lcd_y: 0,
|
||||||
scroll_x: 0,
|
scroll_x: 0,
|
||||||
scroll_y: 0,
|
scroll_y: 0,
|
||||||
@ -291,6 +301,8 @@ impl PPU {
|
|||||||
if !self.get_lcd_control(bus, LCDControl::ObjectEnable) {
|
if !self.get_lcd_control(bus, LCDControl::ObjectEnable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let palette_0 = bus.read(OBJECT_PALETTE_0_ADDRESS);
|
||||||
|
let palette_1 = bus.read(OBJECT_PALETTE_1_ADDRESS);
|
||||||
let long_sprites = self.get_lcd_control(bus, LCDControl::ObjectSize);
|
let long_sprites = self.get_lcd_control(bus, LCDControl::ObjectSize);
|
||||||
let mut addr = SPRITE_ATTRIBUTE_TABLE.begin();
|
let mut addr = SPRITE_ATTRIBUTE_TABLE.begin();
|
||||||
while addr <= SPRITE_ATTRIBUTE_TABLE.end() {
|
while addr <= SPRITE_ATTRIBUTE_TABLE.end() {
|
||||||
@ -329,10 +341,14 @@ impl PPU {
|
|||||||
y,
|
y,
|
||||||
tile_number,
|
tile_number,
|
||||||
is_long: long_sprites,
|
is_long: long_sprites,
|
||||||
palette_one: get_bit(attributes, BitIndex::I4),
|
palette: match get_bit(attributes, BitIndex::I4) {
|
||||||
|
true => palette_1,
|
||||||
|
false => palette_0,
|
||||||
|
},
|
||||||
x_flip: get_bit(attributes, BitIndex::I5),
|
x_flip: get_bit(attributes, BitIndex::I5),
|
||||||
y_flip: get_bit(attributes, BitIndex::I6),
|
y_flip: get_bit(attributes, BitIndex::I6),
|
||||||
over_bg: get_bit(attributes, BitIndex::I7),
|
over_bg: get_bit(attributes, BitIndex::I7),
|
||||||
|
bit_pixels: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
addr += 4;
|
addr += 4;
|
||||||
@ -340,9 +356,9 @@ impl PPU {
|
|||||||
self.sprite_buffer.sort_by(|a, b| a.x().cmp(&b.x()));
|
self.sprite_buffer.sort_by(|a, b| a.x().cmp(&b.x()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_sprite_pixel(&self, lcd_x: u8, bus: &Bus) -> Option<Pixel> {
|
fn find_sprite_pixel(&mut self, lcd_x: u8, bus: &Bus) -> Option<Pixel> {
|
||||||
let lcd_y = self.lcd_y;
|
let lcd_y = self.lcd_y;
|
||||||
for sprite in &self.sprite_buffer {
|
for sprite in &mut self.sprite_buffer {
|
||||||
if let Some(pixel) = sprite.get_pixel(lcd_x, lcd_y, bus, self.last_bg_index) {
|
if let Some(pixel) = sprite.get_pixel(lcd_x, lcd_y, bus, self.last_bg_index) {
|
||||||
return Some(pixel);
|
return Some(pixel);
|
||||||
}
|
}
|
||||||
@ -434,19 +450,32 @@ impl PPU {
|
|||||||
let x = lcd_x.wrapping_sub(window_x.saturating_sub(7));
|
let x = lcd_x.wrapping_sub(window_x.saturating_sub(7));
|
||||||
let y = self.window_y_counter;
|
let y = self.window_y_counter;
|
||||||
|
|
||||||
let default_mode = self.get_lcd_control(bus, LCDControl::TileAddressMode);
|
let bit_pixel_index = (x as usize).rem_euclid(8);
|
||||||
let tilemap_area = match self.get_lcd_control(bus, LCDControl::WindowTileMapAddress) {
|
if bit_pixel_index == 0 {
|
||||||
true => 0x9C00,
|
self.current_window_pixels = None;
|
||||||
false => 0x9800,
|
}
|
||||||
|
|
||||||
|
let bit_pixel = match self.current_window_pixels {
|
||||||
|
Some(bit_pixels_array) => {
|
||||||
|
bit_pixels_array[bit_pixel_index]
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let default_mode = self.get_lcd_control(bus, LCDControl::TileAddressMode);
|
||||||
|
let tilemap_area = match self.get_lcd_control(bus, LCDControl::WindowTileMapAddress) {
|
||||||
|
true => 0x9C00,
|
||||||
|
false => 0x9800,
|
||||||
|
};
|
||||||
|
let (tile_byte_1, tile_byte_2) = PPU::get_tile_bytes(x, y, tilemap_area, default_mode, bus);
|
||||||
|
let bit_pixels_array = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
||||||
|
self.current_window_pixels = Some(bit_pixels_array);
|
||||||
|
|
||||||
|
bit_pixels_array[bit_pixel_index]
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let (tile_byte_1, tile_byte_2) = PPU::get_tile_bytes(x, y, tilemap_area, default_mode, bus);
|
|
||||||
|
|
||||||
let palette = bus.read(BACKGROUND_PALETTE_ADDRESS);
|
self.last_bg_index = bit_pixel & 0b11;
|
||||||
let pixels = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
|
||||||
let index = pixels[(x as usize).rem_euclid(8)];
|
|
||||||
self.last_bg_index = index & 0b11;
|
|
||||||
|
|
||||||
Some(PPU::get_pixel(PPU::get_palette(index, palette)))
|
Some(PPU::get_pixel(PPU::get_palette(bit_pixel, self.bg_palette)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_background_pixel(&mut self, lcd_x: u8, bus: &Bus) -> Option<Pixel> {
|
fn get_background_pixel(&mut self, lcd_x: u8, bus: &Bus) -> Option<Pixel> {
|
||||||
@ -454,22 +483,34 @@ impl PPU {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let lcd_y = self.lcd_y;
|
let lcd_y = self.lcd_y;
|
||||||
let palette = bus.read(BACKGROUND_PALETTE_ADDRESS);
|
|
||||||
let y = lcd_y.wrapping_add(self.scroll_y);
|
let y = lcd_y.wrapping_add(self.scroll_y);
|
||||||
let x = lcd_x.wrapping_add(self.scroll_x);
|
let x = lcd_x.wrapping_add(self.scroll_x);
|
||||||
|
let bit_pixel_index = x.rem_euclid(8) as usize;
|
||||||
|
|
||||||
let default_mode = self.get_lcd_control(bus, LCDControl::TileAddressMode);
|
if bit_pixel_index == 0 {
|
||||||
let tilemap_area = match self.get_lcd_control(bus, LCDControl::BackgroundTileMapAddress) {
|
self.current_background_pixels = None;
|
||||||
true => 0x9C00,
|
}
|
||||||
false => 0x9800,
|
|
||||||
|
let bit_pixel = match self.current_background_pixels {
|
||||||
|
Some(bit_pixels_array) => {
|
||||||
|
bit_pixels_array[bit_pixel_index]
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let default_mode = self.get_lcd_control(bus, LCDControl::TileAddressMode);
|
||||||
|
let tilemap_area = match self.get_lcd_control(bus, LCDControl::BackgroundTileMapAddress) {
|
||||||
|
true => 0x9C00,
|
||||||
|
false => 0x9800,
|
||||||
|
};
|
||||||
|
let (tile_byte_1, tile_byte_2) = PPU::get_tile_bytes(x, y, tilemap_area, default_mode, bus);
|
||||||
|
let bit_pixels_array = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
||||||
|
self.current_background_pixels = Some(bit_pixels_array);
|
||||||
|
|
||||||
|
bit_pixels_array[bit_pixel_index]
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let (tile_byte_1, tile_byte_2) = PPU::get_tile_bytes(x, y, tilemap_area, default_mode, bus);
|
self.last_bg_index = bit_pixel & 0b11;
|
||||||
|
|
||||||
let bg_pixels = PPU::get_byte_pixels(tile_byte_1, tile_byte_2);
|
Some(PPU::get_pixel(PPU::get_palette(bit_pixel, self.bg_palette)))
|
||||||
let index = bg_pixels[x.rem_euclid(8) as usize];
|
|
||||||
self.last_bg_index = index & 0b11;
|
|
||||||
|
|
||||||
Some(PPU::get_pixel(PPU::get_palette(index, palette)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_line(&mut self, bus: &Bus, frame_buffer: &mut [u8]) {
|
fn draw_line(&mut self, bus: &Bus, frame_buffer: &mut [u8]) {
|
||||||
@ -477,6 +518,10 @@ impl PPU {
|
|||||||
if lcd_y as u32 >= LCD_HEIGHT {
|
if lcd_y as u32 >= LCD_HEIGHT {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self.current_background_pixels = None;
|
||||||
|
self.current_window_pixels = None;
|
||||||
|
|
||||||
|
self.bg_palette = bus.read(BACKGROUND_PALETTE_ADDRESS);
|
||||||
let mut lcd_x: u8 = 0;
|
let mut lcd_x: u8 = 0;
|
||||||
let mut window_drawn = false;
|
let mut window_drawn = false;
|
||||||
while (lcd_x as u32) < LCD_WIDTH {
|
while (lcd_x as u32) < LCD_WIDTH {
|
||||||
|
Loading…
Reference in New Issue
Block a user