static int PicoFrameHints(void)
{
struct PicoVideo *pv=&Pico.video;
- int lines, y, lines_vis = 224, line_sample, skip;
+ int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap;
int hint; // Hint counter
- Pico.m.scanline = 0;
+ pv->v_counter = Pico.m.scanline = 0;
if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled
// draw a frame just after vblank in alternative render mode
if (Pico.m.pal) {
line_sample = 68;
- if(pv->reg[1]&8) lines_vis = 240;
+ if (pv->reg[1]&8) lines_vis = 240;
} else {
line_sample = 93;
}
for (y = 0; y < lines_vis; y++)
{
- Pico.m.scanline = y;
+ pv->v_counter = Pico.m.scanline = y;
+ if ((pv->reg[12]&6) == 6) { // interlace mode 2
+ pv->v_counter <<= 1;
+ pv->v_counter |= pv->v_counter >> 8;
+ pv->v_counter &= 0xff;
+ }
// VDP FIFO
pv->lwrite_cnt -= 12;
#endif
}
+ // V-int line (224 or 240)
+ Pico.m.scanline = y;
+ pv->v_counter = 0xe0; // bad for 240 mode
+ if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1;
+
if (!skip)
{
if (DrawScanline < y)
#endif
}
- // V-int line (224 or 240)
- Pico.m.scanline = y;
-
// VDP FIFO
pv->lwrite_cnt=0;
Pico.video.status|=0x200;
if (pv->reg[0]&0x10) SekInterrupt(4);
}
- // V-Interrupt:
pv->status|=0x08; // go into vblank
pv->pending_ints|=0x20;
// PAL line count might actually be 313 according to Steve Snake, but that would complicate things.
lines = Pico.m.pal ? 312 : 262;
+ vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens
for (y++; y < lines; y++)
{
- Pico.m.scanline = y;
+ pv->v_counter = Pico.m.scanline = y;
+ if (y >= vcnt_wrap)
+ pv->v_counter -= Pico.m.pal ? 56 : 6;
+ if ((pv->reg[12]&6) == 6)
+ pv->v_counter = (pv->v_counter << 1) | 1;
+ pv->v_counter &= 0xff;
PAD_DELAY
#ifdef PICO_CD
int status; // Status bits\r
unsigned char pending_ints; // pending interrupts: ??VH????\r
signed char lwrite_cnt; // VDP write count during active display line\r
- unsigned char pad[0x12];\r
+ unsigned short v_counter; // V-counter\r
+ unsigned char pad[0x10];\r
};\r
\r
struct PicoMisc\r
// VideoPort.c\r
PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d);\r
PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a);\r
+PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a);\r
extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp);\r
\r
// Misc.c\r
{\r
a&=0x1c;\r
\r
- if (a==0x00) // data port\r
- {\r
- return VideoRead();\r
- }\r
-\r
if (a==0x04) // control port\r
{\r
struct PicoVideo *pv=&Pico.video;\r
unsigned int d;\r
d=pv->status;\r
- if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)\r
- if (!(pv->reg[1]&0x40)) d|=0x0008; // set V-Blank if display is disabled\r
+ //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)\r
if (SekCyclesLeft < 84+4) d|=0x0004; // H-Blank (Sonic3 vs)\r
\r
- d|=(pv->pending_ints&0x20)<<2; // V-int pending?\r
+ d |= ((pv->reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled\r
+ d |= (pv->pending_ints&0x20)<<2; // V-int pending?\r
if (d&0x100) pv->status&=~0x100; // FIFO no longer full\r
\r
- pv->pending=0; // ctrl port reads clear write-pending flag (Charles MacDonald)\r
+ pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald)\r
\r
elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc);\r
return d;\r
// check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune\r
if ((a&0x1c)==0x08)\r
{\r
- unsigned int hc, d;\r
+ unsigned int d;\r
int lineCycles;\r
\r
lineCycles = (488-SekCyclesLeft)&0x1ff;\r
- d = Pico.m.scanline; // V-Counter\r
-\r
if (Pico.video.reg[12]&1)\r
- hc=hcounts_40[lineCycles];\r
- else hc=hcounts_32[lineCycles];\r
+ d = hcounts_40[lineCycles];\r
+ else d = hcounts_32[lineCycles];\r
\r
- if (Pico.m.pal) {\r
- if (d >= 0x103) d-=56; // based on Gens\r
- } else {\r
- if (d >= 0xEB) d-=6;\r
- }\r
+ elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);\r
+ return d | (Pico.video.v_counter << 8);\r
+ }\r
\r
- if ((Pico.video.reg[12]&6) == 6) {\r
- // interlace mode 2 (Combat Cars (UE) [!])\r
- d <<= 1;\r
- if (d&0xf00) d|= 1;\r
- }\r
+ if (a==0x00) // data port\r
+ {\r
+ return VideoRead();\r
+ }\r
\r
- elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", hc, d, SekCyclesDone(), SekPc);\r
- d&=0xff; d<<=8;\r
- d|=hc;\r
- return d;\r
+ return 0;\r
+}\r
+\r
+unsigned int PicoVideoRead8(unsigned int a)\r
+{\r
+ unsigned int d;\r
+ a&=0x1d;\r
+\r
+ switch (a)\r
+ {\r
+ case 0: return VideoRead() >> 8;\r
+ case 1: return VideoRead() & 0xff;\r
+ case 4: // control port/status reg\r
+ d = Pico.video.status >> 8;\r
+ if (d&1) Pico.video.status&=~0x100; // FIFO no longer full\r
+ Pico.video.pending = 0;\r
+ elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc);\r
+ return d;\r
+ case 5:\r
+ d = Pico.video.status & 0xff;\r
+ //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)\r
+ d |= ((Pico.video.reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled\r
+ d |= (Pico.video.pending_ints&0x20)<<2; // V-int pending?\r
+ if (SekCyclesLeft < 84+4) d |= 4; // H-Blank\r
+ Pico.video.pending = 0;\r
+ elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc);\r
+ return d;\r
+ case 8: // hv counter\r
+ elprintf(EL_HVCNT, "vcounter: %02x (%i) @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc);\r
+ return Pico.video.v_counter;\r
+ case 9:\r
+ d = (488-SekCyclesLeft)&0x1ff;\r
+ if (Pico.video.reg[12]&1)\r
+ d = hcounts_40[d];\r
+ else d = hcounts_32[d];\r
+ elprintf(EL_HVCNT, "hcounter: %02x (%i) @ %06x", d, SekCyclesDone(), SekPc);\r
+ return d;\r
}\r
\r
return 0;\r