#define Z80_STATE_SIZE 0x60\r
\r
#define z80_resetCycles() \\r
- Pico.t.z80c_cnt = Pico.t.z80c_aim = Pico.t.z80_scanline = 0\r
+ Pico.t.z80c_cnt -= Pico.t.z80c_aim, Pico.t.z80c_aim = Pico.t.z80_scanline = 0\r
\r
#define z80_cyclesDone() \\r
(Pico.t.z80c_aim - z80_cyclesLeft)\r
\r
unsigned int z80c_cnt; // z80 cycles done (this frame)\r
unsigned int z80c_aim;\r
+ unsigned int z80c_line_start;\r
int z80_scanline;\r
\r
int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
} else {
// pad. latch hcounter if one of the TH lines is switched to 1
if ((Pico.ms.io_ctl ^ d) & d & 0xa0)
- Pico.ms.vdp_hlatch = vdp_hcounter(228 - z80_cyclesLeft);
+ Pico.ms.vdp_hlatch = vdp_hcounter(z80_cyclesDone() - Pico.t.z80c_line_start);
Pico.ms.io_ctl = d;
}
break;
}
}
+static void z80_exec(int aim)
+{
+ Pico.t.z80c_aim = aim;
+ Pico.t.z80c_cnt += z80_run(Pico.t.z80c_aim - Pico.t.z80c_cnt);
+}
+
// ROM/SRAM bank mapping, see https://www.smspower.org/Development/Mappers
int is_pal = Pico.m.pal;
int lines = is_pal ? 313 : 262;
int cycles_line = 228;
- int cycles_done = 0, cycles_aim = 0;
int skip = PicoIn.skipFrame;
int lines_vis = 192;
int hint; // Hint counter
int nmi;
int y;
+ z80_resetCycles();
PsndStartFrame();
nmi = (PicoIn.pad[0] >> 7) & 1;
for (y = 0; y < lines; y++)
{
pv->v_counter = Pico.m.scanline = y;
- if (y > 218)
- pv->v_counter = y - 6;
+ switch (is_pal ? -lines_vis : lines_vis) {
+ case 192: if (y > 218) pv->v_counter = y - (lines-256); break;
+ case 224: if (y > 234) pv->v_counter = y - (lines-256); break;
+ case -192: if (y > 242) pv->v_counter = y - (lines-256); break;
+ case -224: if (y > 258) pv->v_counter = y - (lines-256); break;
+ case -240: if (y > 266) pv->v_counter = y - (lines-256); break;
+ }
if (y < lines_vis && !skip)
PicoLineSMS(y);
+ Pico.t.z80c_line_start = Pico.t.z80c_aim;
+
// Interrupt handling. Simulate interrupt flagged and immediately reset in
// same insn by flagging the irq, execute for 1 insn, then checking if the
// irq is still pending. (GG Chicago, SMS Back to the Future III)
{
hint = pv->reg[0x0a];
pv->pending_ints |= 2;
- cycles_done += z80_run(1);
+ z80_exec(Pico.t.z80c_cnt + 1);
+
if ((pv->reg[0] & 0x10) && (pv->pending_ints & 2)) {
elprintf(EL_INTS, "hint");
z80_int_assert(1);
}
- pv->pending_ints &= ~2;
+ pv->pending_ints &= ~2; // lost if not caught immediately
}
}
else if (y == lines_vis + 1) {
pv->pending_ints &= ~2;
pv->pending_ints |= 1;
- cycles_done += z80_run(1);
+ z80_exec(Pico.t.z80c_cnt + 1);
if ((pv->reg[1] & 0x20) && (pv->pending_ints & 1)) {
elprintf(EL_INTS, "vint");
}
}
- cycles_aim += cycles_line;
- Pico.t.z80c_aim = cycles_aim;
- cycles_done += z80_run(cycles_aim - cycles_done);
+ z80_exec(Pico.t.z80c_line_start + cycles_line);
}
if (PicoIn.sndOut)