fn draw_8_pixels(
        &self,
        framebuffer: &[Cell<u32>; 256 * 240],
        bus: &mut dyn PpuAddressBus,
    ) -> bool {
        // NOTE: this function is also split into subfunctions
        {
            if self.is_background_enable() || self.is_sprites_enable() {
                return draw_8_pixels_bg_and_sprites(self, framebuffer, bus);
            } else {
                draw_8_pixels_backdrop_color(self, framebuffer, bus);
                return false;
            }
        }

        fn draw_8_pixels_bg_and_sprites(
            ppu: &Ppu,
            framebuffer: &[Cell<u32>; 256 * 240],
            bus: &dyn PpuAddressBus,
        ) -> bool {
            let mut sprite_zero_hit = false;

            for i in 0..8 {
                let tile_offset = i + ppu.bits.fine_x_scroll.get();

                let bg_color_idx = match (
                    ppu.is_background_enable(),
                    ppu.current_scanline_dot + i as u16,
                    ppu.is_background_left_column_enable(),
                ) {
                    // set index to zero if bg is disabled
                    (false, _, _) => 0,
                    // or if on dots 1-8 and bg is disabled for this area
                    (_, 1..=8, false) => 0,
                    _ => {
                        let lo = ((ppu.bg_state.tile_bitplanes_lo.to_u16() >> (15 - tile_offset))
                            & 1) as u8;
                        let hi = (((ppu.bg_state.tile_bitplanes_hi.to_u16() >> (15 - tile_offset))
                            << 1)
                            & 2) as u8;
                        lo | hi
                    }
                };

                let bg_palette_idx = if tile_offset > 7 {
                    ppu.bg_state.tile_palette_indices & 0b11
                } else {
                    (ppu.bg_state.tile_palette_indices & 0b1100) >> 2
                };

                let mut sprite_zero = false;

                let pixel_color = match (
                    ppu.is_sprites_enable(),
                    ppu.current_scanline_dot + i as u16,
                    ppu.is_sprites_left_column_enable(),
                ) {
                    // draw bg color if sprites are disabled
                    (false, _, _) => calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus),
                    // draw bg color if on dots 1-8 and sprite
                    // drawing is disabled for the first 8 pixels
                    (_, 1..=8, false) => calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus),
                    // otherwise, search for an active, non-transparent sprite at the current dot
                    _ => match ppu
                        .sprite_state
                        .get_sprite_at_dot_info(ppu.current_scanline_dot + i as u16)
                    {
                        // draw bg color if no sprite was found
                        None => calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus),
                        Some(info) => {
                            sprite_zero = info.is_sprite_zero;

                            if info.is_in_front || bg_color_idx == 0 {
                                calc_pixel_color(ppu, info.palette_index, info.color_index, bus)
                            } else {
                                calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus)
                            }
                        }
                    },
                };

                if sprite_zero
                    && bg_color_idx != 0
                    && (ppu.current_scanline_dot + i as u16 - 1) != 0xff
                {
                    sprite_zero_hit = true;
                }

                let screen_x = (ppu.current_scanline_dot - 1) as usize + i as usize;
                let screen_y = ppu.current_scanline as usize;

                // OPTIMIZE: unchecked indexing
                framebuffer[screen_y * 256 + screen_x].set(pixel_color);
            }

            sprite_zero_hit
        }

        // draws 8 pixels of backdrop color (or if 'current_vram_addr'
        // >= 0x3f00, draws the color 'current_vram_addr' points to)
        fn draw_8_pixels_backdrop_color(
            ppu: &Ppu,
            framebuffer: &[Cell<u32>; 256 * 240],
            bus: &dyn PpuAddressBus,
        ) {
            for i in 0..8 {
                let pixel_color = {
                    let bg_color_idx = if ppu.current_vram_addr.get_addr() >= 0x3f00 {
                        logln!("background palette hack triggered");
                        (ppu.current_vram_addr.get_addr() & 0b11111) as u8
                    } else {
                        0
                    };

                    let bg_color_byte = bus.read_palette_memory(bg_color_idx);

                    palette::COLOR_LUT.get(
                        bg_color_byte,
                        ppu.is_greyscale_enabled(),
                        ppu.ppumask >> 5,
                    )
                };

                let screen_x = (ppu.current_scanline_dot - 1 + i as u16) as usize;
                let screen_y = ppu.current_scanline as usize;
                framebuffer[screen_y * 256 + screen_x].set(pixel_color);
            }
        }

        fn calc_pixel_color(
            ppu: &Ppu,
            palette_idx: u8,
            color_idx: u8,
            bus: &dyn PpuAddressBus,
        ) -> u32 {
            let final_idx = if color_idx == 0 {
                0
            } else {
                (((palette_idx << 2) as u16) | (color_idx as u16)) as u8
            };

            let color_byte = bus.read_palette_memory(final_idx);
            palette::COLOR_LUT.get(color_byte, ppu.is_greyscale_enabled(), ppu.ppumask >> 5)
        }
    }
// draws 8 pixels, without making any state changes to 'self'.
// returns whether sprite zero was hit
draws 8 pixels, without making any state changes to 'self'.
returns whether sprite zero was hit
draws 8 pixels without making any state changes to ' self ' . returns whether sprite zero was hit
fn draw_8_pixels(
        &self,
        framebuffer: &[Cell<u32>; 256 * 240],
        bus: &mut dyn PpuAddressBus,
    ) -> bool {
        // NOTE: this function is also split into subfunctions
        {
            if self.is_background_enable() || self.is_sprites_enable() {
                return draw_8_pixels_bg_and_sprites(self, framebuffer, bus);
            } else {
                draw_8_pixels_backdrop_color(self, framebuffer, bus);
                return false;
            }
        }
        fn draw_8_pixels_bg_and_sprites(
            ppu: &Ppu,
            framebuffer: &[Cell<u32>; 256 * 240],
            bus: &dyn PpuAddressBus,
        ) -> bool {
            let mut sprite_zero_hit = false;
            for i in 0..8 {
                let tile_offset = i + ppu.bits.fine_x_scroll.get();
                let bg_color_idx = match (
                    ppu.is_background_enable(),
                    ppu.current_scanline_dot + i as u16,
                    ppu.is_background_left_column_enable(),
                ) {
                    // set index to zero if bg is disabled
                    (false, _, _) => 0,
                    // or if on dots 1-8 and bg is disabled for this area
                    (_, 1..=8, false) => 0,
                    _ => {
                        let lo = ((ppu.bg_state.tile_bitplanes_lo.to_u16() >> (15 - tile_offset))
                            & 1) as u8;
                        let hi = (((ppu.bg_state.tile_bitplanes_hi.to_u16() >> (15 - tile_offset))
                            << 1)
                            & 2) as u8;
                        lo | hi
                    }
                };
                let bg_palette_idx = if tile_offset > 7 {
                    ppu.bg_state.tile_palette_indices & 0b11
                } else {
                    (ppu.bg_state.tile_palette_indices & 0b1100) >> 2
                };
                let mut sprite_zero = false;
                let pixel_color = match (
                    ppu.is_sprites_enable(),
                    ppu.current_scanline_dot + i as u16,
                    ppu.is_sprites_left_column_enable(),
                ) {
                    // draw bg color if sprites are disabled
                    (false, _, _) => calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus),
                    // draw bg color if on dots 1-8 and sprite
                    // drawing is disabled for the first 8 pixels
                    (_, 1..=8, false) => calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus),
                    // otherwise, search for an active, non-transparent sprite at the current dot
                    _ => match ppu
                        .sprite_state
                        .get_sprite_at_dot_info(ppu.current_scanline_dot + i as u16)
                    {
                        // draw bg color if no sprite was found
                        None => calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus),
                        Some(info) => {
                            sprite_zero = info.is_sprite_zero;
                            if info.is_in_front || bg_color_idx == 0 {
                                calc_pixel_color(ppu, info.palette_index, info.color_index, bus)
                            } else {
                                calc_pixel_color(ppu, bg_palette_idx, bg_color_idx, bus)
                            }
                        }
                    },
                };
                if sprite_zero
                    && bg_color_idx != 0
                    && (ppu.current_scanline_dot + i as u16 - 1) != 0xff
                {
                    sprite_zero_hit = true;
                }
                let screen_x = (ppu.current_scanline_dot - 1) as usize + i as usize;
                let screen_y = ppu.current_scanline as usize;
                // OPTIMIZE: unchecked indexing
                framebuffer[screen_y * 256 + screen_x].set(pixel_color);
            }
            sprite_zero_hit
        }
        // draws 8 pixels of backdrop color (or if 'current_vram_addr'
        // >= 0x3f00, draws the color 'current_vram_addr' points to)
        fn draw_8_pixels_backdrop_color(
            ppu: &Ppu,
            framebuffer: &[Cell<u32>; 256 * 240],
            bus: &dyn PpuAddressBus,
        ) {
            for i in 0..8 {
                let pixel_color = {
                    let bg_color_idx = if ppu.current_vram_addr.get_addr() >= 0x3f00 {
                        logln!("background palette hack triggered");
                        (ppu.current_vram_addr.get_addr() & 0b11111) as u8
                    } else {
                        0
                    };
                    let bg_color_byte = bus.read_palette_memory(bg_color_idx);
                    palette::COLOR_LUT.get(
                        bg_color_byte,
                        ppu.is_greyscale_enabled(),
                        ppu.ppumask >> 5,
                    )
                };
                let screen_x = (ppu.current_scanline_dot - 1 + i as u16) as usize;
                let screen_y = ppu.current_scanline as usize;
                framebuffer[screen_y * 256 + screen_x].set(pixel_color);
            }
        }
        fn calc_pixel_color(
            ppu: &Ppu,
            palette_idx: u8,
            color_idx: u8,
            bus: &dyn PpuAddressBus,
        ) -> u32 {
            let final_idx = if color_idx == 0 {
                0
            } else {
                (((palette_idx << 2) as u16) | (color_idx as u16)) as u8
            };
            let color_byte = bus.read_palette_memory(final_idx);
            palette::COLOR_LUT.get(color_byte, ppu.is_greyscale_enabled(), ppu.ppumask >> 5)
        }
    }
fn draw_8_pixels ( & self , framebuffer : & [ Cell < u32 > ; 256 * 240 ] , bus : & mut dyn PpuAddressBus , ) -> bool { // NOTE: this function is also split into subfunctions { if self . is_background_enable ( ) || self . is_sprites_enable ( ) { return draw_8_pixels_bg_and_sprites ( self , framebuffer , bus ) ; } else { draw_8_pixels_backdrop_color ( self , framebuffer , bus ) ; return false ; } } fn draw_8_pixels_bg_and_sprites ( ppu : & Ppu , framebuffer : & [ Cell < u32 > ; 256 * 240 ] , bus : & dyn PpuAddressBus , ) -> bool { let mut sprite_zero_hit = false ; for i in 0 .. 8 { let tile_offset = i + ppu . bits . fine_x_scroll . get ( ) ; let bg_color_idx = match ( ppu . is_background_enable ( ) , ppu . current_scanline_dot + i as u16 , ppu . is_background_left_column_enable ( ) , ) { // set index to zero if bg is disabled ( false , _ , _ ) => 0 , // or if on dots 1-8 and bg is disabled for this area ( _ , 1 ..= 8 , false ) => 0 , _ => { let lo = ( ( ppu . bg_state . tile_bitplanes_lo . to_u16 ( ) >> ( 15 - tile_offset ) ) & 1 ) as u8 ; let hi = ( ( ( ppu . bg_state . tile_bitplanes_hi . to_u16 ( ) >> ( 15 - tile_offset ) ) << 1 ) & 2 ) as u8 ; lo | hi } } ; let bg_palette_idx = if tile_offset > 7 { ppu . bg_state . tile_palette_indices & 0b11 } else { ( ppu . bg_state . tile_palette_indices & 0b1100 ) >> 2 } ; let mut sprite_zero = false ; let pixel_color = match ( ppu . is_sprites_enable ( ) , ppu . current_scanline_dot + i as u16 , ppu . is_sprites_left_column_enable ( ) , ) { // draw bg color if sprites are disabled ( false , _ , _ ) => calc_pixel_color ( ppu , bg_palette_idx , bg_color_idx , bus ) , // draw bg color if on dots 1-8 and sprite // drawing is disabled for the first 8 pixels ( _ , 1 ..= 8 , false ) => calc_pixel_color ( ppu , bg_palette_idx , bg_color_idx , bus ) , // otherwise, search for an active, non-transparent sprite at the current dot _ => match ppu . sprite_state . get_sprite_at_dot_info ( ppu . current_scanline_dot + i as u16 ) { // draw bg color if no sprite was found None => calc_pixel_color ( ppu , bg_palette_idx , bg_color_idx , bus ) , Some ( info ) => { sprite_zero = info . is_sprite_zero ; if info . is_in_front || bg_color_idx == 0 { calc_pixel_color ( ppu , info . palette_index , info . color_index , bus ) } else { calc_pixel_color ( ppu , bg_palette_idx , bg_color_idx , bus ) } } } , } ; if sprite_zero && bg_color_idx != 0 && ( ppu . current_scanline_dot + i as u16 - 1 ) != 0xff { sprite_zero_hit = true ; } let screen_x = ( ppu . current_scanline_dot - 1 ) as usize + i as usize ; let screen_y = ppu . current_scanline as usize ; // OPTIMIZE: unchecked indexing framebuffer [ screen_y * 256 + screen_x ] . set ( pixel_color ) ; } sprite_zero_hit } // draws 8 pixels of backdrop color (or if 'current_vram_addr' // >= 0x3f00, draws the color 'current_vram_addr' points to) fn draw_8_pixels_backdrop_color ( ppu : & Ppu , framebuffer : & [ Cell < u32 > ; 256 * 240 ] , bus : & dyn PpuAddressBus , ) { for i in 0 .. 8 { let pixel_color = { let bg_color_idx = if ppu . current_vram_addr . get_addr ( ) >= 0x3f00 { logln ! ( " " ) ; ( ppu . current_vram_addr . get_addr ( ) & 0b11111 ) as u8 } else { 0 } ; let bg_color_byte = bus . read_palette_memory ( bg_color_idx ) ; palette :: COLOR_LUT . get ( bg_color_byte , ppu . is_greyscale_enabled ( ) , ppu . ppumask >> 5 , ) } ; let screen_x = ( ppu . current_scanline_dot - 1 + i as u16 ) as usize ; let screen_y = ppu . current_scanline as usize ; framebuffer [ screen_y * 256 + screen_x ] . set ( pixel_color ) ; } } fn calc_pixel_color ( ppu : & Ppu , palette_idx : u8 , color_idx : u8 , bus : & dyn PpuAddressBus , ) -> u32 { let final_idx = if color_idx == 0 { 0 } else { ( ( ( palette_idx << 2 ) as u16 ) | ( color_idx as u16 ) ) as u8 } ; let color_byte = bus . read_palette_memory ( final_idx ) ; palette :: COLOR_LUT . get ( color_byte , ppu . is_greyscale_enabled ( ) , ppu . ppumask >> 5 ) } }
draws 8 pixels, without making any state changes to 'self'.
draws 8 pixels without making any state changes to ' self ' .
&self
framebuffer
&[Cell<u32>; 256 * 240]
bus
&mut dyn PpuAddressBus
&self
framebuffer
&[Cell<u32>; 256 * 240]
bus
&mut dyn PpuAddressBus