emu works again

This commit is contained in:
Alex Janka 2023-03-08 11:28:32 +11:00
parent 4bae07f165
commit aaca3ff5b2
8 changed files with 42 additions and 12 deletions

View file

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
gb-emu-lib = { path = "../lib" } gb-emu-lib = { path = "../lib", features = [] }
clap = {version = "4.1.8", features = ["derive"]} clap = {version = "4.1.8", features = ["derive"]}
minifb = { path = "../vendored/rust_minifb" } minifb = { path = "../vendored/rust_minifb" }
gilrs = "0.10.1" gilrs = "0.10.1"

View file

@ -85,7 +85,7 @@ fn main() {
cycle_count: args.cycle_count, cycle_count: args.cycle_count,
}; };
let tile_window: Option<Box<dyn Renderer>> = if args.tile_window { let tile_window: Option<Box<dyn Renderer<u32>>> = if args.tile_window {
Some(Box::new(WindowRenderer::new(factor, None))) Some(Box::new(WindowRenderer::new(factor, None)))
} else { } else {
None None
@ -132,7 +132,7 @@ fn create_audio_output() -> (AudioOutput, Stream) {
let sample_rate = config.sample_rate().0; let sample_rate = config.sample_rate().0;
let (output, mut rx) = AudioOutput::new(sample_rate as f32); let (output, mut rx) = AudioOutput::new_unfilled(sample_rate as f32, true);
let stream = device let stream = device
.build_output_stream( .build_output_stream(
@ -183,7 +183,7 @@ impl WindowRenderer {
} }
} }
impl Renderer for WindowRenderer { impl Renderer<u32> for WindowRenderer {
fn prepare(&mut self, width: usize, height: usize) { fn prepare(&mut self, width: usize, height: usize) {
self.width = width; self.width = width;
self.height = height; self.height = height;

View file

@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
gb-emu-lib = { path = "../lib" } gb-emu-lib = { path = "../lib", features = ["async"] }
nih_plug = { path = "../vendored/nih-plug", features = ["standalone"] } nih_plug = { path = "../vendored/nih-plug", features = ["standalone"] }
baseview = { path = "../vendored/baseview" } baseview = { path = "../vendored/baseview" }
pixels = "0.11.0" pixels = "0.11.0"

View file

@ -107,7 +107,7 @@ impl Plugin for GameboyEmu {
}; };
let (sender, receiver) = channel::<EmulatorMessage>(); let (sender, receiver) = channel::<EmulatorMessage>();
let (output, rx) = AudioOutput::new_unfilled(buffer_config.sample_rate); let (output, rx) = AudioOutput::new_unfilled(buffer_config.sample_rate, false);
let (renderer, frame_receiver) = EmulatorRenderer::new(); let (renderer, frame_receiver) = EmulatorRenderer::new();

View file

@ -5,6 +5,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = []
async = []
[dependencies] [dependencies]
rand = "0.8.5" rand = "0.8.5"
async-ringbuf = "0.1.2" async-ringbuf = "0.1.2"

View file

@ -13,6 +13,7 @@ pub enum RomFile {
Raw(Vec<u8>), Raw(Vec<u8>),
} }
#[cfg(feature = "async")]
pub trait Renderer<Format: From<Colour>>: Send { pub trait Renderer<Format: From<Colour>>: Send {
fn prepare(&mut self, width: usize, height: usize); fn prepare(&mut self, width: usize, height: usize);
@ -25,26 +26,43 @@ pub trait Renderer<Format: From<Colour>>: Send {
fn set_rumble(&mut self, _rumbling: bool) {} fn set_rumble(&mut self, _rumbling: bool) {}
} }
#[cfg(not(feature = "async"))]
pub trait Renderer<Format: From<Colour>> {
fn prepare(&mut self, width: usize, height: usize);
fn display(&mut self, buffer: &[Format]);
fn set_title(&mut self, _title: String) {}
fn latest_joypad_state(&mut self) -> JoypadState;
fn set_rumble(&mut self, _rumbling: bool) {}
}
pub struct AudioOutput { pub struct AudioOutput {
pub sample_rate: f32, pub sample_rate: f32,
pub send_rb: AsyncHeapProducer<[f32; 2]>, pub send_rb: AsyncHeapProducer<[f32; 2]>,
pub wait_for_output: bool,
} }
impl AudioOutput { impl AudioOutput {
pub fn new(sample_rate: f32) -> (Self, AsyncHeapConsumer<[f32; 2]>) { pub fn new(sample_rate: f32, wait_for_output: bool) -> (Self, AsyncHeapConsumer<[f32; 2]>) {
let (mut output, rx) = Self::new_unfilled(sample_rate); let (mut output, rx) = Self::new_unfilled(sample_rate, wait_for_output);
executor::block_on( executor::block_on(
output output
.send_rb .send_rb
.push_iter(vec![[0.; 2]; output.send_rb.len() - 1].into_iter()), .push_iter(vec![[0.; 2]; output.send_rb.free_len() - 1].into_iter()),
) )
.unwrap(); .unwrap();
(output, rx) (output, rx)
} }
pub fn new_unfilled(sample_rate: f32) -> (Self, AsyncHeapConsumer<[f32; 2]>) { pub fn new_unfilled(
sample_rate: f32,
wait_for_output: bool,
) -> (Self, AsyncHeapConsumer<[f32; 2]>) {
let rb_len = sample_rate as usize / (60 * 2); let rb_len = sample_rate as usize / (60 * 2);
let rb = AsyncHeapRb::<[f32; 2]>::new(rb_len); let rb = AsyncHeapRb::<[f32; 2]>::new(rb_len);
@ -54,6 +72,7 @@ impl AudioOutput {
Self { Self {
sample_rate, sample_rate,
send_rb, send_rb,
wait_for_output,
}, },
rx, rx,
) )

View file

@ -145,7 +145,10 @@ impl<ColourFormat: From<Colour> + Clone> Cpu<ColourFormat> {
self.set_or_clear_flag(Flags::Zero, result == 0x0); self.set_or_clear_flag(Flags::Zero, result == 0x0);
self.set_or_clear_flag( self.set_or_clear_flag(
Flags::HalfCarry, Flags::HalfCarry,
first.get_low_nibble() - (second.get_low_nibble() + if with_carry { 1 } else { 0 }) first
.get_low_nibble()
.borrowing_sub(second.get_low_nibble(), with_carry)
.0
> 0xF, > 0xF,
); );
result result

View file

@ -122,7 +122,11 @@ impl Apu {
} }
fn push_audio(&mut self) { fn push_audio(&mut self) {
let length = self.out_buffer.len().min(self.output.send_rb.free_len()); let length = if self.output.wait_for_output {
self.out_buffer.len()
} else {
self.out_buffer.len().min(self.output.send_rb.free_len())
};
executor::block_on( executor::block_on(
self.output self.output