use crate::runtime::{ AudioMixer, FRAME_HEIGHT, FRAME_RGBA_BYTES, FRAME_WIDTH, NesRuntime, RuntimeError, }; use super::io::{AudioOutput, InputProvider, VideoOutput}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] pub struct FrameExecution { pub frame_number: u64, pub audio_samples: usize, } pub struct FrameExecutor { mixer: AudioMixer, frame_buffer: Vec, audio_buffer: Vec, } impl FrameExecutor { pub fn from_runtime(runtime: &NesRuntime, sample_rate: u32) -> Self { Self { mixer: runtime.default_audio_mixer(sample_rate), frame_buffer: vec![0; FRAME_RGBA_BYTES], audio_buffer: Vec::new(), } } pub fn mixer(&self) -> &AudioMixer { &self.mixer } pub fn mixer_mut(&mut self) -> &mut AudioMixer { &mut self.mixer } pub fn execute_frame( &mut self, runtime: &mut NesRuntime, input: &mut I, video: &mut V, audio: &mut A, ) -> Result where I: InputProvider, V: VideoOutput, A: AudioOutput, { runtime.set_buttons(input.poll_buttons()); self.audio_buffer.clear(); runtime.run_until_frame_complete_with_audio(&mut self.mixer, &mut self.audio_buffer)?; runtime.render_frame_rgba(&mut self.frame_buffer)?; audio.push_samples(&self.audio_buffer); video.present_rgba(&self.frame_buffer, FRAME_WIDTH, FRAME_HEIGHT); Ok(FrameExecution { frame_number: runtime.frame_number(), audio_samples: self.audio_buffer.len(), }) } }