Skip to content
Snippets Groups Projects
Verified Commit c53c2728 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

refactor: small set of simplifications

parent e675fad1
No related branches found
No related tags found
1 merge request!19Initial tentative audio support 🔉
Pipeline #2270 failed
...@@ -42,6 +42,7 @@ pub struct Emulator { ...@@ -42,6 +42,7 @@ pub struct Emulator {
system: GameBoy, system: GameBoy,
graphics: Option<Graphics>, graphics: Option<Graphics>,
audio: Option<Audio>, audio: Option<Audio>,
title: &'static str,
logic_frequency: u32, logic_frequency: u32,
visual_frequency: f32, visual_frequency: f32,
next_tick_time: f32, next_tick_time: f32,
...@@ -57,11 +58,12 @@ impl Emulator { ...@@ -57,11 +58,12 @@ impl Emulator {
system, system,
graphics: None, graphics: None,
audio: None, audio: None,
title: TITLE,
logic_frequency: GameBoy::CPU_FREQ, logic_frequency: GameBoy::CPU_FREQ,
visual_frequency: GameBoy::VISUAL_FREQ * 2.0, visual_frequency: GameBoy::VISUAL_FREQ,
next_tick_time: 0.0, next_tick_time: 0.0,
next_tick_time_i: 0, next_tick_time_i: 0,
features: vec!["no-vsync"], features: vec!["video", "audio", "no-vsync"],
palettes: [ palettes: [
PaletteInfo::new( PaletteInfo::new(
"basic", "basic",
...@@ -97,14 +99,18 @@ impl Emulator { ...@@ -97,14 +99,18 @@ impl Emulator {
pub fn start(&mut self, screen_scale: f32) { pub fn start(&mut self, screen_scale: f32) {
let sdl = sdl2::init().unwrap(); let sdl = sdl2::init().unwrap();
self.start_graphics(&sdl, screen_scale); if self.features.contains(&"video") {
self.start_audio(&sdl); self.start_graphics(&sdl, screen_scale);
}
if self.features.contains(&"audio") {
self.start_audio(&sdl);
}
} }
pub fn start_graphics(&mut self, sdl: &Sdl, screen_scale: f32) { pub fn start_graphics(&mut self, sdl: &Sdl, screen_scale: f32) {
self.graphics = Some(Graphics::new( self.graphics = Some(Graphics::new(
&sdl, &sdl,
TITLE, self.title,
DISPLAY_WIDTH as u32, DISPLAY_WIDTH as u32,
DISPLAY_HEIGHT as u32, DISPLAY_HEIGHT as u32,
screen_scale, screen_scale,
...@@ -127,7 +133,7 @@ impl Emulator { ...@@ -127,7 +133,7 @@ impl Emulator {
.as_mut() .as_mut()
.unwrap() .unwrap()
.window_mut() .window_mut()
.set_title(format!("{} [{}]", TITLE, rom.title()).as_str()) .set_title(format!("{} [{}]", self.title, rom.title()).as_str())
.unwrap(); .unwrap();
} }
...@@ -299,20 +305,23 @@ impl Emulator { ...@@ -299,20 +305,23 @@ impl Emulator {
last_frame = self.system.ppu_frame(); last_frame = self.system.ppu_frame();
} }
// obtains the new audio buffer and queues it into the audio match self.audio.as_mut() {
// subsystem ready to be processed Some(audio) => {
let audio_buffer = self // obtains the new audio buffer and queues it into the audio
.system // subsystem ready to be processed
.audio_buffer() let audio_buffer = self
.iter() .system
.map(|v| *v as f32 / 7.0) .audio_buffer()
.collect::<Vec<f32>>(); .iter()
self.audio .map(|v| *v as f32 / 14.0)
.as_mut() .collect::<Vec<f32>>();
.unwrap() audio.device.queue_audio(&audio_buffer).unwrap();
.device }
.queue_audio(&audio_buffer) None => (),
.unwrap(); }
// clears the audio buffer to prevent it from
// "exploding" in size
self.system.clear_audio_buffer(); self.system.clear_audio_buffer();
} }
......
...@@ -48,7 +48,7 @@ pub struct Apu { ...@@ -48,7 +48,7 @@ pub struct Apu {
wave_ram: [u8; 16], wave_ram: [u8; 16],
output_timer: u16, output_timer: u16,
output_buffer: Vec<u8> output_buffer: Vec<u8>,
} }
impl Apu { impl Apu {
...@@ -94,18 +94,14 @@ impl Apu { ...@@ -94,18 +94,14 @@ impl Apu {
wave_ram: [0u8; 16], wave_ram: [0u8; 16],
output_timer: 0, output_timer: 0,
output_buffer: Vec::new() output_buffer: Vec::new(),
} }
} }
pub fn clock(&mut self, cycles: u8) { pub fn clock(&mut self, cycles: u8) {
self.clock_f(cycles, 4194304); // @TODO the performance here requires improvement
}
pub fn clock_f(&mut self, cycles: u8, freq: u32) {
// @todo the performance here requires improvement
for _ in 0..cycles { for _ in 0..cycles {
self.cycle(freq); self.cycle();
} }
} }
...@@ -147,7 +143,6 @@ impl Apu { ...@@ -147,7 +143,6 @@ impl Apu {
(self.ch1_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8); (self.ch1_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8);
self.ch1_sound_length |= value & 0x40 == 0x40; self.ch1_sound_length |= value & 0x40 == 0x40;
self.ch1_enabled |= value & 0x80 == 0x80; self.ch1_enabled |= value & 0x80 == 0x80;
//println!("CH1 Enabled {}", self.ch1_enabled);
} }
// 0xFF16 — NR21: Channel 2 length timer & duty cycle // 0xFF16 — NR21: Channel 2 length timer & duty cycle
...@@ -174,9 +169,8 @@ impl Apu { ...@@ -174,9 +169,8 @@ impl Apu {
if value & 0x80 == 0x80 { if value & 0x80 == 0x80 {
//self.ch2_timer = 0; //self.ch2_timer = 0;
//self.ch2_sequence = 0; //self.ch2_sequence = 0;
//@todo improve this reset operation //@TODO improve this reset operation
} }
//println!("CH2 Enabled {}", self.ch2_enabled);
} }
// 0xFF1A — NR30: Channel 3 DAC enable // 0xFF1A — NR30: Channel 3 DAC enable
...@@ -201,7 +195,6 @@ impl Apu { ...@@ -201,7 +195,6 @@ impl Apu {
(self.ch3_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8); (self.ch3_wave_length & 0x00ff) | (((value & 0x07) as u16) << 8);
self.ch3_sound_length |= value & 0x40 == 0x40; self.ch3_sound_length |= value & 0x40 == 0x40;
self.ch3_enabled |= value & 0x80 == 0x80; self.ch3_enabled |= value & 0x80 == 0x80;
//println!("CH3 Enabled {}", self.ch3_enabled);
} }
// 0xFF30-0xFF3F — Wave pattern RAM // 0xFF30-0xFF3F — Wave pattern RAM
...@@ -214,11 +207,10 @@ impl Apu { ...@@ -214,11 +207,10 @@ impl Apu {
} }
#[inline(always)] #[inline(always)]
pub fn cycle(&mut self, freq: u32) { pub fn cycle(&mut self) {
self.ch1_timer = self.ch1_timer.saturating_sub(1); self.ch1_timer = self.ch1_timer.saturating_sub(1);
if self.ch1_timer == 0 { if self.ch1_timer == 0 {
let target_freq = 1048576.0 / (2048.0 - self.ch1_wave_length as f32); self.ch1_timer = (2048 - self.ch1_wave_length) << 2;
self.ch1_timer = (freq as f32 / target_freq) as u16;
self.ch1_sequence = (self.ch1_sequence + 1) & 7; self.ch1_sequence = (self.ch1_sequence + 1) & 7;
if self.ch1_enabled { if self.ch1_enabled {
...@@ -235,8 +227,7 @@ impl Apu { ...@@ -235,8 +227,7 @@ impl Apu {
self.ch2_timer = self.ch2_timer.saturating_sub(1); self.ch2_timer = self.ch2_timer.saturating_sub(1);
if self.ch2_timer == 0 { if self.ch2_timer == 0 {
let target_freq = 1048576.0 / (2048.0 - self.ch2_wave_length as f32); self.ch2_timer = (2048 - self.ch2_wave_length) << 2;
self.ch2_timer = (freq as f32 / target_freq) as u16;
self.ch2_sequence = (self.ch2_sequence + 1) & 7; self.ch2_sequence = (self.ch2_sequence + 1) & 7;
if self.ch2_enabled { if self.ch2_enabled {
...@@ -254,7 +245,8 @@ impl Apu { ...@@ -254,7 +245,8 @@ impl Apu {
self.output_timer = self.output_timer.saturating_sub(1); self.output_timer = self.output_timer.saturating_sub(1);
if self.output_timer == 0 { if self.output_timer == 0 {
self.output_buffer.push(self.output()); self.output_buffer.push(self.output());
self.output_timer = (freq as f32 / 44100.0) as u16; // @todo target sampling rate is hardcoded // @TODO target sampling rate is hardcoded, need to softcode this
self.output_timer = (4194304.0 / 44100.0) as u16;
} }
} }
......
...@@ -54,8 +54,7 @@ pub struct Registers { ...@@ -54,8 +54,7 @@ pub struct Registers {
} }
pub trait AudioProvider { pub trait AudioProvider {
fn output_apu(&self) -> u8; fn audio_output(&self) -> u8;
fn output_clock_apu(&mut self, cycles: u8, freq: u32) -> u8;
fn audio_buffer(&self) -> &Vec<u8>; fn audio_buffer(&self) -> &Vec<u8>;
fn clear_audio_buffer(&mut self); fn clear_audio_buffer(&mut self);
} }
...@@ -384,12 +383,7 @@ pub fn hook_impl(info: &PanicInfo) { ...@@ -384,12 +383,7 @@ pub fn hook_impl(info: &PanicInfo) {
} }
impl AudioProvider for GameBoy { impl AudioProvider for GameBoy {
fn output_apu(&self) -> u8 { fn audio_output(&self) -> u8 {
self.apu_i().output()
}
fn output_clock_apu(&mut self, cycles: u8, freq: u32) -> u8 {
self.apu().clock_f(cycles, freq);
self.apu_i().output() self.apu_i().output()
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment