[cln] Restructure code
This commit is contained in:
3
src/sdl_adapters/mod.rs
Normal file
3
src/sdl_adapters/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod sdl_graphics_adapter;
|
||||
pub mod sdl_audio_adapter;
|
||||
pub mod sdl_keyboard_adapter;
|
71
src/sdl_adapters/sdl_audio_adapter.rs
Normal file
71
src/sdl_adapters/sdl_audio_adapter.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use sdl2::audio::AudioQueue;
|
||||
use crate::device::timer::DeviceTimerManager;
|
||||
use crate::util::EmulatorResult;
|
||||
|
||||
/// An Audio adapter using `AudioQueue`. Generates a square wave of specified frequency
|
||||
pub struct SdlAudioAdapter {
|
||||
sound_timer: Arc<Mutex<u8>>,
|
||||
phase_inc: f32,
|
||||
phase: f32,
|
||||
volume: f32,
|
||||
audio_queue: AudioQueue<f32>,
|
||||
internal_buffer: Vec<f32>,
|
||||
}
|
||||
|
||||
impl SdlAudioAdapter {
|
||||
/// Number of samples per second
|
||||
pub const SAMPLING_FREQ:i32 = 15360;
|
||||
pub const SAMPLES_PER_FRAME: usize = (Self::SAMPLING_FREQ as usize / 60) * 2;
|
||||
pub fn new_timers(freq: f32,
|
||||
volume: f32,
|
||||
audio_queue: AudioQueue<f32>) ->(DeviceTimerManager,SdlAudioAdapter){
|
||||
let device_sound_timer = Arc::new(Mutex::default());
|
||||
let device_timer_manager = DeviceTimerManager::new(device_sound_timer.clone());
|
||||
let sdl_audio_adapter = SdlAudioAdapter::new(device_sound_timer,freq,volume,audio_queue);
|
||||
(device_timer_manager, sdl_audio_adapter)
|
||||
}
|
||||
fn new(sound_timer: Arc<Mutex<u8>>,
|
||||
freq: f32,
|
||||
volume: f32,
|
||||
audio_queue: AudioQueue<f32>) -> SdlAudioAdapter {
|
||||
audio_queue.resume();
|
||||
// ensure frequency isn't too low
|
||||
assert!(((2.0*freq) as i32) < Self::SAMPLING_FREQ);
|
||||
SdlAudioAdapter {
|
||||
sound_timer,
|
||||
internal_buffer: vec![0f32; Self::SAMPLES_PER_FRAME],
|
||||
phase: 0f32,
|
||||
phase_inc: freq/Self::SAMPLING_FREQ as f32,
|
||||
volume,
|
||||
audio_queue,
|
||||
}
|
||||
}
|
||||
pub fn process_push_audio(&mut self) -> EmulatorResult<()> {
|
||||
// fill the audio vector.
|
||||
let sound_timer = {
|
||||
let sound_timer = self.sound_timer.lock().expect("Could not lock to play audio");
|
||||
sound_timer.clone()
|
||||
};
|
||||
if sound_timer>0 && self.audio_queue.size() < Self::SAMPLING_FREQ as u32 {
|
||||
self.fill_audio();
|
||||
self.audio_queue.queue_audio(&self.internal_buffer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fill_audio(&mut self) {
|
||||
let out = &mut self.internal_buffer;
|
||||
|
||||
// Generate a square wave
|
||||
for x in out.iter_mut() {
|
||||
*x = if self.phase <= 0.5 {
|
||||
self.volume
|
||||
} else {
|
||||
-self.volume
|
||||
};
|
||||
|
||||
self.phase = (self.phase + self.phase_inc) % 1.0;
|
||||
}
|
||||
}
|
||||
}
|
39
src/sdl_adapters/sdl_graphics_adapter.rs
Normal file
39
src/sdl_adapters/sdl_graphics_adapter.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use std::sync::MutexGuard;
|
||||
use sdl2::pixels::PixelFormatEnum;
|
||||
use sdl2::render::{TextureAccess, WindowCanvas};
|
||||
use crate::device::Device;
|
||||
use crate::util::EmulatorResult;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SdlGraphicsAdapter {
|
||||
rgb_frame_buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl SdlGraphicsAdapter {
|
||||
pub const RGB_COMPONENTS: usize = 3;
|
||||
pub const RGB_FRAMEBUFFER_SIZE: usize = Self::RGB_COMPONENTS * Device::FRAME_BUFFER_SIZE;
|
||||
pub fn new() -> SdlGraphicsAdapter {
|
||||
let rgb_frame_buffer = vec![0; Self::RGB_FRAMEBUFFER_SIZE];
|
||||
SdlGraphicsAdapter {
|
||||
rgb_frame_buffer
|
||||
}
|
||||
}
|
||||
pub fn draw_screen(&mut self, frame_buffer: MutexGuard<Box<[bool; Device::FRAME_BUFFER_SIZE]>>, window_canvas: &mut WindowCanvas) ->EmulatorResult<()> {
|
||||
for (i, pixel) in frame_buffer.iter().enumerate() {
|
||||
let col_component = if *pixel { 0xff } else { 0 };
|
||||
self.rgb_frame_buffer[3 * i] = col_component;
|
||||
self.rgb_frame_buffer[3 * i + 1] = col_component;
|
||||
self.rgb_frame_buffer[3 * i + 2] = col_component;
|
||||
}
|
||||
// drop the mutex as it is not required anymore
|
||||
drop(frame_buffer);
|
||||
|
||||
let tex_creator = window_canvas.texture_creator();
|
||||
let mut tex = tex_creator.create_texture(PixelFormatEnum::RGB24, TextureAccess::Streaming, Device::FRAME_BUFFER_WIDTH as u32, Device::FRAME_BUFFER_HEIGHT as u32).expect("Failed to create tex");
|
||||
tex.with_lock(None, |u, _i| {
|
||||
u.copy_from_slice(self.rgb_frame_buffer.as_slice());
|
||||
})?;
|
||||
window_canvas.copy(&tex, None, None)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
36
src/sdl_adapters/sdl_keyboard_adapter.rs
Normal file
36
src/sdl_adapters/sdl_keyboard_adapter.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use std::sync::mpsc::Sender;
|
||||
use crate::device::keyboard::{Keyboard, KeyboardEvent};
|
||||
use crate::device::keyboard::KeyboardEvent::{KeyDown, KeyUp};
|
||||
use crate::util::EmulatorResult;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SdlKeyboardAdapter {
|
||||
keyboard_event_sender: Sender<KeyboardEvent>,
|
||||
}
|
||||
|
||||
impl SdlKeyboardAdapter {
|
||||
fn new(keyboard_event_sender: Sender<KeyboardEvent>) -> SdlKeyboardAdapter {
|
||||
SdlKeyboardAdapter {
|
||||
keyboard_event_sender
|
||||
}
|
||||
}
|
||||
/// Creates a paired keyboard and adapter.
|
||||
pub fn new_keyboard()->(SdlKeyboardAdapter, Keyboard){
|
||||
let (sender,receiver) = std::sync::mpsc::channel();
|
||||
let sdl2_kb_adapter = Self::new(sender);
|
||||
let device_kb = Keyboard::new(receiver);
|
||||
(sdl2_kb_adapter,device_kb)
|
||||
}
|
||||
|
||||
pub fn send_key_up(&self, keycode: u8) -> EmulatorResult<u8> {
|
||||
log::trace!("Sending Key up {}",keycode);
|
||||
self.keyboard_event_sender.send(KeyUp(keycode))?;
|
||||
Ok(keycode)
|
||||
}
|
||||
pub fn send_key_down(&self, keycode: u8) -> EmulatorResult<u8> {
|
||||
log::trace!("Sending Key down {}",keycode);
|
||||
self.keyboard_event_sender.send(KeyDown(keycode))?;
|
||||
Ok(keycode)
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user