+static int t_tim_loop(void)
+{
+ u8 vcnt;
+ int ok = 1;
+
+ vdp_wait_for_line_0();
+ burn10(488*220/10);
+ vcnt = read8(VDP_HV_COUNTER);
+ mem_barrier();
+
+ //expect_range(ok, vcnt, 0x80, 0x80);
+ expect(ok, vcnt, 223);
+ return ok;
+}
+
+#define Z80_RD_V_CYCLES(b) (132 + (b) * 38 + 50 + 17)
+
+// 80 80 91 95-96
+static void z80_read_loop(u8 *zram, u16 src)
+{
+ const int pairs = 512 + 256;
+
+ zram[0x1000] = 2; // read loop, save vcnt
+ write16_z80le(&zram[0x1002], src); // src
+ write16_z80le(&zram[0x1004], 0x1100); // vcnt dst
+ write16_z80le(&zram[0x1006], pairs); // reads/2
+ zram[0x1100] = 0;
+ mem_barrier();
+
+ vdp_wait_for_line_0();
+ write16(0xa11100, 0x000);
+ burn10(Z80_RD_V_CYCLES(pairs) * 15 / 7 * 4 / 10);
+
+ write16(0xa11100, 0x100);
+ while (read16(0xa11100) & 0x100)
+ ;
+}
+
+static int t_tim_z80_ram(void)
+{
+ u8 *zram = (u8 *)0xa00000;
+ int ok = 1;
+
+ z80_read_loop(zram, 0);
+
+ expect(ok, zram[0x1000], 0);
+ expect_range(ok, zram[0x1100], 0x80, 0x80);
+ return ok;
+}
+
+static int t_tim_z80_ym(void)
+{
+ u8 *zram = (u8 *)0xa00000;
+ int ok = 1;
+
+ z80_read_loop(zram, 0x4000);
+
+ expect(ok, zram[0x1000], 0);
+ expect_range(ok, zram[0x1100], 0x80, 0x80);
+ return ok;
+}
+
+static int t_tim_z80_vdp(void)
+{
+ u8 *zram = (u8 *)0xa00000;
+ int ok = 1;
+
+ z80_read_loop(zram, 0x7f08);
+
+ expect(ok, zram[0x1000], 0);
+#ifndef PICO
+ expect_range(ok, zram[0x1100], 0x91, 0x91);
+#else
+ expect_range(ok, zram[0x1100], 0x8e, 0x91);
+#endif
+ return ok;
+}
+
+static int t_tim_z80_bank_rom(void)
+{
+ u8 *zram = (u8 *)0xa00000;
+ int i, ok = 1;
+
+ for (i = 0; i < 17; i++)
+ write8(0xa06000, 0); // bank 0
+
+ z80_read_loop(zram, 0x8000);
+
+ expect(ok, zram[0x1000], 0);
+#ifndef PICO
+ expect_range(ok, zram[0x1100], 0x95, 0x96);
+#else
+ expect_range(ok, zram[0x1100], 0x93, 0x96);
+#endif
+ return ok;
+}
+
+/* borderline too slow */
+#if 0
+static void do_vcnt_vb(void)
+{
+ const u32 *srhv = (u32 *)0xc00006; // to read SR and HV counter
+ u32 *ram = (u32 *)0xff0000;
+ u16 vcnt, vcnt_expect = 0;
+ u16 sr, count = 0;
+ u32 val, old;
+
+ vdp_wait_for_line_0();
+ old = read32(srhv);
+ *ram++ = old;
+ for (;;) {
+ val = read32(srhv);
+ vcnt = val & 0xff00;
+ if (vcnt == vcnt_expect)
+ continue;
+ sr = val >> 16;
+ if (vcnt == 0 && !(sr & SR_VB)) // not VB
+ break; // wrapped to start of frame
+// count++;
+ vcnt_expect += 0x100;
+ if (vcnt == vcnt_expect && !((sr ^ (old >> 16)) & SR_VB)) {
+ old = val;
+ continue;
+ }
+ // should have a vcnt jump here
+ *ram++ = old;
+ *ram++ = val;
+ vcnt_expect = vcnt;
+ old = val;
+ }
+ *ram++ = val;
+ *ram = count;
+ mem_barrier();
+}
+#endif
+
+static int t_tim_vcnt(void)
+{
+ const u32 *ram32 = (u32 *)0xff0000;
+ const u8 *ram = (u8 *)0xff0000;
+ u8 pal = read8(0xa10001) & 0x40;
+ u8 vc_jmp_b = pal ? 0x02 : 0xea;
+ u8 vc_jmp_a = pal ? 0xca : 0xe5;
+ u16 lines = pal ? 313 : 262;
+ int ok = 1;
+
+ do_vcnt_vb();
+ expect(ok, ram[0*4+2], 0); // line 0
+ expect_bits(ok, ram[0*4+1], 0, SR_VB);
+ expect(ok, ram[1*4+2], 223); // last no blank
+ expect_bits(ok, ram[1*4+1], 0, SR_VB);
+ expect(ok, ram[2*4+2], 224); // 1st blank
+ expect_bits(ok, ram[2*4+1], SR_VB, SR_VB);
+ expect(ok, ram[3*4+2], vc_jmp_b); // before jump
+ expect_bits(ok, ram[3*4+1], SR_VB, SR_VB);
+ expect(ok, ram[4*4+2], vc_jmp_a); // after jump
+ expect_bits(ok, ram[4*4+1], SR_VB, SR_VB);
+ expect(ok, ram[5*4+2], 0xfe); // before vb clear
+ expect_bits(ok, ram[5*4+1], SR_VB, SR_VB);
+ expect(ok, ram[6*4+2], 0xff); // after vb clear
+ expect_bits(ok, ram[6*4+1], 0, SR_VB);
+ expect(ok, ram[7*4+2], 0); // next line 0
+ expect_bits(ok, ram[7*4+1], 0, SR_VB);
+ expect(ok, ram32[8], lines - 1);
+ return ok;
+}
+
+static int t_tim_vdp_as_vram_w(void)
+{
+ int ok = 1;
+ u8 vcnt;
+
+ write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100));
+ vdp_wait_for_line_0();
+ write16_x16(VDP_DATA_PORT, 112*18 / 16, 0);
+ vcnt = read8(VDP_HV_COUNTER);
+ mem_barrier();
+
+ expect(ok, vcnt, 112*2-1);
+ return ok;
+}
+
+static int t_tim_vdp_as_cram_w(void)
+{
+ int ok = 1;
+ u8 vcnt;
+
+ write32(VDP_CTRL_PORT, CTL_WRITE_CRAM(0));
+ vdp_wait_for_line_0();
+ write16_x16(VDP_DATA_PORT, 112*18 / 16, 0);
+ vcnt = read8(VDP_HV_COUNTER);
+ mem_barrier();
+
+ setup_default_palette();
+
+#ifndef PICO
+ expect(ok, vcnt, 112);
+#else
+ expect_range(ok, vcnt, 111, 112);
+#endif
+ return ok;
+}
+