diff --git a/.gitignore b/.gitignore index 6db043d..870ab25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea /target +/roms diff --git a/README.md b/README.md index aafefa7..76cd15b 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ Screenshot program author: [Javamannen](https://esolangs.org/wiki/User:Javamanne - [X] Outer loop - 60fps display loop - [X] Display adapter - [X] SDL2 adapter -- [ ] Keyboard -- [ ] Audio +- [X] Keyboard +- [X] Audio - [ ] Load/Save memory - - [ ] Load a ROM + - [X] Load a ROM ## Usage instructions diff --git a/src/emu/audio.rs b/src/emu/audio.rs index e69de29..94828bb 100644 --- a/src/emu/audio.rs +++ b/src/emu/audio.rs @@ -0,0 +1,48 @@ +use sdl2::audio::AudioQueue; + +use crate::emu::memory::RamMemory; +use crate::misc::endian::read_big_endian_u16; +use crate::misc::error::DeviceType::AUDIO; +use crate::misc::error::EmulatorError; +use crate::misc::result::EmulatorResult; + +pub const AUDIO_BUFFER_SIZE: usize = 256; + + +pub struct AudioProcessor<'a> { + ram: &'a RamMemory, + frame_buffer: Box<[u8; AUDIO_BUFFER_SIZE]>, + audio_queue: &'a AudioQueue, +} + +impl<'a> AudioProcessor<'a> { + pub fn try_new(ram: &'a RamMemory, audio_queue: &'a AudioQueue) -> EmulatorResult> { + let frame_buffer = vec![0u8; AUDIO_BUFFER_SIZE].into_boxed_slice() + .try_into() + .map_err(|_| { + EmulatorError::AllocationFailure(AUDIO, "Failed to allocate graphics") + })?; + Ok(AudioProcessor { + ram, + audio_queue, + frame_buffer, + }) + } +} + +impl<'a> AudioProcessor<'a> { + pub fn queue(&mut self) -> EmulatorResult<()> { + let audio_base_reg = (self.get_audio_base_reg() as u32) << 8; + let fb = self.frame_buffer.as_mut(); + if self.audio_queue.size() == 0 { + log::warn!("Detected Queue empty!"); + } + self.ram.try_copy_block(audio_base_reg, fb)?; + self.audio_queue.queue_audio(fb).map_err(|s| { EmulatorError::OtherError(Some(AUDIO), s) }) + } + fn get_audio_base_reg(&self) -> u16 { + let data = self.ram.get_data_ref(); + let audio_base_reg = data.get(6..8).unwrap(); + read_big_endian_u16(audio_base_reg.try_into().unwrap()) + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0fb9032..fd5bc48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::Read; use std::time::Duration; use clap::Parser; +use sdl2::audio::{AudioQueue, AudioSpecDesired}; use sdl2::event::Event; use sdl2::EventPump; use sdl2::keyboard::Keycode; @@ -9,6 +10,7 @@ use sdl2::pixels::Color; use sdl2::render::{BlendMode, WindowCanvas}; use simple_logger::SimpleLogger; use crate::args::BytePusherArgs; +use crate::emu::audio::AudioProcessor; use crate::emu::cpu::Cpu; use crate::emu::graphics::GraphicsProcessor; use crate::emu::keyboard::Keyboard; @@ -30,11 +32,12 @@ fn main() -> EmulatorResult<()> { let (file_bytes, x) = try_load_rom(&file_name)?; assert!(x < MEM_LENGTH); - let (mut canvas, mut event_pump) = initiate_sdl(); + let (mut canvas, mut event_pump, mut audio_queue) = initiate_sdl(); let ram = RamMemory::try_from(file_bytes.as_slice())?; let graphics_processor = GraphicsProcessor::try_new(&ram)?; + let mut audio_processor = AudioProcessor::try_new(&ram,&audio_queue)?; let mut keyboard = Keyboard::new(&ram); let cpu = Cpu::new(&ram, &graphics_processor); @@ -70,6 +73,7 @@ fn main() -> EmulatorResult<()> { // draw graphics sdl2_graphics_adapter.draw(&mut canvas)?; // TODO render audio + audio_processor.queue()?; canvas.present(); @@ -115,12 +119,22 @@ fn try_load_rom(file_name_option: &Option) -> EmulatorResult<(Vec, u Ok((file_bytes, bytes_read)) } -fn initiate_sdl() -> (WindowCanvas, EventPump) { +fn initiate_sdl() -> (WindowCanvas, EventPump, AudioQueue) { const BASE_RESOLUTION: u32 = 256; const DRAW_FACTOR: u32 = 4; const WINDOW_RESOLUTION: u32 = BASE_RESOLUTION * DRAW_FACTOR; let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); + // TODO audio subsystem + let audio_subsystem = sdl_context.audio().unwrap(); + let wanted_spec = AudioSpecDesired{ + channels: Some(1), + samples: Some(256), + freq: Some(15360), + }; + let audio_queue = audio_subsystem.open_queue::(None, &wanted_spec).unwrap(); + audio_queue.resume(); + let window = video_subsystem.window("byte-pusher-emu", WINDOW_RESOLUTION, WINDOW_RESOLUTION) .position_centered() @@ -136,5 +150,5 @@ fn initiate_sdl() -> (WindowCanvas, EventPump) { canvas.set_blend_mode(BlendMode::None); canvas.present(); let event_pump = sdl_context.event_pump().unwrap(); - (canvas, event_pump) + (canvas, event_pump, audio_queue) } diff --git a/src/misc/error.rs b/src/misc/error.rs index 85de8ea..9ec9eeb 100644 --- a/src/misc/error.rs +++ b/src/misc/error.rs @@ -15,6 +15,7 @@ pub enum EmulatorError { AllocationFailure(DeviceType, &'static str), UnreachableMemory(DeviceType, u32), EmulatorIOError(Error), + OtherError(Option,String) } impl From for EmulatorError {