diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..288d6d7b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,338 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "cmake" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" +dependencies = [ + "cc", +] + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "encoding_rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "fern" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065" +dependencies = [ + "log", +] + +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80edafed416a46fb378521624fab1cfa2eb514784fd8921adbe8a8d8321da811" +dependencies = [ + "cfg-if 1.0.0", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lib_gb" +version = "1.0.0" +dependencies = [ + "log", +] + +[[package]] +name = "libc" +version = "0.2.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "magenboy" +version = "1.0.0" +dependencies = [ + "chrono", + "fern", + "lib_gb", + "log", + "sdl2", + "wav", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "riff" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9b1a3d5f46d53f4a3478e2be4a5a5ce5108ea58b100dcd139830eae7f79a3a1" + +[[package]] +name = "sdl2" +version = "0.34.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deecbc3fa9460acff5a1e563e05cb5f31bba0aa0c214bb49a43db8159176d54b" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.34.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a29aa21f175b5a41a6e26da572d5e5d1ee5660d35f9f9d0913e8a802098f74" +dependencies = [ + "cfg-if 0.1.10", + "cmake", + "flate2", + "libc", + "tar", + "unidiff", + "version-compare", +] + +[[package]] +name = "tar" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "unidiff" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a62719acf1933bfdbeb73a657ecd9ecece70b405125267dd549e2e2edc232c" +dependencies = [ + "encoding_rs", + "lazy_static", + "regex", +] + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wav" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "549df97e073e1f901a489f159eb451bbe9c790e2f217394f4ce01acda0380b0c" +dependencies = [ + "riff", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..5c90c705 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "gb", + "lib_gb" +] \ No newline at end of file diff --git a/lib_gb/src/ppu/fifo/bg_fetcher.rs b/lib_gb/src/ppu/fifo/bg_fetcher.rs index 01113385..4b2e4a87 100644 --- a/lib_gb/src/ppu/fifo/bg_fetcher.rs +++ b/lib_gb/src/ppu/fifo/bg_fetcher.rs @@ -1,5 +1,5 @@ use crate::{mmu::vram::VRam, utils::{bit_masks::*, vec2::Vec2}}; -use super::fetching_state::FethcingState; +use super::{fetcher_state_machine::FetcherStateMachine, fetching_state::*}; pub struct BGFetcher{ pub fifo:Vec, @@ -8,35 +8,32 @@ pub struct BGFetcher{ current_x_pos:u8, rendered_window:bool, rendering_window:bool, - current_fetching_state:FethcingState, - t_cycles_counter:u8, + fetcher_state_machine:FetcherStateMachine, } impl BGFetcher{ pub fn new()->Self{ + let state_machine = [FetchingState::Sleep, FetchingState::FetchTileNumber, FetchingState::Sleep, FetchingState::FetchLowTile, FetchingState::Sleep, FetchingState::FetchHighTile, FetchingState::Sleep, FetchingState::Push]; BGFetcher{ - current_fetching_state:FethcingState::TileNumber, + fetcher_state_machine:FetcherStateMachine::new(state_machine), current_x_pos:0, fifo:Vec::::with_capacity(8), window_line_counter:0, rendered_window:false, rendering_window:false, - t_cycles_counter:0 } } pub fn reset(&mut self){ self.fifo.clear(); self.current_x_pos = 0; - self.current_fetching_state = FethcingState::TileNumber; + self.fetcher_state_machine.reset(); 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; + self.fetcher_state_machine.reset(); } pub fn try_increment_window_counter(&mut self){ @@ -46,11 +43,6 @@ 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{ @@ -59,12 +51,12 @@ impl BGFetcher{ // In case I was rendering a background pixel need to reset the state of the fectcher // (and maybe clear the fifo but right now Im not doing it since im not sure what about the current_x_pos var) if !last_rendering_status{ - self.current_fetching_state = FethcingState::TileNumber; + self.fetcher_state_machine.reset(); } } - match self.current_fetching_state{ - FethcingState::TileNumber=>{ + match self.fetcher_state_machine.current_state(){ + FetchingState::FetchTileNumber=>{ let tile_num = if self.rendering_window{ let tile_map_address:u16 = if (lcd_control & BIT_6_MASK) == 0 {0x1800} else {0x1C00}; vram.read_current_bank(tile_map_address + (32 * (self.window_line_counter as u16 / 8)) + ((self.current_x_pos - window_pos.x) as u16 / 8)) @@ -77,21 +69,24 @@ impl BGFetcher{ vram.read_current_bank(tile_map_address + ((32 * scy_offset) + scx_offset)) }; - self.current_fetching_state = FethcingState::LowTileData(tile_num); + self.fetcher_state_machine.data = FetchingStateData{low_tile_data:tile_num}; } - FethcingState::LowTileData(tile_num)=>{ + FetchingState::FetchLowTile=>{ + let tile_num = unsafe{self.fetcher_state_machine.data.low_tile_data}; let address = self.get_tila_data_address(lcd_control, bg_pos, ly_register, tile_num); let low_data = vram.read_current_bank(address); - self.current_fetching_state = FethcingState::HighTileData(tile_num, low_data); + self.fetcher_state_machine.data = FetchingStateData{high_tile_data:(tile_num, low_data)}; } - FethcingState::HighTileData(tile_num, low_data)=>{ + FetchingState::FetchHighTile=>{ + let (tile_num, low_data) = unsafe{self.fetcher_state_machine.data.high_tile_data}; let address = self.get_tila_data_address(lcd_control, bg_pos, ly_register, tile_num); let high_data = vram.read_current_bank(address + 1); - self.current_fetching_state = FethcingState::Push(low_data, high_data); + self.fetcher_state_machine.data = FetchingStateData{push_data:(low_data, high_data)}; } - FethcingState::Push(low_data, high_data)=>{ + FetchingState::Push=>{ + let (low_data, high_data) = unsafe{self.fetcher_state_machine.data.push_data}; if self.fifo.is_empty(){ if lcd_control & BIT_0_MASK == 0{ for _ in 0..8{ @@ -108,13 +103,12 @@ impl BGFetcher{ self.current_x_pos += 1; } } - - self.current_fetching_state = FethcingState::TileNumber; } } + FetchingState::Sleep=>{} } - - self.t_cycles_counter = (self.t_cycles_counter + 1) % 8; + + self.fetcher_state_machine.advance(); } 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/fetcher_state_machine.rs b/lib_gb/src/ppu/fifo/fetcher_state_machine.rs new file mode 100644 index 00000000..e09f02d4 --- /dev/null +++ b/lib_gb/src/ppu/fifo/fetcher_state_machine.rs @@ -0,0 +1,30 @@ +use super::fetching_state::*; + +pub struct FetcherStateMachine{ + pub state:usize, + pub data:FetchingStateData, + pub state_machine:[FetchingState;8] +} + +impl FetcherStateMachine{ + pub fn advance(&mut self){ + self.state = (self.state + 1) % 8; + } + + pub fn new(state_machine:[FetchingState;8])->Self{ + Self{ + data:FetchingStateData{low_tile_data:0}, + state:0, + state_machine + } + } + + pub fn reset(&mut self){ + self.state = 0; + self.data.low_tile_data = 0; + } + + pub fn current_state(&self)->&FetchingState{ + &self.state_machine[self.state] + } +} \ No newline at end of file diff --git a/lib_gb/src/ppu/fifo/fetching_state.rs b/lib_gb/src/ppu/fifo/fetching_state.rs index 086456a9..bd2cf339 100644 --- a/lib_gb/src/ppu/fifo/fetching_state.rs +++ b/lib_gb/src/ppu/fifo/fetching_state.rs @@ -1,6 +1,13 @@ -pub enum FethcingState{ - TileNumber, - LowTileData(u8), - HighTileData(u8,u8), - Push(u8,u8) +pub enum FetchingState{ + FetchTileNumber, + FetchLowTile, + FetchHighTile, + Push, + Sleep +} + +pub union FetchingStateData{ + pub low_tile_data:u8, + pub high_tile_data:(u8,u8), + pub push_data:(u8,u8) } \ No newline at end of file diff --git a/lib_gb/src/ppu/fifo/fifo_ppu.rs b/lib_gb/src/ppu/fifo/fifo_ppu.rs index 759bf826..c1bc9452 100644 --- a/lib_gb/src/ppu/fifo/fifo_ppu.rs +++ b/lib_gb/src/ppu/fifo/fifo_ppu.rs @@ -223,27 +223,24 @@ impl FifoPpu{ } 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; + 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; + } } } } - - - self.t_cycles_passed += 2; } } diff --git a/lib_gb/src/ppu/fifo/mod.rs b/lib_gb/src/ppu/fifo/mod.rs index 948958b3..e8e06684 100644 --- a/lib_gb/src/ppu/fifo/mod.rs +++ b/lib_gb/src/ppu/fifo/mod.rs @@ -2,4 +2,5 @@ pub mod fifo_ppu; pub mod fifo_register_updater; mod bg_fetcher; mod fetching_state; +mod fetcher_state_machine; mod sprite_fetcher; \ No newline at end of file diff --git a/lib_gb/src/ppu/fifo/sprite_fetcher.rs b/lib_gb/src/ppu/fifo/sprite_fetcher.rs index 9b720c5a..9bb90cd3 100644 --- a/lib_gb/src/ppu/fifo/sprite_fetcher.rs +++ b/lib_gb/src/ppu/fifo/sprite_fetcher.rs @@ -1,8 +1,6 @@ use std::mem::{self, MaybeUninit}; - use crate::{mmu::vram::VRam, ppu::sprite_attribute::SpriteAttribute, utils::bit_masks::{BIT_0_MASK, BIT_2_MASK}}; - -use super::fetching_state::FethcingState; +use super::{fetcher_state_machine::FetcherStateMachine, fetching_state::*}; pub struct SpriteFetcher{ pub fifo:Vec<(u8, u8)>, @@ -10,9 +8,8 @@ pub struct SpriteFetcher{ pub oam_entries_len:u8, pub rendering:bool, - current_fetching_state:FethcingState, + fetcher_state_machine:FetcherStateMachine, current_oam_entry:u8, - t_cycle_inner_state_counter:u8, } impl SpriteFetcher{ @@ -27,22 +24,22 @@ impl SpriteFetcher{ unsafe{mem::transmute::<_, [SpriteAttribute;10]>(data)} }; + let state_machine:[FetchingState;8] = [FetchingState::FetchTileNumber, FetchingState::FetchTileNumber, FetchingState::Sleep, FetchingState::FetchLowTile, FetchingState::Sleep, FetchingState::FetchHighTile, FetchingState::Sleep, FetchingState::Push]; + SpriteFetcher{ - current_fetching_state:FethcingState::TileNumber, + fetcher_state_machine:FetcherStateMachine::new(state_machine), current_oam_entry:0, oam_entries_len:0, oam_entries, fifo:Vec::<(u8,u8)>::with_capacity(8), rendering:false, - t_cycle_inner_state_counter:0, } } pub fn reset(&mut self){ self.current_oam_entry = 0; self.oam_entries_len = 0; - self.current_fetching_state = FethcingState::TileNumber; - self.t_cycle_inner_state_counter = 0; + self.fetcher_state_machine.reset(); self.fifo.clear(); self.rendering = false; } @@ -50,81 +47,83 @@ impl SpriteFetcher{ pub fn fetch_pixels(&mut self, vram:&VRam, lcd_control:u8, ly_register:u8, current_x_pos:u8){ let sprite_size = if lcd_control & BIT_2_MASK == 0 {8} else{16}; - match self.current_fetching_state{ - FethcingState::TileNumber=>{ - if self.oam_entries_len > self.current_oam_entry{ - let oam_entry = &self.oam_entries[self.current_oam_entry as usize]; - if oam_entry.x <= current_x_pos + 8 && current_x_pos < oam_entry.x{ - let mut tile_number = oam_entry.tile_number; - if lcd_control & BIT_2_MASK != 0{ - tile_number &= !BIT_0_MASK - } - self.current_fetching_state = FethcingState::LowTileData(tile_number); - self.rendering = true; - return; - } - } - // Reach here if not rendering this time a sprite - self.rendering = false; + match self.fetcher_state_machine.current_state(){ + FetchingState::FetchTileNumber=>{ + self.try_fetch_tile_number(current_x_pos, lcd_control); } - FethcingState::LowTileData(tile_num)=>{ - 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); - } + FetchingState::FetchLowTile=>{ + let tile_num = unsafe{self.fetcher_state_machine.data.low_tile_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 low_data = vram.read_current_bank(current_tile_data_address); + self.fetcher_state_machine.data = FetchingStateData{high_tile_data:(tile_num, low_data)}; + self.fetcher_state_machine.advance(); } - 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 high_data = vram.read_current_bank(current_tile_data_address + 1); - self.current_fetching_state = FethcingState::Push(low_data, high_data); - } + FetchingState::FetchHighTile=>{ + let (tile_num, low_data) = unsafe{self.fetcher_state_machine.data.high_tile_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.fetcher_state_machine.data = FetchingStateData{push_data:(low_data, high_data)}; + self.fetcher_state_machine.advance(); } - 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 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); - } + FetchingState::Push=>{ + let (low_data, high_data) = unsafe{self.fetcher_state_machine.data.push_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); } } - 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_oam_entry += 1; + self.fetcher_state_machine.advance(); } + FetchingState::Sleep=>self.fetcher_state_machine.advance() } + } - self.t_cycle_inner_state_counter = (self.t_cycle_inner_state_counter + 1) % 8; + //This is a function on order to abort if rendering + fn try_fetch_tile_number(&mut self, current_x_pos: u8, lcd_control: u8) { + if self.oam_entries_len > self.current_oam_entry{ + let oam_entry = &self.oam_entries[self.current_oam_entry as usize]; + if oam_entry.x <= current_x_pos + 8 && current_x_pos < oam_entry.x{ + let mut tile_number = oam_entry.tile_number; + if lcd_control & BIT_2_MASK != 0{ + tile_number &= !BIT_0_MASK + } + self.rendering = true; + self.fetcher_state_machine.data = FetchingStateData{low_tile_data:tile_number}; + self.fetcher_state_machine.advance(); + return; + } + } + self.rendering = false; } // Receiving the tile_num since in case of extended sprite this could change (the first bit is reset)