From 017512f2823405ea2d02fa04b4c0754d7c4cba65 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 26 Dec 2007 19:00:46 +0000 Subject: [PATCH] some more SVP work git-svn-id: file:///home/notaz/opt/svn/PicoDrive@319 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Cart.c | 1 + Pico/Pico.c | 1 + Pico/PicoFrameHints.c | 8 +- Pico/PicoInt.h | 36 +++-- Pico/carthw/carthw.h | 3 - Pico/carthw/svp/ssp16.c | 346 +++++++++++++++++++++++++++++++++++----- Pico/carthw/svp/ssp16.h | 7 +- Pico/carthw/svp/svp.c | 62 ++++--- 8 files changed, 372 insertions(+), 92 deletions(-) diff --git a/Pico/Cart.c b/Pico/Cart.c index 7c3f36d4..9a24d039 100644 --- a/Pico/Cart.c +++ b/Pico/Cart.c @@ -496,6 +496,7 @@ int PicoCartInsert(unsigned char *rom,unsigned int romsize) PicoMemResetHooks(); PicoDmaHook = NULL; PicoResetHook = NULL; + PicoLineHook = NULL; if (!(PicoMCD & 1)) PicoCartDetect(); diff --git a/Pico/Pico.c b/Pico/Pico.c index bb0f6e5b..6d9d525e 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -19,6 +19,7 @@ int PicoAutoRgnOrder = 0; int emustatus = 0; // rapid_ym2612, multi_ym_updates void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware void (*PicoResetHook)(void) = NULL; +void (*PicoLineHook)(void) = NULL; struct PicoSRAM SRam = {0,}; int z80startCycle, z80stopCycle; // in 68k cycles diff --git a/Pico/PicoFrameHints.c b/Pico/PicoFrameHints.c index 1b352683..49dd37be 100644 --- a/Pico/PicoFrameHints.c +++ b/Pico/PicoFrameHints.c @@ -149,6 +149,8 @@ static int PicoFrameHints(void) #ifdef PICO_CD update_chips(); +#else + if (PicoLineHook) PicoLineHook(); #endif } @@ -210,7 +212,9 @@ static int PicoFrameHints(void) CYCLES_Z80_LINE - CYCLES_Z80_ASD, CYCLES_S68K_LINE - CYCLES_S68K_ASD); #ifdef PICO_CD - update_chips(); + update_chips(); +#else + if (PicoLineHook) PicoLineHook(); #endif // PAL line count might actually be 313 according to Steve Snake, but that would complicate things. @@ -234,6 +238,8 @@ static int PicoFrameHints(void) #ifdef PICO_CD update_chips(); +#else + if (PicoLineHook) PicoLineHook(); #endif } diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index bd10f19e..ef0e8df7 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -410,6 +410,7 @@ extern struct PicoSRAM SRam; extern int emustatus; extern int z80startCycle, z80stopCycle; // in 68k cycles extern void (*PicoResetHook)(void); +extern void (*PicoLineHook)(void); PICO_INTERNAL int CheckDMA(void); // cd/Pico.c @@ -476,23 +477,24 @@ PICO_INTERNAL void z80_exit(void); #define EL_LOGMASK 0 #endif -#define EL_HVCNT 0x0001 /* hv counter reads */ -#define EL_SR 0x0002 /* SR reads */ -#define EL_INTS 0x0004 /* ints and acks */ -#define EL_YM2612R 0x0008 /* 68k ym2612 reads */ -#define EL_INTSW 0x0010 /* log irq switching on/off */ -#define EL_ASVDP 0x0020 /* VDP accesses during active scan */ -#define EL_VDPDMA 0x0040 /* VDP DMA transfers and their timing */ -#define EL_BUSREQ 0x0080 /* z80 busreq r/w or reset w */ -#define EL_Z80BNK 0x0100 /* z80 i/o through bank area */ -#define EL_SRAMIO 0x0200 /* sram i/o */ -#define EL_EEPROM 0x0400 /* eeprom debug */ -#define EL_UIO 0x0800 /* unmapped i/o */ -#define EL_IO 0x1000 /* all i/o */ -#define EL_CDPOLL 0x2000 /* MCD: log poll detection */ - -#define EL_STATUS 0x4000 /* status messages */ -#define EL_ANOMALY 0x8000 /* some unexpected conditions (during emulation) */ +#define EL_HVCNT 0x00000001 /* hv counter reads */ +#define EL_SR 0x00000002 /* SR reads */ +#define EL_INTS 0x00000004 /* ints and acks */ +#define EL_YM2612R 0x00000008 /* 68k ym2612 reads */ +#define EL_INTSW 0x00000010 /* log irq switching on/off */ +#define EL_ASVDP 0x00000020 /* VDP accesses during active scan */ +#define EL_VDPDMA 0x00000040 /* VDP DMA transfers and their timing */ +#define EL_BUSREQ 0x00000080 /* z80 busreq r/w or reset w */ +#define EL_Z80BNK 0x00000100 /* z80 i/o through bank area */ +#define EL_SRAMIO 0x00000200 /* sram i/o */ +#define EL_EEPROM 0x00000400 /* eeprom debug */ +#define EL_UIO 0x00000800 /* unmapped i/o */ +#define EL_IO 0x00001000 /* all i/o */ +#define EL_CDPOLL 0x00002000 /* MCD: log poll detection */ +#define EL_SVP 0x00004000 /* SVP stuff */ + +#define EL_STATUS 0x40000000 /* status messages */ +#define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */ #if EL_LOGMASK extern void lprintf(const char *fmt, ...); diff --git a/Pico/carthw/carthw.h b/Pico/carthw/carthw.h index 32c390ed..70fe1bce 100644 --- a/Pico/carthw/carthw.h +++ b/Pico/carthw/carthw.h @@ -11,11 +11,8 @@ typedef struct { extern svp_t *svp; void PicoSVPInit(void); -void PicoSVPReset(void); unsigned int PicoSVPRead16(unsigned int a, int realsize); void PicoSVPWrite8 (unsigned int a, unsigned int d, int realsize); void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize); -int PicoSVPDma(unsigned int source, unsigned short **srcp, unsigned short **limitp); - diff --git a/Pico/carthw/svp/ssp16.c b/Pico/carthw/svp/ssp16.c index 7ac1467f..26c4cac3 100644 --- a/Pico/carthw/svp/ssp16.c +++ b/Pico/carthw/svp/ssp16.c @@ -131,85 +131,343 @@ * mpys (rj), (ri), b * name: multiply and subtract? * notes: not used by VR code. + * + * + * Assumptions in this code + * P is not directly writeable */ #include "../../PicoInt.h" -#define rX ssp->gr[SSP_X].l -#define rY ssp->gr[SSP_Y].l -#define rA ssp->gr[SSP_A] // 4 -#define rST ssp->gr[SSP_ST].l -#define rSTACK ssp->gr[SSP_STACK].l -#define rPC ssp->gr[SSP_PC].l -#define rP ssp->gr[SSP_P] // 8 -#define rPM0 ssp->gr[SSP_PM0].l -#define rPM1 ssp->gr[SSP_PM1].l -#define rPM2 ssp->gr[SSP_PM2].l -#define rXST ssp->gr[SSP_XST].l // 12 -#define rPM4 ssp->gr[SSP_PM4].l // 14 -#define rPMC ssp->gr[SSP_PMC].l +#define u32 unsigned int + +// 0 +#define rX ssp->gr[SSP_X].h +#define rY ssp->gr[SSP_Y].h +#define rA ssp->gr[SSP_A].h +#define rST ssp->gr[SSP_ST].h // 4 +#define rSTACK ssp->gr[SSP_STACK].h +#define rPC ssp->gr[SSP_PC].h +#define rP ssp->gr[SSP_P] +#define rPM0 ssp->gr[SSP_PM0].h // 8 +#define rPM1 ssp->gr[SSP_PM1].h +#define rPM2 ssp->gr[SSP_PM2].h +#define rXST ssp->gr[SSP_XST].h +#define rPM4 ssp->gr[SSP_PM4].h // 12 +// 13 +#define rPMC ssp->gr[SSP_PMC] // will keep addr in .h, mode in .l #define rAL ssp->gr[SSP_A].l #define GET_PC() (PC - (unsigned short *)Pico.rom) -#define SET_PC() PC = (unsigned short *)Pico.rom + rPC +#define GET_PC_OFFS() ((unsigned int)PC - (unsigned int)Pico.rom) +#define SET_PC(d) PC = (unsigned short *)Pico.rom + d + +#define REG_READ(r) (((r) <= 4) ? ssp->gr[r].h : read_handlers[r]()) +#define REG_WRITE(r,d) { \ + int r1 = r; \ + if (r1 > 4) write_handlers[r1](d); \ + else if (r1 > 0) ssp->gr[r1].h = d; \ +} + +static ssp1601_t *ssp = NULL; +static unsigned short *PC; +static int g_cycles; + +// ----------------------------------------------------- +// register i/o handlers + +// 0-4, 13 +static u32 read_unknown(void) +{ + elprintf(EL_ANOMALY|EL_SVP, "ssp16: unknown read @ %04x", GET_PC_OFFS()); + return 0; +} + +static void write_unknown(u32 d) +{ + elprintf(EL_ANOMALY|EL_SVP, "ssp16: unknown write @ %04x", GET_PC_OFFS()); +} + +// 5 +static u32 read_STACK(void) +{ + u32 d = 0; + if (rSTACK < 6) { + d = ssp->stack[rSTACK]; + rSTACK++; + } else + elprintf(EL_ANOMALY|EL_SVP, "ssp16: stack underflow! (%i) @ %04x", rSTACK, GET_PC_OFFS()); + return d; +} + +static void write_STACK(u32 d) +{ + if (rSTACK > 0) { + rSTACK--; + ssp->stack[rSTACK] = d; + } else + elprintf(EL_ANOMALY|EL_SVP, "ssp16: stack overflow! (%i) @ %04x", rSTACK, GET_PC_OFFS()); +} + +// 6 +static u32 read_PC(void) +{ + return GET_PC(); +} + +static void write_PC(u32 d) +{ + SET_PC(d); + g_cycles--; +} + +// 7 +static u32 read_P(void) +{ + rP.v = (u32)rX * rY * 2; + return rP.h; +} + +static u32 pm_io(int reg, int write, u32 d) +{ + if (ssp->emu_status & SSP_PMC_SET) { + elprintf(EL_SVP, "PM%i (%c) set to %08x @ %04x", reg, write ? 'w' : 'r', rPMC.v, GET_PC_OFFS()); + ssp->pmac_read[write ? reg + 6 : reg] = rPMC.v; + ssp->emu_status &= ~SSP_PMC_SET; + return 0; + } + + if (ssp->pmac_read[reg] != 0) { + elprintf(EL_SVP, "PM%i %c @ %04x", reg, write ? 'w' : 'r', GET_PC_OFFS()); + // do something depending on mode + return 0; + } + + return (u32)-1; +} + +// 8 +static u32 read_PM0(void) +{ + u32 d = pm_io(0, 0, 0); + if (d != (u32)-1) return d; + elprintf(EL_SVP, "PM0 raw r %04x @ %04x", rPM0, GET_PC_OFFS()); + return rPM0; +} + +static void write_PM0(u32 d) +{ + u32 r = pm_io(0, 1, d); + if (r != (u32)-1) return; + elprintf(EL_SVP, "PM0 raw w %04x @ %04x", d, GET_PC_OFFS()); + rPM0 = d; +} + +// 9 +static u32 read_PM1(void) +{ + u32 d = pm_io(1, 0, 0); + if (d != (u32)-1) return d; + // can be removed? + elprintf(EL_SVP, "PM1 raw r %04x @ %04x", rPM1, GET_PC_OFFS()); + return rPM0; +} + +static void write_PM1(u32 d) +{ + u32 r = pm_io(1, 1, d); + if (r != (u32)-1) return; + // can be removed? + elprintf(EL_SVP, "PM1 raw w %04x @ %04x", d, GET_PC_OFFS()); + rPM0 = d; +} + +// 10 +static u32 read_PM2(void) +{ + u32 d = pm_io(2, 0, 0); + if (d != (u32)-1) return d; + // can be removed? + elprintf(EL_SVP, "PM2 raw r %04x @ %04x", rPM2, GET_PC_OFFS()); + return rPM0; +} + +static void write_PM2(u32 d) +{ + u32 r = pm_io(2, 1, d); + if (r != (u32)-1) return; + // can be removed? + elprintf(EL_SVP, "PM2 raw w %04x @ %04x", d, GET_PC_OFFS()); + rPM0 = d; +} + +// 11 +static u32 read_XST(void) +{ + // can be removed? + u32 d = pm_io(3, 0, 0); + if (d != (u32)-1) return d; + + elprintf(EL_SVP, "XST raw r %04x @ %04x", rXST, GET_PC_OFFS()); + return rPM0; +} -void ssp1601_reset(ssp1601_t *ssp) +static void write_XST(u32 d) { + // can be removed? + u32 r = pm_io(3, 1, d); + if (r != (u32)-1) return; + + elprintf(EL_SVP, "XST raw w %04x @ %04x", d, GET_PC_OFFS()); + rPM0 = d; +} + +// 12 +static u32 read_PM4(void) +{ + u32 d = pm_io(4, 0, 0); + if (d != (u32)-1) return d; + // can be removed? + elprintf(EL_SVP, "PM4 raw r %04x @ %04x", rPM4, GET_PC_OFFS()); + return rPM0; +} + +static void write_PM4(u32 d) +{ + u32 r = pm_io(4, 1, d); + if (r != (u32)-1) return; + // can be removed? + elprintf(EL_SVP, "PM4 raw w %04x @ %04x", d, GET_PC_OFFS()); + rPM0 = d; +} + +// 14 +static u32 read_PMC(void) +{ + if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { + if (ssp->emu_status & SSP_PMC_SET) + elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PC_OFFS()); + ssp->emu_status |= SSP_PMC_SET; + return rPMC.l; + } else { + ssp->emu_status |= SSP_PMC_HAVE_ADDR; + return rPMC.h; + } +} + +static void write_PMC(u32 d) +{ + if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { + if (ssp->emu_status & SSP_PMC_SET) + elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PC_OFFS()); + ssp->emu_status |= SSP_PMC_SET; + rPMC.l = d; + } else { + ssp->emu_status |= SSP_PMC_HAVE_ADDR; + rPMC.h = d; + } +} + +// 15 +static u32 read_AL(void) +{ + // TODO: figure out what's up with those blind reads.. + return rAL; +} + +static void write_AL(u32 d) +{ + rAL = d; +} + + +typedef u32 (*read_func_t)(void); +typedef void (*write_func_t)(u32 d); + +static read_func_t read_handlers[16] = +{ + read_unknown, read_unknown, read_unknown, read_unknown, // -, X, Y, A + read_unknown, // 4 ST + read_STACK, + read_PC, + read_P, + read_PM0, // 8 + read_PM1, + read_PM2, + read_XST, + read_PM4, // 12 + read_unknown, // 13 gr13 + read_PMC, + read_AL +}; + +static write_func_t write_handlers[16] = +{ + write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A + write_unknown, // 4 ST + write_STACK, + write_PC, + write_unknown, // 7 P + write_PM0, // 8 + write_PM1, + write_PM2, + write_XST, + write_PM4, // 12 + write_unknown, // 13 gr13 + write_PMC, + write_AL +}; + +void ssp1601_reset(ssp1601_t *l_ssp) +{ + ssp = l_ssp; ssp->emu_status = 0; - ssp->gr[SSP_GR0].v = 0xffff; + ssp->gr[SSP_GR0].v = 0xffff0000; rPC = 0x400; - rSTACK = 5; // ? + rSTACK = 6; // ? using descending stack } -void ssp1601_run(ssp1601_t *ssp, int cycles) +void ssp1601_run(int cycles) { - unsigned short *PC; int op; - SET_PC(); + SET_PC(rPC); + g_cycles = cycles; - while (cycles > 0) + while (g_cycles > 0) { op = *PC; switch (op >> 9) { // ld d, s case 0: - { - int s, d, opdata = 0; if (op == 0) break; // nop - s = op & 0x0f; - d = (op & 0xf0) >> 4; - if (s == SSP_A || s == SSP_P) opdata |= 1; // src is 32bit - if (d == SSP_A || d == SSP_P) opdata |= 2; // dst is 32bit - if (s == SSP_STACK) opdata |= 4; // src is stack - if (d == SSP_STACK) opdata |= 8; // dst is stack - switch (opdata) - { - case 0x0: ssp->gr[d].l = ssp->gr[s].l; break; // 16 <- 16 - case 0x1: ssp->gr[d].l = ssp->gr[s].h; break; // 16 <- 32 - case 0x2: ssp->gr[d].h = ssp->gr[s].l; break; // 32 <- 16 - // TODO: MAME claims that only hi word is transfered. Go figure. - case 0x3: ssp->gr[d].v = ssp->gr[s].v; break; // 32 <- 32 - case 0x4: ; // TODO + if (op == ((SSP_A<<4)|SSP_P)) { // A <- P + // not sure. MAME claims that only hi word is transfered. + read_P(); // update P + ssp->gr[SSP_A].v = ssp->gr[SSP_P].v; + break; } - if (d == SSP_PC) { - SET_PC(); - cycles--; + u32 d = REG_READ(op & 0x0f); + REG_WRITE((op & 0xf0) >> 4, d); } + // flags? break; - } default: - elprintf(0xffff, "ssp: unhandled op %04x @ %04x", op, GET_PC()<<1); - break; + elprintf(EL_ANOMALY|EL_SVP, "ssp16: unhandled op %04x @ %04x", op, GET_PC_OFFS()); + break; } - cycles--; + g_cycles--; PC++; } + read_P(); // update P rPC = GET_PC(); + + if (ssp->gr[SSP_GR0].v != 0xffff0000) + elprintf(EL_ANOMALY|EL_SVP, "ssp16: REG 0 corruption! %08x", ssp->gr[SSP_GR0].v); } diff --git a/Pico/carthw/svp/ssp16.h b/Pico/carthw/svp/ssp16.h index c2a40602..ef222dff 100644 --- a/Pico/carthw/svp/ssp16.h +++ b/Pico/carthw/svp/ssp16.h @@ -34,13 +34,16 @@ typedef struct }; }; unsigned short stack[6]; + unsigned int pmac_read[6]; // read modes/addrs for PM0-PM5 + unsigned int pmac_write[6]; // write ... // #define SSP_PMC_HAVE_ADDR 1 // address written to PMAC, waiting for mode + #define SSP_PMC_SET 2 // PMAC is set unsigned int emu_status; - unsigned int pad[10]; + unsigned int pad[30]; } ssp1601_t; void ssp1601_reset(ssp1601_t *ssp); -void ssp1601_run(ssp1601_t *ssp, int cycles); +void ssp1601_run(int cycles); diff --git a/Pico/carthw/svp/svp.c b/Pico/carthw/svp/svp.c index 79ea68d5..7b916ff5 100644 --- a/Pico/carthw/svp/svp.c +++ b/Pico/carthw/svp/svp.c @@ -2,16 +2,49 @@ svp_t *svp = NULL; +static void PicoSVPReset(void) +{ + elprintf(EL_SVP, "SVP reset"); + + ssp1601_reset(&svp->ssp1601); +} + + +static void PicoSVPLine(void) +{ + // ??? + // OSC_NTSC / 3.0 / 60.0 / 262.0 ~= 1139 + // OSC_PAL / 3.0 / 50.0 / 312.0 ~= 1137 + ssp1601_run(100); + exit(1); +} + + +static int PicoSVPDma(unsigned int source, unsigned short **srcp, unsigned short **limitp) +{ + if ((source & 0xfe0000) == 0x300000) + { + elprintf(EL_VDPDMA|EL_SVP, "SVP DmaSlow from %06x", source); + source &= 0x1fffe; + *srcp = (unsigned short *)(svp->ram + source); + *limitp = (unsigned short *)(svp->ram + sizeof(svp->ram)); + return 1; + } + + return 0; +} + + void PicoSVPInit(void) { void *tmp; - elprintf(0xffff, "SVP init"); + elprintf(EL_SVP, "SVP init"); tmp = realloc(Pico.rom, 0x200000 + sizeof(*svp)); if (tmp == NULL) { - elprintf(EL_STATUS, "OOM for SVP data"); + elprintf(EL_STATUS|EL_SVP, "OOM for SVP data"); return; } @@ -24,28 +57,7 @@ void PicoSVPInit(void) PicoWrite8Hook = PicoSVPWrite8; PicoWrite16Hook = PicoSVPWrite16; PicoDmaHook = PicoSVPDma; -} - - -void PicoSVPReset(void) -{ - elprintf(0xffff, "SVP reset"); - - ssp1601_reset(&svp->ssp1601); -} - - -int PicoSVPDma(unsigned int source, unsigned short **srcp, unsigned short **limitp) -{ - if ((source & 0xfe0000) == 0x300000) - { - elprintf(EL_VDPDMA|0xffff, "SVP DmaSlow from %06x", source); - source &= 0x1fffe; - *srcp = (unsigned short *)(svp->ram + source); - *limitp = (unsigned short *)(svp->ram + sizeof(svp->ram)); - return 1; - } - - return 0; + PicoResetHook = PicoSVPReset; + PicoLineHook = PicoSVPLine; } -- 2.39.5