diff --git a/lib_gb/src/ppu/fifo/bg_fetcher.rs b/lib_gb/src/ppu/fifo/bg_fetcher.rs index 05fac806..6161b044 100644 --- a/lib_gb/src/ppu/fifo/bg_fetcher.rs +++ b/lib_gb/src/ppu/fifo/bg_fetcher.rs @@ -10,6 +10,7 @@ pub struct BGFetcher{ rendered_window:bool, rendering_window:bool, current_fetching_state:FethcingState, + t_cycles_counter:u8, } impl BGFetcher{ @@ -20,7 +21,8 @@ impl BGFetcher{ fifo:Vec::::with_capacity(8), window_line_counter:0, rendered_window:false, - rendering_window:false + rendering_window:false, + t_cycles_counter:0 } } @@ -30,10 +32,12 @@ impl BGFetcher{ self.current_fetching_state = FethcingState::TileNumber; self.rendered_window = false; self.rendering_window = false; + self.t_cycles_counter = 0; } pub fn pause(&mut self){ self.current_fetching_state = FethcingState::TileNumber; + self.t_cycles_counter = 0; } pub fn try_increment_window_counter(&mut self){ @@ -43,6 +47,11 @@ impl BGFetcher{ } pub fn fetch_pixels(&mut self, vram:&VRam, lcd_control:u8, ly_register:u8, window_pos:&Vec2, bg_pos:&Vec2){ + if self.t_cycles_counter % 2 == 0{ + self.t_cycles_counter = (self.t_cycles_counter + 1) % 8; + return; + } + let last_rendering_status = self.rendering_window; self.rendering_window = self.is_redering_wnd(lcd_control, window_pos, ly_register); if self.rendering_window{ @@ -105,6 +114,8 @@ impl BGFetcher{ } } } + + self.t_cycles_counter = (self.t_cycles_counter + 1) % 8; } fn get_tila_data_address(&self, lcd_control:u8, bg_pos:&Vec2, ly_register:u8, tile_num:u8)->u16{ diff --git a/lib_gb/src/ppu/fifo/fifo_ppu.rs b/lib_gb/src/ppu/fifo/fifo_ppu.rs index 7b2308fe..148a0dbe 100644 --- a/lib_gb/src/ppu/fifo/fifo_ppu.rs +++ b/lib_gb/src/ppu/fifo/fifo_ppu.rs @@ -214,31 +214,31 @@ impl FifoPpu{ self.t_cycles_passed += 2; } PpuState::PixelTransfer=>{ - if self.pixel_x_pos < 160{ - if self.lcd_control & BIT_1_MASK != 0{ - self.sprite_fetcher.fetch_pixels(&self.vram, self.lcd_control, self.ly_register, self.pixel_x_pos); - } - if self.sprite_fetcher.rendering{ - self.bg_fetcher.pause(); - } - else{ - self.bg_fetcher.fetch_pixels(&self.vram, self.lcd_control, self.ly_register, &self.window_pos, &self.bg_pos); - for _ in 0..2{ - self.try_push_to_lcd(); - if self.pixel_x_pos == 160 { - self.state = PpuState::Hblank; - if self.h_blank_interrupt_request{ - self.trigger_stat_interrupt = true; - } - self.bg_fetcher.try_increment_window_counter(); - self.bg_fetcher.reset(); - self.sprite_fetcher.reset(); + for _ in 0..2{ + if self.pixel_x_pos < 160{ + if self.lcd_control & BIT_1_MASK != 0{ + self.sprite_fetcher.fetch_pixels(&self.vram, self.lcd_control, self.ly_register, self.pixel_x_pos); + } + if self.sprite_fetcher.rendering{ + self.bg_fetcher.pause(); + } + else{ + self.bg_fetcher.fetch_pixels(&self.vram, self.lcd_control, self.ly_register, &self.window_pos, &self.bg_pos); + self.try_push_to_lcd(); + if self.pixel_x_pos == 160 { + self.state = PpuState::Hblank; + if self.h_blank_interrupt_request{ + self.trigger_stat_interrupt = true; + } + self.bg_fetcher.try_increment_window_counter(); + self.bg_fetcher.reset(); + self.sprite_fetcher.reset(); - // If im on the first iteration and finished the 160 pixels break; - // In this case the number of t_cycles should be eneven but it will break - // my code way too much for now so Im leaving this as it is... (maybe in the future) - break; - } + // If im on the first iteration and finished the 160 pixels break; + // In this case the number of t_cycles should be eneven but it will break + // my code way too much for now so Im leaving this as it is... (maybe in the future) + break; + } } } } diff --git a/lib_gb/src/ppu/fifo/sprite_fetcher.rs b/lib_gb/src/ppu/fifo/sprite_fetcher.rs index e311ce66..517a37f9 100644 --- a/lib_gb/src/ppu/fifo/sprite_fetcher.rs +++ b/lib_gb/src/ppu/fifo/sprite_fetcher.rs @@ -12,6 +12,7 @@ pub struct SpriteFetcher{ current_fetching_state:FethcingState, current_oam_entry:u8, + t_cycle_inner_state_counter:u8, } impl SpriteFetcher{ @@ -34,7 +35,8 @@ impl SpriteFetcher{ oam_entries_len:0, oam_entries, fifo:Vec::<(u8,u8)>::with_capacity(8), - rendering:false + rendering:false, + t_cycle_inner_state_counter:0, } } @@ -42,6 +44,7 @@ impl SpriteFetcher{ self.current_oam_entry = 0; self.oam_entries_len = 0; self.current_fetching_state = FethcingState::TileNumber; + self.t_cycle_inner_state_counter = 0; self.fifo.clear(); self.rendering = false; } @@ -67,54 +70,63 @@ impl SpriteFetcher{ self.rendering = false; } FethcingState::LowTileData(tile_num)=>{ - let oam_attribute = &self.oam_entries[self.current_oam_entry as usize]; - let current_tile_data_address = Self::get_current_tile_data_address(ly_register, oam_attribute, sprite_size, tile_num); - let low_data = vram.read_current_bank(current_tile_data_address); - self.current_fetching_state = FethcingState::HighTileData(tile_num, low_data); + if self.t_cycle_inner_state_counter % 2 != 0{ + let oam_attribute = &self.oam_entries[self.current_oam_entry as usize]; + let current_tile_data_address = Self::get_current_tile_data_address(ly_register, oam_attribute, sprite_size, tile_num); + let low_data = vram.read_current_bank(current_tile_data_address); + self.current_fetching_state = FethcingState::HighTileData(tile_num, low_data); + } } FethcingState::HighTileData(tile_num, low_data)=>{ - let oam_attribute = &self.oam_entries[self.current_oam_entry as usize]; - let current_tile_data_address = Self::get_current_tile_data_address(ly_register, oam_attribute, sprite_size, tile_num); - let high_data = vram.read_current_bank(current_tile_data_address + 1); - self.current_fetching_state = FethcingState::Push(low_data, high_data); + if self.t_cycle_inner_state_counter % 2 != 0{ + let oam_attribute = &self.oam_entries[self.current_oam_entry as usize]; + let current_tile_data_address = Self::get_current_tile_data_address(ly_register, oam_attribute, sprite_size, tile_num); + let high_data = vram.read_current_bank(current_tile_data_address + 1); + self.current_fetching_state = FethcingState::Push(low_data, high_data); + } } FethcingState::Push(low_data, high_data)=>{ - let oam_attribute = &self.oam_entries[self.current_oam_entry as usize]; - let start_x = self.fifo.len(); - - let skip_x = 8 - (oam_attribute.x - current_x_pos) as usize; - - if oam_attribute.flip_x{ - for i in (0 + skip_x)..8{ - let mask = 1 << i; - let mut pixel = (low_data & mask) >> i; - pixel |= ((high_data & mask) >> i) << 1; - if i + skip_x >= start_x { - self.fifo.push((pixel, self.current_oam_entry)); - } - else if self.fifo[i + skip_x].0 == 0{ - self.fifo[i+ skip_x] = (pixel, self.current_oam_entry); + if self.t_cycle_inner_state_counter % 2 != 0{ + + let oam_attribute = &self.oam_entries[self.current_oam_entry as usize]; + let start_x = self.fifo.len(); + + let skip_x = 8 - (oam_attribute.x - current_x_pos) as usize; + + if oam_attribute.flip_x{ + for i in (0 + skip_x)..8{ + let mask = 1 << i; + let mut pixel = (low_data & mask) >> i; + pixel |= ((high_data & mask) >> i) << 1; + if i + skip_x >= start_x { + self.fifo.push((pixel, self.current_oam_entry)); + } + else if self.fifo[i + skip_x].0 == 0{ + self.fifo[i+ skip_x] = (pixel, self.current_oam_entry); + } } } - } - else{ - for i in (0..(8 - skip_x)).rev(){ - let mask = 1 << i; - let mut pixel = (low_data & mask) >> i; - pixel |= ((high_data & mask) >> i) << 1; - if 7 - skip_x - i >= start_x { - self.fifo.push((pixel, self.current_oam_entry)); - } - else if self.fifo[7 - skip_x - i].0 == 0{ - self.fifo[7 - skip_x - i] = (pixel, self.current_oam_entry); + else{ + for i in (0..(8 - skip_x)).rev(){ + let mask = 1 << i; + let mut pixel = (low_data & mask) >> i; + pixel |= ((high_data & mask) >> i) << 1; + if 7 - skip_x - i >= start_x { + self.fifo.push((pixel, self.current_oam_entry)); + } + else if self.fifo[7 - skip_x - i].0 == 0{ + self.fifo[7 - skip_x - i] = (pixel, self.current_oam_entry); + } } } - } - self.current_fetching_state = FethcingState::TileNumber; - self.current_oam_entry += 1; + self.current_fetching_state = FethcingState::TileNumber; + self.current_oam_entry += 1; + } } } + + self.t_cycle_inner_state_counter = (self.t_cycle_inner_state_counter + 1) % 8; } // Receiving the tile_num since in case of extended sprite this could change (the first bit is reset)