static int HighCacheB[41+1];\r
static int HighPreSpr[80*2+1]; // slightly preprocessed sprites\r
\r
+unsigned int VdpSATCache[128]; // VDP sprite cache (1st 32 sprite attr bits)\r
+\r
#define LF_PLANE_1 (1 << 0)\r
#define LF_SH (1 << 1) // must be = 2\r
#define LF_FORCE (1 << 2)\r
// Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size\r
// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8\r
\r
-static NOINLINE void PrepareSprites(int full)\r
+static NOINLINE void PrepareSprites(int max_lines)\r
{\r
const struct PicoVideo *pvid=&Pico.video;\r
const struct PicoEState *est=&Pico.est;\r
int u,link=0,sh;\r
int table=0;\r
int *pd = HighPreSpr;\r
- int max_lines = 224, max_sprites = 80, max_width = 328;\r
+ int max_sprites = 80, max_width = 328;\r
int max_line_sprites = 20; // 20 sprites, 40 tiles\r
\r
if (!(Pico.video.reg[12]&1))\r
if (PicoIn.opt & POPT_DIS_SPRITE_LIM)\r
max_line_sprites = MAX_LINE_SPRITES;\r
\r
- if (pvid->reg[1]&8) max_lines = 240;\r
sh = Pico.video.reg[0xC]&8; // shadow/hilight?\r
\r
table=pvid->reg[5]&0x7f;\r
if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode\r
table<<=8; // Get sprite table address/2\r
\r
- if (!full)\r
- {\r
- int pack;\r
- // updates: tilecode, sx\r
- for (u=0; u < max_sprites && link < max_sprites && (pack = *pd); u++, pd+=2)\r
- {\r
- unsigned int *sprite;\r
- int code2, sx, sy, height, width;\r
-\r
- sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite\r
+ for (u = est->DrawScanline; u < max_lines; u++)\r
+ *((int *)&HighLnSpr[u][0]) = 0;\r
\r
- // parse sprite info\r
- code2 = sprite[1];\r
- sx = (code2>>16)&0x1ff;\r
- sx -= 0x78; // Get X coordinate + 8\r
- sy = (pack << 16) >> 16;\r
- height = (pack >> 24) & 0xf;\r
- width = (pack >> 28);\r
+ for (u = 0; u < max_sprites && link < max_sprites; u++)\r
+ {\r
+ unsigned int *sprite;\r
+ int code, code2, sx, sy, hv, height, width;\r
\r
- if (sy < max_lines &&\r
- sy + (height<<3) > est->DrawScanline) // sprite onscreen (y)?\r
- {\r
- int y = (sy >= est->DrawScanline) ? sy : est->DrawScanline;\r
- int entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);\r
- for (; y < sy + (height<<3) && y < max_lines; y++)\r
- {\r
- int i, cnt;\r
- cnt = HighLnSpr[y][0];\r
- if (HighLnSpr[y][3] >= max_line_sprites) continue; // sprite limit?\r
-\r
- for (i = 0; i < cnt; i++)\r
- if (((HighLnSpr[y][4+i] ^ entry) & 0x7f) == 0) goto found;\r
-\r
- // this sprite was previously missing\r
- HighLnSpr[y][3] ++;\r
- if (sx > -24 && sx < max_width) { // onscreen x\r
- HighLnSpr[y][4+cnt] = entry; // XXX wrong sequence?\r
- HighLnSpr[y][5+cnt] = width; // XXX should count tiles for limit\r
- HighLnSpr[y][0] = cnt + 1;\r
- }\r
-found:;\r
- if (entry & 0x80)\r
- HighLnSpr[y][1] |= SPRL_HAVE_HI;\r
- else HighLnSpr[y][1] |= SPRL_HAVE_LO;\r
- }\r
- }\r
+ sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite\r
\r
- code2 &= ~0xfe000000;\r
- code2 -= 0x00780000; // Get X coordinate + 8 in upper 16 bits\r
- pd[1] = code2;\r
+ // parse sprite info. the 1st half comes from the VDPs internal cache,\r
+ // the 2nd half is read from VRAM\r
+ code = VdpSATCache[link]; // normally but not always equal to sprite[0]\r
+ sy = (code&0x1ff)-0x80;\r
+ hv = (code>>24)&0xf;\r
+ height = (hv&3)+1;\r
+ width = (hv>>2)+1;\r
\r
- // Find next sprite\r
- link=(sprite[0]>>16)&0x7f;\r
- if (!link) break; // End of sprites\r
- }\r
- }\r
- else\r
- {\r
- for (u = 0; u < max_lines; u++)\r
- *((int *)&HighLnSpr[u][0]) = 0;\r
+ code2 = sprite[1];\r
+ sx = (code2>>16)&0x1ff;\r
+ sx -= 0x78; // Get X coordinate + 8\r
\r
- for (u = 0; u < max_sprites && link < max_sprites; u++)\r
+ if (sy < max_lines && sy + (height<<3) >= est->DrawScanline) // sprite onscreen (y)?\r
{\r
- unsigned int *sprite;\r
- int code, code2, sx, sy, hv, height, width;\r
+ int entry, y, w, sx_min, onscr_x, maybe_op = 0;\r
\r
- sprite=(unsigned int *)(PicoMem.vram+((table+(link<<2))&0x7ffc)); // Find sprite\r
+ sx_min = 8-(width<<3);\r
+ onscr_x = sx_min < sx && sx < max_width;\r
+ if (sh && (code2 & 0x6000) == 0x6000)\r
+ maybe_op = SPRL_MAY_HAVE_OP;\r
\r
- // parse sprite info\r
- code = sprite[0];\r
- sy = (code&0x1ff)-0x80;\r
- hv = (code>>24)&0xf;\r
- height = (hv&3)+1;\r
-\r
- width = (hv>>2)+1;\r
- code2 = sprite[1];\r
- sx = (code2>>16)&0x1ff;\r
- sx -= 0x78; // Get X coordinate + 8\r
-\r
- if (sy < max_lines && sy + (height<<3) > est->DrawScanline) // sprite onscreen (y)?\r
+ entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);\r
+ y = (sy >= est->DrawScanline) ? sy : est->DrawScanline;\r
+ for (; y < sy + (height<<3) && y < max_lines; y++)\r
{\r
- int entry, y, w, sx_min, onscr_x, maybe_op = 0;\r
-\r
- sx_min = 8-(width<<3);\r
- onscr_x = sx_min < sx && sx < max_width;\r
- if (sh && (code2 & 0x6000) == 0x6000)\r
- maybe_op = SPRL_MAY_HAVE_OP;\r
-\r
- entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80);\r
- y = (sy >= est->DrawScanline) ? sy : est->DrawScanline;\r
- for (; y < sy + (height<<3) && y < max_lines; y++)\r
- {\r
- unsigned char *p = &HighLnSpr[y][0];\r
- int cnt = p[0];\r
- if (p[3] >= max_line_sprites) continue; // sprite limit?\r
- if ((p[1] & SPRL_MASKED) && !(entry & 0x80)) continue; // masked?\r
-\r
- w = width;\r
- if (p[2] + width > max_line_sprites*2) { // tile limit?\r
- if (y+1 < 240) HighLnSpr[y+1][1] |= SPRL_TILE_OVFL;\r
- if (p[2] >= max_line_sprites*2) continue;\r
- w = max_line_sprites*2 - p[2];\r
- }\r
- p[2] += w;\r
- p[3] ++;\r
-\r
- if (sx == -0x78) {\r
- if (p[1] & (SPRL_HAVE_X|SPRL_TILE_OVFL))\r
- p[1] |= SPRL_MASKED; // masked, no more low sprites for this line\r
- if (!(p[1] & SPRL_HAVE_X) && cnt == 0)\r
- p[1] |= SPRL_HAVE_MASK0; // 1st sprite is masking\r
- } else\r
- p[1] |= SPRL_HAVE_X;\r
-\r
- if (!onscr_x) continue; // offscreen x\r
-\r
- p[4+cnt] = entry;\r
- p[5+cnt] = w; // width clipped by tile limit for sprite renderer\r
- p[0] = cnt + 1;\r
- p[1] |= (entry & 0x80) ? SPRL_HAVE_HI : SPRL_HAVE_LO;\r
- p[1] |= maybe_op; // there might be op sprites on this line\r
- if (cnt > 0 && (code2 & 0x8000) && !(p[4+cnt-1]&0x80))\r
- p[1] |= SPRL_LO_ABOVE_HI;\r
+ unsigned char *p = &HighLnSpr[y][0];\r
+ int cnt = p[0];\r
+ if (p[3] >= max_line_sprites) continue; // sprite limit?\r
+ if ((p[1] & SPRL_MASKED) && !(entry & 0x80)) continue; // masked?\r
+\r
+ w = width;\r
+ if (p[2] + width > max_line_sprites*2) { // tile limit?\r
+ if (y+1 < 240) HighLnSpr[y+1][1] |= SPRL_TILE_OVFL;\r
+ if (p[2] >= max_line_sprites*2) continue;\r
+ w = max_line_sprites*2 - p[2];\r
}\r
+ p[2] += w;\r
+ p[3] ++;\r
+\r
+ if (sx == -0x78) {\r
+ if (p[1] & (SPRL_HAVE_X|SPRL_TILE_OVFL))\r
+ p[1] |= SPRL_MASKED; // masked, no more low sprites for this line\r
+ if (!(p[1] & SPRL_HAVE_X) && cnt == 0)\r
+ p[1] |= SPRL_HAVE_MASK0; // 1st sprite is masking\r
+ } else\r
+ p[1] |= SPRL_HAVE_X;\r
+\r
+ if (!onscr_x) continue; // offscreen x\r
+\r
+ p[4+cnt] = entry;\r
+ p[5+cnt] = w; // width clipped by tile limit for sprite renderer\r
+ p[0] = cnt + 1;\r
+ p[1] |= (entry & 0x80) ? SPRL_HAVE_HI : SPRL_HAVE_LO;\r
+ p[1] |= maybe_op; // there might be op sprites on this line\r
+ if (cnt > 0 && (code2 & 0x8000) && !(p[4+cnt-1]&0x80))\r
+ p[1] |= SPRL_LO_ABOVE_HI;\r
}\r
+ }\r
\r
- *pd++ = (width<<28)|(height<<24)|(hv<<16)|((unsigned short)sy);\r
- *pd++ = (sx<<16)|((unsigned short)code2);\r
+ *pd++ = (width<<28)|(height<<24)|(hv<<16)|((unsigned short)sy);\r
+ *pd++ = (sx<<16)|((unsigned short)code2);\r
\r
- // Find next sprite\r
- link=(code>>16)&0x7f;\r
- if (!link) break; // End of sprites\r
- }\r
- *pd = 0;\r
+ // Find next sprite\r
+ link=(code>>16)&0x7f;\r
+ if (!link) break; // End of sprites\r
+ }\r
+ *pd = 0;\r
\r
#if 0\r
- for (u = 0; u < max_lines; u++)\r
- {\r
- int y;\r
- printf("c%03i: f %x c %2i/%2i w %2i: ", u, HighLnSpr[u][1],\r
- HighLnSpr[u][0], HighLnSpr[u][3], HighLnSpr[u][2]);\r
- for (y = 0; y < HighLnSpr[u][0]; y++)\r
- printf(" %i", HighLnSpr[u][y+4]);\r
- printf("\n");\r
- }\r
-#endif\r
+ for (u = 0; u < max_lines; u++)\r
+ {\r
+ int y;\r
+ printf("c%03i: f %x c %2i/%2i w %2i: ", u, HighLnSpr[u][1],\r
+ HighLnSpr[u][0], HighLnSpr[u][3], HighLnSpr[u][2]);\r
+ for (y = 0; y < HighLnSpr[u][0]; y++)\r
+ printf(" %i", HighLnSpr[u][y+4]);\r
+ printf("\n");\r
}\r
+#endif\r
}\r
\r
#ifndef _ASM_DRAW_C\r
int win=0, edge=0, hvwind=0, lflags;\r
int maxw, maxcells;\r
\r
- if (est->rendstatus & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)) {\r
- // elprintf(EL_STATUS, "PrepareSprites(%i)", (est->rendstatus>>4)&1);\r
- PrepareSprites(est->rendstatus & PDRAW_DIRTY_SPRITES);\r
- est->rendstatus &= ~(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES);\r
- }\r
+ if (!(est->DrawScanline & 15) ||\r
+ (est->rendstatus & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)))\r
+ PrepareSprites((est->DrawScanline+16) & ~15);\r
\r
+ est->rendstatus &= ~(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES);\r
est->rendstatus &= ~(PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO);\r
\r
if (pvid->reg[12]&1) {\r
\r
if (PicoIn.opt & POPT_ALT_RENDERER)\r
return;\r
-\r
- PrepareSprites(1);\r
}\r
\r
static void DrawBlankedLine(int line, int offs, int sh, int bgc)\r
extern const unsigned char hcounts_40[];\r
\r
static int blankline; // display disabled for this line\r
+static unsigned sat; // VRAM addr of sprite attribute table\r
+static int satxbits; // index bits in SAT address\r
\r
int (*PicoDmaHook)(unsigned int source, int len, unsigned short **base, unsigned int *mask) = NULL;\r
\r
static __inline void AutoIncrement(void)\r
{\r
Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]);\r
+ if (Pico.video.addr < Pico.video.reg[0xf]) Pico.video.addr_u ^= 1;\r
}\r
\r
-static NOINLINE unsigned int VideoWrite128(u32 a, u16 d)\r
+static __inline void UpdateSAT(u32 a, u32 d)\r
+{\r
+ Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
+ if (!((a^sat) >> satxbits) && !(a & 4)) {\r
+ int num = (a >> 3) & 0x7f;\r
+ ((u16 *)&VdpSATCache[num])[(a&3) >> 1] = d;\r
+ }\r
+}\r
+\r
+static NOINLINE void VideoWriteVRAM128(u32 a, u16 d)\r
{\r
// nasty\r
- a = ((a & 2) >> 1) | ((a & 0x400) >> 9) | (a & 0x3FC) | ((a & 0x1F800) >> 1);\r
- ((u8 *)PicoMem.vram)[a] = d;\r
- return a;\r
+ u32 b = ((a & 2) >> 1) | ((a & 0x400) >> 9) | (a & 0x3FC) | ((a & 0x1F800) >> 1);\r
+\r
+ ((u8 *)PicoMem.vram)[b] = d;\r
+ if (!((u16)(b^sat) >> satxbits))\r
+ Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
+\r
+ if (!((u16)(a^sat) >> satxbits))\r
+ UpdateSAT(a, d);\r
+}\r
+\r
+static void VideoWriteVRAM(u32 a, u16 d)\r
+{\r
+ PicoMem.vram [(u16)a >> 1] = d;\r
+\r
+ if (!((u16)(a^sat) >> satxbits))\r
+ UpdateSAT(a, d);\r
}\r
\r
static void VideoWrite(u16 d)\r
{\r
case 1: if (a & 1)\r
d = (u16)((d << 8) | (d >> 8));\r
- PicoMem.vram [(a >> 1) & 0x7fff] = d;\r
- if ((unsigned)(a - ((Pico.video.reg[5]&0x7f) << 9)) < 0x400)\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
+ a |= Pico.video.addr_u << 16;\r
+ VideoWriteVRAM(a, d);\r
break;\r
case 3: if (PicoMem.cram [(a >> 1) & 0x3f] != d) Pico.m.dirtyPal = 1;\r
- PicoMem.cram [(a >> 1) & 0x3f] = d; break;\r
- case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d; break;\r
- case 0x81: if (a & 1)\r
- d = (u16)((d << 8) | (d >> 8));\r
+ PicoMem.cram [(a >> 1) & 0x3f] = d & 0xeee; break;\r
+ case 5: PicoMem.vsram[(a >> 1) & 0x3f] = d & 0x7ff; break;\r
+ case 0x81:\r
a |= Pico.video.addr_u << 16;\r
- a = VideoWrite128(a, d);\r
- if ((unsigned)(a - ((Pico.video.reg[5]&0x7f) << 9)) < 0x400)\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
+ VideoWriteVRAM128(a, d);\r
break;\r
//default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, Pico.video.type); break;\r
}\r
switch (Pico.video.type)\r
{\r
case 0: d=PicoMem.vram [a & 0x7fff]; break;\r
- case 8: d=(PicoMem.cram [a & 0x003f] & 0x0eee) | (d & ~0x0eee); break;\r
+ case 8: d=PicoMem.cram [a & 0x003f] | (d & ~0x0eee); break;\r
+\r
case 4: if ((a & 0x3f) >= 0x28) a = 0;\r
- d=(PicoMem.vsram [a & 0x003f] & 0x07ff) | (d & ~0x07ff); break;\r
+ d=PicoMem.vsram [a & 0x003f] | (d & ~0x07ff); break;\r
case 12:a=PicoMem.vram [a & 0x7fff]; if (Pico.video.addr&1) a >>= 8;\r
d=(a & 0x00ff) | (d & ~0x00ff); break;\r
default:elprintf(EL_ANOMALY, "VDP read with bad type %i", Pico.video.type); break;\r
static void DmaSlow(int len, unsigned int source)\r
{\r
u32 inc = Pico.video.reg[0xf];\r
- u32 a = Pico.video.addr;\r
+ u32 a = Pico.video.addr | (Pico.video.addr_u << 16);\r
u16 *r, *base = NULL;\r
u32 mask = 0x1ffff;\r
\r
switch (Pico.video.type)\r
{\r
case 1: // vram\r
+#if 0\r
r = PicoMem.vram;\r
- if (inc == 2 && !(a & 1) && a + len * 2 < 0x10000\r
- && !(((source + len - 1) ^ source) & ~mask))\r
+ if (inc == 2 && !(a & 1) && (a >> 16) == ((a + len*2) >> 16) &&\r
+ (source & ~mask) == ((source + len-1) & ~mask) &&\r
+ (a << 16 >= (sat+0x280) << 16 || (a + len*2) << 16 <= sat << 16))\r
{\r
// most used DMA mode\r
memcpy((char *)r + a, base + (source & mask), len * 2);\r
a += len * 2;\r
}\r
else\r
+#endif\r
{\r
for(; len; len--)\r
{\r
u16 d = base[source++ & mask];\r
if(a & 1) d=(d<<8)|(d>>8);\r
- r[a >> 1] = d;\r
+ VideoWriteVRAM(a, d);\r
// AutoIncrement\r
- a = (u16)(a + inc);\r
+ a = (a+inc) & ~0x20000;\r
}\r
}\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
break;\r
\r
case 3: // cram\r
r = PicoMem.cram;\r
for (; len; len--)\r
{\r
- r[(a / 2) & 0x3f] = base[source++ & mask];\r
+ r[(a / 2) & 0x3f] = base[source++ & mask] & 0xeee;\r
// AutoIncrement\r
- a += inc;\r
+ a = (a+inc) & ~0x20000;\r
}\r
break;\r
\r
r = PicoMem.vsram;\r
for (; len; len--)\r
{\r
- r[(a / 2) & 0x3f] = base[source++ & mask];\r
+ r[(a / 2) & 0x3f] = base[source++ & mask] & 0x7ff;\r
// AutoIncrement\r
- a += inc;\r
+ a = (a+inc) & ~0x20000;\r
}\r
break;\r
\r
case 0x81: // vram 128k\r
- a |= Pico.video.addr_u << 16;\r
for(; len; len--)\r
{\r
- VideoWrite128(a, base[source++ & mask]);\r
+ u16 d = base[source++ & mask];\r
+ VideoWriteVRAM128(a, d);\r
// AutoIncrement\r
- a = (a + inc) & 0x1ffff;\r
+ a = (a+inc) & ~0x20000;\r
}\r
- Pico.video.addr_u = a >> 16;\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
break;\r
\r
default:\r
break;\r
}\r
// remember addr\r
- Pico.video.addr=(u16)a;\r
+ Pico.video.addr = a;\r
+ Pico.video.addr_u = a >> 16;\r
}\r
\r
static void DmaCopy(int len)\r
{\r
- u16 a = Pico.video.addr;\r
+ u32 a = Pico.video.addr | (Pico.video.addr_u << 16);\r
u8 *vr = (u8 *)PicoMem.vram;\r
u8 inc = Pico.video.reg[0xf];\r
int source;\r
source =Pico.video.reg[0x15];\r
source|=Pico.video.reg[0x16]<<8;\r
\r
- // XXX implement VRAM 128k? Is this even working?\r
+ // XXX implement VRAM 128k? Is this even working? count still in bytes?\r
for (; len; len--)\r
{\r
- vr[a] = vr[source++ & 0xffff];\r
+ vr[(u16)a] = vr[(u16)(source++)];\r
+ if (!((u16)(a^sat) >> satxbits))\r
+ UpdateSAT(a, ((u16 *)vr)[(u16)a >> 1]);\r
// AutoIncrement\r
- a=(u16)(a+inc);\r
+ a = (a+inc) & ~0x20000;\r
}\r
// remember addr\r
- Pico.video.addr=a;\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
+ Pico.video.addr = a;\r
+ Pico.video.addr_u = a >> 16;\r
}\r
\r
static NOINLINE void DmaFill(int data)\r
{\r
- u16 a = Pico.video.addr;\r
+ u32 a = Pico.video.addr | (Pico.video.addr_u << 16);\r
u8 *vr = (u8 *)PicoMem.vram;\r
u8 high = (u8)(data >> 8);\r
u8 inc = Pico.video.reg[0xf];\r
for (l = len; l; l--) {\r
// Write upper byte to adjacent address\r
// (here we are byteswapped, so address is already 'adjacent')\r
- vr[a] = high;\r
+ vr[(u16)a] = high;\r
+ if (!((u16)(a^sat) >> satxbits))\r
+ UpdateSAT(a, ((u16 *)vr)[(u16)a >> 1]);\r
\r
// Increment address register\r
- a = (u16)(a + inc);\r
+ a = (a+inc) & ~0x20000;\r
}\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
break;\r
case 3: // cram\r
Pico.m.dirtyPal = 1;\r
+ data &= 0xeee;\r
for (l = len; l; l--) {\r
PicoMem.cram[(a/2) & 0x3f] = data;\r
\r
// Increment address register\r
- a += inc;\r
+ a = (a+inc) & ~0x20000;\r
}\r
break;\r
case 5: { // vsram\r
+ data &= 0x7ff;\r
for (l = len; l; l--) {\r
PicoMem.vsram[(a/2) & 0x3f] = data;\r
\r
// Increment address register\r
- a += inc;\r
+ a = (a+inc) & ~0x20000;\r
}\r
break;\r
}\r
case 0x81: // vram 128k\r
for (l = len; l; l--) {\r
- VideoWrite128(a, data);\r
+ VideoWriteVRAM128(a, data);\r
\r
// Increment address register\r
- a = (a + inc) & 0x1ffff;\r
+ a = (a+inc) & ~0x20000;\r
}\r
- Pico.video.addr_u = a >> 16;\r
- Pico.est.rendstatus |= PDRAW_DIRTY_SPRITES;\r
break;\r
default:\r
a += len * inc;\r
\r
// remember addr\r
Pico.video.addr = a;\r
+ Pico.video.addr_u = a >> 16;\r
// register update\r
Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0;\r
source = Pico.video.reg[0x15];\r
pvid->status |= ((d >> 3) ^ SR_VB) & SR_VB; // forced blanking\r
goto update_irq;\r
case 0x05:\r
- //elprintf(EL_STATUS, "spritep moved to %04x", (unsigned)(Pico.video.reg[5]&0x7f) << 9);\r
+ case 0x06:\r
if (d^dold) Pico.est.rendstatus |= PDRAW_SPRITES_MOVED;\r
break;\r
case 0x0c:\r
// renderers should update their palettes if sh/hi mode is changed\r
if ((d^dold)&8) Pico.m.dirtyPal = 1;\r
break;\r
+ default:\r
+ return;\r
}\r
+ sat = ((pvid->reg[5]&0x7f) << 9) | ((pvid->reg[6]&0x20) << 11);\r
+ satxbits = 9;\r
+ if (Pico.video.reg[12]&1)\r
+ sat &= ~0x200, satxbits = 10; // H40, zero lowest SAT bit\r
+ //elprintf(EL_STATUS, "spritep moved to %04x", sat);\r
return;\r
\r
update_irq:\r
Pico.m.dma_xfers = 0;\r
}\r
\r
+ sat = ((pv->reg[5]&0x7f) << 9) | ((pv->reg[6]&0x20) << 11);\r
+ satxbits = 9;\r
+ if (pv->reg[12]&1)\r
+ sat &= ~0x200, satxbits = 10; // H40, zero lowest SAT bit\r
+\r
// rebuild SAT cache XXX wrong since cache and memory can differ\r
for (l = 0; l < 80; l++) {\r
*((u16 *)VdpSATCache + 2*l ) = PicoMem.vram[(sat>>1) + l*4 ];\r