2 Commits

Author SHA1 Message Date
e05701300c implement backchannel from audio thread 2022-04-22 00:28:19 +02:00
df0c169d54 use the last byte 2022-04-20 23:19:26 +02:00
5 changed files with 52 additions and 10 deletions

View File

@@ -20,10 +20,10 @@ data 0x20000 {
0x44, 0x0, 0x0, 0x47, 0x49, 0x47, 0x45, 0x41,
0x44, 0x0, 0x0, 0x0, 0x42, 0x0, 0x0, 0x0,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0x38,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0x38,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0x38,
0x25, 0, 0x49, 0x25, 0x25, 0, 0x49, 0x38,
0x2a, 0x0, 0x0, 0x0, 0x2d, 0x0, 0x0, 0x0,
0x2c, 0x0, 0x28, 0x0, 0x2a, 0x0, 0x0, 0x0,

File diff suppressed because one or more lines are too long

View File

@@ -91,6 +91,7 @@ impl MicroW8 {
struct Uw8Sound {
stream: cpal::Stream,
tx: mpsc::SyncSender<[u8; 32]>,
rx: mpsc::Receiver<[u8; 32]>,
}
impl super::Runtime for MicroW8 {
@@ -260,15 +261,27 @@ impl super::Runtime for MicroW8 {
};
let (tx, rx) = mpsc::sync_channel::<[u8; 32]>(1);
let (back_tx, back_rx) = mpsc::sync_channel::<[u8; 32]>(2);
let start_time = Instant::now();
let mut sample_index = 0;
let stream = {
device.build_output_stream(
&config,
move |buffer: &mut [f32], _| {
if let Ok(regs) = rx.try_recv() {
if let Ok(mut regs) = rx.try_recv() {
memory.write(&mut store, 80, &regs).unwrap();
memory.read(&mut store, 0x12c80, &mut regs).unwrap();
back_tx.send(regs).unwrap();
}
{
let time = start_time.elapsed().as_millis() as i32;
let mem = memory.data_mut(&mut store);
mem[64..68].copy_from_slice(&time.to_le_bytes());
}
for v in buffer {
*v = snd.call(&mut store, (sample_index,)).unwrap_or(0.0);
sample_index = sample_index.wrapping_add(1);
@@ -280,7 +293,11 @@ impl super::Runtime for MicroW8 {
)?
};
Uw8Sound { stream, tx }
Uw8Sound {
stream,
tx,
rx: back_rx,
}
};
sound.stream.play()?;
@@ -302,6 +319,13 @@ impl super::Runtime for MicroW8 {
fn run_frame(&mut self) -> Result<()> {
let mut result = Ok(());
if let Some(mut instance) = self.instance.take() {
while let Ok(regs) = instance.sound.rx.try_recv() {
instance
.memory
.write(&mut instance.store, 0x12c80, &regs)
.unwrap();
}
{
let time = instance.start_time.elapsed().as_millis() as i32;
let mut gamepad: u32 = 0;

View File

@@ -5,7 +5,14 @@ class APU extends AudioWorkletProcessor {
this.sampleIndex = 0;
this.port.onmessage = (ev) => {
if(this.memory) {
U8(this.memory.buffer, 80, 32).set(U8(ev.data));
if(isNaN(ev.data)) {
let data = U8(ev.data);
U8(this.memory.buffer, 80, 32).set(data);
data.set(U8(this.memory.buffer, 0x12c80, 32));
this.port.postMessage(ev.data);
} else {
this.startTime = ev.data;
}
} else {
this.load(ev.data[0], ev.data[1]);
}
@@ -51,7 +58,9 @@ class APU extends AudioWorkletProcessor {
}
process(inputs, outputs, parameters) {
if(this.snd) {
if(this.snd && this.startTime) {
let u32Mem = new Uint32Array(this.memory.buffer);
u32Mem[16] = Date.now() - this.startTime;
let channels = outputs[0];
let index = this.sampleIndex;
let numSamples = channels[0].length;

View File

@@ -126,7 +126,6 @@ export default function MicroW8(screen, config = {}) {
audioReadyResolve = null;
}
};
audioNode.port.onmessage = (e) => updateAudioReady(e.data);
let audioStateChange = () => {
if(audioContext.state == 'suspended') {
if(config.startButton) {
@@ -211,6 +210,14 @@ export default function MicroW8(screen, config = {}) {
data = loadModuleData(data);
let platform_data = await loadModuleURL(platformUrl);
audioNode.port.onmessage = (e) => {
if(isNaN(e.data)) {
U8(memory.buffer, 0x12c80, 32).set(U8(e.data));
} else {
updateAudioReady(e.data);
}
};
audioNode.port.postMessage([platform_data, data]);
let platform_instance = await instantiate(platform_data);
@@ -240,10 +247,12 @@ export default function MicroW8(screen, config = {}) {
isPaused = false;
audioContext.resume();
startTime += now - pauseTime;
audioNode.port.postMessage(startTime);
} else {
isPaused = true;
audioContext.suspend();
pauseTime = now;
audioNode.port.postMessage(0);
}
};
window.addEventListener('focus', () => updateVisibility(true), { signal: abortController.signal });