note to self:
h32 0x10A .. 0x127 0x1D2 .. 0x1FF 0x000 .. 0x109
pclk 30 | 46 | 266 = 342
hbset 0x126 ... 0x009
pclk 29 | 1 + 46 + 10 | 256
mclk 290 | 570 | 2560 = 3420
68kclk 41.4 81.4 365.7 ~= 488.5
h40 0x14A .. 0x16C 0x1C9 .. 0x1FF 0x000 .. 0x149
pclk 35 | 55 | 330 = 420
hbset 0x166 ... 0x00A
pclk 28 | 7 + 55 + 11 | 319
mclk 28*8 | 7*8 4*8+314+10+(18+11)*8 | 319*8 = 3420
68kclk 32 92 364.5 ~= 488.5
}
else skip=PicoSkipFrame;
}
else skip=PicoSkipFrame;
- Pico.t.m68c_frame_start = SekCyclesDone();
+ Pico.t.m68c_frame_start = Pico.t.m68c_aim;
pv->v_counter = Pico.m.scanline = 0;
z80_resetCycles();
PsndStartFrame();
pv->v_counter = Pico.m.scanline = 0;
z80_resetCycles();
PsndStartFrame();
- Pico.t.m68c_line_start = SekCyclesDone();
+ Pico.t.m68c_line_start = Pico.t.m68c_aim;
do_timing_hacks_as(pv, vdp_slots);
CPUS_RUN(CYCLES_M68K_LINE);
do_timing_hacks_as(pv, vdp_slots);
CPUS_RUN(CYCLES_M68K_LINE);
- pv->status |= SR_VB; // go into vblank
+ pv->status |= SR_VB | PVS_VB2; // go into vblank
// the following SekRun is there for several reasons:
// there must be a delay after vblank bit is set and irq is asserted (Mazin Saga)
// also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants)
// also delay between last H-int and V-int (Golden Axe 3)
// the following SekRun is there for several reasons:
// there must be a delay after vblank bit is set and irq is asserted (Mazin Saga)
// also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants)
// also delay between last H-int and V-int (Golden Axe 3)
- Pico.t.m68c_line_start = SekCyclesDone();
+ Pico.t.m68c_line_start = Pico.t.m68c_aim;
do_timing_hacks_vb();
CPUS_RUN(CYCLES_M68K_VINT_LAG);
do_timing_hacks_vb();
CPUS_RUN(CYCLES_M68K_VINT_LAG);
pv->pending_ints |= 0x20;
if (pv->reg[1] & 0x20) {
Pico.t.m68c_aim = Pico.t.m68c_cnt + 11; // HACK
pv->pending_ints |= 0x20;
if (pv->reg[1] & 0x20) {
Pico.t.m68c_aim = Pico.t.m68c_cnt + 11; // HACK
- Pico.t.m68c_line_start = SekCyclesDone();
+ Pico.t.m68c_line_start = Pico.t.m68c_aim;
do_timing_hacks_vb();
CPUS_RUN(CYCLES_M68K_LINE);
do_timing_hacks_vb();
CPUS_RUN(CYCLES_M68K_LINE);
pevt_log_m68k_o(EVT_NEXT_LINE);
}
pevt_log_m68k_o(EVT_NEXT_LINE);
}
+ pv->status &= ~(SR_VB | PVS_VB2);
+ pv->status |= ((pv->reg[1] >> 3) ^ SR_VB) & SR_VB; // forced blanking
// last scanline
Pico.m.scanline = y;
// last scanline
Pico.m.scanline = y;
- Pico.t.m68c_line_start = SekCyclesDone();
+ Pico.t.m68c_line_start = Pico.t.m68c_aim;
do_timing_hacks_as(pv, vdp_slots);
CPUS_RUN(CYCLES_M68K_LINE);
do_timing_hacks_as(pv, vdp_slots);
CPUS_RUN(CYCLES_M68K_LINE);
#define SR_EMPT (1 << 9)\r
// not part of real SR\r
#define PVS_ACTIVE (1 << 16)\r
#define SR_EMPT (1 << 9)\r
// not part of real SR\r
#define PVS_ACTIVE (1 << 16)\r
+#define PVS_VB2 (1 << 17) // ignores forced blanking\r
\r
struct PicoVideo\r
{\r
\r
struct PicoVideo\r
{\r
// the VDP doesn't look at the 68k level\r
if (pv->pending_ints & pv->reg[1] & 0x20) {\r
pv->pending_ints &= ~0x20;\r
// the VDP doesn't look at the 68k level\r
if (pv->pending_ints & pv->reg[1] & 0x20) {\r
pv->pending_ints &= ~0x20;\r
return (pv->reg[0] & pv->pending_ints & 0x10) >> 2;\r
}\r
else if (pv->pending_ints & pv->reg[0] & 0x10)\r
return (pv->reg[0] & pv->pending_ints & 0x10) >> 2;\r
}\r
else if (pv->pending_ints & pv->reg[0] & 0x10)\r
\r
Pico.m.dirtyPal = 1;\r
Pico.video.status &= ~(SR_VB | SR_F);\r
\r
Pico.m.dirtyPal = 1;\r
Pico.video.status &= ~(SR_VB | SR_F);\r
+ Pico.video.status |= ((Pico.video.reg[1] >> 3) ^ SR_VB) & SR_VB;\r
+ Pico.video.status |= (Pico.video.pending_ints << 2) & SR_F;\r
pvid->pending=0;\r
}\r
\r
pvid->pending=0;\r
}\r
\r
- // preliminary FIFO emulation for Chaos Engine, The (E)\r
- if (!(pvid->status & SR_VB) && (pvid->reg[1] & 0x40) && !(PicoOpt&POPT_DIS_VDP_FIFO)) // active display?\r
+ if (!(pvid->status & SR_VB) && !(PicoOpt&POPT_DIS_VDP_FIFO))\r
{\r
int use = pvid->type == 1 ? 2 : 1;\r
pvid->lwrite_cnt -= use;\r
{\r
int use = pvid->type == 1 ? 2 : 1;\r
pvid->lwrite_cnt -= use;\r
case 0x01:\r
elprintf(EL_INTSW, "vint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x20)>>5,\r
(d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc);\r
case 0x01:\r
elprintf(EL_INTSW, "vint_onoff: %i->%i [%u] pend=%i @ %06x", (dold&0x20)>>5,\r
(d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc);\r
+ if (!(pvid->status & PVS_VB2))\r
+ pvid->status &= ~SR_VB;\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
goto update_irq;\r
case 0x05:\r
//elprintf(EL_STATUS, "spritep moved to %04x", (unsigned)(Pico.video.reg[5]&0x7f) << 9);\r
-PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)\r
+static u32 SrLow(const struct PicoVideo *pv)\r
+ unsigned int c, d = pv->status;\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 (SekCyclesDone() - Pico.t.m68c_line_start >= 488-88)\r
- d|=0x0004; // H-Blank (Sonic3 vs)\r
-\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
+ c = SekCyclesDone() - Pico.t.m68c_line_start - 39;\r
+ if (c < 92)\r
+ d |= SR_HB;\r
+ return d;\r
+}\r
- pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald)\r
+PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)\r
+{\r
+ a &= 0x1c;\r
+ if (a == 0x04) // control port\r
+ {\r
+ struct PicoVideo *pv = &Pico.video;\r
+ unsigned int d = SrLow(pv);\r
+ pv->pending = 0;\r
elprintf(EL_SR, "SR read: %04x [%u] @ %06x", d, SekCyclesDone(), SekPc);\r
return d;\r
}\r
elprintf(EL_SR, "SR read: %04x [%u] @ %06x", d, SekCyclesDone(), SekPc);\r
return d;\r
}\r
return VideoRead();\r
}\r
\r
return VideoRead();\r
}\r
\r
unsigned char PicoVideoRead8CtlH(void)\r
{\r
u8 d = (u8)(Pico.video.status >> 8);\r
unsigned char PicoVideoRead8CtlH(void)\r
{\r
u8 d = (u8)(Pico.video.status >> 8);\r
- if (d & 1)\r
- 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
Pico.video.pending = 0;\r
elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc);\r
return d;\r
\r
unsigned char PicoVideoRead8CtlL(void)\r
{\r
\r
unsigned char PicoVideoRead8CtlL(void)\r
{\r
- u8 d = (u8)Pico.video.status;\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 (SekCyclesDone() - Pico.t.m68c_line_start >= 488-88) d |= 4; // H-Blank\r
+ u8 d = SrLow(&Pico.video);\r
Pico.video.pending = 0;\r
elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc);\r
return d;\r
Pico.video.pending = 0;\r
elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc);\r
return d;\r