Initial commit: NES emulator with GTK4 desktop frontend
Some checks failed
CI / rust (push) Has been cancelled
Some checks failed
CI / rust (push) Has been cancelled
Full NES emulation: CPU, PPU, APU, 47 mappers, iNES/NES 2.0 parsing. GTK4 desktop client with HeaderBar, pixel-perfect Cairo rendering, drag-and-drop ROM loading, and keyboard shortcuts. 187 tests covering core emulation, mappers, and runtime.
This commit is contained in:
63
src/runtime/host/executor.rs
Normal file
63
src/runtime/host/executor.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
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<u8>,
|
||||
audio_buffer: Vec<f32>,
|
||||
}
|
||||
|
||||
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<I, V, A>(
|
||||
&mut self,
|
||||
runtime: &mut NesRuntime,
|
||||
input: &mut I,
|
||||
video: &mut V,
|
||||
audio: &mut A,
|
||||
) -> Result<FrameExecution, RuntimeError>
|
||||
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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user