8bitworkshop/presets/astrocade-bios/bmusic.c

109 lines
2.1 KiB
C

#pragma opt_code_speed
#include "bios.h"
extern byte* MUZPC; // music PC
extern byte* MUZSP; // music SP
extern byte PVOLAB; // channels A and B volume
extern byte PVOLMC; // channel C volume and noise mask
extern byte VOICES; // voices mmask
extern byte DURAT; // note duration
__sfr __at(0x10) hw_tonmo;
__sfr __at(0x11) hw_tonea;
__sfr __at(0x12) hw_toneb;
__sfr __at(0x13) hw_tonec;
__sfr __at(0x14) hw_vibra;
__sfr __at(0x15) hw_volc;
__sfr __at(0x16) hw_volab;
__sfr __at(0x17) hw_voln;
__sfr __at(0x18) hw_sndbx;
extern void portOut(word portVal) __z88dk_fastcall;
static byte NEXT(void) {
return *MUZPC++;
}
static void PUSH(byte b) {
*++MUZSP = b;
}
static byte POP() {
return *MUZSP--;
}
static byte DECTOP() {
return --(*MUZSP);
}
void music_update(void) {
byte op = NEXT();
if (op < 0x80) {
DURAT = op;
op = VOICES;
if (op & 0x01) hw_voln = NEXT();
if (op & 0x02) hw_vibra = NEXT();
if (op & 0x04 && (hw_tonec = *MUZPC)) {
hw_volc = PVOLMC;
}
if (op & 0x08) MUZPC++;
if (op & 0x10) {
if (!(hw_toneb = *MUZPC))
op ^= 0x10;
}
if (op & 0x20) MUZPC++;
if (op & 0x40) {
if (!(hw_tonea = *MUZPC))
op ^= 0x40;
}
if (op & 0x80) MUZPC++;
hw_volab =
((op & 0x40) ? (PVOLAB & 0x0f) : 0) |
((op & 0x10) ? (PVOLAB & 0xf0) : 0);
} else if (op < 0x88) {
portOut( NEXT() | ((op-0x70)<<8) );
} else if (op == 0x88) {
for (byte i=0; i<8; i++) {
portOut( NEXT() | (0x17-i) );
}
} else switch (op & 0xf0) {
case 0x90:
VOICES = NEXT();
break;
case 0xa0:
PUSH(op - 0x9f);
break;
case 0xb0:
PVOLAB = NEXT();
PVOLMC = NEXT();
break;
case 0xc0:
if (DECTOP()) {
MUZPC = (byte*)*(word*)MUZPC;
} else {
MUZPC += 2;
POP();
}
break;
case 0xd0:
MUZPC += op & 0xf;
break;
case 0xe0:
// REST
if (op == 0xe1) {
hw_volab = hw_volc = 0;
DURAT = *MUZPC++;
} else {
// TODO: legatto/stacatto
}
break;
case 0xf0:
hw_volab = hw_volc = 0;
VOICES = 0;
break;
}
}