games/nes: improved time synchronization
games/gb: added some games/nes improvementsfront
parent
c65a3809da
commit
ff5ac0c5cb
|
@ -9,7 +9,7 @@ static int fd;
|
|||
static int sc, ch1c, ch2c, ch3c, ch4c, ch4sr = 1, ch1vec, ch2vec, ch4vec, ch1v, ch2v, ch4v;
|
||||
extern int paused;
|
||||
|
||||
enum { SAMPLE = 44100 };
|
||||
static short sbuf[2*2000], *sbufp;
|
||||
|
||||
static int
|
||||
thresh(int f, int b)
|
||||
|
@ -84,12 +84,14 @@ envelope(int *v, int *c)
|
|||
(*c)++;
|
||||
}
|
||||
|
||||
static void
|
||||
dosample(short *smp)
|
||||
void
|
||||
audiosample(void)
|
||||
{
|
||||
int ch1s, ch2s, ch3s, ch4s, ch1f, ch2f, ch3f, ch4f, k, r, s;
|
||||
u8int f;
|
||||
|
||||
if(sbufp == nil)
|
||||
return;
|
||||
if(sc >= SAMPLE/256){
|
||||
soundlen(0xFF11, 0xFF14, 0);
|
||||
soundlen(0xFF16, 0xFF19, 1);
|
||||
|
@ -179,51 +181,40 @@ dosample(short *smp)
|
|||
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;
|
||||
if(f & 0x08) smp[0] += ch4s;
|
||||
if(f & 0x10) smp[1] += ch1s;
|
||||
if(f & 0x20) smp[1] += ch2s;
|
||||
if(f & 0x40) smp[1] += ch3s;
|
||||
if(f & 0x80) smp[1] += ch4s;
|
||||
}
|
||||
|
||||
void
|
||||
setpri(int pri)
|
||||
{
|
||||
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);
|
||||
if(sbufp < sbuf + nelem(sbuf) - 1){
|
||||
*sbufp = 0;
|
||||
if(f & 0x01) *sbufp += ch1s;
|
||||
if(f & 0x02) *sbufp += ch2s;
|
||||
if(f & 0x04) *sbufp += ch3s;
|
||||
if(f & 0x08) *sbufp += ch4s;
|
||||
*++sbufp = 0;
|
||||
if(f & 0x10) *sbufp += ch1s;
|
||||
if(f & 0x20) *sbufp += ch2s;
|
||||
if(f & 0x40) *sbufp += ch3s;
|
||||
if(f & 0x80) *sbufp += ch4s;
|
||||
sbufp++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
audioproc(void *)
|
||||
int
|
||||
audioout(void)
|
||||
{
|
||||
short samples[10 * 2];
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
setpri(13);
|
||||
|
||||
for(;;){
|
||||
if(paused)
|
||||
memset(samples, 0, sizeof samples);
|
||||
else
|
||||
for(i = 0; i < sizeof samples/4; i++)
|
||||
dosample(samples + 2 * i);
|
||||
write(fd, samples, sizeof samples);
|
||||
}
|
||||
if(sbufp == nil)
|
||||
return -1;
|
||||
if(sbufp == sbuf)
|
||||
return 0;
|
||||
rc = write(fd, sbuf, (sbufp - sbuf) * 2);
|
||||
if(rc > 0)
|
||||
sbufp -= (rc+1)/2;
|
||||
if(sbufp < sbuf)
|
||||
sbufp = sbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -236,5 +227,5 @@ initaudio(void)
|
|||
fd = open("/dev/audio", OWRITE);
|
||||
if(fd < 0)
|
||||
return;
|
||||
proccreate(audioproc, nil, 8192);
|
||||
sbufp = sbuf;
|
||||
}
|
||||
|
|
|
@ -77,4 +77,5 @@ enum {
|
|||
|
||||
MILLION = 1000000,
|
||||
BILLION = 1000000000,
|
||||
SAMPLE = 44100,
|
||||
};
|
||||
|
|
|
@ -8,4 +8,7 @@ void message(char *, ...);
|
|||
void flushram(void);
|
||||
void savestate(char *);
|
||||
void loadstate(char *);
|
||||
void initaudio(void);
|
||||
void initaudio(void);
|
||||
void audiosample(void);
|
||||
int audioout(void);
|
||||
void flush(void);
|
||||
|
|
|
@ -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, scale, paused;
|
||||
int mbc, rombanks, rambanks, clock, ppuclock, divclock, timerclock, audioclock, msgclock, timerfreq, timer, keys, savefd, savereq, loadreq, scale, paused;
|
||||
Rectangle picr;
|
||||
Image *bg, *tmp;
|
||||
Mousectl *mc;
|
||||
|
@ -143,8 +143,7 @@ loadrom(char *file)
|
|||
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(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);
|
||||
|
||||
if(ram && battery){
|
||||
|
@ -234,9 +233,6 @@ void
|
|||
threadmain(int argc, char** argv)
|
||||
{
|
||||
int t;
|
||||
vlong old, new, diff;
|
||||
Mouse m;
|
||||
Point p;
|
||||
|
||||
scale = 1;
|
||||
ARGBEGIN{
|
||||
|
@ -267,8 +263,6 @@ threadmain(int argc, char** argv)
|
|||
if(mc == nil)
|
||||
sysfatal("init mouse: %r");
|
||||
proccreate(keyproc, nil, 8192);
|
||||
syncfreq = CPUFREQ / 50;
|
||||
old = nsec();
|
||||
for(;;){
|
||||
if(savereq){
|
||||
savestate("gb.save");
|
||||
|
@ -286,26 +280,20 @@ threadmain(int argc, char** argv)
|
|||
clock += t;
|
||||
ppuclock += t;
|
||||
divclock += t;
|
||||
audioclock += t;
|
||||
timerclock += t;
|
||||
syncclock += t;
|
||||
checkclock += t;
|
||||
if(ppuclock >= 456){
|
||||
ppustep();
|
||||
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){
|
||||
mem[DIV]++;
|
||||
divclock = 0;
|
||||
}
|
||||
if(audioclock >= CPUFREQ / SAMPLE){
|
||||
audiosample();
|
||||
audioclock -= CPUFREQ / SAMPLE;
|
||||
}
|
||||
if(timer && timerclock >= timerfreq){
|
||||
mem[TIMA]++;
|
||||
if(mem[TIMA] == 0){
|
||||
|
@ -314,23 +302,6 @@ threadmain(int argc, char** argv)
|
|||
}
|
||||
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){
|
||||
msgclock -= t;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,9 +177,6 @@ drawwindow(void)
|
|||
void
|
||||
ppustep(void)
|
||||
{
|
||||
extern Rectangle picr;
|
||||
extern Image *tmp;
|
||||
|
||||
if(mem[LY] == 144){
|
||||
mem[STAT] &= ~3;
|
||||
mem[STAT] |= 1;
|
||||
|
@ -204,14 +201,8 @@ ppustep(void)
|
|||
mem[LY]++;
|
||||
if(mem[LY] > 160){
|
||||
mem[LY] = 0;
|
||||
if(mem[LCDC] & LCDOP){
|
||||
if(tmp){
|
||||
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((mem[LCDC] & LCDOP) == 0)
|
||||
memset(pic, 0, sizeof(pic));
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,8 +255,8 @@ flush(void)
|
|||
extern Rectangle picr;
|
||||
extern Image *tmp, *bg;
|
||||
extern Mousectl *mc;
|
||||
static vlong old, diff;
|
||||
vlong new;
|
||||
static vlong old, delta;
|
||||
vlong new, diff;
|
||||
Mouse m;
|
||||
Point p;
|
||||
int h;
|
||||
|
@ -286,12 +286,17 @@ flush(void)
|
|||
memset(pic, sizeof pic, 0);
|
||||
if(audioout() < 0){
|
||||
new = nsec();
|
||||
diff = 0;
|
||||
if(old != 0){
|
||||
diff = BILLION/60 - (new - old);
|
||||
diff = BILLION/60 - (new - old) - delta;
|
||||
if(diff >= MILLION)
|
||||
sleep(diff/MILLION);
|
||||
}
|
||||
old = new;
|
||||
old = nsec();
|
||||
if(diff != 0){
|
||||
diff = (old - new) - (diff / MILLION) * MILLION;
|
||||
delta += (diff - delta) / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue