ref: 8ec800d6991218c256de524b1132478533bee574
parent: 2b1975d6a669372c7d734213996d5123ee1c378f
author: qwx <qwx@sciops.net>
date: Tue Aug 5 06:02:58 EDT 2025
games/*: eui scaling patch applied
--- a/sys/src/games/2600/tia.c
+++ /dev/null
@@ -1,195 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int ppux=1, ppuy;
-int col, pri;
-u8int p0x, p1x, m0x, m1x, blx;
-u16int coll;
-u8int disp;
-int p0difc;
-int bwmod = 1<<3;
-
-enum {
- SRCPF,
- SRCP0,
- SRCP1,
- SRCM0,
- SRCM1,
- SRCBL,
-};
-
-static void
-pixeldraw(u8int v)
-{
- u32int c;
- union { u32int l; u8int c[4]; } u;
- u32int *p;
- static u32int col[] = {
- 0x000000, 0x404040, 0x6C6C6C, 0x909090, 0xB0B0B0, 0xC8C8C8, 0xDCDCDC, 0xECECEC,
- 0x444400, 0x646410, 0x848424, 0xA0A034, 0xB8B840, 0xD0D050, 0xE8E85C, 0xFCFC68,
- 0x702800, 0x844414, 0x985C28, 0xAC783C, 0xBC8C4C, 0xCCA05C, 0xDCB468, 0xECC878,
- 0x841800, 0x983418, 0xAC5030, 0xC06848, 0xD0805C, 0xE09470, 0xECA880, 0xFCBC94,
- 0x880000, 0x9C2020, 0xB03C3C, 0xC05858, 0xD07070, 0xE08888, 0xECA0A0, 0xFCB4B4,
- 0x78005C, 0x8C2074, 0xA03C88, 0xB0589C, 0xC070B0, 0xD084C0, 0xDC9CD0, 0xECB0E0,
- 0x480078, 0x602090, 0x783CA4, 0x8C58B8, 0xA070CC, 0xB484DC, 0xC49CEC, 0xD4B0FC,
- 0x140084, 0x302098, 0x4C3CAC, 0x6858C0, 0x7C70D0, 0x9488E0, 0xA8A0EC, 0xBCB4FC,
- 0x000088, 0x1C209C, 0x3840B0, 0x505CC0, 0x6874D0, 0x7C8CE0, 0x90A4EC, 0xA4B8FC,
- 0x00187C, 0x1C3890, 0x3854A8, 0x5070BC, 0x6888CC, 0x7C9CDC, 0x90B4EC, 0xA4C8FC,
- 0x002C5C, 0x1C4C78, 0x386890, 0x5084AC, 0x689CC0, 0x7CB4D4, 0x90CCE8, 0xA4E0FC,
- 0x003C2C, 0x1C5C48, 0x387C64, 0x509C80, 0x68B494, 0x7CD0AC, 0x90E4C0, 0xA4FCD4,
- 0x003C00, 0x205C20, 0x407C40, 0x5C9C5C, 0x74B474, 0x8CD08C, 0xA4E4A4, 0xB8FCB8,
- 0x143800, 0x345C1C, 0x507C38, 0x6C9850, 0x84B468, 0x9CCC7C, 0xB4E490, 0xC8FCA4,
- 0x2C3000, 0x4C501C, 0x687034, 0x848C4C, 0x9CA864, 0xB4C078, 0xCCD488, 0xE0EC9C,
- 0x442800, 0x644818, 0x846830, 0xA08444, 0xB89C58, 0xD0B46C, 0xE8CC7C, 0xFCE08C,
- };
-
- c = col[v >> 1];
- u.c[0] = c;
- u.c[1] = c >> 8;
- u.c[2] = c >> 16;
- u.c[3] = 0xff;
- p = (u32int *)pic + ppuy * PICW + ppux * 2;
- p[0] = p[1] = u.l;
-}
-
-static void
-pixel(u8int v, int p, int s)
-{
- if(p > pri){
- col = v;
- pri = p;
- }
- disp |= 1<<s;
-}
-
-static void
-playfield(void)
-{
- int x, p;
- u8int c;
-
- x = ppux / 4;
- if(x >= 20)
- if((reg[CTRLPF] & 1) != 0)
- x = 39 - x;
- else
- x = x - 20;
- if(x < 4){
- if((reg[PF0] & 0x10<<x) == 0)
- return;
- }else if(x < 12){
- if((reg[PF1] & 0x800>>x) == 0)
- return;
- }else
- if((reg[PF2] & 1<<x-12) == 0)
- return;
- if((reg[CTRLPF] & 6) == 2)
- if(ppux < 80){
- c = reg[COLUP0];
- p = 3;
- }else{
- c = reg[COLUP1];
- p = 2;
- }
- else{
- c = reg[COLUPF];
- p = (reg[CTRLPF] & 4) + 1;
- }
- pixel(c, p, SRCPF);
-}
-
-static void
-player(int n)
-{
- u8int c;
- int x;
-
- c = reg[GRP0 + n];
- x = ppux - (n ? p1x : p0x);
- if(x < 0)
- return;
- switch(reg[NUSIZ0 + n] & 7){
- default: if(x >= 8) return; break;
- case 1: if(x >= 8 && (x < 16 || x >= 24)) return; break;
- case 2: if(x >= 8 && (x < 32 || x >= 40)) return; break;
- case 3: if(x >= 40 || ((x & 15) >= 8)) return; break;
- case 4: if(x >= 8 && (x < 64 || x >= 72)) return; break;
- case 5: if(x >= 16) return; x >>= 1; break;
- case 6: if(x >= 72 || ((x & 31) >= 8)) return; break;
- case 7: if(x >= 32) return; x >>= 2; break;
- }
- x &= 7;
- if((reg[REFP0 + n] & 8) == 0)
- x ^= 7;
- if((c & 1<<x) == 0)
- return;
- c = reg[COLUP0 + n];
- pixel(c, 3 - n, SRCP0 + n);
-}
-
-static void
-missile(int n)
-{
- int x;
-
- x = ppux - (n ? m1x : m0x);
- if((reg[RESMP0 + n] & 2) != 0){
- if(n)
- m1x = p1x;
- else
- m0x = p0x;
- return;
- }
- if(x < 0 || x >= 1<<(reg[NUSIZ0] >> 4 & 3) || (reg[ENAM0 + n] & 2) == 0)
- return;
- pixel(reg[COLUP0 + n], 3 - n, SRCM0 + n);
-}
-
-static void
-ball(void)
-{
- int x;
-
- x = ppux - blx;
- if(x < 0 || x >= 1<<(reg[CTRLPF] >> 4 & 3) || (reg[ENABL] & 2) == 0)
- return;
- pixel(reg[COLUPF], (reg[CTRLPF] & 4) + 1, SRCBL);
-}
-
-void
-tiastep(void)
-{
- static u16int colltab[64] = {
- 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0080, 0x8000, 0x80a0,
- 0x0000, 0x0200, 0x0001, 0x0221, 0x0002, 0x0282, 0x8003, 0x82a3,
- 0x0000, 0x0800, 0x0008, 0x0828, 0x0004, 0x0884, 0x800c, 0x88ac,
- 0x4000, 0x4a00, 0x4009, 0x4a29, 0x4006, 0x4a86, 0xc00f, 0xcaaf,
- 0x0000, 0x2000, 0x0010, 0x2030, 0x0040, 0x20c0, 0x8050, 0xa0f0,
- 0x0100, 0x2300, 0x0111, 0x2331, 0x0142, 0x23c2, 0x8153, 0xa3f3,
- 0x0400, 0x2c00, 0x0418, 0x2c38, 0x0444, 0x2cc4, 0x845c, 0xacfc,
- 0x4500, 0x6f00, 0x4519, 0x6f39, 0x4546, 0x6fc6, 0xc55f, 0xefff,
- };
-
- if(ppuy < PICH && ppux < 160){
- col = reg[COLUBK];
- pri = 0;
- disp = 0;
- playfield();
- player(0);
- player(1);
- missile(0);
- missile(1);
- ball();
- coll |= colltab[disp];
- pixeldraw(col);
- }
- if(ppux == 160)
- nrdy = 0;
- if(++ppux == 228){
- ppuy++;
- ppux = 0;
- }
-}
--- a/sys/src/games/c64/vic.c
+++ /dev/null
@@ -1,369 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int region, picidx;
-u16int ppux, ppuy, lastx, wrapx, maxy, lvis, rvis, uvis, dvis, picw, pich, lbord, rbord, ubord, dbord, spr0;
-u16int vc, vcbase, vmli;
-u8int badln, rc, displ, fract, visreg, hbord, vbord, rbord0, lbord0;
-u16int chrp[40];
-u64int pxs, npxs, npxs0, opxs;
-u8int fg;
-
-typedef struct spr spr;
-enum {
- SPRFDMA = 1,
- SPRFYEX = 2,
- SPRFDISP = 4,
-};
-struct spr {
- u8int flags;
- u32int data;
- u8int mc, mcbase, dp;
- u16int x;
-} sp[8];
-
-void
-bordset(void)
-{
- int r, c;
-
- r = (reg[CTRL1] & RSEL) != 0;
- c = (reg[CTRL2] & CSEL) != 0;
- lbord = c ? 0x14 : 0x1c;
- lbord0 = c ? 0xf0 : 0xe0;
- rbord = c ? 0x154 : 0x14c;
- rbord0 = c ? 0x0f : 0x3f;
- ubord = r ? 0x33 : 0x37;
- dbord = r ? 0xfb : 0xf7;
- if((reg[CTRL1] & DEN) == 0)
- ubord = -1;
-}
-
-void
-vicreset(void)
-{
- switch(region){
- case NTSC0:
- lastx = 0x1fc;
- wrapx = 0x19c;
- maxy = 262;
- picw = 412;
- pich = 234;
- spr0 = 0x16c;
- lvis = 0x1e4;
- rvis = 0x184;
- uvis = 41;
- dvis = 13;
- break;
- case NTSC:
- lastx = 0x1fc;
- wrapx = 0x19c;
- maxy = 263;
- picw = 419;
- pich = 235;
- spr0 = 0x174;
- lvis = 0x1e4;
- rvis = 0x18c;
- uvis = 41;
- dvis = 13;
- break;
- case PAL:
- lastx = 0x1f4;
- wrapx = 0x194;
- maxy = 312;
- picw = 404;
- pich = 284;
- spr0 = 0x164;
- lvis = 0x1dc;
- rvis = 0x17c;
- uvis = 16;
- dvis = 300;
- break;
- }
- ppux = 4;
- ppuy = 0;
- bordset();
-}
-
-void
-pixeldraw(u64int p, int n)
-{
- int i;
- union { u8int c[4]; u32int l; } u;
- static u8int cr[] = {0, 255, 136, 170, 204, 0, 0, 238, 221, 102, 255, 51, 119, 170, 0, 187};
- static u8int cg[] = {0, 255, 0, 255, 68, 204, 0, 238, 136, 68, 119, 51, 119, 255, 136, 187};
- static u8int cb[] = {0, 255, 0, 238, 204, 85, 170, 119, 85, 0, 119, 51, 119, 102, 255, 187};
- u8int c;
- u32int *q;
-
- q = (u32int *)pic + picidx;
- for(i = 0; i < n; i++){
- c = p >> 56;
- p <<= 8;
- u.c[0] = cb[c];
- u.c[1] = cg[c];
- u.c[2] = cr[c];
- u.c[3] = 0;
- *q++ = u.l;
- }
- picidx += n;
-}
-
-void
-pixels(u8int d, u16int c)
-{
- u8int c0, c1, c2, n;
- int i;
-
- npxs0 = npxs;
- npxs = 0;
- switch((reg[CTRL1] & (ECM|BMM) | reg[CTRL2] & MCM) >> 4){
- case 0:
- c0 = c >> 8;
- normal:
- fg = d;
- for(i = 0; i < 8; i++){
- npxs = npxs << 8 | ((d & 0x80) != 0 ? c0 : reg[BG0]);
- d <<= 1;
- }
- break;
- case 1:
- c0 = c >> 8 & 7;
- if((c & 0x800) == 0)
- goto normal;
- fg = d & 0xaa | d >> 1 & 0x55;
- for(i = 0; i < 8; i += 2){
- n = d >> 6;
- npxs = npxs << 16 | (n == 3 ? c0 : reg[BG0 + n]) * 0x101;
- d <<= 2;
- }
- break;
- case 2:
- c0 = c & 15;
- c1 = c >> 4 & 15;
- fg = d;
- for(i = 0; i < 8; i++){
- npxs = npxs << 8 | ((d & 0x80) != 0 ? c1 : c0);
- d <<= 1;
- }
- break;
- case 3:
- c0 = c & 15;
- c1 = c >> 4 & 15;
- c2 = c >> 8;
- fg = d & 0xaa | d >> 1 & 0x55;
- for(i = 0; i < 8; i += 2){
- n = d >> 6;
- switch(n){
- default: n = reg[BG0]; break;
- case 1: n = c1; break;
- case 2: n = c0; break;
- case 3: n = c2;
- }
- npxs = npxs << 16 | n * 0x101;
- d <<= 2;
- }
- break;
- case 4:
- c0 = c >> 8;
- fg = d;
- for(i = 0; i < 8; i++){
- npxs = npxs << 8 | ((d & 0x80) != 0 ? c0 : reg[BG0 + (d >> 6 & 3)]);
- d <<= 1;
- }
- break;
- default:
- fg = 0;
- break;
- }
-}
-
-void
-bgpixels(void)
-{
- int i, j, x;
- u8int h;
- u8int spract, s, o;
-
- h = hbord;
- opxs = 0;
- for(i = 0; i < 8; i++){
- if((reg[CTRL2] + 4 & 7) == i)
- pxs = i >= 4 ? npxs : npxs0;
- o = pxs >> 56;
- pxs <<= 8;
-
- x = ppux + i;
- spract = 0;
- for(j = 0; j < 8; j++)
- if((sp[j].flags & SPRFDISP) != 0 && (u16int)(x-sp[j].x) < 48 && (sp[j].data & ((reg[SPRMC]&1<<j)?3:2)<<22) != 0)
- spract |= 1<<j;
- if((spract & spract - 1) != 0 && vbord == 0){
- reg[SPRSPR] |= spract;
- irq |= IRQSPRCOLL;
- }
- if(fg != 0 && spract != 0 && vbord == 0){
- reg[SPRBG] |= spract;
- irq |= IRQBGCOLL;
- }
- s = spract & ~(reg[SPRDP] & ((s8int)fg) >> 7);
- if(s != 0)
- for(j = 0; j < 8; j++)
- if((s & 1<<j) != 0){
- if((reg[SPRMC] & 1<<j) != 0)
- switch(sp[j].data >> 22 & 3){
- case 1: o = reg[SPRMC0]; break;
- case 2: o = reg[SPRCOL+j]; break;
- case 3: o = reg[SPRMC1]; break;
- }
- else
- o = reg[SPRCOL+j];
- break;
- }
- if((h & 0x80) != 0)
- o = reg[EC];
- opxs = opxs << 8 | o;
- h <<= 1;
- fg <<= 1;
- for(j = 0; j < 8; j++)
- if((u16int)(x-sp[j].x) < 48 && ((reg[SPRXE] & 1<<j) == 0 || (x-sp[j].x & 1) != 0))
- if((reg[SPRMC] & 1<<j) != 0){
- if((x-sp[j].x & 1) != 0)
- sp[j].data <<= 2;
- }else
- sp[j].data <<= 1;
- }
-}
-
-void
-vicstep(void)
-{
- u16int gaddr;
- int i;
-
- if(ppuy == 0x30 && (reg[CTRL1] & DEN) != 0)
- fract = 1;
- badln = ((ppuy ^ reg[CTRL1]) & 7) == 0 && fract;
- hbord = ((s8int)(hbord << 7)) >> 7;
- if(ppux == rbord && hbord == 0)
- hbord = rbord0;
- else if(ppux == lbord){
- if(ppuy == dbord)
- vbord = 1;
- if(ppuy == ubord)
- vbord = 0;
- if(!vbord)
- hbord = lbord0;
- }
- if(badln)
- displ = 1;
- if(ppux == 4){
- vc = vcbase;
- vmli = 0;
- if(badln)
- rc = 0;
- }
- if(ppux == 12)
- for(i = 0; i < 8; i++){
- if((sp[i].flags & SPRFDISP) == 0 || (reg[SPRYE] & 1<<i) != 0 && (sp[i].flags & SPRFYEX) == 0)
- continue;
- sp[i].mcbase += 3;
- if(sp[i].mcbase == 63)
- sp[i].flags &= ~(SPRFDMA|SPRFDISP);
- }
- if(ppux >= 0x14 && ppux <= 0x14c){
- if((reg[CTRL1] & BMM) != 0)
- gaddr = (reg[MEMP] & 0x08) << 10 | vc << 3 | rc;
- else
- gaddr = (reg[MEMP] & 0x0e) << 10 | (chrp[vmli] & 0xff) << 3 | rc;
- if(!displ)
- gaddr = 0x3fff;
- if((reg[CTRL1] & ECM) != 0)
- gaddr &= ~0x600;
- pixels(vmemread(gaddr) & -displ, chrp[vmli] & -displ);
- vmli++;
- vc = vc + 1 & 0x3ff;
- }
- if(visreg && (ppux >= lvis || ppux < rvis)){
- bgpixels();
- pixeldraw(opxs, ppux == lvis ? region == NTSC ? 3 : 4 : 8);
- }
- if(ppux == 0x14c){
- for(i = 0; i < 8; i++){
- if((reg[SPRYE] & 1<<i) != 0)
- sp[i].flags ^= SPRFYEX;
- if((reg[SPREN] & 1<<i) == 0 || reg[2*i+1] != (u8int)ppuy)
- continue;
- sp[i].flags |= SPRFDMA;
- sp[i].mcbase = 0;
- if((reg[SPRYE] & 1<<i) != 0)
- sp[i].flags &= ~SPRFYEX;
- }
- }else if(ppux == 0x154)
- npxs = reg[BG0] * 0x0101010101010101ULL;
- if(badln){
- if(ppux == lastx - 8)
- nrdy = 1;
- else if(ppux >= 0xc && ppux <= 0x144)
- chrp[vmli] = vmemread(vc | (reg[MEMP] & 0xf0) << 6) | cram[vc] << 8;
- else if(ppux == 0x154)
- nrdy = 0;
- }
- if(ppux == 0x164){
- if(displ && rc == 7){
- displ = badln;
- vcbase = vc;
- }
- if(displ)
- rc = rc + 1 & 7;
- for(i = 0; i < 8; i++){
- sp[i].mc = sp[i].mcbase;
- if((sp[i].flags & SPRFDMA) != 0 && reg[2*i+1] == (u8int)ppuy)
- sp[i].flags |= SPRFDISP;
- }
- }
- if((u16int)(ppux - spr0) < 128){
- i = ppux - spr0 >> 4;
- nrdy = (sp[i].flags & SPRFDMA) != 0;
- if((ppux & 8) == 0){
- sp[i].dp = vmemread((reg[MEMP] & 0xf0) << 6 | 0x3f8 | i);
- sp[i].x = nrdy ? reg[2 * i] | reg[MSBX] << 8 - i & 0x100 : -1;
- if(nrdy)
- sp[i].data = vmemread(sp[i].dp << 6 | sp[i].mc++) << 16;
- }else if(nrdy){
- sp[i].data = sp[i].data & 0xff00ff | vmemread(sp[i].dp << 6 | sp[i].mc++) << 8;
- sp[i].data = sp[i].data & 0xffff00 | vmemread(sp[i].dp << 6 | sp[i].mc++);
- }
- }else if(ppux - spr0 == 128)
- nrdy = 0;
- if(ppux == wrapx){
- ppuy++;
- if(ppuy == maxy){
- flush();
- ppuy = 0;
- vcbase = 0;
- }
- if((ppuy & 0xff) == reg[RASTER] && ((ppuy ^ reg[CTRL1] << 1) & 0x100) == 0)
- irq |= IRQRASTER;
- if(ppuy == dbord)
- vbord = 1;
- else if(ppuy == ubord)
- vbord = 0;
- else if(ppuy == dvis)
- visreg = 0;
- if(ppuy == uvis){
- picidx = 0;
- visreg = 1;
- }
- if(ppuy == 0xf7)
- fract = 0;
- }
- if(ppux == lastx)
- ppux = 4;
- else
- ppux += 8;
-}
--- a/sys/src/games/eui.h
+++ /dev/null
@@ -1,19 +1,0 @@
-enum{
- MILLION = 1000000,
- BILLION = 1000000000,
-};
-
-extern u64int keys, keys2;
-extern int trace, paused;
-extern int savereq, loadreq;
-extern QLock pauselock;
-extern int scale, fixscale, warp10;
-extern uchar *pic;
-
-void* emalloc(ulong);
-void flushmouse(int);
-void flushscreen(void);
-void flushaudio(int(*)(void));
-void regkeyfn(Rune, void(*)(void));
-void regkey(char*, Rune, int);
-void initemu(int, int, int, ulong, int, void(*)(void*));
--- a/sys/src/games/gb/ppu.c
+++ /dev/null
@@ -1,326 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-u8int ppustate, ppuy, ppuw;
-ulong hblclock, rendclock;
-jmp_buf mainjmp, renderjmp;
-static int cyc, done, ppux, ppux0;
-extern int prish;
-extern u32int white;
-
-Var ppuvars[] = {VAR(ppustate), VAR(ppuy), VAR(hblclock), VAR(rendclock), {nil, 0, 0}};
-
-#define ryield() {if(setjmp(renderjmp) == 0) longjmp(mainjmp, 1);}
-#define myield() {if(setjmp(mainjmp) == 0) longjmp(renderjmp, 1);}
-
-typedef struct sprite sprite;
-struct sprite {
- u8int dy, x, t;
- u8int fetched, pal;
- u16int chr;
-};
-enum {
- SPRPRI = 0x80,
- SPRYFL = 0x40,
- SPRXFL = 0x20,
- SPRPAL = 0x10,
- SPRBANK = 0x08,
-
- TILCOL0 = 0x01,
- TILPRI = 0x02,
- TILSPR = 0x04,
-};
-sprite spr[10], *sprm;
-
-void
-ppurender(void)
-{
- int x, y, i, n, m, win;
- u16int ta, ca, chr;
- u8int tile, attr, pali;
- u32int sr[8], *picp;
- #define eat(nc) if(cyc <= nc){for(i = 0; i < nc; i++) if(--cyc == 0) ryield();} else cyc -= nc;
-
- ryield();
-
- attr = 0;
- for(;;){
- eat(6*2);
- m = 168 + (reg[SCX] & 7);
- win = 0;
- if((reg[LCDC] & WINEN) != 0 && ppuy >= reg[WY] && reg[WX] <= 166)
- if(reg[WX] == 0)
- m = 7;
- else if(reg[WX] == 166)
- m = 0;
- else{
- m = reg[WX] + (reg[SCX] & 7) + 1;
- win = -1;
- }
- ppux = 0;
- ppux0 = 0;
- picp = (u32int*)pic + ppuy * PICW;
- y = ppuy + reg[SCY] << 1 & 14;
- ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | reg[SCX] >> 3;
- x = -(reg[SCX] & 7);
- restart:
- do{
- tile = vram[ta];
- if((mode & COL) != 0)
- attr = vram[8192 + ta];
- if((reg[LCDC] & BGTILE) != 0)
- ca = (tile << 4) + y;
- else
- ca = 0x1000 + ((s32int)(tile << 24) >> 20) + y;
- if((attr & 0x40) != 0)
- ca ^= 14;
- ca |= (attr & 8) << 10;
- chr = vram[ca] << 8 | vram[ca+1];
- pali = attr << 2 & 0x1c;
- if((attr & 0x20) == 0)
- for(i = 0; i < 8; i++){
- sr[i] = pal[pali | chr >> 15 | chr >> 6 & 2] | ((chr & 0x8080) == 0) << prish;
- chr <<= 1;
- }
- else
- for(i = 0; i < 8; i++){
- sr[i] = pal[pali | chr << 1 & 2 | chr >> 8 & 1] | ((chr & 0x0101) == 0) << prish;
- chr >>= 1;
- }
- if((attr & 0x80) != 0)
- for(i = 0; i < 8; i++)
- sr[i] |= 2 << prish;
- if((reg[LCDC] & BGEN) == 0 && (mode & COL) == 0 && ((mode & CGB) != 0 || win == 0))
- for(i = 0; i < 8; i++)
- sr[i] = white;
- if(cyc <= 2*8){
- for(i = 0; i < 2*8; i++)
- if(--cyc == 0)
- ryield();
- y = ppuy + reg[SCY] << 1 & 14;
- ta = 0x1800 | reg[LCDC] << 7 & 0x400 | ppuy + reg[SCY] << 2 & 0x3e0 | ta & 0x1f;
- }else
- cyc -= 2*8;
- m -= 8;
- n = m < 8 ? m : 8;
- if((ta & 0x1f) == 0x1f)
- ta &= ~0x1f;
- else
- ta++;
- for(i = 0; i < n; i++, x++)
- if(x >= 0)
- picp[x] = sr[i];
- ppux = x;
- }while(m > 8);
- if(win == -1){
- win = 1;
- ta = 0x1800 | reg[LCDC] << 4 & 0x400 | ppuw - reg[WY] << 2 & 0x3e0;
- y = ppuw - reg[WY] << 1 & 14;
- cyc += 2;
- m = 175 - reg[WX];
- goto restart;
- }
- done = 1;
- ryield();
- }
-}
-
-void
-oamsearch(void)
-{
- u8int *p;
- sprite *q;
- int y0, sy;
- u8int t, tn;
- u8int *chrp;
-
- y0 = ppuy + 16;
- sy = (reg[LCDC] & SPR16) != 0 ? 16 : 8;
- sprm = spr;
- if((reg[LCDC] & SPREN) == 0)
- return;
- for(p = oam; p < oam + 160; p += 4){
- if((u8int)(y0 - p[0]) >= sy)
- continue;
- if((mode & COL) == 0){
- for(q = spr; q < sprm; q++)
- if(q->x > p[1]){
- if(sprm != spr + 10){
- memmove(q + 1, q, (sprm - q) * sizeof(sprite));
- sprm++;
- }else
- memmove(q + 1, q, (sprm - 1 - q) * sizeof(sprite));
- goto found;
- }
- if(q == spr + 10)
- continue;
- sprm++;
- found:;
- }else
- q = sprm++;
- q->dy = y0 - p[0];
- q->x = p[1];
- q->t = t = p[3];
- if((t & SPRYFL) != 0)
- q->dy ^= sy - 1;
- tn = p[2];
- if(sy == 16)
- tn = tn & ~1 | q->dy >> 3;
- chrp = vram + (tn << 4 | q->dy << 1 & 14);
- if((mode & COL) != 0){
- chrp += t << 10 & 0x2000;
- q->pal = 0x20 | t << 2 & 0x1c;
- }else
- q->pal = 4 + (t >> 2 & 4);
- q->chr = chrp[0] << 8 | chrp[1];
- if(p[1] < 8)
- if((t & SPRXFL) != 0)
- q->chr >>= 8 - p[1];
- else
- q->chr <<= 8 - p[1];
- q->fetched = 0;
- if((mode & COL) != 0 && sprm == spr + 10)
- break;
- }
-}
-
-void
-sprites(void)
-{
- sprite *q;
- u8int attr;
- u32int *picp;
- int x, x1;
- u16int chr;
-
- picp = (u32int*)pic + ppuy * PICW;
- for(q = spr; q < sprm; q++){
- if(q->x <= ppux0 || q->x >= ppux + 8)
- continue;
- x = q->x - 8;
- if(x < ppux0) x = ppux0;
- x1 = q->x;
- if(x1 > ppux) x1 = ppux;
- for(; x < x1; x++){
- attr = picp[x] >> prish;
- chr = q->chr;
- if((chr & ((q->t & SPRXFL) != 0 ? 0x0101 : 0x8080)) != 0 && (attr & TILSPR) == 0 &&
- ((mode & COL) != 0 && (reg[LCDC] & BGPRI) == 0 ||
- (attr & TILCOL0) != 0 ||
- (attr & TILPRI) == 0 && (q->t & SPRPRI) == 0))
- if((q->t & SPRXFL) == 0)
- picp[x] = pal[q->pal | chr >> 15 | chr >> 6 & 2] | TILSPR << prish;
- else
- picp[x] = pal[q->pal | chr << 1 & 2 | chr >> 8 & 1] | TILSPR << prish;
- if((q->t & SPRXFL) != 0)
- q->chr >>= 1;
- else
- q->chr <<= 1;
- }
- }
- ppux0 = ppux;
-}
-
-void
-ppusync(void)
-{
- if(ppustate != 3)
- return;
- cyc = clock - rendclock;
- if(cyc != 0)
- myield();
- sprites();
- rendclock = clock;
-}
-
-int
-linelen(void)
-{
- int t;
-
- t = 174 + (reg[SCX] & 7);
- if((reg[LCDC] & WINEN) != 0 && ppuy >= reg[WY] && reg[WX] < 166)
- if(reg[WX] == 0)
- t += 7;
- else
- t += 6;
- return t*2;
-}
-
-void
-hblanktick(void *)
-{
- extern Event evhblank;
- int t;
-
- switch(ppustate){
- case 0:
- hblclock = clock + evhblank.time;
- if(reg[WX] <= 166 && reg[WY] <= 143)
- ppuw++;
- if(++ppuy == 144){
- ppustate = 1;
- if((reg[STAT] & IRQM1) != 0)
- reg[IF] |= IRQLCDS;
- addevent(&evhblank, 456*2);
- reg[IF] |= IRQVBL;
- flush();
- }else{
- ppustate = 2;
- if((reg[STAT] & IRQM2) != 0)
- reg[IF] |= IRQLCDS;
- addevent(&evhblank, 80*2);
- }
- if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
- reg[IF] |= IRQLCDS;
- break;
- case 1:
- hblclock = clock + evhblank.time;
- if(reg[WX] <= 166 && reg[WY] <= 143)
- ppuw++;
- if(++ppuy == 154){
- ppuy = 0;
- ppuw = 0;
- ppustate = 2;
- if((reg[STAT] & IRQM2) != 0)
- reg[IF] |= IRQLCDS;
- addevent(&evhblank, 80*2);
- }else
- addevent(&evhblank, 456*2);
- if((reg[STAT] & IRQLYC) != 0 && ppuy == reg[LYC])
- reg[IF] |= IRQLCDS;
- break;
- case 2:
- oamsearch();
- rendclock = clock + evhblank.time;
- ppustate = 3;
- addevent(&evhblank, linelen());
- break;
- case 3:
- ppusync();
- if(!done) print("not done?!\n");
- done = 0;
- ppustate = 0;
- if((reg[STAT] & IRQM0) != 0)
- reg[IF] |= IRQLCDS;
- t = hblclock + 456 * 2 - clock;
- addevent(&evhblank, t < 0 ? 456 * 2 : t);
- if(dma & DMAHBLANK)
- dma |= DMAREADY;
- break;
- }
-}
-
-void
-ppuinit(void)
-{
- static char ppustack[4096];
-
- renderjmp[JMPBUFPC] = (uintptr)ppurender;
- renderjmp[JMPBUFSP] = (uintptr)(ppustack + sizeof(ppustack) - 64);
- myield();
-}
--- a/sys/src/games/gba/apu.c
+++ /dev/null
@@ -1,390 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-Event evsamp;
-int srate, sratediv;
-s16int sbuf[2*4000], *sbufp, bias;
-enum {
- Freq = 44100,
-};
-static int stime;
-s8int snddma[2];
-static int fd;
-
-u16int envctr, envrel, envmod;
-u8int sweepen, sweepctr;
-u16int sweepfreq;
-typedef struct chan chan;
-struct chan {
- u8int n, ectr;
- u16int len;
- u16int *env, *freq;
- u16int fctr, fthr;
- u32int finc;
- u8int vol;
-};
-u8int wave[64], wpos, wbank;
-u16int lfsr;
-
-chan sndch[4] = {
- {
- .n = 0,
- .env = reg + 0x62/2,
- .freq = reg + 0x64/2,
- },
- {
- .n = 1,
- .env = reg + 0x68/2,
- .freq = reg + 0x6c/2,
- },
- {
- .n = 2,
- },
- {
- .n = 3,
- .env = reg + 0x78/2,
- .freq = reg + 0x7c/2,
- }
-};
-
-Var apuvars[] = {
- ARR(snddma), VAR(envctr), VAR(envrel), VAR(envmod), VAR(sweepen),
- VAR(sweepctr), VAR(sweepfreq), ARR(wave), VAR(wpos), VAR(wbank), VAR(lfsr),
- VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].fctr), VAR(sndch[0].fthr), VAR(sndch[0].finc), VAR(sndch[0].vol),
- VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].fctr), VAR(sndch[1].fthr), VAR(sndch[1].finc), VAR(sndch[1].vol),
- VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].fctr), VAR(sndch[2].fthr), VAR(sndch[2].finc), VAR(sndch[2].vol),
- VAR(sndch[3].ectr), VAR(sndch[3].len), VAR(sndch[3].fctr), VAR(sndch[3].fthr), VAR(sndch[3].finc), VAR(sndch[3].vol),
- {nil, 0, 0},
-};
-
-void
-rate(int i, u16int v)
-{
- switch(i){
- case 0: case 1:
- sndch[i].finc = 131072ULL * 65536 / (srate * (2048 - (v & 0x7ff)));
- break;
- case 2:
- sndch[2].finc = 2097152ULL * 65536 / (srate * (2048 - (v & 0x7ff)));
- break;
- case 3:
- sndch[3].finc = 524288ULL * 65536 / srate;
- if((v & 7) != 0)
- sndch[3].finc /= v & 7;
- else
- sndch[3].finc <<= 1;
- sndch[3].finc >>= (v >> 4 & 15) + 1;
- }
-}
-
-void
-env(chan *c)
-{
- if((envmod & 1) == 0 && c->len > 0 && (*c->freq & 1<<14) != 0)
- --c->len;
- if(c->len == 0){
- c->vol = 0;
- return;
- }
- if((envmod & 7) != 7 || c->ectr == 0 || --c->ectr != 0)
- return;
- c->ectr = *c->env >> 8 & 7;
- if((*c->env & 1<<11) != 0){
- if(c->vol < 15)
- c->vol++;
- }else
- if(c->vol > 0)
- c->vol--;
-}
-
-s8int
-wavesamp(void)
-{
- s8int x;
- u16int vol, cnt;
- int v;
-
- sndch[2].fctr = v = sndch[2].fctr + sndch[2].finc;
- if(sndch[2].len == 0 || (reg[0x70/2] & 1<<7) == 0)
- return 0;
- vol = reg[0x72/2];
- cnt = reg[0x70/2];
- for(;;){
- x = wave[wbank ^ wpos];
- v -= 0x10000;
- if(v < 0)
- break;
- wpos++;
- if((cnt & 1<<5) != 0)
- wpos &= 63;
- else
- wpos &= 31;
- }
- if((vol & 1<<15) != 0)
- x = (x >> 2) + (x >> 3);
- else if((vol & 3<<14) == 0)
- x = 0;
- else
- x = x >> (vol >> 14 & 3);
- return x;
-}
-
-s8int
-lfsrsamp(void)
-{
- int v;
- u16int l;
-
- sndch[3].fctr = v = sndch[3].fctr + sndch[3].finc;
- for(;;){
- l = lfsr;
- v -= 0x10000;
- if(v < 0)
- break;
- lfsr >>= 1;
- if(((l ^ lfsr) & 1) != 0)
- if((reg[0x7c/2] & 1<<3) != 0)
- lfsr |= 0x40;
- else
- lfsr |= 0x4000;
- }
- if((l & 1) != 0)
- return -sndch[3].vol;
- else
- return sndch[3].vol;
-}
-
-void
-sweep(int wb)
-{
- u16int fr;
- int d;
- u16int cnt;
-
- cnt = reg[0x60/2];
- d = sweepfreq >> (cnt & 7);
- if((cnt & 1<<3) != 0)
- d = -d;
- fr = sweepfreq + d;
- if(fr > 2047){
- sndch[0].len = 0;
- sndch[0].vol = 0;
- sweepen = 0;
- }else if(wb){
- sweepfreq = fr;
- reg[0x64/2] = reg[0x64/2] & 0xfc00 | fr;
- rate(0, fr);
- sweep(0);
- }
-}
-
-void
-sndstart(chan *c, u16int v)
-{
- u16int cnt;
-
- c->vol = *c->env >> 12;
- c->ectr = *c->env >> 8 & 7;
- if(c->len == 0)
- c->len = 64;
- if(c == sndch){
- cnt = reg[0x60/2];
- sweepen = (cnt & 0x07) != 0 && (cnt & 0x70) != 0;
- sweepctr = cnt >> 4 & 7;
- sweepfreq = v & 0x7ff;
- if((cnt & 0x07) != 0)
- sweep(0);
- }
-}
-
-void
-sampletick(void *)
-{
- u16int cntl, cnth;
- s16int ch[6];
- s16int s[2];
- int i;
-
- addevent(&evsamp, sratediv);
-
- if(--envctr == 0){
- envctr = envrel;
- env(&sndch[0]);
- env(&sndch[1]);
- if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[0x74/2] & 1<<14) != 0)
- sndch[2].len--;
- env(&sndch[3]);
- if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
- sweepctr = reg[0x60/2] >> 4 & 7;
- sweep(1);
- }
- envmod++;
- }
-
- sndch[0].fctr += sndch[0].finc;
- if(sndch[0].fctr >= sndch[0].fthr)
- ch[0] = sndch[0].vol;
- else
- ch[0] = -sndch[0].vol;
- sndch[1].fctr += sndch[1].finc;
- if(sndch[1].fctr >= sndch[1].fthr)
- ch[1] = sndch[1].vol;
- else
- ch[1] = -sndch[1].vol;
- ch[2] = wavesamp();
- ch[3] = lfsrsamp();
-
- cntl = reg[SOUNDCNTL];
- cnth = reg[SOUNDCNTH];
- for(i = 0; i < 4; i++)
- ch[i] = ch[i] >> (cnth & 3);
- ch[5] = snddma[0] << 1 + (cnth >> 2 & 1);
- ch[6] = snddma[1] << 1 + (cnth >> 3 & 1);
-
- s[0] = 0;
- s[1] = 0;
- for(i = 0; i < 4; i++){
- if((cntl & 1<<8<<i) != 0)
- s[1] += ch[i] * (1 + (cntl & 7));
- if((cntl & 1<<12<<i) != 0)
- s[0] += ch[i] * (1 + (cntl >> 4 & 7));
- }
- for(i = 5; i < 6; i++){
- if((cnth & 1<<3<<i) != 0)
- s[1] += ch[i];
- if((cnth & 1<<4<<i) != 0)
- s[0] += ch[i];
- }
- s[0] += bias;
- s[1] += bias;
- if(s[0] < -0x200) s[0] = -0x200;
- else if(s[0] > 0x1ff) s[0] = 0x1ff;
- if(s[1] < -0x200) s[1] = -0x200;
- else if(s[1] > 0x1ff) s[1] = 0x1ff;
-
- stime -= Freq;
- while(stime < 0){
- if(sbufp < sbuf + nelem(sbuf)){
- sbufp[0] = s[0] << 6;
- sbufp[1] = s[1] << 6;
- sbufp += 2;
- }
- stime += srate;
- }
-}
-
-
-void
-sndwrite(u16int a, u16int v)
-{
- int sh, p, i;
- static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
-
- switch(a){
- case 0x62:
- sndch[0].fthr = thr[v >> 6 & 3];
- sndch[0].len = 64 - (v & 63);
- break;
- case 0x64:
- rate(0, v);
- if((v & 1<<15) != 0)
- sndstart(&sndch[0], v);
- break;
- case 0x68:
- sndch[1].fthr = thr[v >> 6 & 3];
- break;
- case 0x6c:
- rate(1, v);
- if((v & 1<<15) != 0)
- sndstart(&sndch[1], v);
- break;
- case 0x70:
- wbank = v >> 1 & 32;
- break;
- case 0x72:
- sndch[2].len = 256 - (v & 0xff);
- break;
- case 0x74:
- rate(2, v);
- if((v & 1<<15) != 0 && sndch[2].len == 0)
- sndch[2].len = 256;
- break;
- case 0x7c:
- rate(3, v);
- if((v & 1<<15) != 0){
- if((v & 1<<3) != 0)
- lfsr = 0x7f;
- else
- lfsr = 0x7fff;
- sndstart(&sndch[3], v);
- }
- break;
- case SOUNDBIAS*2:
- sh = 9 - (v >> 14 & 3);
- if(sratediv != 1<<sh){
- srate = 1 << 24 - sh;
- sratediv = 1 << sh;
- envrel = srate / 512;
- rate(0, reg[0x64/2]);
- rate(1, reg[0x6c/2]);
- rate(2, reg[0x74/2]);
- rate(3, reg[0x7c/2]);
- }
- bias = (v & 0x3ff) - 0x200;
- break;
- case 0x90: case 0x92: case 0x94: case 0x96:
- case 0x98: case 0x9a: case 0x9c: case 0x9e:
- p = ~reg[0x70/2] >> 1 & 32;
- for(i = a - 0x90; i < a - 0x90 + 2; i++){
- wave[(wpos + 2 * i) & 31 + p] = v >> 4 & 0xf;
- wave[(wpos + 2 * i + 1) & 31 + p] = v & 0xf;
- v >>= 8;
- }
- break;
- }
-}
-
-void
-audioinit(void)
-{
- fd = open("/dev/audio", OWRITE);
- if(fd < 0)
- sysfatal("open: %r");
- sbufp = sbuf;
- sndwrite(SOUNDBIAS*2, 0x200);
- evsamp.f = sampletick;
- addevent(&evsamp, sratediv);
-}
-
-int
-audioout(void)
-{
- int rc;
- static int cl;
- static vlong t0;
-
- if(t0 == 0)
- t0 = nsec();
- if(sbufp == nil)
- return -1;
- if(sbufp == sbuf)
- return 0;
- cl = clock;
- vlong t = nsec();
- rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2);
- vlong t2 = nsec();
- double Δ = (t2 - t) / 1000000.0;
- double τ = (t2 - t0) / 1000000.0;
- double τ0 = rc * 1000.0 / (44100.0 * 4);
- fprint(2, "%d %f %f\n", rc, Δ, τ-τ0);
- t0 = t2;
- if(rc > 0)
- sbufp -= (rc+1)/2;
- if(sbufp < sbuf)
- sbufp = sbuf;
- return 0;
-}
--- a/sys/src/games/gba/ppu.c
+++ /dev/null
@@ -1,781 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int hblank, ppuy;
-u8int bldy, blda, bldb;
-u32int hblclock;
-int ppux0;
-u32int pixcol[480];
-u8int pixpri[480];
-u8int pixwin[240];
-int objalpha;
-
-typedef struct bg bg;
-struct bg {
- uchar n;
- s32int rpx0, rpy0, rpx1, rpy1, rpx, rpy;
- u16int tx, ty;
- u8int tnx, tny;
-
- u8int mosaic, mctr, lasti;
- u32int curc;
- u8int curpri;
-};
-static bg bgst[4] = {{.n = 0}, {.n = 1}, {.n = 2}, {.n = 3}};
-
-Var ppuvars[] = {
- VAR(hblank), VAR(ppuy), VAR(hblclock),
- VAR(bldy), VAR(blda), VAR(bldb), VAR(objalpha),
- VAR(bgst[2].rpx0), VAR(bgst[2].rpy0), VAR(bgst[3].rpx0), VAR(bgst[3].rpy0),
- {nil, 0, 0},
-};
-
-typedef struct sprite sprite;
-struct sprite {
- uchar w, wb, h;
- s16int x;
- uchar ysh;
-
- uchar *base;
- u16int *pal;
- u16int inc;
-
- u32int t0;
- u16int t1;
- uchar depth;
-
- s32int rx, ry;
- s16int dx, dy;
-
- u8int mctr, mcol;
-};
-static sprite sprt[128], *sp = sprt;
-enum {
- SPRROT = 1<<8,
- SPRDIS = 1<<9,
- SPRDOUB = 1<<9,
- SPRMOSA = 1<<12,
- SPR8 = 1<<13,
- SPRWIDE = 1<<14,
- SPRTALL = 1<<15,
- SPRHFLIP = 1<<28,
- SPRVFLIP = 1<<29,
- SPRSIZE0 = 1<<30,
- SPRSIZE1 = 1<<31,
-
- NOWIN = 0,
- OBJWIN = 1,
- WIN2 = 2,
- WIN1 = 4,
-
- OBJALPHA = 1<<16,
- SRCOBJ = 4<<17,
- SRCBACK = 5<<17,
-
- VACANT = 0x10,
- BACKDROP = 8,
-};
-#define SRCBG(n) ((n)<<17)
-
-void
-sprinit(void)
-{
- u16int *p, *pp;
- u16int cnt, t1;
- u32int t0;
- int budg;
- uchar ws, h, hb, d, dy, s;
- static uchar wss[16] = {3, 4, 5, 6, 4, 5, 5, 6, 3, 3, 4, 5};
- static uchar hss[16] = {3, 4, 5, 6, 3, 3, 4, 5, 4, 5, 5, 6};
-
- sp = sprt;
- cnt = reg[DISPCNT];
- budg = (cnt & HBLFREE) != 0 ? 954 : 1210;
- for(p = oam; p < oam + 512; p += 4){
- t0 = p[0];
- if((t0 & (SPRROT|SPRDIS)) == SPRDIS)
- continue;
- t0 |= p[1] << 16;
- s = t0 >> 30 & 3 | t0 >> 12 & 12;
- hb = h = 1 << hss[s];
- dy = ppuy - (u8int) t0;
- if((t0 & (SPRROT|SPRDOUB)) == (SPRROT|SPRDOUB))
- hb <<= 1;
- if(dy >= hb || (u8int)t0 + hb > 256 && ppuy + 256 - (u8int)t0 >= hb)
- continue;
- if((t0 & SPRMOSA) != 0){
- dy = dy - dy % ((reg[MOSAIC] >> 12 & 15) + 1);
- sp->mctr = 0;
- }
- sp->x = (s32int)(t0 << 7) >> 23;
- sp->t0 = t0;
- ws = wss[s];
- sp->wb = sp->w = 1<<ws;
- sp->h = h;
- sp->t1 = t1 = p[2];
- sp->base = vram + 0x10000 + ((t1 & 0x3ff) << 5);
- d = (t0 & SPR8) != 0;
- sp->ysh = (cnt & OBJNOMAT) != 0 ? 2 + d + ws : 10;
- if((t0 & SPRROT) != 0){
- if((t0 & SPRDOUB) != 0)
- sp->wb <<= 1;
- budg -= 10 + sp->w*2;
- pp = oam + 3 + (t0 >> 21 & 0x1f0);
- sp->dx = pp[0];
- sp->dy = pp[8];
- sp->rx = (dy - hb/2) * (s16int) pp[4] + (sp->w << 7) - sp->dx * sp->wb/2;
- sp->ry = (dy - hb/2) * (s16int)pp[12] + (sp->h << 7) - sp->dy * sp->wb/2;
- if(sp->x < 0){
- sp->rx -= sp->x * sp->dx;
- sp->ry -= sp->x * sp->dy;
- }
- }else{
- budg -= sp->w;
- if((t0 & SPRVFLIP) != 0)
- dy = h - 1 - dy;
- sp->base += (dy & 7) << 2 + d;
- sp->base += dy >> 3 << sp->ysh;
- if((t0 & SPRHFLIP) != 0)
- sp->base += sp->w - 7 << 2 + d;
- sp->inc = (1 << 5 + d) - (1 << 2 + d);
- if(sp->x < 0)
- if((t0 & SPRHFLIP) != 0){
- sp->base -= ((-sp->x & 7) >> 1 - d) + (-sp->x >> 3 << 5 + d);
- if((t0 & SPR8) == 0 && (sp->x & 1) != 0)
- sp->base--;
- }else
- sp->base += ((-sp->x & 7) >> 1 - d) + (-sp->x >> 3 << 5 + d);
- }
- if((t0 & SPR8) != 0)
- sp->pal = pram + 0x100;
- else
- sp->pal = pram + 0x100 + (t1 >> 8 & 0xf0);
- if(budg < 0)
- break;
- sp++;
- }
-}
-
-void
-spr(int x1)
-{
- int x0, i, dx, sx0, sx1;
- u8int pri, v, d, *b;
- u16int x, y;
- u32int c, t0;
- sprite *s;
-
- x0 = ppux0;
- for(s = sprt; s < sp; s++){
- if(s->x >= x1 || s->x + s->wb <= x0)
- continue;
- t0 = s->t0;
- pri = s->t1 >> 10 & 3;
- sx0 = s->x >= x0 ? s->x : x0;
- sx1 = s->x + s->wb;
- if(x1 < sx1)
- sx1 = x1;
- dx = sx0 - s->x;
- for(i = sx0; i < sx1; i++, dx++){
- if((t0 & SPRROT) != 0){
- d = (t0 & SPR8) != 0;
- x = s->rx >> 8;
- y = s->ry >> 8;
- s->rx += s->dx;
- s->ry += s->dy;
- if(x < s->w && y < s->h){
- b = s->base;
- b += (y & 7) << 2 + d;
- b += y >> 3 << s->ysh;
- b += (x & 7) >> 1 - d;
- b += x >> 3 << 5 + d;
- v = *b;
- if(!d)
- if((x & 1) != 0)
- v >>= 4;
- else
- v &= 0xf;
- }else
- v = 0;
- }else if((t0 & SPRHFLIP) != 0){
- if((t0 & SPR8) != 0)
- v = *--s->base;
- else if((dx & 1) != 0)
- v = *s->base & 0x0f;
- else
- v = *--s->base >> 4;
- if((dx & 7) == 7)
- s->base -= s->inc;
- }else{
- v = *s->base;
- if((t0 & SPR8) != 0)
- s->base++;
- else if((dx & 1) != 0){
- v >>= 4;
- s->base++;
- }else
- v &= 0xf;
- if((dx & 7) == 7)
- s->base += s->inc;
- }
- if((t0 & SPRMOSA) != 0)
- if(s->mctr == 0){
- s->mctr = reg[MOSAIC] >> 8 & 15;
- s->mcol = v;
- }else{
- --s->mctr;
- v = s->mcol;
- }
- if(v != 0){
- c = s->pal[v] | SRCOBJ;
- switch(t0 >> 10 & 3){
- case 1:
- c |= OBJALPHA;
- objalpha++;
- case 0:
- if(pri < pixpri[i]){
- pixcol[i] = c;
- pixpri[i] = pri;
- }
- break;
- case 2:
- if((reg[DISPCNT] & 1<<15) != 0)
- pixwin[i] |= OBJWIN;
- break;
- }
- }
- }
- }
-}
-
-void
-bgpixel(bg *b, int i, u32int c, int pri)
-{
- u8int *p;
- u32int *q;
- int j;
-
- if(b != nil){
- c |= SRCBG(b->n);
- if(b->mosaic){
- for(j = (u8int)(b->lasti+1); j <= i; j++){
- if(b->mctr == 0){
- if(j == i){
- b->curc = c;
- b->curpri = pri;
- }else
- b->curpri = VACANT;
- b->mctr = reg[MOSAIC] & 15;
- }else
- b->mctr--;
- if(b->curpri != VACANT && (pixwin[j] & 1<<b->n) == 0)
- bgpixel(nil, j, b->curc, b->curpri);
- }
- b->lasti = i;
- return;
- }
- }
- p = pixpri + i;
- q = pixcol + i;
- if(pri < p[0]){
- p[240] = p[0];
- p[0] = pri;
- q[240] = q[0];
- q[0] = c;
- }else if(pri < p[240]){
- p[240] = pri;
- q[240] = c;
- }
-}
-
-
-
-void
-bginit(bg *b, int scal, int)
-{
- u16int x, y;
- u16int *rr;
- int msz;
-
- b->mosaic = (reg[BG0CNT + b->n] & BGMOSAIC) != 0;
- if(b->mosaic){
- b->mctr = 0;
- b->lasti = -1;
- }
- if(scal){
- rr = reg + (b->n - 2 << 3);
- if(ppuy == 0){
- b->rpx0 = (s32int)(rr[BG2XL] | rr[BG2XH] << 16) << 4 >> 4;
- b->rpy0 = (s32int)(rr[BG2YL] | rr[BG2YH] << 16) << 4 >> 4;
- }
- if(!b->mosaic || ppuy % ((reg[MOSAIC] >> 4 & 15) + 1) == 0){
- b->rpx1 = b->rpx0;
- b->rpy1 = b->rpy0;
- }
- b->rpx = b->rpx1;
- b->rpy = b->rpy1;
- b->rpx0 += (s16int)rr[BG2PB];
- b->rpy0 += (s16int)rr[BG2PD];
- }else{
- rr = reg + (b->n << 1);
- x = rr[BG0HOFS] & 0x1ff;
- y = ppuy;
- if(b->mosaic){
- msz = (reg[MOSAIC] >> 4 & 15) + 1;
- y = y - y % msz;
- }
- y += (rr[BG0VOFS] & 0x1ff);
- b->tx = x >> 3;
- b->ty = y >> 3;
- b->tnx = x & 7;
- b->tny = y & 7;
- }
-}
-
-void
-bgsinit(void)
-{
- switch(reg[DISPCNT] & 7){
- case 0:
- bginit(&bgst[0], 0, 0);
- bginit(&bgst[1], 0, 0);
- bginit(&bgst[2], 0, 0);
- bginit(&bgst[3], 0, 0);
- break;
- case 1:
- bginit(&bgst[0], 0, 0);
- bginit(&bgst[1], 0, 0);
- bginit(&bgst[2], 1, 0);
- break;
- case 2:
- bginit(&bgst[2], 1, 0);
- bginit(&bgst[3], 1, 0);
- break;
- case 3:
- case 4:
- case 5:
- bginit(&bgst[2], 1, 1);
- break;
- }
-}
-
-void
-bitbg(bg *b, int x1)
-{
- u8int *base, *p, pri, d;
- u16int cnt, *rr, sx, sy;
- int i, v;
-
- cnt = reg[DISPCNT];
- if((cnt & 1<<8 + b->n) == 0)
- return;
- rr = reg + (b->n - 2 << 3);
- if((cnt & 7) != 5){
- sx = 240 << 8;
- sy = 160 << 8;
- d = (cnt & 7) == 3;
- }else{
- sx = 160 << 8;
- sy = 128 << 8;
- d = 1;
- }
- base = vram;
- if((cnt & FRAME) != 0 && (cnt & 7) != 3)
- base += 0xa000;
- pri = reg[BG0CNT + b->n] & 3;
- for(i = ppux0; i < x1; i++){
- if(((pixwin[i] & 1<<b->n) == 0 || b->mosaic) && (u32int)b->rpx < sx && (u32int)b->rpy < sy){
- if(d){
- p = base + 2 * (b->rpx >> 8) + 480 * (b->rpy >> 8);
- v = p[0] | p[1] << 8;
- }else{
- v = base[(b->rpx >> 8) + 240 * (b->rpy >> 8)];
- if(v != 0)
- v = pram[v];
- else
- v = -1;
- }
- if(v >= 0)
- bgpixel(b, i, v, pri);
-
- }
- b->rpx += (s16int) rr[BG2PA];
- b->rpy += (s16int) rr[BG2PC];
- }
-}
-
-void
-txtbg(bg *b, int x1)
-{
- u8int y, v, d, *cp;
- u16int bgcnt, ta0, ta, tx, ty, t, *pal;
- u32int ca;
- int i, x, mx;
-
- if((reg[DISPCNT] & 1<<8 + b->n) == 0)
- return;
- bgcnt = reg[BG0CNT + b->n];
- d = bgcnt >> 7 & 1;
- tx = b->tx;
- ty = b->ty;
- ta0 = (bgcnt << 3 & 0xf800) + ((ty & 0x1f) << 6);
- switch(bgcnt >> 14){
- case 2: ta0 += ty << 6 & 0x800; break;
- case 3: ta0 += ty << 7 & 0x1000; break;
- }
- x = ppux0;
- i = b->tnx;
- for(; x < x1; tx++, i = 0){
- ta = ta0 + ((tx & 0x1f) << 1);
- if((bgcnt & 1<<14) != 0)
- ta += tx << 6 & 0x800;
- t = vram[ta] | vram[ta+1] << 8;
- if(d)
- pal = pram;
- else
- pal = pram + (t >> 8 & 0xf0);
- ca = (bgcnt << 12 & 0xc000) + ((t & 0x3ff) << 5+d);
- if(ca >= 0x10000)
- continue;
- y = b->tny;
- if((t & 1<<11) != 0)
- y ^= 7;
- ca += y << 2+d;
- cp = vram + ca;
- for(; i < 8; i++, x++){
- if(x >= x1)
- goto out;
- if((pixwin[x] & 1<<b->n) != 0 && !b->mosaic)
- continue;
- mx = i;
- if((t & 1<<10) != 0)
- mx ^= 7;
- v = cp[mx >> 1-d];
- if(!d)
- if((mx & 1) != 0)
- v >>= 4;
- else
- v &= 0xf;
- if(v != 0)
- bgpixel(b, x, pal[v], bgcnt & 3);
- }
- }
-out:
- b->tx = tx;
- b->tnx = i;
-}
-
-void
-rotbg(bg *b, int x1)
-{
- uchar *p, v;
- u16int bgcnt, *rr, ta;
- int i, row, sz, x, y;
-
- rr = reg + (b->n - 2 << 3);
- if((reg[DISPCNT] & 1<<8 + b->n) == 0)
- return;
- bgcnt = reg[BG0CNT + b->n];
- row = (bgcnt >> 14) + 4;
- sz = 1 << 3 + row;
- for(i = ppux0; i < x1; i++){
- x = b->rpx >> 8;
- y = b->rpy >> 8;
- b->rpx += (s16int) rr[BG2PA];
- b->rpy += (s16int) rr[BG2PC];
- if((pixwin[i] & 1<<b->n) != 0 && !b->mosaic)
- continue;
- if((bgcnt & DISPWRAP) != 0){
- x &= sz - 1;
- y &= sz - 1;
- }else if((uint)x >= sz || (uint)y >= sz)
- continue;
- ta = (bgcnt << 3 & 0xf800) + ((y >> 3) << row) + (x >> 3);
- p = vram + (bgcnt << 12 & 0xc000) + (vram[ta] << 6);
- p += (x & 7) + ((y & 7) << 3);
- if((v = *p) != 0)
- bgpixel(b, i, pram[v], bgcnt & 3);
-
- }
-}
-
-void
-windows(int x1)
-{
- static u8int wintab[8] = {2, 3, 1, 1, 0, 0, 0, 0};
- int i, sx0, sx1;
- u16int v, h;
- u16int cnt;
-
- cnt = reg[DISPCNT];
- if((cnt >> 13) != 0){
- if((cnt & 1<<13) != 0){
- v = reg[WIN0V];
- h = reg[WIN0H];
- if(ppuy < (u8int)v && ppuy >= v >> 8){
- sx1 = (u8int)h;
- sx0 = h >> 8;
- if(sx0 < ppux0)
- sx0 = ppux0;
- if(sx1 > x1)
- sx1 = x1;
- for(i = sx0; i < sx1; i++)
- pixwin[i] |= WIN1;
- }
- }
- if((cnt & 1<<14) != 0){
- v = reg[WIN1V];
- h = reg[WIN1H];
- if(ppuy < (u8int)v && ppuy >= v >> 8){
- sx1 = (u8int)h;
- sx0 = h >> 8;
- if(sx0 < ppux0)
- sx0 = ppux0;
- if(sx1 > x1)
- sx1 = x1;
- for(i = sx0; i < sx1; i++)
- pixwin[i] |= WIN2;
- }
- }
- for(i = ppux0; i < x1; i++){
- v = wintab[pixwin[i]];
- h = reg[WININ + (v & 2) / 2];
- if((v & 1) != 0)
- h >>= 8;
- pixwin[i] = ~h;
- }
- }
- for(i = ppux0; i < x1; i++)
- if(pixpri[i] == VACANT || (pixwin[i] & 1<<4) != 0){
- pixcol[i] = pram[0] | SRCBACK;
- pixpri[i] = BACKDROP;
- }else{
- pixcol[i+240] = pram[0] | SRCBACK;
- pixpri[i+240] = BACKDROP;
- }
- objalpha = 0;
-}
-
-u16int
-mix(u16int c1, u16int c2)
-{
- u16int r, g, b, eva, evb;
-
- eva = blda;
- evb = bldb;
- b = ((c1 & 0x7c00) * eva + (c2 & 0x7c00) * evb) >> 4;
- g = ((c1 & 0x03e0) * eva + (c2 & 0x03e0) * evb) >> 4;
- r = ((c1 & 0x001f) * eva + (c2 & 0x001f) * evb) >> 4;
- if(b > 0x7c00) b = 0x7c00;
- if(g > 0x03e0) g = 0x03e0;
- if(r > 0x001f) r = 0x001f;
- return b & 0x7c00 | g & 0x03e0 | r;
-}
-
-u16int
-brighten(u16int c1)
-{
- u16int r, g, b, y;
-
- y = bldy;
- b = c1 & 0x7c00;
- b = b + (0x7c00 - b) * y / 16;
- g = c1 & 0x03e0;
- g = g + (0x03e0 - g) * y / 16;
- r = c1 & 0x001f;
- r = r + (0x001f - r) * y / 16;
- if(b > 0x7c00) b = 0x7c00;
- if(g > 0x03e0) g = 0x03e0;
- if(r > 0x001f) r = 0x001f;
- return b & 0x7c00 | g & 0x03e0 | r;
-}
-
-u16int
-darken(u16int c1)
-{
- u16int r, g, b, y;
-
- y = 16 - bldy;
- b = c1 & 0x7c00;
- b = b * y / 16;
- g = c1 & 0x03e0;
- g = g * y / 16;
- r = c1 & 0x001f;
- r = r * y / 16;
- return b & 0x7c00 | g & 0x03e0 | r;
-}
-
-void
-colormath(int x1)
-{
- u16int bldcnt;
- u32int *p;
- int i;
-
- bldcnt = reg[BLDCNT];
- if((bldcnt & 3<<6) == 0 && objalpha == 0)
- return;
- p = pixcol + ppux0;
- for(i = ppux0; i < x1; i++, p++){
- if((*p & OBJALPHA) != 0)
- goto alpha;
- if((pixwin[i] & 1<<5) != 0 || (bldcnt & 1<<(*p >> 17)) == 0)
- continue;
- switch(bldcnt >> 6 & 3){
- case 1:
- alpha:
- if((bldcnt & 1<<8+(p[240] >> 17)) == 0)
- continue;
- *p = mix(*p, p[240]);
- break;
- case 2:
- *p = brighten(*p);
- break;
- case 3:
- *p = darken(*p);
- break;
- }
- }
-}
-
-void
-syncppu(int x1)
-{
- int i;
- u16int cnt;
-
- if(hblank || ppuy >= 160)
- return;
- if(x1 >= 240)
- x1 = 240;
- else if(x1 <= ppux0)
- return;
- cnt = reg[DISPCNT];
- if((cnt & FBLANK) != 0){
- for(i = ppux0; i < x1; i++)
- pixcol[i] = 0xffff;
- ppux0 = x1;
- return;
- }
-
- if((cnt & 1<<12) != 0)
- spr(x1);
- windows(x1);
- switch(cnt & 7){
- case 0:
- txtbg(&bgst[0], x1);
- txtbg(&bgst[1], x1);
- txtbg(&bgst[2], x1);
- txtbg(&bgst[3], x1);
- break;
- case 1:
- txtbg(&bgst[0], x1);
- txtbg(&bgst[1], x1);
- rotbg(&bgst[2], x1);
- break;
- case 2:
- rotbg(&bgst[2], x1);
- rotbg(&bgst[3], x1);
- break;
- case 3:
- case 4:
- case 5:
- bitbg(&bgst[2], x1);
- }
- colormath(x1);
- ppux0 = x1;
-}
-
-void
-linecopy(u32int *p, int y)
-{
- uchar *q;
- u16int *r;
- u16int v;
- union { u16int w; u8int b[2]; } u;
- int n;
-
- q = pic + y * 240 * 2;
- r = (u16int*)q;
- n = 240;
- while(n--){
- v = *p++;
- u.b[0] = v;
- u.b[1] = v >> 8;
- *r++ = u.w;
- }
-}
-
-void
-hblanktick(void *)
-{
- extern Event evhblank;
- u16int stat;
-
- stat = reg[DISPSTAT];
- if(hblank){
- hblclock = clock + evhblank.time;
- addevent(&evhblank, 240*4);
- hblank = 0;
- ppux0 = 0;
- memset(pixpri, VACANT, sizeof(pixpri));
- memset(pixwin, 0, 240);
- if(++ppuy >= 228){
- ppuy = 0;
- flush();
- }
- if(ppuy < 160){
- sprinit();
- bgsinit();
- }else if(ppuy == 160){
- dmastart(DMAVBL);
- if((stat & IRQVBLEN) != 0)
- setif(IRQVBL);
- }
- if((stat & IRQVCTREN) != 0 && ppuy == stat >> 8)
- setif(IRQVCTR);
- }else{
- syncppu(240);
- if(ppuy < 160)
- linecopy(pixcol, ppuy);
- addevent(&evhblank, 68*4);
- hblank = 1;
- if((stat & IRQHBLEN) != 0)
- setif(IRQHBL);
- if(ppuy < 160)
- dmastart(DMAHBL);
- }
-}
-
-void
-ppuwrite(u16int a, u16int v)
-{
- syncppu((clock - hblclock) / 4);
- switch(a){
- case BLDALPHA*2:
- blda = v & 0x1f;
- if(blda > 16)
- blda = 16;
- bldb = v >> 8 & 0x1f;
- if(bldb > 16)
- bldb = 16;
- break;
- case BLDY*2:
- bldy = v & 0x1f;
- if(bldy > 16)
- bldy = 16;
- break;
- case BG2XL*2: bgst[2].rpx0 = bgst[2].rpx0 & 0xffff0000 | v; break;
- case BG2XH*2: bgst[2].rpx0 = bgst[2].rpx0 & 0xffff | (s32int)(v << 20) >> 4; break;
- case BG2YL*2: bgst[2].rpy0 = bgst[2].rpy0 & 0xffff0000 | v; break;
- case BG2YH*2: bgst[2].rpy0 = bgst[2].rpy0 & 0xffff | (s32int)(v << 20) >> 4; break;
- case BG3XL*2: bgst[3].rpx0 = bgst[3].rpx0 & 0xffff0000 | v; break;
- case BG3XH*2: bgst[3].rpx0 = bgst[3].rpx0 & 0xffff | (s32int)(v << 20) >> 4; break;
- case BG3YL*2: bgst[3].rpy0 = bgst[3].rpy0 & 0xffff0000 | v; break;
- case BG3YH*2: bgst[3].rpy0 = bgst[3].rpy0 & 0xffff | (s32int)(v << 20) >> 4; break;
- }
-}
--- a/sys/src/games/md/vdp.c
+++ /dev/null
@@ -1,378 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-u16int vdpstat = 0x3400;
-int vdpx, vdpy, vdpyy, frame, intla;
-u16int hctr;
-static int xmax, xdisp;
-static int sx, snx, col, pri, lum;
-enum { DARK, NORM, BRIGHT };
-enum { ymax = 262, yvbl = 234 };
-
-void
-vdpmode(void)
-{
- if((reg[MODE4] & WIDE) != 0){
- xmax = 406;
- xdisp = 320;
- }else{
- xdisp = 256;
- xmax = 342;
- }
- intla = (reg[MODE4] & 6) == 6;
-}
-
-static void
-pixeldraw(int x, int y, int v)
-{
- u32int *p;
- union { u32int l; u8int b[4]; } u;
-
- u.b[0] = v >> 16;
- u.b[1] = v >> 8;
- u.b[2] = v;
- u.b[3] = 0;
- *((u32int *)pic + (x + y * 320)) = u.l;
-}
-
-static u32int
-shade(u32int v, int l)
-{
- if(l == 1)
- return v;
- if(l == 2)
- return v << 1 & 0xefefef;
- return v >> 1 & 0xf7f7f7;
-}
-
-static void
-pixel(int v, int p)
-{
- if(p >= pri){
- col = v;
- pri = p;
- }
-}
-
-struct pctxt {
- u8int ws, w, hs, h;
- u16int tx, ty;
- u8int tnx, tny;
- u16int t;
- u32int c;
-} pctxt[3];
-int lwin, rwin;
-
-static void
-tile(struct pctxt *p)
-{
- u16int a;
- int y;
-
- switch(p - pctxt){
- default: a = (reg[PANT] & 0x38) << 9; break;
- case 1: a = (reg[PBNT] & 7) << 12; break;
- case 2: a = (reg[PWNT] & 0x3e) << 9; break;
- }
- a += p->ty << p->ws;
- a += p->tx;
- p->t = vram[a];
- y = p->tny;
- if(intla){
- if((p->t & 0x1000) != 0)
- y = 15 - y;
- a = (p->t & 0x7ff) << 5 | y << 1;
- }else{
- if((p->t & 0x1000) != 0)
- y = 7 - y;
- a = (p->t & 0x7ff) << 4 | y << 1;
- }
- p->c = vram[a] << 16 | vram[a+1];
-}
-
-static void
-planeinit(void)
-{
- static int szs[] = {5, 6, 6, 7};
- int v, a, i;
- struct pctxt *p;
-
- pctxt[0].hs = pctxt[1].hs = szs[reg[PLSIZ] >> 4 & 3];
- pctxt[0].ws = pctxt[1].ws = szs[reg[PLSIZ] & 3];
- pctxt[2].ws = (reg[MODE4] & WIDE) != 0 ? 6 : 5;
- pctxt[2].hs = 5;
- for(i = 0; i <= 2; i++){
- pctxt[i].h = 1<<pctxt[i].hs;
- pctxt[i].w = 1<<pctxt[i].ws;
- }
- a = reg[HORSCR] << 9 & 0x7fff;
- switch(reg[MODE3] & 3){
- case 1: a += vdpy << 1 & 0xe; break;
- case 2: a += vdpy << 1 & 0xff0; break;
- case 3: a += vdpy << 1 & 0xffe; break;
- }
- for(i = 0; i < 2; i++){
- p = pctxt + i;
- v = -(vram[a + i] & 0x3ff);
- p->tnx = v & 7;
- p->tx = v >> 3 & pctxt[i].w - 1;
- if(intla){
- v = vsram[i] + vdpyy;
- p->tny = v & 15;
- p->ty = v >> 4 & pctxt[i].h - 1;
- }else{
- v = vsram[i] + vdpy;
- p->tny = v & 7;
- p->ty = v >> 3 & pctxt[i].h - 1;
- }
- tile(p);
- if(p->tnx != 0)
- if((p->t & 0x800) != 0)
- p->c >>= p->tnx << 2;
- else
- p->c <<= p->tnx << 2;
- }
- sx = 0;
- snx = 0;
- v = reg[WINV] << 3 & 0xf8;
- if((reg[WINV] & 0x80) != 0 ? vdpy < v : vdpy >= v){
- lwin = 0;
- rwin = reg[WINH] << 4 & 0x1f0;
- if((reg[WINH] & 0x80) != 0){
- lwin = rwin;
- rwin = 320;
- }
- }else{
- lwin = 0;
- rwin = 320;
- }
- if(rwin > lwin){
- p = pctxt + 2;
- p->tx = lwin >> 3 & pctxt[2].w - 1;
- p->tnx = lwin & 7;
- p->tny = vdpy & 7;
- p->ty = vdpy >> 3 & pctxt[2].h - 1;
- tile(p);
- }
-}
-
-static void
-plane(int n, int vis)
-{
- struct pctxt *p;
- u8int v, pr;
-
- p = pctxt + n;
- if((p->t & 0x800) != 0){
- v = p->c & 15;
- p->c >>= 4;
- }else{
- v = p->c >> 28;
- p->c <<= 4;
- }
- if(vis != 0){
- if(v != 0){
- v |= p->t >> 9 & 48;
- pr = 2 - (n & 1) + (p->t >> 13 & 4);
- pixel(v, pr);
- }
- lum |= p->t >> 15;
- }
- if(++p->tnx == 8){
- p->tnx = 0;
- if(++p->tx == p->w)
- p->tx = 0;
- tile(pctxt + n);
- }
-}
-
-static void
-planes(void)
-{
- int i, w;
- u16int v;
-
- if((reg[MODE3] & 4) != 0 && ++snx == 16){
- snx = 0;
- sx++;
- for(i = 0; i < 2; i++){
- v = vsram[sx + i] + vdpy;
- pctxt[i].tny = v & 7;
- pctxt[i].ty = v >> 3 & pctxt[i].h - 1;
- }
- }
- w = vdpx < rwin && vdpx >= lwin;
- plane(0, !w);
- plane(1, 1);
- if(w)
- plane(2, 1);
-}
-
-static struct sprite {
- u16int y, x;
- u8int w, h;
- u16int t;
- u32int c[4];
-} spr[21], *lsp;
-
-static void
-spritesinit(void)
-{
- u16int t, *p, dy, c;
- u32int v;
- int i, ns, np, nt;
- struct sprite *q;
-
- t = (reg[SPRTAB] << 8 & 0x7f00);
- p = vram + t;
- q = spr;
- ns = (reg[MODE4] & WIDE) != 0 ? 20 : 16;
- np = 0;
- nt = 0;
- do{
- if(intla){
- q->y = (p[0] & 0x3ff) - 256;
- q->h = (p[1] >> 8 & 3) + 1 << 4;
- dy = vdpyy - q->y;
- }else{
- q->y = (p[0] & 0x3ff) - 128;
- q->h = (p[1] >> 8 & 3) + 1 << 3;
- dy = vdpy - q->y;
- }
- if(dy >= q->h)
- continue;
- q->t = p[2];
- if((q->t & 0x1000) != 0)
- dy = q->h + ~dy;
- q->x = (p[3] & 0x3ff) - 128;
- if(q->x == 0xff80)
- break;
- q->w = (p[1] >> 10 & 3) + 1 << 3;
- c = ((q->t & 0x7ff) << 4+intla) + (dy << 1);
- for(i = 0; i < q->w >> 3 && np < xdisp; i++){
- v = vram[c] << 16 | vram[(u16int)(c+1)];
- c += q->h << 1;
- if((q->t & 0x800) != 0)
- q->c[(q->w >> 3) - 1 - i] = v;
- else
- q->c[i] = v;
- np += 8;
- }
- if((u16int)-q->x < q->w){
- i = -(s16int)q->x;
- if((q->t & 0x800) != 0)
- q->c[i>>3] >>= (i & 7) << 2;
- else
- q->c[i>>3] <<= (i & 7) << 2;
- }
- if(++q == spr + ns || np >= xdisp){
- vdpstat |= STATOVR;
- break;
- }
- }while(p = vram + (u16int)(t + ((p[1] & 0x7f) << 2)), p - vram != t && ++nt < 80);
- lsp = q;
-}
-
-static void
-sprites(void)
-{
- struct sprite *p;
- u16int dx;
- int v, col, set;
- u32int *c;
-
- set = 0;
- col = 0;
- for(p = spr; p < lsp; p++){
- dx = vdpx - p->x;
- if(dx >= p->w)
- continue;
- c = p->c + (dx >> 3);
- if((p->t & 0x800) != 0){
- v = *c & 15;
- *c >>= 4;
- }else{
- v = *c >> 28;
- *c <<= 4;
- }
- if(v != 0)
- if(set != 0)
- vdpstat |= STATCOLL;
- else{
- set = 1 | p->t & 0x8000;
- col = p->t >> 9 & 48 | v;
- }
- }
- if(set)
- if((reg[MODE4] & SHI) != 0)
- if((col & 0xfe) == 0x3e)
- lum = col & 1;
- else{
- pixel(col, set >> 13 | 2);
- if((col & 0xf) == 0xe)
- lum = 1;
- else
- lum |= set >> 15;
- }
- else
- pixel(col, set >> 13 | 2);
-}
-
-void
-vdpstep(void)
-{
- u32int v;
-
- if(vdpx == 0){
- planeinit();
- spritesinit();
- }
- if(vdpx < 320 && vdpy < 224)
- if(vdpx < xdisp){
- col = reg[BGCOL] & 0x3f;
- pri = 0;
- lum = 0;
- planes();
- sprites();
- if((reg[MODE2] & 0x40) != 0 && (vdpx >= 8 || (reg[MODE1] & 0x20) == 0)){
- v = cramc[col];
- if((reg[MODE4] & SHI) != 0)
- v = shade(v, lum);
- pixeldraw(vdpx, vdpy, v);
- }else
- pixeldraw(vdpx, vdpy, 0);
- }else
- pixeldraw(vdpx, vdpy, 0xcccccc);
- if(++vdpx >= xmax){
- z80irq = 0;
- vdpx = 0;
- if(++vdpy >= ymax){
- vdpy = 0;
- irq &= ~INTVBL;
- vdpstat ^= STATFR;
- vdpstat &= ~(STATINT | STATVBL | STATOVR | STATCOLL);
- flush();
- }
- if(intla)
- vdpyy = vdpy << 1 | frame;
- if(vdpy == 0 || vdpy >= 225)
- hctr = reg[HORCTR];
- else
- if(hctr-- == 0){
- if((reg[MODE1] & IE1) != 0)
- irq |= INTHOR;
- hctr = reg[HORCTR];
- }
- if(vdpy == yvbl){
- vdpstat |= STATVBL | STATINT;
- frame ^= 1;
- z80irq = 1;
- if((reg[MODE2] & IE0) != 0)
- irq |= INTVBL;
- }
- }
-}
--- a/sys/src/games/nes/ppu.c
+++ /dev/null
@@ -1,280 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <draw.h>
-#include <mouse.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int ppuy, ppux, odd;
-
-static void
-pixel(int x, int y, int val, int back)
-{
- union { u8int c[4]; u32int l; } u;
- static u8int palred[64] = {
- 0x7C, 0x00, 0x00, 0x44, 0x94, 0xA8, 0xA8, 0x88,
- 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xBC, 0x00, 0x00, 0x68, 0xD8, 0xE4, 0xF8, 0xE4,
- 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xF8, 0x3C, 0x68, 0x98, 0xF8, 0xF8, 0xF8, 0xFC,
- 0xF8, 0xB8, 0x58, 0x58, 0x00, 0x78, 0x00, 0x00,
- 0xFC, 0xA4, 0xB8, 0xD8, 0xF8, 0xF8, 0xF0, 0xFC,
- 0xF8, 0xD8, 0xB8, 0xB8, 0x00, 0xF8, 0x00, 0x00,
- };
- static u8int palgreen[64] = {
- 0x7C, 0x00, 0x00, 0x28, 0x00, 0x00, 0x10, 0x14,
- 0x30, 0x78, 0x68, 0x58, 0x40, 0x00, 0x00, 0x00,
- 0xBC, 0x78, 0x58, 0x44, 0x00, 0x00, 0x38, 0x5C,
- 0x7C, 0xB8, 0xA8, 0xA8, 0x88, 0x00, 0x00, 0x00,
- 0xF8, 0xBC, 0x88, 0x78, 0x78, 0x58, 0x78, 0xA0,
- 0xB8, 0xF8, 0xD8, 0xF8, 0xE8, 0x78, 0x00, 0x00,
- 0xFC, 0xE4, 0xB8, 0xB8, 0xB8, 0xA4, 0xD0, 0xE0,
- 0xD8, 0xF8, 0xF8, 0xF8, 0xFC, 0xD8, 0x00, 0x00,
- };
- static u8int palblue[64] = {
- 0x7C, 0xFC, 0xBC, 0xBC, 0x84, 0x20, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
- 0xBC, 0xF8, 0xF8, 0xFC, 0xCC, 0x58, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x44, 0x88, 0x00, 0x00, 0x00,
- 0xF8, 0xFC, 0xFC, 0xF8, 0xF8, 0x98, 0x58, 0x44,
- 0x00, 0x18, 0x54, 0x98, 0xD8, 0x78, 0x00, 0x00,
- 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xC0, 0xB0, 0xA8,
- 0x78, 0x78, 0xB8, 0xD8, 0xFC, 0xF8, 0x00, 0x00,
- };
-
- u.c[0] = palblue[val];
- u.c[1] = palgreen[val];
- u.c[2] = palred[val];
- u.c[3] = back ? 0 : 0xFF;
- *((u32int *)pic + y * 256 + x) = u.l;
-}
-
-static int
-iscolor(int x, int y)
-{
- return pic[4 * (y * 256 + x) + 3] != 0;
-}
-
-static int
-pal(int c, int a, int spr)
-{
- if(c == 0)
- return ppuread(0x3F00);
- return ppuread(0x3F00 | ((a&3)<<2) | (c & 3) | (spr << 4));
-}
-
-static void
-incppuy(void)
-{
- int y;
-
- if((ppuv & 0x7000) != 0x7000){
- ppuv += 0x1000;
- return;
- }
- y = (ppuv >> 5) & 31;
- if(y++ == 29){
- y = 0;
- ppuv ^= 0x800;
- }
- ppuv = (ppuv & 0x0C1F) | ((y & 31) << 5);
-}
-
-static void
-drawbg(void)
-{
- static int t;
- u8int c, a;
- static u8int nr1, nr2, na;
- static u16int r1, r2, a1, a2;
-
- if(ppux >= 2 && ppux <= 257 || ppux >= 322 && ppux <= 337){
- c = (r1 >> (15-ppusx)) & 1 | (r2 >> (14-ppusx)) & 2;
- if(ppuy < 240 && ppux <= 257){
- a = (a1 >> (15-ppusx)) & 1 | (a2 >> (14-ppusx)) & 2;
- pixel(ppux-2, ppuy, pal(c, a, 0), c == 0);
- }
- r1 <<= 1;
- r2 <<= 1;
- a1 <<= 1;
- a2 <<= 1;
- }
- if(ppux >= 256 && ppux <= 320){
- if(ppux == 256)
- incppuy();
- if(ppux == 257)
- ppuv = (ppuv & 0x7BE0) | (pput & 0x041F);
- return;
- }
- switch(ppux & 7){
- case 0:
- if(ppux != 0){
- if((ppuv & 0x1f) == 0x1f){
- ppuv &= ~0x1f;
- ppuv ^= 0x400;
- }else
- ppuv++;
- }
- break;
- case 1:
- t = ppuread(0x2000 | ppuv & 0x0FFF);
- if(ppux != 1){
- r1 |= nr1;
- r2 |= nr2;
- if(na & 1)
- a1 |= 0xff;
- if(na & 2)
- a2 |= 0xff;
- }
- break;
- case 3:
- na = ppuread(0x23C0 | ppuv & 0x0C00 | ((ppuv & 0x0380) >> 4) | ((ppuv & 0x001C) >> 2));
- if((ppuv & 0x0002) != 0) na >>= 2;
- if((ppuv & 0x0040) != 0) na >>= 4;
- break;
- case 5:
- nr1 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12);
- break;
- case 7:
- nr2 = ppuread(((mem[PPUCTRL] & BGTABLE) << 8) | t << 4 | ppuv >> 12 | 8);
- break;
- }
-}
-
-static void
-drawsprites(int show)
-{
- uchar *p;
- int big, dx, dy, i, x, cc, pri;
- u8int r1, r2, c;
- static int n, m, nz, s0, t0;
- static struct { u8int x, a; u16int t; } s[8], *sp;
- static struct { u8int x, a, r1, r2; } t[8];
-
- big = (mem[PPUCTRL] & BIGSPRITE) != 0;
- if(ppux == 65){
- s0 = 0;
- for(p = oam, sp = s, n = 0; p < oam + sizeof(oam); p += 4){
- if((dy = p[0]) >= 0xEF)
- continue;
- dy = ppuy - dy;
- if(dy < 0 || dy >= (big ? 16 : 8))
- continue;
- if(p == oam)
- s0 = 1;
- sp->t = p[1];
- sp->a = p[2];
- sp->x = p[3];
- if((sp->a & (1<<7)) != 0)
- dy = (big ? 15 : 7) - dy;
- if(big){
- sp->t |= (sp->t & 1) << 8;
- if(dy >= 8){
- sp->t |= 1;
- dy -= 8;
- }else
- sp->t &= 0x1fe;
- }else
- sp->t |= (mem[PPUCTRL] & SPRTABLE) << 5;
- sp->t = sp->t << 4 | dy;
- sp++;
- if(++n == 8)
- break;
- }
- }
- if(ppux >= 2 && ppux <= 257 && m > 0){
- x = ppux - 2;
- dx = x - t[0].x;
- if(t0 && dx >= 0 && dx < 8 && ppux != 257){
- if((nz & 1) != 0 && iscolor(x, ppuy) && show)
- mem[PPUSTATUS] |= SPRITE0HIT;
- nz >>= 1;
- }
- cc = -1;
- pri = 0;
- for(i = m - 1; i >= 0; i--){
- dx = x - t[i].x;
- if(dx < 0 || dx > 7)
- continue;
- c = (t[i].r1 & 1) | (t[i].r2 & 1) << 1;
- if(c != 0){
- cc = pal(c, t[i].a & 3, 1);
- pri = (t[i].a & (1<<5)) == 0;
- }
- t[i].r1 >>= 1;
- t[i].r2 >>= 1;
- }
- if(cc != -1 && show && (pri || !iscolor(x, ppuy)))
- pixel(x, ppuy, cc, 0);
- }
- if(ppux == 257){
- for(i = 0; i < n; i++){
- r1 = ppuread(s[i].t);
- r2 = ppuread(s[i].t | 8);
- if((s[i].a & (1<<6)) == 0){
- r1 = ((r1 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
- r2 = ((r2 * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
- }
- t[i].x = s[i].x;
- t[i].a = s[i].a;
- t[i].r1 = r1;
- t[i].r2 = r2;
- }
- m = n;
- nz = t[0].r1 | t[0].r2;
- t0 = s0;
- }
-}
-
-static void
-flush(void)
-{
- flushmouse(1);
- flushscreen();
- flushaudio(audioout);
-}
-
-void
-ppustep(void)
-{
- extern int nmi;
- int mask;
-
- if(ppuy < 240 || ppuy == 261){
- mask = mem[PPUMASK];
- if((mask & BGDISP) != 0)
- drawbg();
- if((((mask & BGDISP) == 0 && ppux <= 257 || ppux < 10 && (mask & BG8DISP) == 0) && ppux >= 2) && ppuy != 261)
- pixel(ppux - 2, ppuy, ppuread(0x3F00), 1);
- if((mask & SPRITEDISP) != 0 && ppuy != 261)
- drawsprites(ppux >= 10 || (mask & SPRITE8DISP) != 0);
- if(ppux == 240 && (mask & SPRITEDISP) != 0)
- mapper[map](SCAN, 0);
- if(ppuy == 261){
- if(ppux == 1)
- mem[PPUSTATUS] &= ~(PPUVBLANK|SPRITE0HIT);
- else if(ppux >= 280 && ppux <= 304 && (mask & BGDISP) != 0)
- ppuv = (pput & 0x7BE0) | (ppuv & 0x041F);
- }
- }else if(ppuy == 241){
- if(ppux == 1){
- mem[PPUSTATUS] |= PPUVBLANK;
- if((mem[PPUCTRL] & PPUNMI) != 0)
- nmi = 2;
- flush();
- }
- }
- ppux++;
- if(ppux > 340){
- ppux = 0;
- ppuy++;
- if(ppuy > 261){
- ppuy = 0;
- if(odd && (mem[PPUMASK] & (BGDISP | SPRITEDISP)) != 0)
- ppux++;
- odd ^= 1;
- }
- }
-}
--- a/sys/src/games/snes/ppu.c
+++ /dev/null
@@ -1,936 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../eui.h"
-#include "dat.h"
-#include "fns.h"
-
-int ppux, ppuy, rx;
-static u8int mode, bright, pixelpri[2], hires;
-static u32int pixelcol[2];
-u16int vtime = 0x1ff, htime = 0x1ff, subcolor;
-u16int hofs[5], vofs[5];
-s16int m7[6];
-
-enum {
- M7A,
- M7B,
- M7C,
- M7D,
- M7X,
- M7Y
-};
-
-enum { OBJ = 4, COL = 5, OBJNC = 8 };
-
-static u16int
-darken(u16int v)
-{
- u8int r, g, b;
-
- r = (v >> 10) & 0x1f;
- g = (v >> 5) & 0x1f;
- b = v & 0x1f;
- r = r * bright / 15;
- g = g * bright / 15;
- b = b * bright / 15;
- return r << 10 | g << 5 | b;
-}
-
-static void
-pixeldraw(int x, int y, u16int v, int s)
-{
- union { u16int w; u8int b[2]; } u;
-
- if(bright != 0xf && s >= 0)
- v = darken(v);
- u.b[0] = v;
- u.b[1] = v >> 8;
- *((u16int *)pic + (x + y * 256)) = u.w; /* FIXME: some weird shit in the diff */
-}
-
-static int
-window(int n)
-{
- int a, w1, w2;
-
- a = reg[0x2123 + (n >> 1)];
- if((n & 1) != 0)
- a >>= 4;
- if((a & (WIN1|WIN2)) == 0)
- return 0;
- w1 = rx >= reg[0x2126] && rx <= reg[0x2127];
- w2 = rx >= reg[0x2128] && rx <= reg[0x2129];
- if((a & INVW1) != 0)
- w1 = !w1;
- if((a & INVW2) != 0)
- w2 = !w2;
- if((a & (WIN1|WIN2)) != (WIN1|WIN2))
- return (a & WIN1) != 0 ? w1 : w2;
- a = reg[0x212a + (n >> 2)] >> ((n & 3) << 1);
- switch(a & 3){
- case 1: return w1 & w2;
- case 2: return w1 ^ w2;
- case 3: return w1 ^ w2 ^ 1;
- }
- return w1 | w2;
-}
-
-static void
-npixel(int n, int v, int pri)
-{
- int a;
-
- a = 1<<n;
- if((reg[TM] & a) != 0 && pri > pixelpri[0] && ((reg[TMW] & a) == 0 || !window(n))){
- pixelcol[0] = v;
- pixelpri[0] = pri;
- }
- if((reg[TS] & a) != 0 && pri > pixelpri[1] && ((reg[TSW] & a) == 0 || !window(n))){
- pixelcol[1] = v;
- pixelpri[1] = pri;
- }
-}
-
-static void
-spixel(int n, int v, int pri)
-{
- int a;
-
- a = 1<<n;
- if((reg[TS] & a) != 0 && pri > 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<<n;
- if((reg[TM] & a) != 0 && pri > 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)
-{
- int a;
- u16int ta;
- u16int t;
-
- a = reg[0x2107 + n];
- ta = ((a & ~3) << 9) + ((tx & 0x1f) << 1) + ((ty & 0x1f) << 6);
- if((a & 1) != 0)
- ta += (tx & 0x20) << 6;
- if((a & 2) != 0)
- ta += (ty & 0x20) << (6 + (a & 1));
- t = vram[ta++];
- return t | vram[ta] << 8;
-}
-
-static void
-chr(int n, int nb, int w, int h, u16int t, int x, int y, u32int c[])
-{
- u16int a;
-
- if(w == 16)
- t += (x >> 3 ^ t >> 14) & 1;
- if(h == 16){
- if(y >= 8){
- t += (~t >> 11) & 16;
- y -= 8;
- }else
- t += (t >> 11) & 16;
- }
- if((t & 0x8000) != 0)
- y = 7 - y;
- a = reg[0x210b + (n >> 1)];
- if((n & 1) != 0)
- a >>= 4;
- else
- a &= 0xf;
- a = (a << 13) + (t & 0x3ff) * 8 * nb + y * 2;
- c[0] = vram[a++];
- c[0] |= vram[a] << 8;
- if(nb != 2){
- a += 15;
- c[0] |= vram[a++] << 16;
- c[0] |= vram[a] << 24;
- if(nb == 8){
- a += 15;
- c[1] = vram[a++];
- c[1] |= vram[a] << 8;
- a += 15;
- c[1] |= vram[a++] << 16;
- c[1] |= vram[a] << 24;
- }
- }
-}
-
-static int
-palette(int n, int p)
-{
- switch(mode){
- case 0:
- return p << 2 | n << 5;
- case 1:
- if(n >= 2)
- return p << 2;
- case 2:
- case 6:
- return p << 4;
- case 5:
- if(n == 0)
- return p << 4;
- return p << 2;
- case 3:
- if(n != 0)
- return p << 4;
- case 4:
- if(n != 0)
- return p << 2;
- if((reg[CGWSEL] & DIRCOL) != 0)
- return 0x10000;
- }
- return 0;
-}
-
-static void
-shift(u32int *c, int nb, int n, int d)
-{
- if(d){
- c[0] >>= n;
- if(nb == 8)
- c[1] >>= n;
- }else{
- c[0] <<= n;
- if(nb == 8)
- c[1] <<= n;
- }
-}
-
-static u8int
-bgpixel(u32int *c, int nb, int d)
-{
- u8int v;
-
- if(d){
- v = c[0] & 1 | c[0] >> 7 & 2;
- if(nb != 2){
- v |= c[0] >> 14 & 4 | c[0] >> 21 & 8;
- if(nb == 8){
- v |= c[1] << 4 & 16 | c[1] >> 3 & 32 | c[1] >> 10 & 64 | c[1] >> 17 & 128;
- c[1] >>= 1;
- }
- }
- c[0] >>= 1;
- }else{
- v = c[0] >> 7 & 1 | c[0] >> 14 & 2;
- if(nb != 2){
- v |= c[0] >> 21 & 4 | c[0] >> 28 & 8;
- if(nb == 8){
- v |= c[1] >> 3 & 16 | c[1] >> 10 & 32 | c[1] >> 17 & 64 | c[1] >> 24 & 128;
- c[1] <<= 1;
- }
- }
- c[0] <<= 1;
- }
- return v;
-}
-
-static struct bgctxt {
- 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
-bginit(int n, int nb, int prilo, int prihi)
-{
- struct bgctxt *p;
- int sx, sy;
-
- p = bgctxts + n;
- p->hsh = ((reg[BGMODE] & (1<<(4+n))) != 0) ? 4 : 3;
- p->wsh = mode >= 5 ? 4 : p->hsh;
- p->h = 1<<p->hsh;
- p->w = 1<<p->wsh;
- p->nb = nb;
- p->pri[0] = prilo;
- p->pri[1] = prihi;
- sx = hofs[n];
- sy = vofs[n] + ppuy;
- if(reg[MOSAIC] != 0 && (reg[MOSAIC] & (1<<n)) != 0){
- p->msz = (reg[MOSAIC] >> 4) + 1;
- if(p->msz != 1){
- sx -= p->mx = sx % p->msz;
- sy -= sy % p->msz;
- }
- }else
- p->msz = 1;
- if(mode >= 5)
- sx <<= 1;
-redo:
- 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->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);
- if(p->msz != 1 && p->mx != 0 && sx % p->msz == 0){
- p->mv = bgpixel(p->c, nb, p->t & 0x4000);
- if(p->tnx + p->mx >= 8){
- sx += p->mx;
- goto redo;
- }else if(p->mx > 1)
- shift(p->c, nb, p->mx - 1, p->t & 0x4000);
- }
-
-}
-
-static void
-bg(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;
- 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->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<<p->wsh;
- p->h = 1<<p->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 {
- int x, y, x0, y0;
- u8int msz, mx, mv;
-} b7[2];
-
-void
-calc7(void)
-{
- s16int t;
-
- if((reg[0x2105] & 7) != 7)
- return;
- t = hofs[4] - m7[M7X];
- if((t & 0x2000) != 0)
- t |= ~0x3ff;
- else
- t &= 0x3ff;
- b7->x0 = (t * m7[M7A]) & ~63;
- b7->y0 = (t * m7[M7C]) & ~63;
- t = vofs[4] - m7[M7Y];
- if((t & 0x2000) != 0)
- t |= ~0x3ff;
- else
- t &= 0x3ff;
- b7->x0 += (t * m7[M7B]) & ~63;
- b7->y0 += (t * m7[M7D]) & ~63;
- b7->x0 += m7[M7X] << 8;
- b7->y0 += m7[M7Y] << 8;
-}
-
-static void
-bg7init(int n)
-{
- u8int m, y;
- struct bg7ctxt *p;
-
- p = b7 + n;
- m = reg[M7SEL];
- y = ppuy;
- p->msz = 1;
- if((reg[MOSAIC] & 1) != 0){
- p->msz = (reg[MOSAIC] >> 4) + 1;
- if(p->msz != 1)
- y -= y % p->msz;
- }
- if(n == 1)
- if((reg[MOSAIC] & 2) != 0)
- p->msz = (reg[MOSAIC] >> 4) + 1;
- else
- p->msz = 1;
- if((m & 2) != 0)
- y = 255 - y;
- p->x = b7->x0 + ((m7[M7B] * y) & ~63);
- p->y = b7->y0 + ((m7[M7D] * y) & ~63);
- if((m & 1) != 0){
- p->x += 255 * m7[M7A];
- p->y += 255 * m7[M7C];
- }
-}
-
-static void
-bg7(int n)
-{
- u16int x, y;
- u8int m, v, t;
- struct bg7ctxt *p;
-
- p = b7 + n;
- m = reg[M7SEL];
- x = p->x >> 8;
- y = p->y >> 8;
- if((m & 0x80) == 0){
- x &= 1023;
- y &= 1023;
- }else if(x > 1023 || y > 1023){
- if((m & 0x40) != 0){
- t = 0;
- goto lookup;
- }
- v = 0;
- goto end;
- }
- t = vram[x >> 2 & 0xfe | y << 5 & 0x7f00];
-lookup:
- v = vram[t << 7 | y << 4 & 0x70 | x << 1 & 0x0e | 1];
-end:
- if(p->msz != 1){
- if(p->mx == 0)
- p->mv = v;
- else
- v = p->mv;
- if(++p->mx == p->msz)
- p->mx = 0;
- }
- if(n == 1){
- if((v & 0x7f) != 0)
- if((v & 0x80) != 0)
- pixel(1, v & 0x7f, 0x71);
- else
- pixel(1, v, 0x11);
- }else if(v != 0)
- pixel(0, v, 0x40);
- if((m & 1) != 0){
- p->x -= m7[M7A];
- p->y -= m7[M7C];
- }else{
- p->x += m7[M7A];
- p->y += m7[M7C];
- }
-}
-
-static void
-bgsinit(void)
-{
- static int bitch[8];
-
- pixel = npixel;
- switch(mode){
- case 0:
- bginit(0, 2, 0x80, 0xb0);
- bginit(1, 2, 0x71, 0xa1);
- bginit(2, 2, 0x22, 0x52);
- bginit(3, 2, 0x13, 0x43);
- break;
- case 1:
- bginit(0, 4, 0x80, 0xb0);
- bginit(1, 4, 0x71, 0xa1);
- bginit(2, 2, 0x12, (reg[BGMODE] & 8) != 0 ? 0xd2 : 0x42);
- break;
- 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].w = bgctxts[1].w = 0;
- if(bitch[mode]++ == 0)
- print("bg mode %d not implemented\n", mode);
- }
-}
-
-static void
-bgs(void)
-{
- switch(mode){
- case 0:
- bg(0);
- bg(1);
- bg(2);
- bg(3);
- break;
- case 1:
- bg(0);
- bg(1);
- 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)
- bg7(1);
- break;
- }
-}
-
-static void
-sprites(void)
-{
- static struct {
- short x;
- u8int y, i, c, sx, sy;
- u16int t0, t1;
- } s[32], *sp;
- static struct {
- short x;
- u8int sx, i, c, pal, pri;
- u32int *ch;
- } t[32], *tp;
- static u32int ch[34];
- static u8int *p, q;
- static int n, m;
- static int *sz;
- static int szs[] = {
- 8, 8, 16, 16, 8, 8, 32, 32,
- 8, 8, 64, 64, 16, 16, 32, 32,
- 16, 16, 64, 64, 32, 32, 64, 64,
- 16, 32, 32, 64, 16, 32, 32, 32
- };
- static u16int base[2];
- u8int dy, v, col, pri0, pri1, prio;
- u16int a;
- u32int w, *cp;
- int i, nt, dx;
-
- if(rx == 0){
- n = 0;
- sp = s;
- sz = szs + ((reg[OBSEL] & 0xe0) >> 3);
- base[0] = (reg[OBSEL] & 0x07) << 14;
- base[1] = base[0] + (((reg[OBSEL] & 0x18) + 8) << 10);
- }
- if((rx & 1) == 0){
- p = oam + 2 * rx;
- if(p[1] == 0xf0)
- goto nope;
- q = (oam[512 + (rx >> 3)] >> (rx & 6)) & 3;
- dy = ppuy - p[1];
- sp->sx = sz[q & 2];
- sp->sy = sz[(q & 2) + 1];
- if(dy >= sp->sy)
- goto nope;
- sp->x = p[0];
- if((q & 1) != 0)
- sp->x |= 0xff00;
- if(sp->x <= -(short)sp->sx && sp->x != -256)
- goto nope;
- if(n == 32){
- reg[0x213e] |= 0x40;
- goto nope;
- }
- sp->i = rx >> 1;
- sp->y = p[1];
- sp->c = p[3];
- sp->t0 = p[2] << 5;
- sp->t1 = base[sp->c & 1];
- sp++;
- n++;
- }
-nope:
- if(ppuy != 0){
- col = 0;
- pri0 = 0;
- pri1 = 128;
- if((reg[OAMADDH] & 0x80) != 0)
- prio = oamaddr >> 2;
- else
- prio = 0;
- for(i = 0, tp = t; i < m; i++, tp++){
- dx = rx - tp->x;
- if(dx < 0 || dx >= tp->sx)
- continue;
- w = *tp->ch;
- if((tp->c & 0x40) != 0){
- v = w & 1 | w >> 7 & 2 | w >> 14 & 4 | w >> 21 & 8;
- *tp->ch = w >> 1;
- }else{
- v = w >> 7 & 1 | w >> 14 & 2 | w >> 21 & 4 | w >> 28 & 8;
- *tp->ch = w << 1;
- }
- if((dx & 7) == 7)
- tp->ch++;
- nt = (tp->i - prio) & 0x7f;
- if(v != 0 && nt < pri1){
- col = tp->pal + v;
- pri0 = tp->pri;
- pri1 = nt;
- }
- }
- if(col > 0)
- pixel(OBJ, col, pri0);
- }
- if(rx == 255){
- cp = ch;
- m = n;
- for(sp = s + n - 1, tp = t + n - 1; sp >= s; sp--, tp--){
- tp->x = sp->x;
- tp->sx = 0;
- tp->c = sp->c;
- tp->pal = 0x80 | sp->c << 3 & 0x70;
- tp->pri = 3 * (0x10 + (sp->c & 0x30));
- if((tp->c & 8) != 0)
- tp->pri |= OBJ;
- else
- tp->pri |= OBJNC;
- tp->ch = cp;
- tp->i = sp->i;
- nt = sp->sx >> 3;
- dy = ppuy - sp->y;
- if((sp->c & 0x80) != 0)
- dy = sp->sy - 1 - dy;
- 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++){
- if(cp < ch + nelem(ch)){
- w = vram[sp->t1 | (a -= 16) & 0x1fff] << 16;
- w |= vram[sp->t1 | (a + 1) & 0x1fff] << 24;
- w |= vram[sp->t1 | (a -= 16) & 0x1fff] << 0;
- w |= vram[sp->t1 | (a + 1) & 0x1fff] << 8;
- *cp++ = w;
- tp->sx += 8;
- }else
- reg[0x213e] |= 0x80;
- }
- }else
- for(i = 0; i < nt; i++){
- if(cp < ch + nelem(ch)){
- w = vram[sp->t1 | a & 0x1fff];
- w |= vram[sp->t1 | ++a & 0x1fff] << 8;
- w |= vram[sp->t1 | (a += 15) & 0x1fff] << 16;
- w |= vram[sp->t1 | ++a & 0x1fff] << 24;
- *cp++ = w;
- tp->sx += 8;
- a += 15;
- }else
- reg[0x213e] |= 0x80;
- }
- if(sp->x < 0 && (i = (-sp->x) & 7) != 0)
- if((sp->c & 0x40) != 0)
- *tp->ch >>= i;
- else
- *tp->ch <<= i;
- }
- }
-}
-
-static u16int
-colormath(int n)
-{
- u16int v, w, r, g, b;
- u8int m, m2, div;
- int cw;
-
- m = reg[CGWSEL];
- m2 = reg[CGADSUB];
- cw = -1;
- switch(m >> 6){
- default: v = 1; break;
- case 1: v = cw = window(COL); break;
- case 2: v = !(cw = window(COL)); break;
- case 3: v = 0; break;
- }
- if(v){
- if((pixelcol[n] & 0x10000) != 0)
- v = pixelcol[n];
- else
- v = cgram[pixelcol[n] & 0xff];
- }
- if((m2 & (1 << (pixelpri[n] & 0xf))) == 0)
- return v;
- switch((m >> 4) & 3){
- case 0: break;
- case 1: if(cw < 0) cw = window(COL); if(!cw) return v; break;
- case 2: if(cw < 0) cw = window(COL); if(cw) return v; break;
- default: return v;
- }
- div = (m2 & 0x40) != 0;
- if((m & 2) != 0){
- if((pixelcol[1-n] & 0x10000) != 0)
- w = pixelcol[1-n];
- else
- w = cgram[pixelcol[1-n] & 0xff];
- div = div && (pixelpri[1-n] & 0xf) != COL;
- }else
- w = subcolor;
- if((m2 & 0x80) != 0){
- r = (v & 0x7c00) - (w & 0x7c00);
- g = (v & 0x03e0) - (w & 0x03e0);
- b = (v & 0x001f) - (w & 0x001f);
- if(r > 0x7c00) r = 0;
- if(g > 0x03e0) g = 0;
- if(b > 0x001f) b = 0;
- if(div){
- r = (r >> 1) & 0xfc00;
- g = (g >> 1) & 0xffe0;
- b >>= 1;
- }
- return r | g | b;
- }else{
- r = (v & 0x7c00) + (w & 0x7c00);
- g = (v & 0x03e0) + (w & 0x03e0);
- b = (v & 0x001f) + (w & 0x001f);
- if(div){
- r = (r >> 1) & 0xfc00;
- g = (g >> 1) & 0xffe0;
- b >>= 1;
- }
- if(r > 0x7c00) r = 0x7c00;
- if(g > 0x03e0) g = 0x03e0;
- if(b > 0x001f) b = 0x001f;
- return r | g | b;
- }
-}
-
-void
-ppustep(void)
-{
- int yvbl;
-
- 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){
- rx = ppux - XLEFT;
- if(ppuy < yvbl && (reg[INIDISP] & 0x80) == 0){
- pixelcol[0] = 0;
- pixelpri[0] = COL;
- pixelcol[1] = 0x10000 | subcolor;
- pixelpri[1] = COL;
- bgs();
- sprites();
- if(ppuy != 0)
- 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 ? 0x6739 : 0, -1);
- }
-
- if(ppux == 134)
- cpupause = 1;
- if(ppux == 0x116 && ppuy <= yvbl)
- hdma |= reg[0x420c];
- 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();
- }
- if(ppuy < yvbl)
- bgsinit();
- if(ppuy == yvbl){
- 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);
- reg[0x4218] = keylatch >> 16;
- reg[0x4219] = keylatch >> 24;
- keylatch = keylatch << 16 | 0xffff;
- }
- }
- if((reg[NMITIMEN] & (HCNTIRQ|VCNTIRQ)) == VCNTIRQ && vtime == ppuy)
- irq |= IRQPPU;
- }
-}
--
⑨