mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
first working version with sound
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
include "../include/microw8-api.cwa"
|
||||
|
||||
export fn upd() {}
|
||||
|
||||
export fn snd(index: i32) -> f32 {
|
||||
let inline saw = index & 255;
|
||||
let inline env = (-index #>> 9) & 255;
|
||||
let inline saw = index;
|
||||
let inline env = (-index #>> 9);
|
||||
let inline sample = saw & env;
|
||||
sample as f32 / 255 as f32 - 0.5
|
||||
(sample & 255) as f32 / 255 as f32 - 0.5
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
2
web/run
Executable file
2
web/run
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
rm -rf .parcel-cache && yarn parcel src/index.html
|
||||
60
web/src/audiolet.js
Normal file
60
web/src/audiolet.js
Normal file
@@ -0,0 +1,60 @@
|
||||
class APU extends AudioWorkletProcessor {
|
||||
constructor() {
|
||||
super();
|
||||
this.sampleIndex = 0;
|
||||
this.port.onmessage = (ev) => {
|
||||
this.load(ev.data[0], ev.data[1]);
|
||||
};
|
||||
}
|
||||
|
||||
async load(platform_data, data) {
|
||||
let memory = new WebAssembly.Memory({ initial: 4, maximum: 4 });
|
||||
|
||||
let importObject = {
|
||||
env: {
|
||||
memory
|
||||
},
|
||||
};
|
||||
|
||||
for (let n of ['acos', 'asin', 'atan', 'atan2', 'cos', 'exp', 'log', 'sin', 'tan', 'pow']) {
|
||||
importObject.env[n] = Math[n];
|
||||
}
|
||||
|
||||
for (let i = 9; i < 64; ++i) {
|
||||
importObject.env['reserved' + i] = () => { };
|
||||
}
|
||||
|
||||
for (let i = 0; i < 16; ++i) {
|
||||
importObject.env['g_reserved' + i] = 0;
|
||||
}
|
||||
|
||||
let instantiate = async (data) => (await WebAssembly.instantiate(data, importObject)).instance;
|
||||
|
||||
let platform_instance = await instantiate(platform_data);
|
||||
|
||||
for (let name in platform_instance.exports) {
|
||||
importObject.env[name] = platform_instance.exports[name]
|
||||
}
|
||||
|
||||
let instance = await instantiate(data);
|
||||
|
||||
this.snd = instance.exports.snd;
|
||||
}
|
||||
|
||||
process(inputs, outputs, parameters) {
|
||||
if(this.snd) {
|
||||
let channels = outputs[0];
|
||||
let index = this.sampleIndex;
|
||||
let numSamples = channels[0].length;
|
||||
for(let i = 0; i < numSamples; ++i) {
|
||||
channels[0][i] = this.snd(index++);
|
||||
channels[1][i] = this.snd(index++);
|
||||
}
|
||||
this.sampleIndex = index & 0xffffffff;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
registerProcessor('apu', APU);
|
||||
@@ -1,5 +1,15 @@
|
||||
import loaderUrl from "data-url:../../platform/bin/loader.wasm";
|
||||
import platformUrl from "data-url:../../platform/bin/platform.uw8";
|
||||
import audioWorkletUrl from "data-url:./audiolet.js";
|
||||
|
||||
class AudioNode extends AudioWorkletNode {
|
||||
constructor(context) {
|
||||
super(context, 'apu', {outputChannelCount: [2]});
|
||||
}
|
||||
}
|
||||
|
||||
let U8 = (d) => new Uint8Array(d);
|
||||
let U32 = (d) => new Uint32Array(d);
|
||||
|
||||
export default function MicroW8(screen, config = {}) {
|
||||
if(!config.setMessage) {
|
||||
@@ -18,9 +28,6 @@ export default function MicroW8(screen, config = {}) {
|
||||
|
||||
let currentData;
|
||||
|
||||
let U8 = (d) => new Uint8Array(d);
|
||||
let U32 = (d) => new Uint32Array(d);
|
||||
|
||||
let pad = 0;
|
||||
let keyboardElement = config.keyboardElement == undefined ? screen : config.keyboardElement;
|
||||
if(keyboardElement) {
|
||||
@@ -90,6 +97,16 @@ export default function MicroW8(screen, config = {}) {
|
||||
cancelFunction = null;
|
||||
}
|
||||
|
||||
let audioContext = new AudioContext({sampleRate: 44100});
|
||||
let keepRunning = true;
|
||||
cancelFunction = () => {
|
||||
audioContext.close();
|
||||
keepRunning = false;
|
||||
}
|
||||
|
||||
await audioContext.audioWorklet.addModule(audioWorkletUrl);
|
||||
let audioNode = new AudioNode(audioContext);
|
||||
|
||||
let cartridgeSize = data.byteLength;
|
||||
|
||||
config.setMessage(cartridgeSize);
|
||||
@@ -119,7 +136,7 @@ export default function MicroW8(screen, config = {}) {
|
||||
if(!devkitMode) {
|
||||
memSize.maximum = 4;
|
||||
}
|
||||
let memory = new WebAssembly.Memory({ initial: 4, maximum: devkitMode ? 16 : 4 });
|
||||
let memory = new WebAssembly.Memory(memSize);
|
||||
let memU8 = U8(memory.buffer);
|
||||
|
||||
let importObject = {
|
||||
@@ -142,9 +159,9 @@ export default function MicroW8(screen, config = {}) {
|
||||
|
||||
let instantiate = async (data) => (await WebAssembly.instantiate(data, importObject)).instance;
|
||||
|
||||
let loadModuleURL = async (url) => instantiate(loadModuleData(await (await fetch(url)).arrayBuffer()));
|
||||
let loadModuleURL = async (url) => loadModuleData(await (await fetch(url)).arrayBuffer());
|
||||
|
||||
loader = await loadModuleURL(loaderUrl);
|
||||
loader = await instantiate(await loadModuleURL(loaderUrl));
|
||||
|
||||
for (let n of ['acos', 'asin', 'atan', 'atan2', 'cos', 'exp', 'log', 'sin', 'tan', 'pow']) {
|
||||
importObject.env[n] = Math[n];
|
||||
@@ -160,7 +177,10 @@ export default function MicroW8(screen, config = {}) {
|
||||
|
||||
data = loadModuleData(data);
|
||||
|
||||
let platform_instance = await loadModuleURL(platformUrl);
|
||||
let platform_data = await loadModuleURL(platformUrl);
|
||||
audioNode.port.postMessage([platform_data, data]);
|
||||
|
||||
let platform_instance = await instantiate(platform_data);
|
||||
|
||||
for (let name in platform_instance.exports) {
|
||||
importObject.env[name] = platform_instance.exports[name]
|
||||
@@ -172,12 +192,11 @@ export default function MicroW8(screen, config = {}) {
|
||||
|
||||
let startTime = Date.now();
|
||||
|
||||
let keepRunning = true;
|
||||
cancelFunction = () => keepRunning = false;
|
||||
|
||||
const timePerFrame = 1000 / 60;
|
||||
let nextFrame = startTime;
|
||||
|
||||
audioNode.connect(audioContext.destination);
|
||||
|
||||
function mainloop() {
|
||||
if (!keepRunning) {
|
||||
return;
|
||||
@@ -216,7 +235,9 @@ export default function MicroW8(screen, config = {}) {
|
||||
let u32Mem = U32(memory.buffer);
|
||||
u32Mem[16] = now - startTime;
|
||||
u32Mem[17] = pad | gamepad;
|
||||
instance.exports.upd();
|
||||
if(instance.exports.upd) {
|
||||
instance.exports.upd();
|
||||
}
|
||||
platform_instance.exports.endFrame();
|
||||
|
||||
let palette = U32(memory.buffer.slice(0x13000, 0x13000 + 1024));
|
||||
|
||||
Reference in New Issue
Block a user