games/gb: improved audio code
This commit is contained in:
parent
ec8d0d9e80
commit
d9af840ca2
5 changed files with 185 additions and 94 deletions
|
@ -4,17 +4,17 @@
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
Event evsamp, evenv;
|
Event evsamp;
|
||||||
|
extern Event evenv, evwave;
|
||||||
s16int sbuf[2*4000], *sbufp;
|
s16int sbuf[2*4000], *sbufp;
|
||||||
enum {
|
enum {
|
||||||
Freq = 44100,
|
Freq = 44100,
|
||||||
SRATEDIV = 8388608 / Freq,
|
SRATEDIV = FREQ / Freq
|
||||||
ENVDIV = 8388608 / 512
|
|
||||||
};
|
};
|
||||||
static int fd;
|
static int fd;
|
||||||
|
|
||||||
u16int envmod;
|
u16int envmod;
|
||||||
u8int sweepen, sweepctr;
|
u8int sweepen, sweepcalc, sweepctr;
|
||||||
u16int sweepfreq;
|
u16int sweepfreq;
|
||||||
typedef struct chan chan;
|
typedef struct chan chan;
|
||||||
struct chan {
|
struct chan {
|
||||||
|
@ -25,9 +25,11 @@ struct chan {
|
||||||
u32int finc;
|
u32int finc;
|
||||||
u8int vol;
|
u8int vol;
|
||||||
};
|
};
|
||||||
u8int wave[32];
|
|
||||||
u8int wpos;
|
u8int wpos;
|
||||||
u16int lfsr;
|
u16int lfsr;
|
||||||
|
u8int apustatus;
|
||||||
|
ulong waveclock;
|
||||||
|
u8int wavebuf;
|
||||||
|
|
||||||
chan sndch[4] = {
|
chan sndch[4] = {
|
||||||
{
|
{
|
||||||
|
@ -51,8 +53,8 @@ chan sndch[4] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
Var apuvars[] = {
|
Var apuvars[] = {
|
||||||
VAR(envmod), VAR(sweepen),
|
VAR(apustatus), VAR(envmod), VAR(sweepen), VAR(sweepcalc),
|
||||||
VAR(sweepctr), VAR(sweepfreq), ARR(wave), VAR(wpos), VAR(lfsr),
|
VAR(sweepctr), VAR(sweepfreq), VAR(wpos), VAR(lfsr), VAR(waveclock), VAR(wavebuf),
|
||||||
VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].fctr), VAR(sndch[0].fthr), VAR(sndch[0].finc), VAR(sndch[0].vol),
|
VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].fctr), VAR(sndch[0].fthr), VAR(sndch[0].finc), VAR(sndch[0].vol),
|
||||||
VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].fctr), VAR(sndch[1].fthr), VAR(sndch[1].finc), VAR(sndch[1].vol),
|
VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].fctr), VAR(sndch[1].fthr), VAR(sndch[1].finc), VAR(sndch[1].vol),
|
||||||
VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].fctr), VAR(sndch[2].fthr), VAR(sndch[2].finc), VAR(sndch[2].vol),
|
VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].fctr), VAR(sndch[2].fthr), VAR(sndch[2].finc), VAR(sndch[2].vol),
|
||||||
|
@ -68,7 +70,7 @@ rate(int i, u16int v)
|
||||||
sndch[i].finc = 131072ULL * 65536 / (Freq * (2048 - (v & 0x7ff)));
|
sndch[i].finc = 131072ULL * 65536 / (Freq * (2048 - (v & 0x7ff)));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sndch[2].finc = 2097152ULL * 65536 / (Freq * (2048 - (v & 0x7ff)));
|
sndch[2].finc = 4 * (2048 - (v & 0x7ff));
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
sndch[3].finc = 524288ULL * 65536 / Freq;
|
sndch[3].finc = 524288ULL * 65536 / Freq;
|
||||||
|
@ -84,12 +86,12 @@ void
|
||||||
env(chan *c)
|
env(chan *c)
|
||||||
{
|
{
|
||||||
if((envmod & 1) == 0 && c->len > 0 && (*c->freq & 1<<6) != 0)
|
if((envmod & 1) == 0 && c->len > 0 && (*c->freq & 1<<6) != 0)
|
||||||
--c->len;
|
if(--c->len == 0){
|
||||||
if(c->len == 0){
|
apustatus &= ~(1<<c->n);
|
||||||
c->vol = 0;
|
c->vol = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if((envmod & 7) != 7 || c->ectr == 0 || --c->ectr != 0)
|
if((apustatus & 1<<c->n) == 0 || (envmod & 7) != 7 || c->ectr == 0 || --c->ectr != 0)
|
||||||
return;
|
return;
|
||||||
c->ectr = *c->env & 7;
|
c->ectr = *c->env & 7;
|
||||||
if((*c->env & 1<<3) != 0){
|
if((*c->env & 1<<3) != 0){
|
||||||
|
@ -100,22 +102,27 @@ env(chan *c)
|
||||||
c->vol--;
|
c->vol--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wavetick(void *)
|
||||||
|
{
|
||||||
|
addevent(&evwave, sndch[2].finc);
|
||||||
|
wpos = wpos + 1 & 31;
|
||||||
|
wavebuf = reg[WAVE + (wpos >> 1)];
|
||||||
|
waveclock = clock;
|
||||||
|
}
|
||||||
|
|
||||||
s8int
|
s8int
|
||||||
wavesamp(void)
|
wavesamp(void)
|
||||||
{
|
{
|
||||||
s8int x;
|
u8int x;
|
||||||
int v;
|
|
||||||
|
|
||||||
sndch[2].fctr = v = sndch[2].fctr + sndch[2].finc;
|
if((apustatus & 1<<4) == 0)
|
||||||
if(sndch[2].len == 0 || (reg[NR30] & 1<<7) == 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
for(;;){
|
x = wavebuf;
|
||||||
x = wave[wpos];
|
if((wpos & 1) == 0)
|
||||||
v -= 0x10000;
|
x >>= 4;
|
||||||
if(v < 0)
|
else
|
||||||
break;
|
x &= 0xf;
|
||||||
wpos = wpos + 1 & 31;
|
|
||||||
}
|
|
||||||
if((reg[NR32] & 3<<5) == 0)
|
if((reg[NR32] & 3<<5) == 0)
|
||||||
x = 0;
|
x = 0;
|
||||||
else
|
else
|
||||||
|
@ -137,13 +144,13 @@ lfsrsamp(void)
|
||||||
break;
|
break;
|
||||||
lfsr >>= 1;
|
lfsr >>= 1;
|
||||||
if(((l ^ lfsr) & 1) != 0)
|
if(((l ^ lfsr) & 1) != 0)
|
||||||
if((reg[0x7c/2] & 1<<3) != 0)
|
if((reg[NR43] & 1<<3) != 0)
|
||||||
lfsr |= 0x40;
|
lfsr |= 0x40;
|
||||||
else
|
else
|
||||||
lfsr |= 0x4000;
|
lfsr |= 0x4000;
|
||||||
}
|
}
|
||||||
if((l & 1) != 0)
|
if((l & 1) != 0)
|
||||||
return -sndch[3].vol;
|
return 0;
|
||||||
else
|
else
|
||||||
return sndch[3].vol;
|
return sndch[3].vol;
|
||||||
}
|
}
|
||||||
|
@ -160,11 +167,13 @@ sweep(int wb)
|
||||||
if((cnt & 1<<3) != 0)
|
if((cnt & 1<<3) != 0)
|
||||||
d = -d;
|
d = -d;
|
||||||
fr = sweepfreq + d;
|
fr = sweepfreq + d;
|
||||||
|
sweepcalc |= cnt;
|
||||||
if(fr > 2047){
|
if(fr > 2047){
|
||||||
sndch[0].len = 0;
|
sndch[0].len = 0;
|
||||||
sndch[0].vol = 0;
|
sndch[0].vol = 0;
|
||||||
|
apustatus &= ~1;
|
||||||
sweepen = 0;
|
sweepen = 0;
|
||||||
}else if(wb){
|
}else if(wb && (cnt & 7) != 0){
|
||||||
sweepfreq = fr;
|
sweepfreq = fr;
|
||||||
reg[NR13] = fr;
|
reg[NR13] = fr;
|
||||||
reg[NR14] = reg[NR14] & 0xf8 | fr >> 8;
|
reg[NR14] = reg[NR14] & 0xf8 | fr >> 8;
|
||||||
|
@ -174,7 +183,7 @@ sweep(int wb)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sndstart(chan *c, u16int v)
|
sndstart(chan *c, u8int v)
|
||||||
{
|
{
|
||||||
u8int cnt;
|
u8int cnt;
|
||||||
|
|
||||||
|
@ -182,29 +191,41 @@ sndstart(chan *c, u16int v)
|
||||||
c->ectr = *c->env & 7;
|
c->ectr = *c->env & 7;
|
||||||
if(c->len == 0)
|
if(c->len == 0)
|
||||||
c->len = 64;
|
c->len = 64;
|
||||||
|
apustatus |= 1<<c->n;
|
||||||
if(c == sndch){
|
if(c == sndch){
|
||||||
cnt = reg[NR10];
|
cnt = reg[NR10];
|
||||||
sweepen = (cnt & 0x07) != 0 && (cnt & 0x70) != 0;
|
sweepen = (cnt & 0x07) != 0 || (cnt & 0x70) != 0;
|
||||||
sweepctr = cnt >> 4 & 7;
|
sweepctr = cnt >> 4 & 7;
|
||||||
sweepfreq = v & 0x7ff;
|
sweepctr += sweepctr - 1 & 8;
|
||||||
|
sweepfreq = v << 8 & 0x700 | reg[NR13];
|
||||||
|
sweepcalc = 0;
|
||||||
if((cnt & 0x07) != 0)
|
if((cnt & 0x07) != 0)
|
||||||
sweep(0);
|
sweep(0);
|
||||||
}
|
}
|
||||||
|
if((*c->freq & 0x40) == 0 && (v & 0x40) != 0 && (envmod & 1) != 0 && --c->len == 0 || (*c->env & 0xf8) == 0){
|
||||||
|
apustatus &= ~(1<<c->n);
|
||||||
|
c->vol = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
envtick(void *)
|
envtick(void *)
|
||||||
{
|
{
|
||||||
addevent(&evenv, ENVDIV);
|
addevent(&evenv, FREQ / 512);
|
||||||
|
|
||||||
env(&sndch[0]);
|
env(&sndch[0]);
|
||||||
env(&sndch[1]);
|
env(&sndch[1]);
|
||||||
if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[NR34] & 0x40) != 0)
|
if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[NR34] & 0x40) != 0)
|
||||||
sndch[2].len--;
|
if(--sndch[2].len == 0){
|
||||||
|
apustatus &= ~4;
|
||||||
|
delevent(&evwave);
|
||||||
|
}
|
||||||
env(&sndch[3]);
|
env(&sndch[3]);
|
||||||
if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
|
if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
|
||||||
sweepctr = reg[NR10] >> 4 & 7;
|
sweepctr = reg[NR10] >> 4 & 7;
|
||||||
sweep(1);
|
sweepctr += sweepctr - 1 & 8;
|
||||||
|
if((reg[NR10] & 0x70) != 0)
|
||||||
|
sweep(1);
|
||||||
}
|
}
|
||||||
envmod++;
|
envmod++;
|
||||||
}
|
}
|
||||||
|
@ -223,12 +244,12 @@ sampletick(void *)
|
||||||
if(sndch[0].fctr >= sndch[0].fthr)
|
if(sndch[0].fctr >= sndch[0].fthr)
|
||||||
ch[0] = sndch[0].vol;
|
ch[0] = sndch[0].vol;
|
||||||
else
|
else
|
||||||
ch[0] = -sndch[0].vol;
|
ch[0] = 0;
|
||||||
sndch[1].fctr += sndch[1].finc;
|
sndch[1].fctr += sndch[1].finc;
|
||||||
if(sndch[1].fctr >= sndch[1].fthr)
|
if(sndch[1].fctr >= sndch[1].fthr)
|
||||||
ch[1] = sndch[1].vol;
|
ch[1] = sndch[1].vol;
|
||||||
else
|
else
|
||||||
ch[1] = -sndch[1].vol;
|
ch[1] = 0;
|
||||||
ch[2] = wavesamp();
|
ch[2] = wavesamp();
|
||||||
ch[3] = lfsrsamp();
|
ch[3] = lfsrsamp();
|
||||||
|
|
||||||
|
@ -237,19 +258,20 @@ sampletick(void *)
|
||||||
s[0] = 0;
|
s[0] = 0;
|
||||||
s[1] = 0;
|
s[1] = 0;
|
||||||
for(i = 0; i < 4; i++){
|
for(i = 0; i < 4; i++){
|
||||||
|
if(i == 2 ? ((reg[NR30] & 0x80) == 0) : ((*sndch[i].env & 0xf8) == 0))
|
||||||
|
continue;
|
||||||
|
ch[i] = ch[i] * 2 - 15;
|
||||||
if((cnth & 1<<i) != 0)
|
if((cnth & 1<<i) != 0)
|
||||||
s[1] += ch[i] * (1 + (cntl & 7));
|
s[0] += ch[i];
|
||||||
if((cnth & 1<<4<<i) != 0)
|
if((cnth & 1<<4<<i) != 0)
|
||||||
s[0] += ch[i] * (1 + (cntl >> 4 & 7));
|
s[1] += ch[i];
|
||||||
}
|
}
|
||||||
if(s[0] < -0x200) s[0] = -0x200;
|
s[0] *= 1 + (cntl & 7);
|
||||||
else if(s[0] > 0x1ff) s[0] = 0x1ff;
|
s[1] *= 1 + (cntl >> 4 & 7);
|
||||||
if(s[1] < -0x200) s[1] = -0x200;
|
|
||||||
else if(s[1] > 0x1ff) s[1] = 0x1ff;
|
|
||||||
|
|
||||||
if(sbufp < sbuf + nelem(sbuf)){
|
if(sbufp < sbuf + nelem(sbuf)){
|
||||||
sbufp[0] = s[0] << 6;
|
sbufp[0] = s[0] * 60;
|
||||||
sbufp[1] = s[1] << 6;
|
sbufp[1] = s[1] * 60;
|
||||||
sbufp += 2;
|
sbufp += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,14 +280,34 @@ void
|
||||||
sndwrite(u8int a, u8int v)
|
sndwrite(u8int a, u8int v)
|
||||||
{
|
{
|
||||||
static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
|
static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
|
||||||
|
static u8int clrreg[] = {
|
||||||
|
0x80, 0x3f, 0x00, 0xff, 0xbf,
|
||||||
|
0xff, 0x3f, 0x00, 0xff, 0xbf,
|
||||||
|
0x7f, 0xff, 0x9f, 0xff, 0xbf,
|
||||||
|
0xff, 0xff, 0x00, 0x00, 0xbf,
|
||||||
|
0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
if((reg[NR52] & 0x80) == 0 && a != NR52)
|
if((reg[NR52] & 0x80) == 0 && a != NR52 && ((mode & CGB) != 0 || a != NR11 && a != NR21 && a != NR31 && a != NR41))
|
||||||
return;
|
return;
|
||||||
switch(a){
|
switch(a){
|
||||||
|
case NR10:
|
||||||
|
if((sweepcalc & 0x08) != 0 && (reg[NR10] & ~v & 0x08) != 0){
|
||||||
|
sndch[0].vol = 0;
|
||||||
|
apustatus &= ~1;
|
||||||
|
sweepcalc = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NR11:
|
case NR11:
|
||||||
sndch[0].fthr = thr[v >> 6 & 3];
|
sndch[0].fthr = thr[v >> 6 & 3];
|
||||||
sndch[0].len = 64 - (v & 63);
|
sndch[0].len = 64 - (v & 63);
|
||||||
break;
|
break;
|
||||||
|
case NR12:
|
||||||
|
if((v & 0xf8) == 0){
|
||||||
|
sndch[0].vol = 0;
|
||||||
|
apustatus &= ~1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NR13:
|
case NR13:
|
||||||
rate(0, reg[NR14] << 8 & 0x700 | v);
|
rate(0, reg[NR14] << 8 & 0x700 | v);
|
||||||
break;
|
break;
|
||||||
|
@ -276,6 +318,13 @@ sndwrite(u8int a, u8int v)
|
||||||
break;
|
break;
|
||||||
case NR21:
|
case NR21:
|
||||||
sndch[1].fthr = thr[v >> 6 & 3];
|
sndch[1].fthr = thr[v >> 6 & 3];
|
||||||
|
sndch[1].len = 64 - (v & 63);
|
||||||
|
break;
|
||||||
|
case NR22:
|
||||||
|
if((v & 0xf8) == 0){
|
||||||
|
sndch[1].vol = 0;
|
||||||
|
apustatus &= ~2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NR23:
|
case NR23:
|
||||||
rate(1, reg[NR24] << 8 & 0x700 | v);
|
rate(1, reg[NR24] << 8 & 0x700 | v);
|
||||||
|
@ -286,8 +335,10 @@ sndwrite(u8int a, u8int v)
|
||||||
sndstart(&sndch[1], v);
|
sndstart(&sndch[1], v);
|
||||||
break;
|
break;
|
||||||
case NR30:
|
case NR30:
|
||||||
if((v & 1<<7) != 0 && sndch[2].len == 0)
|
if((v & 0x80) == 0){
|
||||||
sndch[2].len = 256;
|
apustatus &= ~4;
|
||||||
|
delevent(&evwave);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NR31:
|
case NR31:
|
||||||
sndch[2].len = 256 - (v & 0xff);
|
sndch[2].len = 256 - (v & 0xff);
|
||||||
|
@ -297,6 +348,25 @@ sndwrite(u8int a, u8int v)
|
||||||
break;
|
break;
|
||||||
case NR34:
|
case NR34:
|
||||||
rate(2, v << 8 & 0x700 | reg[NR33]);
|
rate(2, v << 8 & 0x700 | reg[NR33]);
|
||||||
|
if((v & 0x80) != 0){
|
||||||
|
if(sndch[2].len == 0)
|
||||||
|
sndch[2].len = 256;
|
||||||
|
wpos = 0;
|
||||||
|
if((reg[NR30] & 0x80) != 0){
|
||||||
|
apustatus |= 4;
|
||||||
|
delevent(&evwave);
|
||||||
|
addevent(&evwave, sndch[2].finc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NR41:
|
||||||
|
sndch[3].len = 64 - (v & 63);
|
||||||
|
break;
|
||||||
|
case NR42:
|
||||||
|
if((v & 0xf8) == 0){
|
||||||
|
sndch[3].vol = 0;
|
||||||
|
apustatus &= ~8;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NR43:
|
case NR43:
|
||||||
rate(3, v);
|
rate(3, v);
|
||||||
|
@ -311,42 +381,44 @@ sndwrite(u8int a, u8int v)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NR52:
|
case NR52:
|
||||||
|
apustatus = v & 0xf0 | apustatus & 0x0f;
|
||||||
if((v & 0x80) == 0){
|
if((v & 0x80) == 0){
|
||||||
memset(reg + NR10, 0, NR52 - NR10);
|
memcpy(reg + NR10, clrreg, NR52 - NR10);
|
||||||
sndch[0].len = 0;
|
if((mode & CGB) != 0){
|
||||||
sndch[1].len = 0;
|
sndch[0].len = 0;
|
||||||
sndch[2].len = 0;
|
sndch[1].len = 0;
|
||||||
sndch[3].len = 0;
|
sndch[2].len = 0;
|
||||||
|
sndch[3].len = 0;
|
||||||
|
apustatus = 0;
|
||||||
|
delevent(&evwave);
|
||||||
|
}
|
||||||
|
}else if((reg[NR52] & 0x80) == 0){
|
||||||
|
envmod = 0;
|
||||||
|
delevent(&evenv);
|
||||||
|
addevent(&evenv, FREQ / 512);
|
||||||
|
sndch[0].fctr = 0;
|
||||||
|
sndch[1].fctr = 0;
|
||||||
|
sndch[3].fctr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
reg[a] = v;
|
||||||
|
|
||||||
int
|
|
||||||
apuread(void)
|
|
||||||
{
|
|
||||||
u8int v;
|
|
||||||
|
|
||||||
v = reg[NR52] & 0xf0;
|
|
||||||
if(sndch[0].len != 0) v |= 1;
|
|
||||||
if(sndch[1].len != 0) v |= 2;
|
|
||||||
if(sndch[2].len != 0) v |= 4;
|
|
||||||
if(sndch[3].len != 0) v |= 8;
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8int
|
u8int
|
||||||
waveread(u8int a)
|
waveread(u8int a)
|
||||||
{
|
{
|
||||||
a <<= 1;
|
if((apustatus & 4) != 0)
|
||||||
return wave[a + wpos & 31] << 4 | wave[a + wpos + 1 & 31];
|
if((mode & CGB) != 0 || clock - waveclock == 0)
|
||||||
|
return wavebuf;
|
||||||
|
else
|
||||||
|
return 0xff;
|
||||||
|
return reg[WAVE + a];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wavewrite(u8int a, u8int v)
|
wavewrite(u8int a, u8int v)
|
||||||
{
|
{
|
||||||
a <<= 1;
|
reg[WAVE + a] = v;
|
||||||
wave[a + wpos & 31] = v >> 4;
|
|
||||||
wave[a + wpos + 1 & 31] = v & 0x0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -358,8 +430,6 @@ audioinit(void)
|
||||||
sbufp = sbuf;
|
sbufp = sbuf;
|
||||||
evsamp.f = sampletick;
|
evsamp.f = sampletick;
|
||||||
addevent(&evsamp, SRATEDIV);
|
addevent(&evsamp, SRATEDIV);
|
||||||
evenv.f = envtick;
|
|
||||||
addevent(&evenv, ENVDIV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -20,6 +20,8 @@ extern ulong clock;
|
||||||
|
|
||||||
extern u8int ppuy, ppustate;
|
extern u8int ppuy, ppustate;
|
||||||
|
|
||||||
|
extern u8int apustatus;
|
||||||
|
|
||||||
extern u8int mode;
|
extern u8int mode;
|
||||||
extern u8int mbc, feat;
|
extern u8int mbc, feat;
|
||||||
extern int keys, scale;
|
extern int keys, scale;
|
||||||
|
@ -69,6 +71,7 @@ enum {
|
||||||
WX = 0x4B,
|
WX = 0x4B,
|
||||||
KEY1 = 0x4D,
|
KEY1 = 0x4D,
|
||||||
VBK = 0x4F,
|
VBK = 0x4F,
|
||||||
|
RP = 0x56,
|
||||||
HDMASH = 0x51,
|
HDMASH = 0x51,
|
||||||
HDMASL = 0x52,
|
HDMASL = 0x52,
|
||||||
HDMADH = 0x53,
|
HDMADH = 0x53,
|
||||||
|
@ -128,6 +131,7 @@ enum {
|
||||||
PICH = 144,
|
PICH = 144,
|
||||||
MILLION = 1000000,
|
MILLION = 1000000,
|
||||||
BILLION = 1000000000,
|
BILLION = 1000000000,
|
||||||
|
FREQ = 1<<23
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Event {
|
struct Event {
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
Event evhblank, evtimer, evnever;
|
Event evhblank, evtimer, evenv, evwave;
|
||||||
extern Event evsamp, evenv;
|
extern Event evsamp;
|
||||||
Event *events[NEVENT] = {&evhblank, &evtimer, &evnever, &evsamp, &evenv};
|
Event *events[NEVENT] = {&evhblank, &evtimer, &evenv, &evsamp, &evwave};
|
||||||
Event *elist;
|
Event *elist;
|
||||||
static int timshtab[4] = {12, 4, 6, 8}, timsh;
|
static int timshtab[4] = {12, 4, 6, 8}, timsh;
|
||||||
ulong timclock;
|
ulong timclock;
|
||||||
|
@ -103,20 +103,17 @@ timertick(void *)
|
||||||
reg[IF] |= IRQTIM;
|
reg[IF] |= IRQTIM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nevertick(void *)
|
|
||||||
{
|
|
||||||
addevent(&evnever, 10000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
eventinit(void)
|
eventinit(void)
|
||||||
{
|
{
|
||||||
extern void hblanktick(void *);
|
extern void hblanktick(void *);
|
||||||
|
extern void envtick(void *);
|
||||||
|
extern void wavetick(void *);
|
||||||
|
|
||||||
evhblank.f = hblanktick;
|
evhblank.f = hblanktick;
|
||||||
addevent(&evhblank, 240*4);
|
addevent(&evhblank, 240*4);
|
||||||
evtimer.f = timertick;
|
evtimer.f = timertick;
|
||||||
evnever.f = nevertick;
|
evenv.f = envtick;
|
||||||
addevent(&evnever, 10000000);
|
addevent(&evenv, FREQ / 512);
|
||||||
|
evwave.f = wavetick;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ int dmastep(void);
|
||||||
void audioinit(void);
|
void audioinit(void);
|
||||||
int audioout(void);
|
int audioout(void);
|
||||||
void sndwrite(u8int, u8int);
|
void sndwrite(u8int, u8int);
|
||||||
int apuread(void);
|
|
||||||
u8int waveread(u8int);
|
u8int waveread(u8int);
|
||||||
void wavewrite(u8int, u8int);
|
void wavewrite(u8int, u8int);
|
||||||
u8int timread(void);
|
u8int timread(void);
|
||||||
|
|
|
@ -27,7 +27,7 @@ regread(u8int a)
|
||||||
|
|
||||||
switch(a){
|
switch(a){
|
||||||
case JOYP:
|
case JOYP:
|
||||||
v = keys & 0x30 | 0xcf;
|
v = reg[a] & 0xff;
|
||||||
if((reg[a] & 0x10) == 0)
|
if((reg[a] & 0x10) == 0)
|
||||||
v &= 0xf0 | ~keys;
|
v &= 0xf0 | ~keys;
|
||||||
if((reg[a] & 0x20) == 0)
|
if((reg[a] & 0x20) == 0)
|
||||||
|
@ -50,10 +50,13 @@ regread(u8int a)
|
||||||
case NR14: case NR24: case NR34: case NR44:
|
case NR14: case NR24: case NR34: case NR44:
|
||||||
return reg[a] | 0xbf;
|
return reg[a] | 0xbf;
|
||||||
case NR52:
|
case NR52:
|
||||||
return apuread();
|
return apustatus;
|
||||||
|
case NR11: case NR21:
|
||||||
|
return reg[a] | 0x3f;
|
||||||
|
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
|
||||||
|
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||||
|
return waveread(a & 0xf);
|
||||||
default:
|
default:
|
||||||
if((a & 0xf0) == 0x30)
|
|
||||||
return waveread(a & 0xf);
|
|
||||||
return reg[a];
|
return reg[a];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +81,8 @@ regwrite(u8int a, u8int v)
|
||||||
u8int u;
|
u8int u;
|
||||||
|
|
||||||
switch(a){
|
switch(a){
|
||||||
|
case JOYP: v |= 0xcf; break;
|
||||||
|
case SC: v |= 0x7c; break;
|
||||||
case DIV:
|
case DIV:
|
||||||
divclock = clock;
|
divclock = clock;
|
||||||
v = 0;
|
v = 0;
|
||||||
|
@ -111,13 +116,13 @@ regwrite(u8int a, u8int v)
|
||||||
break;
|
break;
|
||||||
case VBK:
|
case VBK:
|
||||||
if((mode & COL) == 0)
|
if((mode & COL) == 0)
|
||||||
break;
|
goto ff;
|
||||||
vramb = vram + ((v & 1) << 13);
|
vramb = vram + ((v & 1) << 13);
|
||||||
v |= 0xfe;
|
v |= 0xfe;
|
||||||
break;
|
break;
|
||||||
case SVBK:
|
case SVBK:
|
||||||
if((mode & COL) == 0)
|
if((mode & COL) == 0)
|
||||||
break;
|
goto ff;
|
||||||
v &= 7;
|
v &= 7;
|
||||||
wramb = wram + (v + (v - 1 >> 3 & 1) << 12);
|
wramb = wram + (v + (v - 1 >> 3 & 1) << 12);
|
||||||
v |= 0xf8;
|
v |= 0xf8;
|
||||||
|
@ -161,29 +166,45 @@ regwrite(u8int a, u8int v)
|
||||||
reg[OCPS] = reg[OCPS] + 1 - ((reg[OCPS] & 0x3f) + 1 & 0x40);
|
reg[OCPS] = reg[OCPS] + 1 - ((reg[OCPS] & 0x3f) + 1 & 0x40);
|
||||||
break;
|
break;
|
||||||
case IF: v |= 0xe0; break;
|
case IF: v |= 0xe0; break;
|
||||||
|
case IE: v &= 0x1f; break;
|
||||||
case KEY1: v |= 0x7e; break;
|
case KEY1: v |= 0x7e; break;
|
||||||
case HDMAC:
|
case HDMAC:
|
||||||
if((mode & COL) == 0)
|
if((mode & COL) == 0)
|
||||||
break;
|
goto ff;
|
||||||
dma = (v & 0x80) != 0 ? -1 : 1;
|
dma = (v & 0x80) != 0 ? -1 : 1;
|
||||||
break;
|
break;
|
||||||
case NR10: v |= 0x80; goto snd;
|
case NR10: v |= 0x80; goto snd;
|
||||||
case NR14: case NR24: v |= 0x38; goto snd;
|
case NR14: case NR24: v |= 0x38; goto snd;
|
||||||
|
case NR30: v |= 0x7f; goto snd;
|
||||||
case NR32: v |= 0x9f; goto snd;
|
case NR32: v |= 0x9f; goto snd;
|
||||||
case NR41: v |= 0xc0; goto snd;
|
case NR41: v |= 0xc0; goto snd;
|
||||||
case NR44: v |= 0x3f; goto snd;
|
case NR44: v |= 0x3f; goto snd;
|
||||||
case NR52: v |= 0x70; goto snd;
|
case NR52: v |= 0x70; goto snd;
|
||||||
case NR11: case NR12: case NR13:
|
case NR11: case NR12: case NR13:
|
||||||
case NR21: case NR22: case NR23:
|
case NR21: case NR22: case NR23:
|
||||||
case NR30: case NR31: case NR33: case NR34:
|
case NR31: case NR33: case NR34:
|
||||||
case NR42: case NR43:
|
case NR42: case NR43:
|
||||||
case NR50: case NR51:
|
case NR50: case NR51:
|
||||||
snd:
|
snd:
|
||||||
sndwrite(a, v);
|
sndwrite(a, v);
|
||||||
|
return;
|
||||||
|
case SB:
|
||||||
|
case TMA:
|
||||||
break;
|
break;
|
||||||
|
case HDMASL: case HDMASH: case HDMADL: case HDMADH: case RP:
|
||||||
|
if((mode & COL) == 0)
|
||||||
|
goto ff;
|
||||||
|
break;
|
||||||
|
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
|
||||||
|
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||||
|
wavewrite(a & 0xf, v);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
if(a >= 0x80)
|
||||||
|
break;
|
||||||
|
ff:
|
||||||
|
v = 0xff;
|
||||||
}
|
}
|
||||||
if((a & 0xf0) == 0x30)
|
|
||||||
wavewrite(a, v);
|
|
||||||
reg[a] = v;
|
reg[a] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue