// XXX: no proper handling of 32col mode..
if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0 && // 32x not blanking
(Pico.video.reg[12] & 1) && // 40col mode
- (PicoDrawMask & PDRAW_32X_ON))
+ (!(Pico.video.debug_p & PVD_KILL_32X)))
{
int md_bg = Pico.video.reg[7] & 0x3f;
if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 0 || // 32x blanking
// XXX: how is 32col mode hadled by real hardware?
!(Pico.video.reg[12] & 1) || // 32col mode
- !(PicoDrawMask & PDRAW_32X_ON))
+ (Pico.video.debug_p & PVD_KILL_32X))
{
return;
}
struct PicoVideo *pvid=&Pico.video;
int table=0,u,link=0,*sprite=0,*fsprite,oldsprite[2];
int x,y,max_sprites = 80, oldcol, oldreg;
+ unsigned char olddbg;
if (!(pvid->reg[12]&1))
max_sprites = 64;
fsprite[1] = (sprite[1] & ~0x01ff8000) | 0x800000;
oldreg = pvid->reg[7];
oldcol = Pico.cram[0];
+ olddbg = pvid->debug_p;
pvid->reg[7] = 0;
Pico.cram[0] = 0;
- PicoDrawMask = PDRAW_SPRITES_LOW_ON;
+ pvid->debug_p = PVD_KILL_A | PVD_KILL_B;
PicoFrameFull();
for (y = 0; y < 8*4; y++)
fsprite[1] = oldsprite[1];
pvid->reg[7] = oldreg;
Pico.cram[0] = oldcol;
- PicoDrawMask = -1;
+ pvid->debug_p = olddbg;
}
#define dump_ram(ram,fname) \
static int HighCacheB[41+1];\r
static int HighPreSpr[80*2+1]; // slightly preprocessed sprites\r
\r
+#define LF_PLANE_1 (1 << 0)\r
+#define LF_SH (1 << 1) // must be = 2\r
+#define LF_FORCE (1 << 2)\r
+\r
#define SPRL_HAVE_HI 0x80 // have hi priority sprites\r
#define SPRL_HAVE_LO 0x40 // *lo*\r
#define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line\r
\r
int rendstatus_old;\r
int rendlines;\r
-int PicoDrawMask = -1;\r
\r
static int skip_next_line=0;\r
\r
-//unsigned short ppt[] = { 0x0f11, 0x0ff1, 0x01f1, 0x011f, 0x01ff, 0x0f1f, 0x0f0e, 0x0e7c };\r
-\r
struct TileStrip\r
{\r
int nametab; // Position in VRAM of name table (for this tile line)\r
TileNormMaker(TileNormAS_onlymark, pix_sh_as_onlymark)\r
TileFlipMaker(TileFlipAS_onlymark, pix_sh_as_onlymark)\r
\r
+// mark pixel as sprite pixel (AS)\r
+#define pix_and(x) \\r
+ pd[x] = (pd[x] & 0xc0) | (pd[x] & (pal | t))\r
+\r
+TileNormMaker(TileNorm_and, pix_and)\r
+TileFlipMaker(TileFlip_and, pix_and)\r
\r
// --------------------------------------------\r
\r
#ifndef _ASM_DRAW_C\r
-static void DrawStrip(struct TileStrip *ts, int plane_sh, int cellskip)\r
+static void DrawStrip(struct TileStrip *ts, int lflags, int cellskip)\r
{\r
int tilex,dx,ty,code=0,addr=0,cells;\r
int oldcode=-1,blank=-1; // The tile we know is blank\r
int pal=0,sh;\r
\r
// Draw tiles across screen:\r
- sh=(plane_sh<<5)&0x40;\r
+ sh = (lflags & LF_SH) << 5; // 0x40\r
tilex=((-ts->hscroll)>>3)+cellskip;\r
ty=(ts->line&7)<<1; // Y-Offset into tile\r
dx=((ts->hscroll-1)&7)+1;\r
if(dx != 8) cells++; // have hscroll, need to draw 1 cell more\r
dx+=cellskip<<3;\r
\r
- for (; cells > 0; dx+=8,tilex++,cells--)\r
+ for (; cells > 0; dx+=8, tilex++, cells--)\r
{\r
unsigned int pack;\r
\r
- code=Pico.vram[ts->nametab+(tilex&ts->xmask)];\r
- if (code==blank) continue;\r
- if (code>>15) { // high priority tile\r
+ code = Pico.vram[ts->nametab + (tilex & ts->xmask)];\r
+ if (code == blank)\r
+ continue;\r
+ if ((code >> 15) | (lflags & LF_FORCE)) { // high priority tile\r
int cval = code | (dx<<16) | (ty<<25);\r
if(code&0x1000) cval^=7<<26;\r
*ts->hc++ = cval; // cache it\r
{\r
short blank=-1; // The tile we know is blank\r
while ((code=*hc++)) {\r
- if((short)code == blank) continue;\r
+ if (!(code & 0x8000) || (short)code == blank)\r
+ continue;\r
// Get tile address/2:\r
- addr=(code&0x7ff)<<4;\r
- addr+=(unsigned int)code>>25; // y offset into tile\r
+ addr = (code & 0x7ff) << 4;\r
+ addr += code >> 25; // y offset into tile\r
\r
pack = *(unsigned int *)(Pico.vram + addr);\r
if (!pack) {\r
}\r
#endif\r
\r
+static NOINLINE void DrawTilesFromCacheForced(const int *hc)\r
+{\r
+ int code, addr, dx;\r
+ unsigned int pack;\r
+ int pal;\r
+\r
+ // *ts->hc++ = code | (dx<<16) | (ty<<25);\r
+ while ((code = *hc++)) {\r
+ // Get tile address/2:\r
+ addr = (code & 0x7ff) << 4;\r
+ addr += (code >> 25) & 0x0e; // y offset into tile\r
+\r
+ dx = (code >> 16) & 0x1ff;\r
+ pal = ((code >> 9) & 0x30);\r
+ pack = *(unsigned int *)(Pico.vram + addr);\r
+\r
+ if (code & 0x0800) TileFlip_and(dx, pack, pal);\r
+ else TileNorm_and(dx, pack, pal);\r
+ }\r
+}\r
+\r
static void DrawSpriteInterlace(unsigned int *sprite)\r
{\r
int width=0,height=0;\r
}\r
\r
\r
-static void DrawAllSpritesInterlace(int pri, int sh)\r
+static NOINLINE void DrawAllSpritesInterlace(int pri, int sh)\r
{\r
struct PicoVideo *pvid=&Pico.video;\r
int i,u,table,link=0,sline=Pico.est.DrawScanline<<1;\r
struct PicoEState *est=&Pico.est;\r
unsigned char *sprited = &HighLnSpr[est->DrawScanline][0];\r
struct PicoVideo *pvid=&Pico.video;\r
- int win=0,edge=0,hvwind=0;\r
- int maxw,maxcells;\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
}\r
\r
/* - layer B low - */\r
- if (PicoDrawMask & PDRAW_LAYERB_ON)\r
- DrawLayer(1|(sh<<1), HighCacheB, 0, maxcells, est);\r
+ if (!(pvid->debug_p & PVD_KILL_B)) {\r
+ lflags = LF_PLANE_1 | (sh << 1);\r
+ if (pvid->debug_p & PVD_FORCE_B)\r
+ lflags |= LF_FORCE;\r
+ DrawLayer(lflags, HighCacheB, 0, maxcells, est);\r
+ }\r
/* - layer A low - */\r
- if (!(PicoDrawMask & PDRAW_LAYERA_ON));\r
+ lflags = 0 | (sh << 1);\r
+ if (pvid->debug_p & PVD_FORCE_A)\r
+ lflags |= LF_FORCE;\r
+ if (pvid->debug_p & PVD_KILL_A)\r
+ ;\r
else if (hvwind == 1)\r
DrawWindow(0, maxcells>>1, 0, sh, est);\r
else if (hvwind == 2) {\r
- DrawLayer(0|(sh<<1), HighCacheA, (win&0x80) ? 0 : edge<<1, (win&0x80) ? edge<<1 : maxcells, est);\r
- DrawWindow( (win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh, est);\r
- } else\r
- DrawLayer(0|(sh<<1), HighCacheA, 0, maxcells, est);\r
+ DrawLayer(lflags, HighCacheA, (win&0x80) ? 0 : edge<<1, (win&0x80) ? edge<<1 : maxcells, est);\r
+ DrawWindow( (win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh, est);\r
+ }\r
+ else\r
+ DrawLayer(lflags, HighCacheA, 0, maxcells, est);\r
/* - sprites low - */\r
- if (!(PicoDrawMask & PDRAW_SPRITES_LOW_ON));\r
+ if (pvid->debug_p & PVD_KILL_S_LO)\r
+ ;\r
else if (est->rendstatus & PDRAW_INTERLACE)\r
DrawAllSpritesInterlace(0, sh);\r
else if (sprited[1] & SPRL_HAVE_LO)\r
DrawAllSprites(sprited, 0, sh, est);\r
\r
/* - layer B hi - */\r
- if ((PicoDrawMask & PDRAW_LAYERB_ON) && HighCacheB[0])\r
+ if (!(pvid->debug_p & PVD_KILL_B) && HighCacheB[0])\r
DrawTilesFromCache(HighCacheB, sh, maxw, est);\r
/* - layer A hi - */\r
- if (!(PicoDrawMask & PDRAW_LAYERA_ON));\r
+ if (pvid->debug_p & PVD_KILL_A)\r
+ ;\r
else if (hvwind == 1)\r
DrawWindow(0, maxcells>>1, 1, sh, est);\r
else if (hvwind == 2) {\r
if (HighCacheA[0])\r
DrawTilesFromCache(HighCacheA, sh, maxw, est);\r
/* - sprites hi - */\r
- if (!(PicoDrawMask & PDRAW_SPRITES_HI_ON));\r
+ if (pvid->debug_p & PVD_KILL_S_HI)\r
+ ;\r
else if (est->rendstatus & PDRAW_INTERLACE)\r
DrawAllSpritesInterlace(1, sh);\r
// have sprites without layer pri bit ontop of sprites with that bit\r
else if (sprited[1] & SPRL_HAVE_HI)\r
DrawAllSprites(sprited, 1, 0, est);\r
\r
+ if (pvid->debug_p & PVD_FORCE_B)\r
+ DrawTilesFromCacheForced(HighCacheB);\r
+ else if (pvid->debug_p & PVD_FORCE_A)\r
+ DrawTilesFromCacheForced(HighCacheA);\r
+\r
#if 0\r
{\r
int *c, a, b;\r
return;\r
}\r
\r
+ if (Pico.video.debug_p & (PVD_FORCE_A | PVD_FORCE_B))\r
+ bgc = 0x3f;\r
+\r
// Draw screen:\r
BackFill(bgc, sh, &Pico.est);\r
if (Pico.video.reg[1]&0x40)\r
if (hvwin==1) { winend|=maxcolc<<16; planeend|=maxcolc<<16; }\r
\r
HighCache2A[1] = HighCache2B[1] = 0;\r
- if (PicoDrawMask & PDRAW_LAYERB_ON)\r
+ if (!(pvid->debug_p & PVD_KILL_B))\r
DrawLayerFull(1, HighCache2B, START_ROW, (maxcolc<<16)|END_ROW, est);\r
- if (PicoDrawMask & PDRAW_LAYERA_ON) switch (hvwin)\r
+ if (!(pvid->debug_p & PVD_KILL_A)) switch (hvwin)\r
{\r
case 4:\r
// fullscreen window\r
DrawLayerFull(0, HighCache2A, START_ROW, (maxcolc<<16)|END_ROW, est);\r
break;\r
}\r
- if (PicoDrawMask & PDRAW_SPRITES_LOW_ON)\r
+ if (!(pvid->debug_p & PVD_KILL_S_LO))\r
DrawAllSpritesFull(0, maxw);\r
\r
if (HighCache2B[1]) DrawTilesFromCacheF(HighCache2B, est);\r
if (HighCache2A[1]) DrawTilesFromCacheF(HighCache2A, est);\r
- if (PicoDrawMask & PDRAW_LAYERA_ON) switch (hvwin)\r
+ if (!(pvid->debug_p & PVD_KILL_A)) switch (hvwin)\r
{\r
case 4:\r
// fullscreen window\r
DrawWindowFull(winstart, winend, 1, est);\r
break;\r
}\r
- if (PicoDrawMask & PDRAW_SPRITES_HI_ON)\r
+ if (!(pvid->debug_p & PVD_KILL_S_HI))\r
DrawAllSpritesFull(1, maxw);\r
}\r
\r
@ int cells; // 0x14\r
@ };\r
\r
-@ void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells,\r
+@ void DrawLayer(int lflags, int *hcache, int cellskip, int maxcells,\r
@ struct PicoEState *est)\r
\r
.global DrawLayer\r
ldrb r7, [r11, #16] @ ??vv??hh\r
\r
mov r6, r1 @ hcache\r
- orr r9, r3, r0, lsl #30\r
- orr r9, r9, r2, lsl #8 @ r9=sh[31]|cellskip[15:8]|maxcells[7:0] (tmp)\r
+ orr r9, r3, r0, lsl #29 @ r9=force[31]|sh[30]|plane[29]\r
+ orr r9, r9, r2, lsl #8 @ |cellskip[15:8]|maxcells[7:0] (tmp)\r
\r
mov r1, r7, lsl #4\r
orr r1, r1, #0x00ff\r
and r1, r1, #7\r
add r7, r1, #1 @ r7=dx=((ts->hscroll-1)&7)+1\r
\r
- tst r9, #1<<31\r
+ movs r3, r9, lsl #1 @ (force[31]|sh[30]) << 1\r
mov r3, #0\r
- orrne r10,r10, #1<<23 @ r10=(cells<<24|sh<<23|hi_not_empty<<22|had_output<<21|ty)\r
- movne r3, #0x40 @ default to shadowed pal on sh mode\r
+ orrmi r10,r10, #1<<23 @ r10=cells[31:24]|sh[23]|hi_not_empty[22]\r
+ orrcs r10,r10, #1<<20 @ |had_output[21]|force[20]|ty[15:0]\r
+ movmi r3, #0x40 @ default to shadowed pal on sh mode\r
\r
cmp r7, #8\r
addne r10,r10, #0x01000000 @ we will loop cells+1 times if there is scroll\r
add r8, r8, #1\r
\r
tst r7, #0x8000\r
+ tsteq r10, #1<<20 @ force?\r
bne .DrawStrip_hiprio\r
\r
cmp r7, r9\r
orr r10, r10, #1<<22\r
\r
.DrawStrip_hiprio:\r
- tst r10, #0x00c00000\r
+ tst r10, #0x00d00000 @ sh[23]|hi_not_empty[22]|force[20]\r
beq .DrawStrip_hiprio_maybempt\r
sub r0, r1, r11\r
orr r7, r7, r0, lsl #16\r
bic r4, r1, #0xfe00\r
add r1, r11, r4 @ r1=pdest\r
\r
- mov r7, r6, lsl #16\r
+ movs r7, r6, lsl #16\r
+ bpl .dtfc_loop @ !(code & 0x8000)\r
cmp r5, r7, lsr #16\r
beq .dtfc_samecode @ if (code==prevcode)\r
\r
dx += cellskip << 3;
// low priority tiles
- if (PicoDrawMask & PDRAW_LAYERB_ON)
+ if (!(pv->debug_p & PVD_KILL_B))
draw_strip(nametab, dx, cells, tilex | 0x0000 | (ty << 16));
// sprites
- if (PicoDrawMask & PDRAW_SPRITES_LOW_ON)
+ if (!(pv->debug_p & PVD_KILL_S_LO))
draw_sprites(scanline);
// high priority tiles (use virtual layer switch just for fun)
- if (PicoDrawMask & PDRAW_LAYERA_ON)
+ if (!(pv->debug_p & PVD_KILL_A))
draw_strip(nametab, dx, cells, tilex | 0x1000 | (ty << 16));
if (pv->reg[0] & 0x20)
void vidConvCpyRGB565(void *to, void *from, int pixels);\r
#endif\r
void PicoDoHighPal555(int sh, int line, struct PicoEState *est);\r
-extern int PicoDrawMask;\r
-#define PDRAW_LAYERB_ON (1<<2)\r
-#define PDRAW_LAYERA_ON (1<<3)\r
-#define PDRAW_SPRITES_LOW_ON (1<<4)\r
-#define PDRAW_SPRITES_HI_ON (1<<7)\r
-#define PDRAW_32X_ON (1<<8)\r
// internals\r
#define PDRAW_SPRITES_MOVED (1<<0) // (asm)\r
#define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority\r
#define OSC_NTSC 53693100\r
#define OSC_PAL 53203424\r
\r
+#define PVD_KILL_A (1 << 0)\r
+#define PVD_KILL_B (1 << 1)\r
+#define PVD_KILL_S_LO (1 << 2)\r
+#define PVD_KILL_S_HI (1 << 3)\r
+#define PVD_KILL_32X (1 << 4)\r
+#define PVD_FORCE_A (1 << 5)\r
+#define PVD_FORCE_B (1 << 6)\r
+#define PVD_FORCE_S (1 << 7)\r
+\r
struct PicoVideo\r
{\r
unsigned char reg[0x20];\r
unsigned char pending_ints; // pending interrupts: ??VH????\r
signed char lwrite_cnt; // VDP write count during active display line\r
unsigned short v_counter; // V-counter\r
+ unsigned short debug; // raw debug register\r
+ unsigned char debug_p; // ... parsed: PVD_*\r
unsigned char addr_u;\r
- unsigned char pad[0x0f];\r
+ unsigned char pad[0x0c];\r
};\r
\r
struct PicoMisc\r
// elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d);\r
a&=0x1c;\r
\r
- if (a==0x00) // Data port 0 or 2\r
+ switch (a)\r
{\r
+ case 0x00: // Data port 0 or 2\r
// try avoiding the sync..\r
if (Pico.m.scanline < 224 && (pvid->reg[1]&0x40) &&\r
!(!pvid->pending &&\r
if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2)\r
DmaFill(d);\r
\r
- return;\r
- }\r
+ break;\r
\r
- if (a==0x04) // Control (command) port 4 or 6\r
- {\r
+ case 0x04: // Control (command) port 4 or 6\r
if (pvid->pending)\r
{\r
// Low word of command:\r
pvid->pending=1;\r
}\r
}\r
+ break;\r
+\r
+ // case 0x08: // 08 0a - HV counter - lock up\r
+ // case 0x0c: // 0c 0e - HV counter - lock up\r
+ // case 0x10: // 10 12 - PSG - handled by caller\r
+ // case 0x14: // 14 16 - PSG - handled by caller\r
+ // case 0x18: // 18 1a - no effect?\r
+ case 0x1c: // 1c 1e - debug\r
+ pvid->debug = d;\r
+ pvid->debug_p = 0;\r
+ if (d & (1 << 6)) {\r
+ pvid->debug_p |= PVD_KILL_A | PVD_KILL_B;\r
+ pvid->debug_p |= PVD_KILL_S_LO | PVD_KILL_S_HI;\r
+ }\r
+ switch ((d >> 7) & 3) {\r
+ case 1:\r
+ pvid->debug_p &= ~(PVD_KILL_S_LO | PVD_KILL_S_HI);\r
+ pvid->debug_p |= PVD_FORCE_S;\r
+ break;\r
+ case 2:\r
+ pvid->debug_p &= ~PVD_KILL_A;\r
+ pvid->debug_p |= PVD_FORCE_A;\r
+ break;\r
+ case 3:\r
+ pvid->debug_p &= ~PVD_KILL_B;\r
+ pvid->debug_p |= PVD_FORCE_B;\r
+ break;\r
+ }\r
+ break;\r
}\r
}\r
\r
#include "input_pico.h"
#include "version.h"
-#include <pico/pico.h>
+#include <pico/pico_int.h>
#include <pico/patch.h>
#ifdef PANDORA
static void draw_frame_debug(void)
{
char layer_str[48] = "layers: ";
- if (PicoDrawMask & PDRAW_LAYERB_ON) memcpy(layer_str + 8, "B", 1);
- if (PicoDrawMask & PDRAW_LAYERA_ON) memcpy(layer_str + 10, "A", 1);
- if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) memcpy(layer_str + 12, "spr_lo", 6);
- if (PicoDrawMask & PDRAW_SPRITES_HI_ON) memcpy(layer_str + 19, "spr_hi", 6);
- if (PicoDrawMask & PDRAW_32X_ON) memcpy(layer_str + 26, "32x", 4);
+ struct PicoVideo *pv = &Pico.video;
+
+ if (!(pv->debug_p & PVD_KILL_B)) memcpy(layer_str + 8, "B", 1);
+ if (!(pv->debug_p & PVD_KILL_A)) memcpy(layer_str + 10, "A", 1);
+ if (!(pv->debug_p & PVD_KILL_S_LO)) memcpy(layer_str + 12, "spr_lo", 6);
+ if (!(pv->debug_p & PVD_KILL_S_HI)) memcpy(layer_str + 19, "spr_hi", 6);
+ if (!(pv->debug_p & PVD_KILL_32X)) memcpy(layer_str + 26, "32x", 4);
pemu_forced_frame(1, 0);
make_bg(1);
static void debug_menu_loop(void)
{
+ struct PicoVideo *pv = &Pico.video;
int inp, mode = 0;
int spr_offs = 0, dumped = 0;
char *tmp;
}
break;
case 1:
- if (inp & PBTN_LEFT) PicoDrawMask ^= PDRAW_LAYERB_ON;
- if (inp & PBTN_RIGHT) PicoDrawMask ^= PDRAW_LAYERA_ON;
- if (inp & PBTN_DOWN) PicoDrawMask ^= PDRAW_SPRITES_LOW_ON;
- if (inp & PBTN_UP) PicoDrawMask ^= PDRAW_SPRITES_HI_ON;
- if (inp & PBTN_MA2) PicoDrawMask ^= PDRAW_32X_ON;
+ if (inp & PBTN_LEFT) pv->debug_p ^= PVD_KILL_B;
+ if (inp & PBTN_RIGHT) pv->debug_p ^= PVD_KILL_A;
+ if (inp & PBTN_DOWN) pv->debug_p ^= PVD_KILL_S_LO;
+ if (inp & PBTN_UP) pv->debug_p ^= PVD_KILL_S_HI;
+ if (inp & PBTN_MA2) pv->debug_p ^= PVD_KILL_32X;
if (inp & PBTN_MOK) {
PsndOut = NULL; // just in case
PicoSkipFrame = 1;