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"
|
#include "fns.h"
|
||||||
|
|
||||||
static int fd;
|
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 };
|
enum { SAMPLE = 44100 };
|
||||||
|
|
||||||
|
@ -32,14 +32,75 @@ freq(int lower)
|
||||||
return f;
|
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
|
static void
|
||||||
dosample(short *smp)
|
dosample(short *smp)
|
||||||
{
|
{
|
||||||
int ch1s, ch2s, ch3s, ch4s, ch1f, ch2f, ch3f, ch4f, k, r, s;
|
int ch1s, ch2s, ch3s, ch4s, ch1f, ch2f, ch3f, ch4f, k, r, s;
|
||||||
u8int f;
|
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);
|
ch1f = freq(0xFF13);
|
||||||
if(ch1c >= ch1f)
|
if(ch1c >= ch1f)
|
||||||
ch1c = 0;
|
ch1c = 0;
|
||||||
|
@ -47,8 +108,8 @@ dosample(short *smp)
|
||||||
ch1s = 1;
|
ch1s = 1;
|
||||||
else
|
else
|
||||||
ch1s = -1;
|
ch1s = -1;
|
||||||
ch1s *= mem[0xFF12] >> 4;
|
ch1s *= ch1v >> 4;
|
||||||
ch1s *= 10000 / 0xF;
|
ch1s *= 8000 / 0xF;
|
||||||
ch1c++;
|
ch1c++;
|
||||||
|
|
||||||
ch2f = freq(0xFF18);
|
ch2f = freq(0xFF18);
|
||||||
|
@ -58,8 +119,8 @@ dosample(short *smp)
|
||||||
ch2s = 1;
|
ch2s = 1;
|
||||||
else
|
else
|
||||||
ch2s = -1;
|
ch2s = -1;
|
||||||
ch2s *= mem[0xFF17] >> 4;
|
ch2s *= ch2v >> 4;
|
||||||
ch2s *= 10000 / 0xF;
|
ch2s *= 8000 / 0xF;
|
||||||
ch2c++;
|
ch2c++;
|
||||||
|
|
||||||
ch3f = freq(0xFF1D) * 100 / 32;
|
ch3f = freq(0xFF1D) * 100 / 32;
|
||||||
|
@ -86,7 +147,7 @@ dosample(short *smp)
|
||||||
ch3s >>= 2;
|
ch3s >>= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ch3s *= 10000 / 0xF;
|
ch3s *= 8000 / 0xF;
|
||||||
ch3c++;
|
ch3c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,12 +174,15 @@ dosample(short *smp)
|
||||||
ch4s = -1;
|
ch4s = -1;
|
||||||
else
|
else
|
||||||
ch4s = 1;
|
ch4s = 1;
|
||||||
ch4s *= mem[0xFF21] >> 4;
|
ch4s *= ch4v >> 4;
|
||||||
ch4s *= 10000 / 0xF;
|
ch4s *= 8000 / 0xF;
|
||||||
|
|
||||||
smp[0] = 0;
|
smp[0] = 0;
|
||||||
smp[1] = 0;
|
smp[1] = 0;
|
||||||
f = mem[0xFF25];
|
f = mem[0xFF25];
|
||||||
|
r = mem[0xFF26] & 15;
|
||||||
|
r = r | (r << 4);
|
||||||
|
f &= r;
|
||||||
if(f & 0x01) smp[0] += ch1s;
|
if(f & 0x01) smp[0] += ch1s;
|
||||||
if(f & 0x02) smp[0] += ch2s;
|
if(f & 0x02) smp[0] += ch2s;
|
||||||
if(f & 0x04) smp[0] += ch3s;
|
if(f & 0x04) smp[0] += ch3s;
|
||||||
|
@ -145,6 +209,10 @@ audioproc(void *)
|
||||||
void
|
void
|
||||||
initaudio(void)
|
initaudio(void)
|
||||||
{
|
{
|
||||||
|
mem[0xFF26] = 0xF;
|
||||||
|
ch1v = 0xF0;
|
||||||
|
ch2v = 0xF0;
|
||||||
|
ch4v = 0xF0;
|
||||||
fd = open("/dev/audio", OWRITE);
|
fd = open("/dev/audio", OWRITE);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -9,6 +9,8 @@ extern uchar mem[], *ram;
|
||||||
extern uchar *cart;
|
extern uchar *cart;
|
||||||
extern int mbc, rombanks, rambanks;
|
extern int mbc, rombanks, rambanks;
|
||||||
|
|
||||||
|
extern int scale;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
rB,
|
rB,
|
||||||
rC,
|
rC,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
uchar *cart, *ram;
|
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;
|
Rectangle picr;
|
||||||
Image *bg, *tmp;
|
Image *bg, *tmp;
|
||||||
Mousectl *mc;
|
Mousectl *mc;
|
||||||
|
@ -140,10 +140,10 @@ loadrom(char *file)
|
||||||
initdraw(nil, nil, title);
|
initdraw(nil, nil, title);
|
||||||
originwindow(screen, Pt(0, 0), screen->r.min);
|
originwindow(screen, Pt(0, 0), screen->r.min);
|
||||||
p = divpt(addpt(screen->r.min, screen->r.max), 2);
|
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);
|
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
||||||
if(screen->chan != XRGB32 || screen->chan != XBGR32)
|
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);
|
draw(screen, screen->r, bg, nil, ZP);
|
||||||
|
|
||||||
if(ram && battery){
|
if(ram && battery){
|
||||||
|
@ -230,10 +230,17 @@ threadmain(int argc, char** argv)
|
||||||
Mouse m;
|
Mouse m;
|
||||||
Point p;
|
Point p;
|
||||||
|
|
||||||
|
scale = 1;
|
||||||
ARGBEGIN{
|
ARGBEGIN{
|
||||||
case 'a':
|
case 'a':
|
||||||
initaudio();
|
initaudio();
|
||||||
break;
|
break;
|
||||||
|
case '2':
|
||||||
|
scale = 2;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
scale = 3;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sysfatal("unknown flag -%c", ARGC());
|
sysfatal("unknown flag -%c", ARGC());
|
||||||
}ARGEND;
|
}ARGEND;
|
||||||
|
@ -279,7 +286,7 @@ threadmain(int argc, char** argv)
|
||||||
if(getwindow(display, Refnone) < 0)
|
if(getwindow(display, Refnone) < 0)
|
||||||
sysfatal("resize failed: %r");
|
sysfatal("resize failed: %r");
|
||||||
p = divpt(addpt(screen->r.min, screen->r.max), 2);
|
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);
|
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,20 +118,20 @@ memwrite(u16int p, u8int v)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 5:
|
case 5:
|
||||||
switch(p >> 13){
|
switch(p >> 12){
|
||||||
case 0:
|
case 0: case 1:
|
||||||
if((v & 0x0F) == 0x0A)
|
if((v & 0x0F) == 0x0A)
|
||||||
ramswitch(1, rambank);
|
ramswitch(1, rambank);
|
||||||
else
|
else
|
||||||
ramswitch(0, rambank);
|
ramswitch(0, rambank);
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 2:
|
||||||
romswitch((rombank & 0x100) | v);
|
romswitch((rombank & 0x100) | v);
|
||||||
return;
|
return;
|
||||||
case 2:
|
case 3:
|
||||||
romswitch((((int)v & 1) << 8) | (rombank & 0xFF));
|
romswitch((((int)v & 1) << 8) | (rombank & 0xFF));
|
||||||
return;
|
return;
|
||||||
case 3:
|
case 4:
|
||||||
ramswitch(ramen, v & 15);
|
ramswitch(ramen, v & 15);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -162,6 +162,8 @@ memwrite(u16int p, u8int v)
|
||||||
timerfreq = 256;
|
timerfreq = 256;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0xFF26:
|
||||||
|
v = (v & 0xF0) | (mem[p] & 0x0F);
|
||||||
case 0xFF41:
|
case 0xFF41:
|
||||||
v &= ~7;
|
v &= ~7;
|
||||||
v |= mem[p] & 7;
|
v |= mem[p] & 7;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
uchar pic[160*144*4];
|
uchar pic[160*144*4*9];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
resolvetile(u8int tx, u8int ty, u8int toy, int window, u8int* tnl1, u8int *tnl2)
|
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
|
static void
|
||||||
pixel(int x, int y, int val, int back)
|
pixel(int x, int y, int val, int back)
|
||||||
{
|
{
|
||||||
|
int X, Y;
|
||||||
|
uchar *p;
|
||||||
|
|
||||||
val = (3 - val) * 0x55;
|
val = (3 - val) * 0x55;
|
||||||
pic[y*160*4 + x*4] = val;
|
if(scale > 1){
|
||||||
pic[y*160*4 + x*4 + 1] = val;
|
for(X = scale * x; X < scale * (x+1); X++)
|
||||||
pic[y*160*4 + x*4 + 2] = val;
|
for(Y = scale * y; Y < scale * (y+1); Y++){
|
||||||
pic[y*160*4 + x*4 + 3] = back ? 0 : 0xFF;
|
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
|
static void
|
||||||
pixelbelow(int x, int y, int val)
|
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);
|
pixel(x, y, val, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,10 +206,10 @@ ppustep(void)
|
||||||
mem[LY] = 0;
|
mem[LY] = 0;
|
||||||
if(mem[LCDC] & LCDOP){
|
if(mem[LCDC] & LCDOP){
|
||||||
if(tmp){
|
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);
|
draw(screen, picr, tmp, nil, ZP);
|
||||||
}else
|
}else
|
||||||
loadimage(screen, picr, pic, sizeof(pic));
|
loadimage(screen, picr, pic, 160*144*4*scale*scale);
|
||||||
flushimage(display, 1);
|
flushimage(display, 1);
|
||||||
memset(pic, sizeof pic, 0);
|
memset(pic, sizeof pic, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue