X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2Fgames%2Fsnes%2Fppu.c;h=5819e032c10b30de478675dc4ed3bdb6bd6c3563;hb=1195ca910c393e542d6aa23035fa75719af1107e;hp=5edc52f5e069277e9bb703d65839c1f0bece3a24;hpb=105625e10b469d4012c148154563007cfa3acc4d;p=plan9front.git diff --git a/sys/src/games/snes/ppu.c b/sys/src/games/snes/ppu.c index 5edc52f5e..5819e032c 100644 --- a/sys/src/games/snes/ppu.c +++ b/sys/src/games/snes/ppu.c @@ -1,14 +1,14 @@ #include #include #include +#include #include "dat.h" #include "fns.h" int ppux, ppuy, rx; -static u8int mode, bright, pixelpri[2]; +static u8int mode, bright, pixelpri[2], hires; static u32int pixelcol[2]; -u16int vtime = 0x1ff, htime = 0x1ff, subcolor, mosatop; -uchar pic[256*239*2*9]; +u16int vtime = 0x1ff, htime = 0x1ff, subcolor; u16int hofs[5], vofs[5]; s16int m7[6]; @@ -38,38 +38,33 @@ darken(u16int v) } static void -pixeldraw(int x, int y, u16int v) +pixeldraw(int x, int y, u16int v, int s) { - uchar *p; - u16int *q; + u16int *p; union { u16int w; u8int b[2]; } u; - int i; - if(bright != 0xf) + if(bright != 0xf && s >= 0) v = darken(v); - if(scale == 1){ - p = pic + (x + y * 256) * 2; - *p++ = v; - *p = v >> 8; - return; - } + p = (u16int *)pic + (x + y * 256) * scale; u.b[0] = v; u.b[1] = v >> 8; - if(scale == 2){ - q = (u16int*)pic + (x + y * 256 * 2) * 2; - *q++ = u.w; - *q = u.w; - q += 256 * 2 - 1; - *q++ = u.w; - *q = u.w; - }else{ - q = (u16int*)pic + (x + y * 256 * 3) * 3; - for(i = 0; i < 3; i++){ - *q++ = u.w; - *q++ = u.w; - *q = u.w; - q += 256 * 3 - 2; - } + switch(scale){ + case 16: *p++ = u.w; + case 15: *p++ = u.w; + case 14: *p++ = u.w; + case 13: *p++ = u.w; + case 12: *p++ = u.w; + case 11: *p++ = u.w; + case 10: *p++ = u.w; + case 9: *p++ = u.w; + case 8: *p++ = u.w; + case 7: *p++ = u.w; + case 6: *p++ = u.w; + case 5: *p++ = u.w; + case 4: *p++ = u.w; + case 3: *p++ = u.w; + case 2: if(s < 1) *p++ = u.w; + default: *p = u.w; } } @@ -101,7 +96,7 @@ window(int n) } static void -pixel(int n, int v, int pri) +npixel(int n, int v, int pri) { int a; @@ -116,6 +111,32 @@ pixel(int n, int v, int pri) } } +static void +spixel(int n, int v, int pri) +{ + int a; + + a = 1< pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){ + pixelcol[1] = v; + pixelpri[1] = pri; + } +} + +static void +mpixel(int n, int v, int pri) +{ + int a; + + a = 1< pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){ + pixelcol[0] = v; + pixelpri[0] = pri; + } +} + +static void (*pixel)(int, int, int) = npixel; + static u16int tile(int n, int tx, int ty) { @@ -134,16 +155,18 @@ tile(int n, int tx, int ty) } static void -chr(int n, int nb, int sz, u16int t, int x, int y, u32int c[]) +chr(int n, int nb, int w, int h, u16int t, int x, int y, u32int c[]) { u16int a; - if(sz == 16){ + if(w == 16) + t += (x >> 3 ^ t >> 14) & 1; + if(h == 16){ if(y >= 8){ - t += ((x >> 3 ^ t >> 14) & 1) + ((~t >> 11) & 16); + t += (~t >> 11) & 16; y -= 8; }else - t += ((x >> 3 ^ t >> 14) & 1) + ((t >> 11) & 16); + t += (t >> 11) & 16; } if((t & 0x8000) != 0) y = 7 - y; @@ -242,12 +265,13 @@ bgpixel(u32int *c, int nb, int d) } static struct bgctxt { - u8int sz, szsh, nb, pri[2]; + u8int w, h, wsh, hsh, nb, pri[2]; u16int tx, ty, tnx, tny; u16int t; u32int c[2]; int pal; u8int msz, mv, mx; + u16int otx, oty, otny; } bgctxts[4]; static void @@ -257,8 +281,10 @@ bginit(int n, int nb, int prilo, int prihi) int sx, sy; p = bgctxts + n; - p->szsh = (reg[BGMODE] & (1<<(4+n))) != 0 ? 4 : 3; - p->sz = 1<szsh; + p->hsh = ((reg[BGMODE] & (1<<(4+n))) != 0) ? 4 : 3; + p->wsh = mode >= 5 ? 4 : p->hsh; + p->h = 1<hsh; + p->w = 1<wsh; p->nb = nb; p->pri[0] = prilo; p->pri[1] = prihi; @@ -272,13 +298,15 @@ bginit(int n, int nb, int prilo, int prihi) } }else p->msz = 1; + if(mode >= 5) + sx <<= 1; redo: - p->tx = sx >> p->szsh; - p->tnx = sx & (p->sz - 1); - p->ty = sy >> p->szsh; - p->tny = sy & (p->sz - 1); + p->tx = sx >> p->wsh; + p->tnx = sx & (p->w - 1); + p->ty = sy >> p->hsh; + p->tny = sy & (p->h - 1); p->t = tile(n, p->tx, p->ty); - chr(n, nb, p->sz, p->t, p->tnx, p->tny, p->c); + chr(n, nb, p->w, p->h, p->t, p->tnx, p->tny, p->c); p->pal = palette(n, p->t >> 10 & 7); if((p->tnx & 7) != 0) shift(p->c, nb, p->tnx & 7, p->t & 0x4000); @@ -311,14 +339,111 @@ bg(int n) } if(v != 0) pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]); - if(++p->tnx == p->sz){ + if(++p->tnx == p->w){ p->tx++; p->tnx = 0; p->t = tile(n, p->tx, p->ty); p->pal = palette(n, p->t >> 10 & 7); } if((p->tnx & 7) == 0) - chr(n, p->nb, p->sz, p->t, p->tnx, p->tny, p->c); + chr(n, p->nb, p->w, p->h, p->t, p->tnx, p->tny, p->c); +} + +static void +optinit(void) +{ + struct bgctxt *p; + + p = bgctxts + 2; + p->hsh = (reg[BGMODE] & (1<<6)) != 0 ? 4 : 3; + p->wsh = mode >= 5 ? 4 : p->hsh; + p->w = 1<wsh; + p->h = 1<hsh; + p->tnx = hofs[2] & (p->w - 1); + p->tx = hofs[2] >> p->wsh; + bgctxts[0].otx = bgctxts[1].otx = 0xffff; + bgctxts[0].oty = bgctxts[0].ty; + bgctxts[0].otny = bgctxts[0].tny; + bgctxts[1].oty = bgctxts[1].ty; + bgctxts[1].otny = bgctxts[1].tny; +} + +static void +opt(void) +{ + struct bgctxt *p; + u16int hval, vval; + int sx, sy; + + p = bgctxts + 2; + if(++p->tnx == p->w){ + if(mode == 4){ + hval = tile(2, p->tx, vofs[2] >> p->hsh); + if((hval & 0x8000) != 0){ + vval = hval; + hval = 0; + }else + vval = 0; + }else{ + hval = tile(2, p->tx, vofs[2] >> p->hsh); + vval = tile(2, p->tx, (vofs[2]+8) >> p->hsh); + } + sx = (rx & ~7) + (hval & 0x1ff8); + sy = ppuy + (vval & 0x1fff); + if((vval & 0x2000) != 0){ + bgctxts[0].oty = sy >> bgctxts[0].hsh; + bgctxts[0].otny = sy & (bgctxts[0].h - 1); + }else{ + bgctxts[0].oty = bgctxts[0].ty; + bgctxts[0].otny = bgctxts[0].tny; + } + if((vval & 0x4000) != 0){ + bgctxts[1].oty = sy >> bgctxts[1].hsh; + bgctxts[1].otny = sy & (bgctxts[1].h - 1); + }else{ + bgctxts[1].oty = bgctxts[1].ty; + bgctxts[1].otny = bgctxts[1].tny; + } + if((hval & 0x2000) != 0) + bgctxts[0].otx = sx >> bgctxts[0].wsh; + else + bgctxts[0].otx = 0xffff; + if((hval & 0x4000) != 0) + bgctxts[1].otx = sx >> bgctxts[1].wsh; + else + bgctxts[1].otx = 0xffff; + p->tnx = 0; + p->tx++; + } +} + +static void +bgopt(int n) +{ + struct bgctxt *p; + u8int v; + + p = bgctxts + n; + v = bgpixel(p->c, p->nb, p->t & 0x4000); + if(p->msz != 1) + if(p->mx++ == 0) + p->mv = v; + else{ + if(p->mx == p->msz) + p->mx = 0; + v = p->mv; + } + if(v != 0) + pixel(n, p->pal + v, p->pri[(p->t & 0x2000) != 0]); + if(++p->tnx == p->w){ + p->tx++; + p->tnx = 0; + } + if((p->tnx & 7) == 0){ + p->t = tile(n, p->otx == 0xffff ? p->tx : p->otx, p->oty); + p->pal = palette(n, p->t >> 10 & 7); + chr(n, p->nb, p->w, p->h, p->t, p->tnx, p->otny, p->c); + } } struct bg7ctxt { @@ -437,6 +562,7 @@ bgsinit(void) { static int bitch[8]; + pixel = npixel; switch(mode){ case 0: bginit(0, 2, 0x80, 0xb0); @@ -452,18 +578,32 @@ bgsinit(void) case 2: bginit(0, 4, 0x40, 0xa0); bginit(1, 4, 0x11, 0x71); + optinit(); break; case 3: bginit(0, 8, 0x40, 0xa0); bginit(1, 4, 0x11, 0x71); break; + case 4: + bginit(0, 8, 0x40, 0xa0); + bginit(1, 2, 0x11, 0x71); + optinit(); + break; + case 5: + bginit(0, 4, 0x40, 0xa0); + bginit(1, 2, 0x11, 0x71); + break; + case 6: + bginit(0, 4, 0x40, 0xa0); + optinit(); + break; case 7: bg7init(0); if((reg[SETINI] & EXTBG) != 0) bg7init(1); break; default: - bgctxts[0].sz = bgctxts[1].sz = 0; + bgctxts[0].w = bgctxts[1].w = 0; if(bitch[mode]++ == 0) print("bg mode %d not implemented\n", mode); } @@ -485,10 +625,32 @@ bgs(void) bg(2); break; case 2: + case 4: + opt(); + bgopt(0); + bgopt(1); + break; case 3: bg(0); bg(1); break; + case 5: + pixel = spixel; + bg(0); + bg(1); + pixel = mpixel; + bg(0); + bg(1); + pixel = npixel; + break; + case 6: + opt(); + pixel = spixel; + bgopt(0); + pixel = mpixel; + bgopt(0); + pixel = npixel; + break; case 7: bg7(0); if((reg[SETINI] & EXTBG) != 0) @@ -511,7 +673,7 @@ sprites(void) u32int *ch; } t[32], *tp; static u32int ch[34]; - static u8int *p, q, over; + static u8int *p, q; static int n, m; static int *sz; static int szs[] = { @@ -528,7 +690,6 @@ sprites(void) if(rx == 0){ n = 0; - over = 1; sp = s; sz = szs + ((reg[OBSEL] & 0xe0) >> 3); base[0] = (reg[OBSEL] & 0x07) << 14; @@ -547,10 +708,10 @@ sprites(void) sp->x = p[0]; if((q & 1) != 0) sp->x |= 0xff00; - if(sp->x < -(short)sp->sx && sp->x != -256) + if(sp->x <= -(short)sp->sx && sp->x != -256) goto nope; if(n == 32){ - over |= 0x40; + reg[0x213e] |= 0x40; goto nope; } sp->i = rx >> 1; @@ -616,6 +777,14 @@ nope: a = sp->t0 | (dy & 7) << 1; if(dy >= 8) a += (dy & ~7) << 6; + if(sp->x < 0 && (i = (-sp->x >> 3)) != 0){ + if((sp->c & 0x40) != 0) + a -= i << 5; + else + a += i << 5; + nt -= i; + tp->sx += i << 3; + } if((sp->c & 0x40) != 0){ a += sp->sx * 4; for(i = 0; i < nt; i++){ @@ -627,7 +796,7 @@ nope: *cp++ = w; tp->sx += 8; }else - over |= 0x80; + reg[0x213e] |= 0x80; } }else for(i = 0; i < nt; i++){ @@ -640,15 +809,19 @@ nope: tp->sx += 8; a += 15; }else - over |= 0x80; + reg[0x213e] |= 0x80; } + if(sp->x < 0 && (i = (-sp->x) & 7) != 0) + if((sp->c & 0x40) != 0) + *tp->ch >>= i; + else + *tp->ch <<= i; } - reg[0x213e] = over; } } static u16int -colormath(void) +colormath(int n) { u16int v, w, r, g, b; u8int m, m2, div; @@ -664,12 +837,12 @@ colormath(void) case 3: v = 0; break; } if(v){ - if((pixelcol[0] & 0x10000) != 0) - v = pixelcol[0]; + if((pixelcol[n] & 0x10000) != 0) + v = pixelcol[n]; else - v = cgram[pixelcol[0] & 0xff]; + v = cgram[pixelcol[n] & 0xff]; } - if((m2 & (1 << (pixelpri[0] & 0xf))) == 0) + if((m2 & (1 << (pixelpri[n] & 0xf))) == 0) return v; switch((m >> 4) & 3){ case 0: break; @@ -679,11 +852,11 @@ colormath(void) } div = (m2 & 0x40) != 0; if((m & 2) != 0){ - if((pixelcol[1] & 0x10000) != 0) - w = pixelcol[1]; + if((pixelcol[1-n] & 0x10000) != 0) + w = pixelcol[1-n]; else - w = cgram[pixelcol[1] & 0xff]; - div = div && (pixelpri[1] & 0xf) != COL; + w = cgram[pixelcol[1-n] & 0xff]; + div = div && (pixelpri[1-n] & 0xf) != COL; }else w = subcolor; if((m2 & 0x80) != 0){ @@ -722,6 +895,7 @@ ppustep(void) mode = reg[BGMODE] & 7; bright = reg[INIDISP] & 0xf; + hires = mode >= 5 && mode < 7 || (reg[SETINI] & 8) != 0; yvbl = (reg[SETINI] & OVERSCAN) != 0 ? 0xf0 : 0xe1; if(ppux >= XLEFT && ppux <= XRIGHT && ppuy < 0xf0){ @@ -734,20 +908,28 @@ ppustep(void) bgs(); sprites(); if(ppuy != 0) - pixeldraw(rx, ppuy - 1, colormath()); + if(hires){ + pixeldraw(rx, ppuy - 1, colormath(1), 0); + pixeldraw(rx, ppuy - 1, colormath(0), 1); + }else + pixeldraw(rx, ppuy - 1, colormath(0), 0); }else if(ppuy != 0) - pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x31c8 : 0); + pixeldraw(rx, ppuy - 1, ppuy >= yvbl ? 0x6739 : 0, -1); } + if(ppux == 134) + cpupause = 1; if(ppux == 0x116 && ppuy <= yvbl) hdma |= reg[0x420c]; - if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy)) + if((reg[NMITIMEN] & HCNTIRQ) != 0 && htime+4 == ppux && ((reg[NMITIMEN] & VCNTIRQ) == 0 || vtime == ppuy)) irq |= IRQPPU; if(++ppux >= 340){ ppux = 0; if(++ppuy >= 262){ ppuy = 0; reg[RDNMI] &= ~VBLANK; + reg[0x213e] = 1; + reg[0x213f] ^= 0x80; hdma = reg[0x420c]<<8; flush(); } @@ -757,6 +939,8 @@ ppustep(void) reg[RDNMI] |= VBLANK; if((reg[NMITIMEN] & VBLANK) != 0) nmi = 2; + if((reg[INIDISP] & 0x80) == 0) + oamaddr = reg[0x2102] << 1 | (reg[0x2103] & 1) << 9; if((reg[NMITIMEN] & AUTOJOY) != 0){ memwrite(0x4016, 1); memwrite(0x4016, 0);