stink
This commit is contained in:
parent
0636cb7dc3
commit
37fbdb0ed0
7 changed files with 82 additions and 34 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
} 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();
|
vars.emulator_core.run_until_buffer_full();
|
||||||
|
nih_warn!("...finished with processing audio");
|
||||||
} else {
|
} 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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
};
|
};
|
||||||
|
|
||||||
executor::block_on(
|
if length > 0 {
|
||||||
self.output
|
executor::block_on(
|
||||||
.send_rb
|
self.output
|
||||||
.push_slice(&self.out_buffer.drain(..length).collect::<Vec<[f32; 2]>>()),
|
.send_rb
|
||||||
)
|
.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 {
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 => {}
|
||||||
|
|
Loading…
Add table
Reference in a new issue