games/gb: better audio, scaling, fixed serious MMC5 bug
This commit is contained in:
parent
8ebb846fb2
commit
d7f507b5b9
5 changed files with 121 additions and 27 deletions
|
@ -6,7 +6,7 @@
|
|||
#include "fns.h"
|
||||
|
||||
static int fd;
|
||||
int ch1c, ch2c, ch3c, ch4c, ch4sr = 1;
|
||||
static int sc, ch1c, ch2c, ch3c, ch4c, ch4sr = 1, ch1vec, ch2vec, ch4vec, ch1v, ch2v, ch4v;
|
||||
|
||||
enum { SAMPLE = 44100 };
|
||||
|
||||
|
@ -32,14 +32,75 @@ freq(int lower)
|
|||
return f;
|
||||
}
|
||||
|
||||
static void
|
||||
soundlen(int len, int ctrl, int n)
|
||||
{
|
||||
if(mem[ctrl] & 128){
|
||||
mem[0xFF26] |= (1<<n);
|
||||
mem[ctrl] &= ~128;
|
||||
switch(n){
|
||||
case 0:
|
||||
ch1v = mem[0xFF12];
|
||||
break;
|
||||
case 1:
|
||||
ch2v = mem[0xFF17];
|
||||
break;
|
||||
case 3:
|
||||
ch4v = mem[0xFF21];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if((mem[ctrl] & 64) == 0){
|
||||
mem[0xFF26] |= (1<<n);
|
||||
return;
|
||||
}
|
||||
if((mem[0xFF26] & (1<<n)) == 0)
|
||||
return;
|
||||
if(mem[len] == ((n == 2) ? 255 : 63)){
|
||||
mem[0xFF26] &= ~(1<<n);
|
||||
return;
|
||||
}
|
||||
mem[len]++;
|
||||
}
|
||||
|
||||
static void
|
||||
envelope(int *v, int *c)
|
||||
{
|
||||
int f;
|
||||
|
||||
f = (*v & 7) * SAMPLE / 64;
|
||||
if(f == 0)
|
||||
return;
|
||||
if(*c >= f){
|
||||
if(*v & 8){
|
||||
if((*v >> 4) < 0xF)
|
||||
*v += 0x10;
|
||||
}else
|
||||
if((*v >> 4) > 0)
|
||||
*v -= 0x10;
|
||||
*c = 0;
|
||||
}
|
||||
(*c)++;
|
||||
}
|
||||
|
||||
static void
|
||||
dosample(short *smp)
|
||||
{
|
||||
int ch1s, ch2s, ch3s, ch4s, ch1f, ch2f, ch3f, ch4f, k, r, s;
|
||||
u8int f;
|
||||
|
||||
ch4s = 0;
|
||||
|
||||
if(sc >= SAMPLE/256){
|
||||
soundlen(0xFF11, 0xFF14, 0);
|
||||
soundlen(0xFF16, 0xFF19, 1);
|
||||
soundlen(0xFF1B, 0xFF1E, 2);
|
||||
soundlen(0xFF20, 0xFF23, 3);
|
||||
sc = 0;
|
||||
}
|
||||
sc++;
|
||||
envelope(&ch1v, &ch1vec);
|
||||
envelope(&ch2v, &ch2vec);
|
||||
envelope(&ch4v, &ch4vec);
|
||||
|
||||
ch1f = freq(0xFF13);
|
||||
if(ch1c >= ch1f)
|
||||
ch1c = 0;
|
||||
|
@ -47,8 +108,8 @@ dosample(short *smp)
|
|||
ch1s = 1;
|
||||
else
|
||||
ch1s = -1;
|
||||
ch1s *= mem[0xFF12] >> 4;
|
||||
ch1s *= 10000 / 0xF;
|
||||
ch1s *= ch1v >> 4;
|
||||
ch1s *= 8000 / 0xF;
|
||||
ch1c++;
|
||||
|
||||
ch2f = freq(0xFF18);
|
||||
|
@ -58,8 +119,8 @@ dosample(short *smp)
|
|||
ch2s = 1;
|
||||
else
|
||||
ch2s = -1;
|
||||
ch2s *= mem[0xFF17] >> 4;
|
||||
ch2s *= 10000 / 0xF;
|
||||
ch2s *= ch2v >> 4;
|
||||
ch2s *= 8000 / 0xF;
|
||||
ch2c++;
|
||||
|
||||
ch3f = freq(0xFF1D) * 100 / 32;
|
||||
|
@ -86,7 +147,7 @@ dosample(short *smp)
|
|||
ch3s >>= 2;
|
||||
break;
|
||||
}
|
||||
ch3s *= 10000 / 0xF;
|
||||
ch3s *= 8000 / 0xF;
|
||||
ch3c++;
|
||||
}
|
||||
|
||||
|
@ -113,12 +174,15 @@ dosample(short *smp)
|
|||
ch4s = -1;
|
||||
else
|
||||
ch4s = 1;
|
||||
ch4s *= mem[0xFF21] >> 4;
|
||||
ch4s *= 10000 / 0xF;
|
||||
ch4s *= ch4v >> 4;
|
||||
ch4s *= 8000 / 0xF;
|
||||
|
||||
smp[0] = 0;
|
||||
smp[1] = 0;
|
||||
f = mem[0xFF25];
|
||||
r = mem[0xFF26] & 15;
|
||||
r = r | (r << 4);
|
||||
f &= r;
|
||||
if(f & 0x01) smp[0] += ch1s;
|
||||
if(f & 0x02) smp[0] += ch2s;
|
||||
if(f & 0x04) smp[0] += ch3s;
|
||||
|
@ -145,6 +209,10 @@ audioproc(void *)
|
|||
void
|
||||
initaudio(void)
|
||||
{
|
||||
mem[0xFF26] = 0xF;
|
||||
ch1v = 0xF0;
|
||||
ch2v = 0xF0;
|
||||
ch4v = 0xF0;
|
||||
fd = open("/dev/audio", OWRITE);
|
||||
if(fd < 0)
|
||||
return;
|
||||
|
|
|
@ -9,6 +9,8 @@ extern uchar mem[], *ram;
|
|||
extern uchar *cart;
|
||||
extern int mbc, rombanks, rambanks;
|
||||
|
||||
extern int scale;
|
||||
|
||||
enum {
|
||||
rB,
|
||||
rC,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "fns.h"
|
||||
|
||||
uchar *cart, *ram;
|
||||
int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, syncclock, syncfreq, sleeps, checkclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq;
|
||||
int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, syncclock, syncfreq, sleeps, checkclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq, scale;
|
||||
Rectangle picr;
|
||||
Image *bg, *tmp;
|
||||
Mousectl *mc;
|
||||
|
@ -140,10 +140,10 @@ loadrom(char *file)
|
|||
initdraw(nil, nil, title);
|
||||
originwindow(screen, Pt(0, 0), screen->r.min);
|
||||
p = divpt(addpt(screen->r.min, screen->r.max), 2);
|
||||
picr = (Rectangle){subpt(p, Pt(80, 72)), addpt(p, Pt(80, 72))};
|
||||
picr = (Rectangle){subpt(p, Pt(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))};
|
||||
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
||||
if(screen->chan != XRGB32 || screen->chan != XBGR32)
|
||||
tmp = allocimage(display, Rect(0, 0, 160, 144), XRGB32, 0, 0);
|
||||
tmp = allocimage(display, Rect(0, 0, scale * 160, scale * 144), XRGB32, 0, 0);
|
||||
draw(screen, screen->r, bg, nil, ZP);
|
||||
|
||||
if(ram && battery){
|
||||
|
@ -230,10 +230,17 @@ threadmain(int argc, char** argv)
|
|||
Mouse m;
|
||||
Point p;
|
||||
|
||||
scale = 1;
|
||||
ARGBEGIN{
|
||||
case 'a':
|
||||
initaudio();
|
||||
break;
|
||||
case '2':
|
||||
scale = 2;
|
||||
break;
|
||||
case '3':
|
||||
scale = 3;
|
||||
break;
|
||||
default:
|
||||
sysfatal("unknown flag -%c", ARGC());
|
||||
}ARGEND;
|
||||
|
@ -279,7 +286,7 @@ threadmain(int argc, char** argv)
|
|||
if(getwindow(display, Refnone) < 0)
|
||||
sysfatal("resize failed: %r");
|
||||
p = divpt(addpt(screen->r.min, screen->r.max), 2);
|
||||
picr = (Rectangle){subpt(p, Pt(80, 72)), addpt(p, Pt(80, 72))};
|
||||
picr = (Rectangle){subpt(p, Pt(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))};
|
||||
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,20 +118,20 @@ memwrite(u16int p, u8int v)
|
|||
}
|
||||
return;
|
||||
case 5:
|
||||
switch(p >> 13){
|
||||
case 0:
|
||||
switch(p >> 12){
|
||||
case 0: case 1:
|
||||
if((v & 0x0F) == 0x0A)
|
||||
ramswitch(1, rambank);
|
||||
else
|
||||
ramswitch(0, rambank);
|
||||
return;
|
||||
case 1:
|
||||
case 2:
|
||||
romswitch((rombank & 0x100) | v);
|
||||
return;
|
||||
case 2:
|
||||
case 3:
|
||||
romswitch((((int)v & 1) << 8) | (rombank & 0xFF));
|
||||
return;
|
||||
case 3:
|
||||
case 4:
|
||||
ramswitch(ramen, v & 15);
|
||||
return;
|
||||
|
||||
|
@ -162,6 +162,8 @@ memwrite(u16int p, u8int v)
|
|||
timerfreq = 256;
|
||||
}
|
||||
break;
|
||||
case 0xFF26:
|
||||
v = (v & 0xF0) | (mem[p] & 0x0F);
|
||||
case 0xFF41:
|
||||
v &= ~7;
|
||||
v |= mem[p] & 7;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
uchar pic[160*144*4];
|
||||
uchar pic[160*144*4*9];
|
||||
|
||||
static void
|
||||
resolvetile(u8int tx, u8int ty, u8int toy, int window, u8int* tnl1, u8int *tnl2)
|
||||
|
@ -32,17 +32,32 @@ resolvetile(u8int tx, u8int ty, u8int toy, int window, u8int* tnl1, u8int *tnl2)
|
|||
static void
|
||||
pixel(int x, int y, int val, int back)
|
||||
{
|
||||
int X, Y;
|
||||
uchar *p;
|
||||
|
||||
val = (3 - val) * 0x55;
|
||||
pic[y*160*4 + x*4] = val;
|
||||
pic[y*160*4 + x*4 + 1] = val;
|
||||
pic[y*160*4 + x*4 + 2] = val;
|
||||
pic[y*160*4 + x*4 + 3] = back ? 0 : 0xFF;
|
||||
if(scale > 1){
|
||||
for(X = scale * x; X < scale * (x+1); X++)
|
||||
for(Y = scale * y; Y < scale * (y+1); Y++){
|
||||
p = pic + Y * scale * 160 * 4 + X * 4;
|
||||
p[0] = val;
|
||||
p[1] = val;
|
||||
p[2] = val;
|
||||
p[3] = back ? 0 : 0xFF;
|
||||
}
|
||||
}else{
|
||||
p = pic + y*160*4 + x*4;
|
||||
p[0] = val;
|
||||
p[1] = val;
|
||||
p[2] = val;
|
||||
p[3] = back ? 0 : 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pixelbelow(int x, int y, int val)
|
||||
{
|
||||
if(pic[y*160*4 + x*4 + 3] == 0)
|
||||
if(pic[y*scale*scale*160*4 + x*scale*4 + 3] == 0)
|
||||
pixel(x, y, val, 0);
|
||||
}
|
||||
|
||||
|
@ -191,10 +206,10 @@ ppustep(void)
|
|||
mem[LY] = 0;
|
||||
if(mem[LCDC] & LCDOP){
|
||||
if(tmp){
|
||||
loadimage(tmp, tmp->r, pic, sizeof(pic));
|
||||
loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale);
|
||||
draw(screen, picr, tmp, nil, ZP);
|
||||
}else
|
||||
loadimage(screen, picr, pic, sizeof(pic));
|
||||
loadimage(screen, picr, pic, 160*144*4*scale*scale);
|
||||
flushimage(display, 1);
|
||||
memset(pic, sizeof pic, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue