diff --git a/sys/src/games/gb/audio.c b/sys/src/games/gb/audio.c index 94e08967b..92356b045 100644 --- a/sys/src/games/gb/audio.c +++ b/sys/src/games/gb/audio.c @@ -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<= 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; diff --git a/sys/src/games/gb/dat.h b/sys/src/games/gb/dat.h index 1ecf533bb..ce33d6d24 100644 --- a/sys/src/games/gb/dat.h +++ b/sys/src/games/gb/dat.h @@ -9,6 +9,8 @@ extern uchar mem[], *ram; extern uchar *cart; extern int mbc, rombanks, rambanks; +extern int scale; + enum { rB, rC, diff --git a/sys/src/games/gb/gb.c b/sys/src/games/gb/gb.c index 5f2509ab9..edc8e238a 100644 --- a/sys/src/games/gb/gb.c +++ b/sys/src/games/gb/gb.c @@ -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); } } diff --git a/sys/src/games/gb/mem.c b/sys/src/games/gb/mem.c index 81f37b201..f033a8ad5 100644 --- a/sys/src/games/gb/mem.c +++ b/sys/src/games/gb/mem.c @@ -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; diff --git a/sys/src/games/gb/ppu.c b/sys/src/games/gb/ppu.c index dde9576c6..920ce2d42 100644 --- a/sys/src/games/gb/ppu.c +++ b/sys/src/games/gb/ppu.c @@ -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); }