pub fn cycle(&mut self, cpu_duration: u8) -> u8 {
        let mut int_flag = 0x00;

        if self
            .registers
            .control
            .contains(ControlFlags::DISPLAY_ENABLE)
        {
            self.mode_clock += cpu_duration as usize;

            let status_int_flags: StatusInterruptFlags =
                StatusInterruptFlags::from_bits_truncate(self.read8(0xFF41));

            // If the interrupt for LY Coincidence is set, and it's a coincidence, set interrupt bit
            if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_LYC)
                && self.registers.ly == self.registers.lyc
            {
                // Set interrupt bit
                int_flag |= INT_LCD_STAT;
            }

            match self.mode {
                // OAM read mode, scanline active
                Mode::ReadOam => {
                    if self.mode_clock >= 80 {
                        // Enter scanline Mode::ReadVram
                        self.mode_clock = 0;
                        self.mode = Mode::ReadVram;
                    }
                }
                // VRAM read mode, scanline active
                // Treat end of Mode::ReadVram as end of scanline
                Mode::ReadVram => {
                    if self.mode_clock >= 172 {
                        // Enter hblank
                        self.mode_clock = 0;
                        self.mode = Mode::HBlank;
                        if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_HBLANK) {
                            // Set interrupt bit
                            int_flag |= INT_LCD_STAT;
                        }

                        // Write a scanline to the framebuffer
                        self.renderscan();
                    }
                }

                // Hblank
                // After the last hblank, push the screen data to canvas
                Mode::HBlank => {
                    if self.mode_clock >= 204 {
                        self.mode_clock = 0;
                        self.registers.ly += 1;

                        if self.registers.ly == 144 {
                            // Enter vblank
                            self.mode = Mode::VBlank;
                            // Set interrupt bit
                            int_flag |= INT_VBLANK;
                            if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_VBLANK) {
                                // Set interrupt bit
                                int_flag |= INT_LCD_STAT;
                            }
                            self.gpu.load_texture(self.screen_buffer.as_ref());
                        } else {
                            self.mode = Mode::ReadOam;
                            if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_OAM) {
                                // Set interrupt bit
                                int_flag |= INT_LCD_STAT;
                            }
                        }
                    }
                }

                // Vblank (10 lines)
                Mode::VBlank => {
                    if self.mode_clock >= 456 {
                        self.mode_clock = 0;
                        self.registers.ly += 1;

                        if self.registers.ly > 153 {
                            // Restart scanning modes
                            self.mode = Mode::ReadOam;
                            self.registers.ly = 0;
                        }
                    }
                }
            }
        }

        int_flag
    }
/// Cycle the PPU based on the how long the CPU spent since it last cycled.
/// Return a byte containing the Interrupt Flag value from the PPU
Cycle the PPU based on the how long the CPU spent since it last cycled.
Return a byte containing the Interrupt Flag value from the PPU
Cycle the PPU based on the how long the CPU spent since it last cycled . Return a byte containing the Interrupt Flag value from the PPU
pub fn cycle(&mut self, cpu_duration: u8) -> u8 {
        let mut int_flag = 0x00;
        if self
            .registers
            .control
            .contains(ControlFlags::DISPLAY_ENABLE)
        {
            self.mode_clock += cpu_duration as usize;
            let status_int_flags: StatusInterruptFlags =
                StatusInterruptFlags::from_bits_truncate(self.read8(0xFF41));
            // If the interrupt for LY Coincidence is set, and it's a coincidence, set interrupt bit
            if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_LYC)
                && self.registers.ly == self.registers.lyc
            {
                // Set interrupt bit
                int_flag |= INT_LCD_STAT;
            }
            match self.mode {
                // OAM read mode, scanline active
                Mode::ReadOam => {
                    if self.mode_clock >= 80 {
                        // Enter scanline Mode::ReadVram
                        self.mode_clock = 0;
                        self.mode = Mode::ReadVram;
                    }
                }
                // VRAM read mode, scanline active
                // Treat end of Mode::ReadVram as end of scanline
                Mode::ReadVram => {
                    if self.mode_clock >= 172 {
                        // Enter hblank
                        self.mode_clock = 0;
                        self.mode = Mode::HBlank;
                        if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_HBLANK) {
                            // Set interrupt bit
                            int_flag |= INT_LCD_STAT;
                        }
                        // Write a scanline to the framebuffer
                        self.renderscan();
                    }
                }
                // Hblank
                // After the last hblank, push the screen data to canvas
                Mode::HBlank => {
                    if self.mode_clock >= 204 {
                        self.mode_clock = 0;
                        self.registers.ly += 1;
                        if self.registers.ly == 144 {
                            // Enter vblank
                            self.mode = Mode::VBlank;
                            // Set interrupt bit
                            int_flag |= INT_VBLANK;
                            if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_VBLANK) {
                                // Set interrupt bit
                                int_flag |= INT_LCD_STAT;
                            }
                            self.gpu.load_texture(self.screen_buffer.as_ref());
                        } else {
                            self.mode = Mode::ReadOam;
                            if status_int_flags.contains(StatusInterruptFlags::INT_ENABLE_OAM) {
                                // Set interrupt bit
                                int_flag |= INT_LCD_STAT;
                            }
                        }
                    }
                }
                // Vblank (10 lines)
                Mode::VBlank => {
                    if self.mode_clock >= 456 {
                        self.mode_clock = 0;
                        self.registers.ly += 1;
                        if self.registers.ly > 153 {
                            // Restart scanning modes
                            self.mode = Mode::ReadOam;
                            self.registers.ly = 0;
                        }
                    }
                }
            }
        }
        int_flag
    }
pub fn cycle ( & mut self , cpu_duration : u8 ) -> u8 { let mut int_flag = 0x00 ; if self . registers . control . contains ( ControlFlags :: DISPLAY_ENABLE ) { self . mode_clock += cpu_duration as usize ; let status_int_flags : StatusInterruptFlags = StatusInterruptFlags :: from_bits_truncate ( self . read8 ( 0xFF41 ) ) ; // If the interrupt for LY Coincidence is set, and it's a coincidence, set interrupt bit if status_int_flags . contains ( StatusInterruptFlags :: INT_ENABLE_LYC ) && self . registers . ly == self . registers . lyc { // Set interrupt bit int_flag |= INT_LCD_STAT ; } match self . mode { // OAM read mode, scanline active Mode :: ReadOam => { if self . mode_clock >= 80 { // Enter scanline Mode::ReadVram self . mode_clock = 0 ; self . mode = Mode :: ReadVram ; } } // VRAM read mode, scanline active // Treat end of Mode::ReadVram as end of scanline Mode :: ReadVram => { if self . mode_clock >= 172 { // Enter hblank self . mode_clock = 0 ; self . mode = Mode :: HBlank ; if status_int_flags . contains ( StatusInterruptFlags :: INT_ENABLE_HBLANK ) { // Set interrupt bit int_flag |= INT_LCD_STAT ; } // Write a scanline to the framebuffer self . renderscan ( ) ; } } // Hblank // After the last hblank, push the screen data to canvas Mode :: HBlank => { if self . mode_clock >= 204 { self . mode_clock = 0 ; self . registers . ly += 1 ; if self . registers . ly == 144 { // Enter vblank self . mode = Mode :: VBlank ; // Set interrupt bit int_flag |= INT_VBLANK ; if status_int_flags . contains ( StatusInterruptFlags :: INT_ENABLE_VBLANK ) { // Set interrupt bit int_flag |= INT_LCD_STAT ; } self . gpu . load_texture ( self . screen_buffer . as_ref ( ) ) ; } else { self . mode = Mode :: ReadOam ; if status_int_flags . contains ( StatusInterruptFlags :: INT_ENABLE_OAM ) { // Set interrupt bit int_flag |= INT_LCD_STAT ; } } } } // Vblank (10 lines) Mode :: VBlank => { if self . mode_clock >= 456 { self . mode_clock = 0 ; self . registers . ly += 1 ; if self . registers . ly > 153 { // Restart scanning modes self . mode = Mode :: ReadOam ; self . registers . ly = 0 ; } } } } } int_flag }
Cycle the PPU based on the how long the CPU spent since it last cycled.
Cycle the PPU based on the how long the CPU spent since it last cycled .
&mut self
cpu_duration
u8
&mut self
cpu_duration
u8