This commit is contained in:
Alex Janka 2023-03-26 21:33:09 +11:00
parent 0636cb7dc3
commit 37fbdb0ed0
7 changed files with 82 additions and 34 deletions

View file

@ -115,6 +115,7 @@ impl Plugin for GameboyEmu {
context: &mut impl ProcessContext<Self>, context: &mut impl ProcessContext<Self>,
) -> ProcessStatus { ) -> ProcessStatus {
if let Some(ref mut vars) = self.vars { if let Some(ref mut vars) = self.vars {
nih_warn!("processing audio...");
while let Some(event) = context.next_event() { while let Some(event) = context.next_event() {
if let Some(Basic(as_bytes)) = event.as_midi() { if let Some(Basic(as_bytes)) = event.as_midi() {
match event { match event {
@ -182,21 +183,31 @@ impl Plugin for GameboyEmu {
} }
} }
} }
nih_warn!("...finished processing note events");
if buffer.channels() != 2 { if buffer.channels() != 2 {
nih_warn!("literally just panicking because there number of channels != 2 and if this is the problem you are literally stupid");
panic!() panic!()
} }
nih_warn!("...not stupid");
for sample in buffer.iter_samples() { for sample in buffer.iter_samples() {
if vars.rx.is_empty() { if vars.rx.is_empty() {
nih_warn!("...rx empty: running until buffer full");
vars.emulator_core.run_until_buffer_full(); vars.emulator_core.run_until_buffer_full();
nih_warn!("...buffer full");
} }
if let Some(a) = executor::block_on(vars.rx.pop()) { if let Some(a) = executor::block_on(vars.rx.pop()) {
for (source, dest) in a.iter().zip(sample) { for (source, dest) in a.iter().zip(sample) {
*dest = *source; *dest = *source;
} }
}
}
vars.emulator_core.run_until_buffer_full();
} else { } else {
nih_warn!("...could not rx audio from emulator")
}
}
nih_warn!("...running emulator until buffer is full again");
vars.emulator_core.run_until_buffer_full();
nih_warn!("...finished with processing audio");
} else {
nih_warn!("processing audio before emulator init");
while context.next_event().is_some() {} while context.next_event().is_some() {}
} }
self.update_save_state(); self.update_save_state();
@ -243,8 +254,11 @@ impl Plugin for GameboyEmu {
let (window, frame_receiver, key_handler) = EmulatorRenderer::new(); let (window, frame_receiver, key_handler) = EmulatorRenderer::new();
*self.frame_receiver.lock().unwrap() = Some(frame_receiver); *self
*self.key_handler.lock().unwrap() = Some(key_handler); .frame_receiver
.lock()
.expect("could not lock frame receiver") = Some(frame_receiver);
*self.key_handler.lock().expect("could not lock key handler") = Some(key_handler);
let (serial_tx, gb_serial_rx) = mpsc::channel::<u8>(); let (serial_tx, gb_serial_rx) = mpsc::channel::<u8>();
let serial_target = SerialTarget::Custom { let serial_target = SerialTarget::Custom {

View file

@ -23,6 +23,7 @@ pub struct Emulator {
impl Emulator { impl Emulator {
pub fn new(frame_receiver: Arc<FrameReceiver>, joypad_sender: Arc<JoypadSender>) -> Self { pub fn new(frame_receiver: Arc<FrameReceiver>, joypad_sender: Arc<JoypadSender>) -> Self {
nih_warn!("new emulator rx/tx struct");
Self { Self {
frame_receiver, frame_receiver,
joypad_sender, joypad_sender,
@ -75,18 +76,26 @@ impl Editor for Emulator {
} }
fn size(&self) -> (u32, u32) { fn size(&self) -> (u32, u32) {
nih_warn!("editor size");
((WIDTH * EXTRA_SCALE) as u32, (HEIGHT * EXTRA_SCALE) as u32) ((WIDTH * EXTRA_SCALE) as u32, (HEIGHT * EXTRA_SCALE) as u32)
} }
fn set_scale_factor(&self, _factor: f32) -> bool { fn set_scale_factor(&self, _factor: f32) -> bool {
nih_warn!("editor scale factor");
true true
} }
fn param_value_changed(&self, _id: &str, _normalized_value: f32) {} fn param_value_changed(&self, _id: &str, _normalized_value: f32) {
nih_warn!("editor param value changed");
}
fn param_modulation_changed(&self, _id: &str, _modulation_offset: f32) {} fn param_modulation_changed(&self, _id: &str, _modulation_offset: f32) {
nih_warn!("editor param modulator changed");
}
fn param_values_changed(&self) {} fn param_values_changed(&self) {
nih_warn!("editor param valueS changed");
}
} }
pub struct EmulatorWindow { pub struct EmulatorWindow {
@ -132,7 +141,7 @@ fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize, Vec<[u8
physical_size.height, physical_size.height,
SurfaceTexture::new(physical_size.width, physical_size.height, window), SurfaceTexture::new(physical_size.width, physical_size.height, window),
) )
.unwrap(), .expect("could not init pixbuf"),
scale, scale,
scaled_buf, scaled_buf,
) )
@ -140,9 +149,11 @@ fn init_pixbuf(info: WindowInfo, window: &mut Window) -> (Pixels, usize, Vec<[u8
impl WindowHandler for EmulatorWindow { impl WindowHandler for EmulatorWindow {
fn on_frame(&mut self, _window: &mut Window) { fn on_frame(&mut self, _window: &mut Window) {
nih_warn!("window frame event"); nih_warn!("rendering window frame");
if let Some(ref mut receiver) = *self.frame_receiver.lock().expect("failed to lock mutex") { if let Some(ref mut receiver) = *self.frame_receiver.lock().expect("failed to lock mutex") {
nih_warn!("...got frame receiver");
if let Some(ref buf) = receiver.try_iter().last() { if let Some(ref buf) = receiver.try_iter().last() {
nih_warn!("...got frame");
if self.scale != 1 { if self.scale != 1 {
scale_buffer_in_place(buf, &mut self.scaled_buf, WIDTH, HEIGHT, self.scale); scale_buffer_in_place(buf, &mut self.scaled_buf, WIDTH, HEIGHT, self.scale);
} }
@ -154,12 +165,15 @@ impl WindowHandler for EmulatorWindow {
{ {
pixel.copy_from_slice(source); pixel.copy_from_slice(source);
} }
self.pix.render().unwrap(); self.pix
.render()
.expect("could not render pixbuf to window");
} }
} }
} }
fn on_event(&mut self, window: &mut Window, event: baseview::Event) -> EventStatus { fn on_event(&mut self, window: &mut Window, event: baseview::Event) -> EventStatus {
nih_warn!("window event");
match event { match event {
Event::Window(WindowEvent::Resized(info)) => { Event::Window(WindowEvent::Resized(info)) => {
(self.pix, self.scale, self.scaled_buf) = init_pixbuf(info, window); (self.pix, self.scale, self.scaled_buf) = init_pixbuf(info, window);
@ -181,7 +195,9 @@ impl WindowHandler for EmulatorWindow {
if let Some(ref mut sender) = if let Some(ref mut sender) =
*self.joypad_sender.lock().expect("failed to lock mutex") *self.joypad_sender.lock().expect("failed to lock mutex")
{ {
sender.send((button, status)).unwrap(); sender
.send((button, status))
.expect("could not send button status");
} }
EventStatus::Captured EventStatus::Captured
} else { } else {
@ -218,14 +234,19 @@ impl EmulatorRenderer {
} }
impl Renderer<[u8; 4]> for EmulatorRenderer { impl Renderer<[u8; 4]> for EmulatorRenderer {
fn prepare(&mut self, _width: usize, _height: usize) {} fn prepare(&mut self, _width: usize, _height: usize) {
nih_warn!("preparing emulator");
}
#[allow(unused_must_use)] #[allow(unused_must_use)]
fn display(&mut self, buffer: &[[u8; 4]]) { fn display(&mut self, buffer: &[[u8; 4]]) {
nih_warn!("sending frame from emulator thread");
self.tx.send(buffer.to_vec()); self.tx.send(buffer.to_vec());
nih_warn!("...finished sending frame");
} }
fn latest_joypad_state(&mut self) -> JoypadState { fn latest_joypad_state(&mut self) -> JoypadState {
nih_warn!("begin getting latest joypad state");
while let Ok((key, state)) = self.keys.try_recv() { while let Ok((key, state)) = self.keys.try_recv() {
match key { match key {
JoypadButtons::Down => self.joypad.down = state, JoypadButtons::Down => self.joypad.down = state,
@ -238,6 +259,7 @@ impl Renderer<[u8; 4]> for EmulatorRenderer {
JoypadButtons::A => self.joypad.a = state, JoypadButtons::A => self.joypad.a = state,
} }
} }
nih_warn!("end getting latest joypad state");
self.joypad self.joypad
} }
} }

View file

@ -147,21 +147,23 @@ where
} }
pub fn run_until_buffer_full(&mut self) { pub fn run_until_buffer_full(&mut self) {
println!("hello from gameboy");
while !self.cpu.memory.is_audio_buffer_full() { while !self.cpu.memory.is_audio_buffer_full() {
self.run(); self.run();
} }
println!("gooby from gameboy");
} }
fn run_cycle(&mut self) { fn run_cycle(&mut self) {
let will_pause = unsafe { PAUSE_QUEUED }; // let will_pause = unsafe { PAUSE_QUEUED };
let pause_enabled = unsafe { PAUSE_ENABLED }; // let pause_enabled = unsafe { PAUSE_ENABLED };
self.cpu.exec_next(); self.cpu.exec_next();
if !pause_enabled && self.cpu.reg.pc >= 0x100 { // if !pause_enabled && self.cpu.reg.pc >= 0x100 {
unsafe { PAUSE_ENABLED = true }; // unsafe { PAUSE_ENABLED = true };
} // }
if will_pause { // if will_pause {
pause_then_step(); // pause_then_step();
} // }
} }
fn process_messages(&mut self) { fn process_messages(&mut self) {

View file

@ -331,7 +331,7 @@ where
pub fn increment_timers(&mut self, machine_cycles: u8) { pub fn increment_timers(&mut self, machine_cycles: u8) {
let steps = (machine_cycles as usize) * 4; let steps = (machine_cycles as usize) * 4;
self.memory.camera.lock().unwrap().tick(steps); // self.memory.camera.lock().unwrap().tick(steps);
let timer_return = self.memory.timers.tick(steps); let timer_return = self.memory.timers.tick(steps);
@ -359,12 +359,12 @@ where
.interrupts .interrupts
.set_interrupt(Interrupt::LcdStat, gpu_interrupts.lcd_stat); .set_interrupt(Interrupt::LcdStat, gpu_interrupts.lcd_stat);
if gpu_interrupts.vblank { // if gpu_interrupts.vblank {
let latest_state = self.memory.gpu.window.latest_joypad_state(); // let latest_state = self.memory.gpu.window.latest_joypad_state();
let joypad_interrupt = self.memory.update_pressed_keys(latest_state); // let joypad_interrupt = self.memory.update_pressed_keys(latest_state);
self.memory // self.memory
.interrupts // .interrupts
.set_interrupt(Interrupt::Joypad, joypad_interrupt); // .set_interrupt(Interrupt::Joypad, joypad_interrupt);
} // }
} }
} }

View file

@ -147,8 +147,10 @@ impl Apu {
.collect(), .collect(),
); );
if self.buffer.len() >= CYCLES_PER_FRAME { if self.buffer.len() >= CYCLES_PER_FRAME {
println!("finished 1 frame of audio... pushing...");
self.next_audio(); self.next_audio();
} else if !self.out_buffer.is_empty() { } else if !self.out_buffer.is_empty() {
println!("pushing remainder...");
self.push_audio(); self.push_audio();
} }
} }
@ -173,12 +175,17 @@ impl Apu {
self.out_buffer.len().min(self.output.send_rb.free_len()) self.out_buffer.len().min(self.output.send_rb.free_len())
}; };
if length > 0 {
executor::block_on( executor::block_on(
self.output self.output
.send_rb .send_rb
.push_slice(&self.out_buffer.drain(..length).collect::<Vec<[f32; 2]>>()), .push_slice(&self.out_buffer.drain(..length).collect::<Vec<[f32; 2]>>()),
) )
.unwrap(); .expect("APU: error sending audio to output ringbuffer");
} else {
println!("buffer already full - skipped filling");
}
println!("finished pushing audio");
} }
pub fn is_buffer_full(&self) -> bool { pub fn is_buffer_full(&self) -> bool {

View file

@ -455,6 +455,8 @@ where
} }
fn render_window(&mut self) { fn render_window(&mut self) {
println!("gpu sending frame");
self.window.display(&self.buffer); self.window.display(&self.buffer);
println!("gpu finished sending frame");
} }
} }

View file

@ -204,11 +204,12 @@ impl Serial {
match &self.target { match &self.target {
SerialTarget::Stdout => { SerialTarget::Stdout => {
print!("{}", self.output_byte as char); print!("{}", self.output_byte as char);
stdout().flush().unwrap(); stdout().flush().expect("Serial: error sending to stdout");
} }
SerialTarget::Custom { rx: _, tx } => { SerialTarget::Custom { rx: _, tx } => {
if let Some(tx) = tx { if let Some(tx) = tx {
tx.send(self.output_byte).unwrap(); tx.send(self.output_byte)
.expect("Serial: error sending to custom tx");
} }
} }
SerialTarget::None => {} SerialTarget::None => {}