1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-27 01:51:35 +00:00
8bitworkshop/src/audio/z80worker.js
2017-04-15 18:24:27 -04:00

172 lines
4.4 KiB
JavaScript

"use strict";
/****************************************************************************
Midway/Williams Audio Boards
----------------------------
6809 MEMORY MAP
Function Address R/W Data
---------------------------------------------------------------
Program RAM 0000-07FF R/W D0-D7
Music (YM-2151) 2000-2001 R/W D0-D7
6821 PIA 4000-4003 R/W D0-D7
HC55516 clock low, digit latch 6000 W D0
HC55516 clock high 6800 W xx
Bank select 7800 W D0-D2
Banked Program ROM 8000-FFFF R D0-D7
****************************************************************************/
var window = {};
importScripts("../emu.js");
importScripts("../cpu/z80.js");
window.buildZ80({
applyContention: false
});
var cpu, ram, rom, membus, iobus;
var audio;
var command = 0;
var dac = 0;
var current_buffer;
var last_tstate;
var timer;
var curTime;
var timerPeriod = 20;
var sampleRate;
var numChannels = 2;
var bufferLength;
var cpuFrequency = 18432000/6; // 3.072 MHz
var cpuCyclesPerFrame = cpuFrequency/60;
var cpuAudioFactor = 32;
rom = new RAM(0x4000).mem;
// sample: [0xe,0x0,0x6,0x0,0x78,0xb9,0x30,0x06,0xa9,0xd3,0x00,0x04,0x18,0xf6,0x0c,0x79,0xd6,0xff,0x38,0xee,0x76,0x18,0xea];
rom.fill(0x76); // HALT opcodes
function fillBuffer() {
var t = cpu.getTstates() / cpuAudioFactor;
while (last_tstate < t) {
current_buffer[last_tstate*2] = dac;
current_buffer[last_tstate*2+1] = dac;
last_tstate++;
}
}
function start() {
ram = new RAM(0x400);
membus = {
read: new AddressDecoder([
[0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : null; }],
[0x4000, 0x7fff, 0x3ff, function(a) { return ram.mem[a]; }]
]),
write: new AddressDecoder([
[0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }],
]),
isContended: function() { return false; },
};
iobus = {
read: function(addr) {
return command & 0xff;
},
write: function(addr, val) {
dac = (val & 0xff) << 8;
fillBuffer();
}
};
cpu = window.Z80({
display: {},
memory: membus,
ioBus: iobus
});
current_buffer = new Int16Array(bufferLength);
console.log('started audio');
}
function timerCallback() {
cpu.setTstates(0);
last_tstate = 0;
var numStates = Math.floor(bufferLength * cpuAudioFactor / numChannels);
cpu.runFrame(numStates);
//console.log(numStates, cpu.getTstates());
cpu.setTstates(numStates); // TODO?
fillBuffer();
postMessage({samples:current_buffer});
if (!cpu.getHalted()) {
curTime += timerPeriod;
var dt = curTime - new Date().getTime();
if (dt < 0) dt = 0;
timer = setTimeout(timerCallback, dt);
} else {
timer = 0;
//console.log("HALT @ " + cpu.getPC());
}
}
function reset() {
if (!bufferLength) return;
cpu.reset();
if (!timer) {
curTime = new Date().getTime() - timerPeriod*4;
timerCallback();
}
}
onmessage = function(e) {
if (e && e.data) {
if (e.data.command) {
command = e.data.command & 0xff;
reset();
} else if (e.data.sampleRate) {
console.log(e.data);
sampleRate = e.data.sampleRate;
bufferLength = numChannels*sampleRate*timerPeriod/1000;
start();
reset();
} else if (e.data.rom) {
rom = e.data.rom;
command = 0x0;
reset();
}
}
}
/**
0000 56 _main::
57 ;<stdin>:10:
0000 0E 00 [ 7] 58 ld c,#0x00
59 ;<stdin>:11:
0002 60 00111$:
0002 06 00 [ 7] 61 ld b,#0x00
0004 62 00104$:
0004 78 [ 4] 63 ld a,b
0005 B9 [ 4] 64 cp a,c
0006 30 06 [12] 65 jr NC,00107$
0008 A9 [ 4] 66 xor a, c
0009 D3 00 [11] 67 out (_dac),a
000B 04 [ 4] 68 inc b
000C 18 F6 [12] 69 jr 00104$
000E 70 00107$:
71 ;<stdin>:10:
000E 0C [ 4] 72 inc c
000F 79 [ 4] 73 ld a,c
0010 D6 FF [ 7] 74 sub a, #0xff
0012 38 EE [12] 75 jr C,00111$
76 ;<stdin>:13:
0014 18 EA [12] 77 jr _main
**/