moa/emulator/frontends/minifb/src/bin/moa-synth.rs

111 lines
3.0 KiB
Rust

use std::sync::mpsc;
use moa_minifb;
use moa_peripherals_yamaha::{Ym2612, Sn76489};
use moa_core::host::gfx::Frame;
use moa_core::host::{Host, KeyboardUpdater, Key};
use moa_core::{System, Error, ClockElapsed, Address, Addressable, Steppable, Transmutable, TransmutableBox, wrap_transmutable};
pub struct SynthControlsUpdater(mpsc::Sender<(Key, bool)>);
impl KeyboardUpdater for SynthControlsUpdater {
fn update_keyboard(&mut self, key: Key, state: bool) {
self.0.send((key, state)).unwrap();
}
}
struct SynthControl {
receiver: mpsc::Receiver<(Key, bool)>,
}
impl SynthControl {
pub fn new(receiver: mpsc::Receiver<(Key, bool)>) -> Self {
Self {
receiver,
}
}
}
impl Steppable for SynthControl {
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
if let Ok((key, state)) = self.receiver.try_recv() {
match key {
Key::Enter => {
system.get_bus().write_u8(0x00, 0x28)?;
system.get_bus().write_u8(0x01, if state { 0xF0 } else { 0x00 })?;
},
Key::A => {
system.get_bus().write_u8(0x10, 0x84)?;
system.get_bus().write_u8(0x10, 0x0F)?;
system.get_bus().write_u8(0x10, if state { 0x90 } else { 0x9F })?;
},
_ => { },
}
}
Ok(1_000_000)
}
}
impl Transmutable for SynthControl {
fn as_steppable(&mut self) -> Option<&mut dyn Steppable> {
Some(self)
}
}
fn set_register(device: &mut dyn Addressable, bank: u8, reg: u8, data: u8) -> Result<(), Error> {
let addr = (bank as Address) * 2;
device.write_u8(addr, reg)?;
device.write_u8(addr + 1, data)?;
Ok(())
}
fn initialize_ym(ym_sound: TransmutableBox) -> Result<(), Error> {
let mut borrow = ym_sound.borrow_mut();
let device = borrow.as_addressable().unwrap();
set_register(device, 0, 0x30, 0x71)?;
set_register(device, 0, 0x34, 0x0D)?;
set_register(device, 0, 0x38, 0x33)?;
set_register(device, 0, 0x3C, 0x00)?;
set_register(device, 0, 0xA4, 0x22)?;
set_register(device, 0, 0xA0, 0x69)?;
set_register(device, 0, 0xB0, 0x30)?;
Ok(())
}
fn main() {
let matches = moa_minifb::new("YM2612 Tester/Synth")
.get_matches();
moa_minifb::run(matches, |host| {
let mut system = System::new();
let (sender, receiver) = mpsc::channel();
let control = wrap_transmutable(SynthControl::new(receiver));
system.add_device("control", control)?;
let ym_sound = wrap_transmutable(Ym2612::create(host)?);
initialize_ym(ym_sound.clone())?;
system.add_addressable_device(0x00, ym_sound)?;
let sn_sound = wrap_transmutable(Sn76489::create(host)?);
system.add_addressable_device(0x10, sn_sound)?;
let frame = Frame::new_shared(384, 128);
host.add_window(Frame::new_updater(frame.clone()))?;
host.register_keyboard(Box::new(SynthControlsUpdater(sender)))?;
Ok(system)
});
}