games/nes: improved time synchronization

games/gb: added some games/nes improvements
This commit is contained in:
aiju 2014-02-27 19:52:02 +01:00
parent c65a3809da
commit ff5ac0c5cb
6 changed files with 95 additions and 93 deletions

View file

@ -9,7 +9,7 @@ static int fd;
static int sc, ch1c, ch2c, ch3c, ch4c, ch4sr = 1, ch1vec, ch2vec, ch4vec, ch1v, ch2v, ch4v; static int sc, ch1c, ch2c, ch3c, ch4c, ch4sr = 1, ch1vec, ch2vec, ch4vec, ch1v, ch2v, ch4v;
extern int paused; extern int paused;
enum { SAMPLE = 44100 }; static short sbuf[2*2000], *sbufp;
static int static int
thresh(int f, int b) thresh(int f, int b)
@ -84,12 +84,14 @@ envelope(int *v, int *c)
(*c)++; (*c)++;
} }
static void void
dosample(short *smp) audiosample(void)
{ {
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;
if(sbufp == nil)
return;
if(sc >= SAMPLE/256){ if(sc >= SAMPLE/256){
soundlen(0xFF11, 0xFF14, 0); soundlen(0xFF11, 0xFF14, 0);
soundlen(0xFF16, 0xFF19, 1); soundlen(0xFF16, 0xFF19, 1);
@ -179,51 +181,40 @@ dosample(short *smp)
ch4s *= ch4v >> 4; ch4s *= ch4v >> 4;
ch4s *= 8000 / 0xF; ch4s *= 8000 / 0xF;
smp[0] = 0;
smp[1] = 0;
f = mem[0xFF25]; f = mem[0xFF25];
r = mem[0xFF26] & 15; r = mem[0xFF26] & 15;
r = r | (r << 4); r = r | (r << 4);
f &= r; f &= r;
if(f & 0x01) smp[0] += ch1s; if(sbufp < sbuf + nelem(sbuf) - 1){
if(f & 0x02) smp[0] += ch2s; *sbufp = 0;
if(f & 0x04) smp[0] += ch3s; if(f & 0x01) *sbufp += ch1s;
if(f & 0x08) smp[0] += ch4s; if(f & 0x02) *sbufp += ch2s;
if(f & 0x10) smp[1] += ch1s; if(f & 0x04) *sbufp += ch3s;
if(f & 0x20) smp[1] += ch2s; if(f & 0x08) *sbufp += ch4s;
if(f & 0x40) smp[1] += ch3s; *++sbufp = 0;
if(f & 0x80) smp[1] += ch4s; if(f & 0x10) *sbufp += ch1s;
} if(f & 0x20) *sbufp += ch2s;
if(f & 0x40) *sbufp += ch3s;
void if(f & 0x80) *sbufp += ch4s;
setpri(int pri) sbufp++;
{
char buf[64];
int fd;
snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
if((fd = open(buf, OWRITE)) >= 0){
fprint(fd, "pri %d\n", pri);
close(fd);
} }
} }
void int
audioproc(void *) audioout(void)
{ {
short samples[10 * 2]; int rc;
int i;
setpri(13); if(sbufp == nil)
return -1;
for(;;){ if(sbufp == sbuf)
if(paused) return 0;
memset(samples, 0, sizeof samples); rc = write(fd, sbuf, (sbufp - sbuf) * 2);
else if(rc > 0)
for(i = 0; i < sizeof samples/4; i++) sbufp -= (rc+1)/2;
dosample(samples + 2 * i); if(sbufp < sbuf)
write(fd, samples, sizeof samples); sbufp = sbuf;
} return 0;
} }
void void
@ -236,5 +227,5 @@ initaudio(void)
fd = open("/dev/audio", OWRITE); fd = open("/dev/audio", OWRITE);
if(fd < 0) if(fd < 0)
return; return;
proccreate(audioproc, nil, 8192); sbufp = sbuf;
} }

View file

@ -77,4 +77,5 @@ enum {
MILLION = 1000000, MILLION = 1000000,
BILLION = 1000000000, BILLION = 1000000000,
SAMPLE = 44100,
}; };

View file

@ -9,3 +9,6 @@ void flushram(void);
void savestate(char *); void savestate(char *);
void loadstate(char *); void loadstate(char *);
void initaudio(void); void initaudio(void);
void audiosample(void);
int audioout(void);
void flush(void);

View file

@ -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, scale, paused; int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, audioclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq, scale, paused;
Rectangle picr; Rectangle picr;
Image *bg, *tmp; Image *bg, *tmp;
Mousectl *mc; Mousectl *mc;
@ -143,8 +143,7 @@ loadrom(char *file)
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(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 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) tmp = allocimage(display, Rect(0, 0, scale * 160, scale * 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){
@ -234,9 +233,6 @@ void
threadmain(int argc, char** argv) threadmain(int argc, char** argv)
{ {
int t; int t;
vlong old, new, diff;
Mouse m;
Point p;
scale = 1; scale = 1;
ARGBEGIN{ ARGBEGIN{
@ -267,8 +263,6 @@ threadmain(int argc, char** argv)
if(mc == nil) if(mc == nil)
sysfatal("init mouse: %r"); sysfatal("init mouse: %r");
proccreate(keyproc, nil, 8192); proccreate(keyproc, nil, 8192);
syncfreq = CPUFREQ / 50;
old = nsec();
for(;;){ for(;;){
if(savereq){ if(savereq){
savestate("gb.save"); savestate("gb.save");
@ -286,26 +280,20 @@ threadmain(int argc, char** argv)
clock += t; clock += t;
ppuclock += t; ppuclock += t;
divclock += t; divclock += t;
audioclock += t;
timerclock += t; timerclock += t;
syncclock += t;
checkclock += t;
if(ppuclock >= 456){ if(ppuclock >= 456){
ppustep(); ppustep();
ppuclock -= 456; ppuclock -= 456;
while(nbrecv(mc->c, &m) > 0)
;
if(nbrecvul(mc->resizec) > 0){
if(getwindow(display, Refnone) < 0)
sysfatal("resize failed: %r");
p = divpt(addpt(screen->r.min, screen->r.max), 2);
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(divclock >= 256){ if(divclock >= 256){
mem[DIV]++; mem[DIV]++;
divclock = 0; divclock = 0;
} }
if(audioclock >= CPUFREQ / SAMPLE){
audiosample();
audioclock -= CPUFREQ / SAMPLE;
}
if(timer && timerclock >= timerfreq){ if(timer && timerclock >= timerfreq){
mem[TIMA]++; mem[TIMA]++;
if(mem[TIMA] == 0){ if(mem[TIMA] == 0){
@ -314,23 +302,6 @@ threadmain(int argc, char** argv)
} }
timerclock = 0; timerclock = 0;
} }
if(syncclock >= syncfreq){
sleep(10);
sleeps++;
syncclock = 0;
}
if(checkclock >= CPUFREQ){
new = nsec();
diff = new - old - sleeps * 10 * MILLION;
diff = BILLION - diff;
if(diff <= 0)
syncfreq = CPUFREQ;
else
syncfreq = ((vlong)CPUFREQ) * 10 * MILLION / diff;
old = new;
checkclock = 0;
sleeps = 0;
}
if(msgclock > 0){ if(msgclock > 0){
msgclock -= t; msgclock -= t;
if(msgclock <= 0){ if(msgclock <= 0){
@ -340,3 +311,43 @@ threadmain(int argc, char** argv)
} }
} }
} }
void
flush(void)
{
extern uchar pic[160*144*4*3*3];
Mouse m;
Point p;
static vlong old;
vlong new, diff;
while(nbrecv(mc->c, &m) > 0)
;
if(nbrecvul(mc->resizec) > 0){
if(getwindow(display, Refnone) < 0)
sysfatal("resize failed: %r");
p = divpt(addpt(screen->r.min, screen->r.max), 2);
picr = (Rectangle){subpt(p, Pt(scale * 80, scale * 72)), addpt(p, Pt(scale * 80, scale * 72))};
if(bg->chan != screen->chan){
freeimage(bg);
bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
}
draw(screen, screen->r, bg, nil, ZP);
}
if(screen->chan != tmp->chan){
loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale);
draw(screen, picr, tmp, nil, ZP);
}else
loadimage(screen, picr, pic, 160*144*4*scale*scale);
flushimage(display, 1);
memset(pic, sizeof pic, 0);
if(audioout() < 0){
new = nsec();
if(old != 0){
diff = BILLION/60 - (new - old);
if(diff >= MILLION)
sleep(diff/MILLION);
}
old = nsec();
}
}

View file

@ -177,9 +177,6 @@ drawwindow(void)
void void
ppustep(void) ppustep(void)
{ {
extern Rectangle picr;
extern Image *tmp;
if(mem[LY] == 144){ if(mem[LY] == 144){
mem[STAT] &= ~3; mem[STAT] &= ~3;
mem[STAT] |= 1; mem[STAT] |= 1;
@ -204,14 +201,8 @@ ppustep(void)
mem[LY]++; mem[LY]++;
if(mem[LY] > 160){ if(mem[LY] > 160){
mem[LY] = 0; mem[LY] = 0;
if(mem[LCDC] & LCDOP){ if((mem[LCDC] & LCDOP) == 0)
if(tmp){ memset(pic, 0, sizeof(pic));
loadimage(tmp, tmp->r, pic, 160*144*4*scale*scale); flush();
draw(screen, picr, tmp, nil, ZP);
}else
loadimage(screen, picr, pic, 160*144*4*scale*scale);
flushimage(display, 1);
memset(pic, sizeof pic, 0);
}
} }
} }

View file

@ -255,8 +255,8 @@ flush(void)
extern Rectangle picr; extern Rectangle picr;
extern Image *tmp, *bg; extern Image *tmp, *bg;
extern Mousectl *mc; extern Mousectl *mc;
static vlong old, diff; static vlong old, delta;
vlong new; vlong new, diff;
Mouse m; Mouse m;
Point p; Point p;
int h; int h;
@ -286,12 +286,17 @@ flush(void)
memset(pic, sizeof pic, 0); memset(pic, sizeof pic, 0);
if(audioout() < 0){ if(audioout() < 0){
new = nsec(); new = nsec();
diff = 0;
if(old != 0){ if(old != 0){
diff = BILLION/60 - (new - old); diff = BILLION/60 - (new - old) - delta;
if(diff >= MILLION) if(diff >= MILLION)
sleep(diff/MILLION); sleep(diff/MILLION);
} }
old = new; old = nsec();
if(diff != 0){
diff = (old - new) - (diff / MILLION) * MILLION;
delta += (diff - delta) / 100;
}
} }
} }