X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=testpico%2Fmain.c;h=1d27128bceb9b0c8563fdfc1da264be4af9ae70f;hb=HEAD;hp=d02a4680ad593eb59fb0d969633062c7a4e92fde;hpb=6474d733133dc605ee02e4e2e02f025c41d202df;p=megadrive.git diff --git a/testpico/main.c b/testpico/main.c index d02a468..44fe5b9 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -8,6 +8,10 @@ #include "asmtools.h" //#pragma GCC diagnostic ignored "-Wunused-function" +#ifndef VERSION +#define VERSION "unknown build" +#endif + #define VDP_DATA_PORT 0xC00000 #define VDP_CTRL_PORT 0xC00004 #define VDP_HV_COUNTER 0xC00008 @@ -346,10 +350,11 @@ void exception(const struct exc_frame *f) printf(" PC: %08x SR: %04x \n", f->g.pc, f->g.sr); sp_add = 6; } - for (i = 0; i < 8; i++) + sp = (u32 *)(f->ar[7] + sp_add); + for (i = 0; i < 7; i++) printf(" D%d: %08x A%d: %08x \n", i, f->dr[i], i, f->ar[i]); + printf(" D%d: %08x SP: %08x \n", i, f->dr[i], (u32)sp); printf(" \n"); - sp = (u32 *)(f->ar[7] + sp_add); printf(" %08x %08x %08x %08x\n", sp[0], sp[1], sp[2], sp[3]); printf(" %08x %08x %08x %08x\n", sp[4], sp[5], sp[6], sp[7]); } @@ -384,12 +389,16 @@ static void vdp_wait_for_fifo_empty(void) { while (!(read16(VDP_CTRL_PORT) & 0x200)) /* fifo not empty */; + + mem_barrier(); } static void vdp_wait_for_dma_idle(void) { while (read16(VDP_CTRL_PORT) & 2) /* dma busy */; + + mem_barrier(); } static void vdp_wait_for_line_0(void) @@ -402,6 +411,18 @@ static void vdp_wait_for_line_0(void) /* blanking */; while (read8(VDP_HV_COUNTER) != 0) ; + + mem_barrier(); +} + +static void wait_next_vsync(void) +{ + while (read16(VDP_CTRL_PORT) & SR_VB) + /* blanking */; + while (!(read16(VDP_CTRL_PORT) & SR_VB)) + /* not blanking */; + + mem_barrier(); } static void t_dma_zero_wrap_early(void) @@ -445,13 +466,13 @@ static void t_dma_zero_fill_early(void) #define expect(ok_, v0_, v1_) \ do { if ((v0_) != (v1_)) { \ - printf("%s: %08x %08x\n", #v0_, v0_, v1_); \ + printf("%d %s: %08x %08x\n", __LINE__, #v0_, v0_, v1_); \ ok_ = 0; \ }} while (0) #define expect_sh2(ok_, sh2_, v0_, v1_) \ do { if ((v0_) != (v1_)) { \ - printf("%csh2: %08x %08x\n", sh2_ ? 's' : 'm', v0_, v1_); \ + printf("%d %csh2: %08x %08x\n", __LINE__, sh2_ ? 's' : 'm', v0_, v1_); \ ok_ = 0; \ }} while (0) @@ -801,6 +822,33 @@ static int t_dma_fill_src(void) return ok; } +// should not see the busy flag +static int t_dma_busy_vram(void) +{ + const u32 *src = (const u32 *)0x3c0000; + u16 sr[3]; + int ok = 1; + + vdp_wait_for_line_0(); + + do_setup_dma(src, 1); + write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA); + sr[0] = read16(VDP_CTRL_PORT); + + do_setup_dma(src, 4); + write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA); + sr[1] = read16(VDP_CTRL_PORT); + + VDP_setReg(VDP_DMA_LEN0, 8); + write32(VDP_CTRL_PORT, CTL_WRITE_VRAM(0x100) | CTL_WRITE_DMA); + sr[2] = read16(VDP_CTRL_PORT); + + expect_bits(ok, sr[0], 0, SR_DMA); + expect_bits(ok, sr[1], 0, SR_DMA); + expect_bits(ok, sr[2], 0, SR_DMA); + return ok; +} + // (((a & 2) >> 1) ^ 1) | ((a & $400) >> 9) | (a & $3FC) | ((a & $1F800) >> 1) static int t_dma_128k(void) { @@ -1780,11 +1828,12 @@ static void x32_cmd(enum x32x_cmd cmd, u32 a0, u32 a1, u16 is_slave) printf("exc m s: %02x %02x\n", r8[0x0e], r8[0x0f]); write16(r, 0); } - v = read16(&r[1]); + v = read8(&r8[2]); if (v != 0) { printf("cmd err: %x\n", v); write16(&r[1], 0); } + mem_barrier(); } static int t_32x_reset_btn(void) @@ -1819,16 +1868,19 @@ static int t_32x_reset_btn(void) expect(ok, r32[0x20/4], 0x00005a20); expect(ok, r32[0x24/4], 0x5a5a5a24); expect(ok, r32[0x28/4], 0x5a5a5a28); - expect(ok, r32[0x2c/4], 0x07075a2c); // 7 - last_irq_vec + expect(ok, r32[0x2c/4], 0x075a5a2c); // 7 - last_irq_vec if (!(r16[0x00/2] & 0x8000)) { - expect(ok, r8 [0x81], 0); - expect(ok, r16[0x82/2], 0); - expect(ok, r16[0x84/2], 0); - expect(ok, r16[0x86/2], 0); - //expect(ok, r16[0x88/2], 0); // triggers fill? + expect(ok, r8 [0x81], 1); + expect(ok, r16[0x82/2], 1); + expect(ok, r16[0x84/2], 0xff); + expect(ok, r16[0x86/2], 0xffff); + expect(ok, r16[0x88/2], 0); expect(ok, r8 [0x8b] & ~2, 0); // FEN toggles periodically? expect(ok, r16[0x8c/2], 0); expect(ok, r16[0x8e/2], 0); + // setup vdp for t_32x_init + r8 [0x81] = 0; + r16[0x82/2] = r16[0x84/2] = r16[0x86/2] = 0; } r32[0x20/4] = r32[0x24/4] = r32[0x28/4] = r32[0x2c/4] = 0; for (s = 0; s < 2; s++) @@ -1846,7 +1898,18 @@ static int t_32x_reset_btn(void) expect(ok, s_icnt[i], 0x100); } expect(ok, m_icnt[7], 0x101); // VRES happened + expect(ok, s_icnt[7], 0x100); // masked on slave + + x32_cmd(CMD_GETSR, 0, 0, 1); + expect_sh2(ok, 1, r32[0x24/4] & ~1, 0xf0); // still masked + x32_cmd(CMD_SETSR, 0x10, 0, 1); + expect(ok, r16[0x00/2], 0x8083); + write8(r8, 0x00); // FM=0 + mem_barrier(); + expect(ok, m_icnt[7], 0x101); expect(ok, s_icnt[7], 0x101); + expect(ok, r32[0x2c/4], 0x00070000); // 7 - last_irq_vec + r32[0x2c/4] = 0; memcpy_(do_32x_disable, x32x_disable, x32x_disable_end - x32x_disable); @@ -1855,7 +1918,7 @@ static int t_32x_reset_btn(void) expect(ok, r16[0x00/2], 0x82); expect(ok, r16[0x02/2], 0); expect(ok, r16[0x04/2], 3); - expect(ok, r16[0x06/2], 1); // RV + expect(ok, r16[0x06/2], 0); // RV cleared by x32x_disable expect(ok, r32[0x08/4], 0x5a5a08); expect(ok, r32[0x0c/4], 0x5a5a0c); expect(ok, r16[0x10/2], 0x5a10); @@ -1863,7 +1926,6 @@ static int t_32x_reset_btn(void) // setup for t_32x_init, t_32x_sh_defaults r16[0x04/2] = 0; - r16[0x06/2] = 0; // can just set without ADEN r16[0x10/2] = 0x1234; // warm reset indicator mem_barrier(); expect(ok, r16[0x06/2], 0); // RV @@ -1907,9 +1969,40 @@ static int t_32x_init(void) r32[0x28/4] = 0; r32[0x2c/4] = 0; - // these have garbage or old values (survive MD's power cycle) + // check writable bits without ADEN + // 08,0c have garbage or old values (survive MD's power cycle) + write16(&r16[0x00/2], 0); + mem_barrier(); + expect(ok, r16[0x00/2], 0x80); + write16(&r16[0x00/2], 0xfffe); + mem_barrier(); + expect(ok, r16[0x00/2], 0x8082); + r16[0x00/2] = 0x82; + r16[0x02/2] = 0xffff; + r32[0x04/4] = 0xffffffff; + r32[0x08/4] = 0xffffffff; + r32[0x0c/4] = 0xffffffff; + r16[0x10/2] = 0xffff; + r32[0x14/4] = 0xffffffff; + r32[0x18/4] = 0xffffffff; + r32[0x1c/4] = 0xffffffff; + mem_barrier(); + expect(ok, r16[0x00/2], 0x82); + expect(ok, r16[0x02/2], 0x03); + expect(ok, r16[0x04/2], 0x03); + expect(ok, r16[0x06/2], 0x07); + expect(ok, r32[0x08/4], 0x00fffffe); + expect(ok, r32[0x0c/4], 0x00ffffff); + expect(ok, r16[0x10/2], 0xfffc); + expect(ok, r32[0x14/4], 0); + expect(ok, r16[0x18/2], 0); + expect(ok, r16[0x1a/2], 0x0101); + expect(ok, r32[0x1c/4], 0); + r16[0x02/2] = 0; + r32[0x04/4] = 0; r32[0x08/4] = 0; r32[0x0c/4] = 0; + r16[0x1a/2] = 0; // could just set RV, but BIOS reads ROM, so can't memcpy_(do_32x_enable, x32x_enable, @@ -2067,7 +2160,7 @@ static int t_32x_sh_fb(void) return ok; } -static int t_32x_irq(void) +static int t_32x_irq_cmd(void) { u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE); u16 *m_icnt = (u16 *)fbl_icnt; @@ -2100,7 +2193,9 @@ static int t_32x_irq(void) write16(&r16[0x02/2], 0xaaaa); // INTS+unused_bits mem_barrier(); expect(ok, r16[0x02/2], 2); - burn10(10); + //burn10(10); + x32_cmd(CMD_WRITE8, 0x20004001, 0, 0); // mask again + x32_cmd(CMD_WRITE8, 0x20004001, 0, 1); mem_barrier(); expect(ok, r16[0x02/2], 0); expect(ok, r8 [0x2c], 4); @@ -2119,6 +2214,102 @@ static int t_32x_irq(void) return ok; } +static int t_32x_irq_vint(void) +{ + u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE); + u16 *m_icnt = (u16 *)fbl_icnt; + u16 *s_icnt = m_icnt + 8; + u32 *r = (u32 *)0xa15100; + u16 *r16 = (u16 *)r; + u8 *r8 = (u8 *)r; + int ok = 1, i; + + vdp_wait_for_line_0(); + write8(r, 0x00); // FM=0 + r[0x2c/4] = 0; + mem_barrier(); + for (i = 0; i < 8; i++) + write32(&fbl_icnt[i], 0); + mem_barrier(); + x32_cmd(CMD_SETSR, 0xf0, 0, 0); // master mask at sr + x32_cmd(CMD_WRITE8, 0x20004001, 8, 0); // unmask both 32x vint + x32_cmd(CMD_WRITE8, 0x20004001, 8, 1); + burn10(10); + mem_barrier(); + expect(ok, r16[0x2c/2], 0); // no pending vints + expect(ok, r16[0x2e/2], 0); // no exception_index + + write8(&r8[0x23], 0x5a); // no-32x-source-autoclear flag + wait_next_vsync(); + burn10(10); + expect(ok, r8 [0x2c], 0); + expect(ok, r8 [0x2d], 12/2); + write8(&r8[0x2d], 0); + burn10(10); + expect(ok, r8 [0x2c], 0); + expect(ok, r8 [0x2d], 12/2); + + x32_cmd(CMD_WRITE16, 0x20004016, 0, 0); // clear on 32x (from master) + burn10(10); + write16(&r[0x2c/4], 0); + burn10(10); + expect(ok, r8 [0x2c], 0); + expect(ok, r8 [0x2d], 12/2); + // (here the slave can't accept commands as it keeps retaking the irq) + write8(&r8[0x23], 0); // handler 32x clear on + burn10(10); + write16(&r[0x2c/4], 0); + burn10(10); + expect(ok, r16[0x2c/2], 0); // no pending vints + expect(ok, r16[0x2e/2], 0); // no exception_index + write8(r, 0x00); // FM=0 + mem_barrier(); + expect(ok, m_icnt[12/2], 0); + expect_range(ok, s_icnt[12/2], 0x10, 0x1000); + + x32_cmd(CMD_SETSR, 0x10, 0, 0); // master unmask at sr + wait_next_vsync(); + burn10(10); + expect(ok, r8 [0x2c], 12/2); + expect(ok, r8 [0x2d], 12/2); + + x32_cmd(CMD_WRITE8, 0x20004001, 0, 0); // mask + x32_cmd(CMD_WRITE8, 0x20004001, 0, 1); + write16(&r[0x2c/4], 0); + wait_next_vsync(); + burn10(10); + expect(ok, r16[0x2c/2], 0); // no pending vints + expect(ok, r16[0x2e/2], 0); // no exception_index + + x32_cmd(CMD_WRITE8, 0x20004001, 8, 1); // slave unmask + burn10(10); + x32_cmd(CMD_WRITE8, 0x20004001, 0, 1); // mask + burn10(10); + expect(ok, r8 [0x2c], 0); + expect(ok, r8 [0x2d], 12/2); + write16(&r[0x2c/4], 0); + + vdp_wait_for_line_0(); + x32_cmd(CMD_WRITE8, 0x20004001, 8, 0); // master unmask + burn10(10); + x32_cmd(CMD_WRITE8, 0x20004001, 0, 0); // mask + burn10(10); + expect(ok, r8 [0x2c], 0); + expect(ok, r8 [0x2d], 0); + + write8(&r8[0x23], 0); // handler 32x clear on + write8(r, 0x00); // FM=0 + mem_barrier(); + expect(ok, m_icnt[12/2], 1); + for (i = 0; i < 8; i++) { + if (i == 12/2) + continue; + expect(ok, m_icnt[i], 0); + expect(ok, s_icnt[i], 0); + } + return ok; +} + static int t_32x_reg_w(void) { u32 *r32 = (u32 *)0xa15100; @@ -2144,7 +2335,8 @@ static int t_32x_reg_w(void) // prepare for reset btn press tests static int t_32x_reset_prep(void) { - u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE); + u32 *fbl = (u32 *)0x840000; + u32 *fbl_icnt = fbl + IRQ_CNT_FB_BASE / 4; u32 *r32 = (u32 *)0xa15100; u16 *r16 = (u16 *)r32; u8 *r8 = (u8 *)r32; @@ -2159,6 +2351,7 @@ static int t_32x_reset_prep(void) write32(&fbl_icnt[i], 0x01000100); x32_cmd(CMD_WRITE8, 0x20004001, 0x02, 0); // unmask cmd x32_cmd(CMD_WRITE8, 0x20004001, 0x02, 1); // unmask slave + x32_cmd(CMD_SETSR, 0xf0, 0, 1); // mask slave irqs (on the cpu) burn10(10); write8(r8, 0x00); // FM=0 expect(ok, r32[0x2c/4], 0); @@ -2174,6 +2367,21 @@ static int t_32x_reset_prep(void) r32[0x24/4] = 0x5a5a5a24; r32[0x28/4] = 0x5a5a5a28; r32[0x2c/4] = 0x5a5a5a2c; + if (!(r16[0x00/2] & 0x8000)) { + wait_next_vsync(); + r16[0x8a/2] = 0x0001; + mem_barrier(); + for (i = 0; i < 220/2; i++) + write32(&fbl[i], 0); + r8 [0x81] = 1; + r16[0x82/2] = 0xffff; + r16[0x84/2] = 0xffff; + r16[0x86/2] = 0xffff; + r16[0x8a/2] = 0x0000; + r16[0x8c/2] = 0xffff; + r16[0x8e/2] = 0xffff; + r16[0x100/2] = 0; + } return ok; } @@ -2203,6 +2411,7 @@ static const struct { { T_MD, t_dma_fill3_vsram, "dma fill3 vsram" }, { T_MD, t_dma_fill_dis, "dma fill disabled" }, { T_MD, t_dma_fill_src, "dma fill src incr" }, + { T_MD, t_dma_busy_vram, "dma no busy" }, { T_MD, t_dma_128k, "dma 128k mode" }, { T_MD, t_vdp_128k_b16, "vdp 128k addr bit16" }, // { t_vdp_128k_b16_inc, "vdp 128k bit16 inc" }, // mystery @@ -2246,7 +2455,8 @@ static const struct { { T_32, t_32x_md_rom, "32x md rom" }, { T_32, t_32x_md_fb, "32x md fb" }, { T_32, t_32x_sh_fb, "32x sh fb" }, - { T_32, t_32x_irq, "32x irq" }, + { T_32, t_32x_irq_cmd, "32x irq cmd" }, + { T_32, t_32x_irq_vint, "32x irq vint" }, { T_32, t_32x_reg_w, "32x reg w" }, { T_32, t_32x_reset_prep, "32x rstprep" }, // must be last 32x }; @@ -2284,14 +2494,6 @@ static void setup_z80(void) ; } -static void wait_next_vsync(void) -{ - while (read16(VDP_CTRL_PORT) & SR_VB) - /* blanking */; - while (!(read16(VDP_CTRL_PORT) & SR_VB)) - /* not blanking */; -} - static unused int hexinc(char *c) { (*c)++; @@ -2377,6 +2579,7 @@ int main() VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP); + printf("%s\n", VERSION); have_32x = read32(0xa130ec) == MKLONG('M','A','R','S'); en_32x = have_32x && (read16(0xa15100) & 1); v8 = read8(0xa10001); @@ -2385,6 +2588,12 @@ int main() (v8 & 0x40) ? "pal" : "ntsc", have_32x ? "32X" : "", en_32x ? "+" : ""); + printf("reset hvc %04x->%04x\n", read16(-4), read16(-2)); + + // sanity check + extern u32 sh2_test[]; + if (sh2_test[0] != read32(0x3e0) || sh2_test[0x200/4] != read32(0x3e4)) + printf("bad 0x3c0 tab\n"); for (i = 0; i < ARRAY_SIZE(g_tests); i++) { // print test number if we haven't scrolled away @@ -2420,7 +2629,7 @@ int main() printf_ypos = 0; printf(" "); - if (have_32x) { + if (have_32x && (read16(0xa15100) & 1)) { u8 *p = (u8 *)0xff0040; u32 len = x32x_switch_rv_end - x32x_switch_rv; px32x_switch_rv = (void *)p; p += len; @@ -2434,14 +2643,18 @@ int main() // todo: broken printf px32x_switch_rv(0); } - for (i = 0; i < 60*60 && !(pget_input() & BTNM_A); i++) - wait_next_vsync(); -#ifndef PICO + for (i = 0; i < 60*60 && !(pget_input() & BTNM_A); i++) { + while (read16(VDP_CTRL_PORT) & SR_VB) + write16(-4, read16(VDP_HV_COUNTER)); /* blanking */ + while (!(read16(VDP_CTRL_PORT) & SR_VB)) + write16(-4, read16(VDP_HV_COUNTER)); /* not blanking */; + } +#if 0 //ndef PICO // blank due to my lame tv being burn-in prone VDP_setReg(VDP_MODE2, VDP_MODE2_MD); #endif while (!(pget_input() & BTNM_A)) - burn10(488*100/10); + write16(-4, read16(VDP_HV_COUNTER)); VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);