From e42a47e2086e6512519dd86af420363498302f49 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 2 Oct 2017 23:38:12 +0300 Subject: [PATCH] some more risky timing changes But should be closer to the real thing. Let's see what this will break... --- pico/cd/mcd.c | 2 +- pico/debug.c | 2 +- pico/draw.c | 7 +-- pico/memory.c | 1 - pico/pico.c | 30 +++++------ pico/pico/pico.c | 2 +- pico/pico_cmn.c | 132 +++++++++++++++++++++++++++++---------------- pico/pico_int.h | 23 ++++++-- pico/sound/sound.c | 10 ++-- pico/state.c | 1 + 10 files changed, 129 insertions(+), 81 deletions(-) diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c index 687dfc3c..6d23604c 100644 --- a/pico/cd/mcd.c +++ b/pico/cd/mcd.c @@ -146,7 +146,7 @@ static void pcd_set_cycle_mult(void) { // ~1.63 for NTSC, ~1.645 for PAL if (Pico.m.pal) - mcd_m68k_cycle_mult = ((12500000ull << 16) / (50*312*488)); + mcd_m68k_cycle_mult = ((12500000ull << 16) / (50*313*488)); else mcd_m68k_cycle_mult = ((12500000ull << 16) / (60*262*488)) + 1; } diff --git a/pico/debug.c b/pico/debug.c index e780262e..af5241c1 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -358,7 +358,7 @@ void PDebugZ80Frame(void) return; if (Pico.m.pal) { - lines = 312; + lines = 313; line_sample = 68; } else { lines = 262; diff --git a/pico/draw.c b/pico/draw.c index 5e8d86b4..e2e4fb49 100644 --- a/pico/draw.c +++ b/pico/draw.c @@ -1553,13 +1553,14 @@ void PicoDrawSync(int to, int blank_last_line) pprof_start(draw); - if (rendlines != 240) + if (rendlines != 240) { offs = 8; + if (to > 223) + to = 223; + } for (line = Pico.est.DrawScanline; line < to; line++) - { PicoLine(line, offs, sh, bgc); - } // last line if (line <= to) diff --git a/pico/memory.c b/pico/memory.c index 3900208b..5d1d25f7 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -539,7 +539,6 @@ static void PicoWrite8_z80(u32 a, u32 d) } if ((a & 0x4000) == 0x0000) { // z80 RAM - SekCyclesBurnRun(2); // FIXME hack Pico.zram[a & 0x1fff] = (u8)d; return; } diff --git a/pico/pico.c b/pico/pico.c index 23f7efb2..f0c54d17 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -22,7 +22,6 @@ int PicoAutoRgnOrder; struct PicoSRAM SRam; int emustatus; // rapid_ym2612, multi_ym_updates -int scanlines_total; void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware void (*PicoResetHook)(void) = NULL; @@ -227,29 +226,24 @@ void PicoLoopPrepare(void) // force setting possibly changed.. Pico.m.pal = (PicoRegionOverride == 2 || PicoRegionOverride == 8) ? 1 : 0; - // FIXME: PAL has 313 scanlines.. - scanlines_total = Pico.m.pal ? 312 : 262; - Pico.m.dirtyPal = 1; rendstatus_old = -1; } - -// dma2vram settings are just hacks to unglitch Legend of Galahad (needs <= 104 to work) -// same for Outrunners (92-121, when active is set to 24) -// 96 is VR hack +// this table is wrong and should be removed +// keeping it for now to compensate wrong timing elswhere, mainly for Outrunners static const int dma_timings[] = { - 167, 167, 166, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy - 102, 205, 204, 102, // vblank: 40cell: - 16, 16, 15, 8, // active: 32cell: - 24, 18, 17, 9 // ... + 83, 166, 83, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy + 102, 204, 102, 102, // vblank: 40cell: + 8, 16, 8, 8, // active: 32cell: + 17, 18, 9, 9 // ... }; static const int dma_bsycles[] = { - (488<<8)/167, (488<<8)/167, (488<<8)/166, (488<<8)/83, - (488<<8)/102, (488<<8)/233, (488<<8)/204, (488<<8)/102, - (488<<8)/16, (488<<8)/16, (488<<8)/15, (488<<8)/8, - (488<<8)/24, (488<<8)/18, (488<<8)/17, (488<<8)/9 + (488<<8)/83, (488<<8)/166, (488<<8)/83, (488<<8)/83, + (488<<8)/102, (488<<8)/204, (488<<8)/102, (488<<8)/102, + (488<<8)/8, (488<<8)/16, (488<<8)/8, (488<<8)/8, + (488<<8)/9, (488<<8)/18, (488<<8)/9, (488<<8)/9 }; // grossly inaccurate.. FIXME FIXXXMEE @@ -304,8 +298,8 @@ PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done) pprof_start(z80); elprintf(EL_BUSREQ, "z80 sync %i (%u|%u -> %u|%u)", cnt, - z80_cycle_cnt, z80_cycle_cnt / 288, - z80_cycle_aim, z80_cycle_aim / 288); + z80_cycle_cnt, z80_cycle_cnt / 228, + z80_cycle_aim, z80_cycle_aim / 228); if (cnt > 0) z80_cycle_cnt += z80_run(cnt); diff --git a/pico/pico/pico.c b/pico/pico/pico.c index bff5a2a4..d893f9df 100644 --- a/pico/pico/pico.c +++ b/pico/pico/pico.c @@ -23,7 +23,7 @@ PICO_INTERNAL void PicoReratePico(void) { int rate = guessed_rates[PicoPicohw.r12 & 7]; if (Pico.m.pal) - fifo_bytes_line = (rate<<16)/50/312/2; + fifo_bytes_line = (rate<<16)/50/313/2; else fifo_bytes_line = (rate<<16)/60/262/2; PicoPicoPCMRerate(rate); } diff --git a/pico/pico_cmn.c b/pico/pico_cmn.c index 78fdd120..b44bfba2 100644 --- a/pico/pico_cmn.c +++ b/pico/pico_cmn.c @@ -8,7 +8,6 @@ #define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC #define CYCLES_M68K_VINT_LAG 68 -#define CYCLES_M68K_ASD 148 // pad delay (for 6 button pads) #define PAD_DELAY() { \ @@ -53,13 +52,28 @@ static void SekSyncM68k(void) static inline void SekRunM68k(int cyc) { SekCycleAim += cyc; + cyc = SekCycleAim - SekCycleCnt; + if (cyc <= 0) + return; + SekCycleCnt += cyc >> 6; // refresh slowdowns SekSyncM68k(); } +static void do_hint(struct PicoVideo *pv) +{ + pv->pending_ints |= 0x10; + if (pv->reg[0] & 0x10) { + elprintf(EL_INTS, "hint: @ %06x [%u]", SekPc, SekCyclesDone()); + SekInterrupt(4); + } +} + static int PicoFrameHints(void) { - struct PicoVideo *pv=&Pico.video; - int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap; + struct PicoVideo *pv = &Pico.video; + int line_sample = Pico.m.pal ? 68 : 93; + int lines, y, lines_vis, skip; + int vcnt_wrap, vcnt_adj; unsigned int cycles; int hint; // Hint counter @@ -77,25 +91,15 @@ static int PicoFrameHints(void) } else skip=PicoSkipFrame; - if (Pico.m.pal) { - line_sample = 68; - if (pv->reg[1]&8) lines_vis = 240; - } else { - line_sample = 93; - } - z80_resetCycles(); PsndStartFrame(); - pv->status&=~0x88; // clear V-Int, come out of vblank + // Load H-Int counter + hint = (pv->status & PVS_ACTIVE) ? pv->hint_cnt : pv->reg[10]; - hint=pv->reg[10]; // Load H-Int counter - //dprintf("-hint: %i", hint); + pv->status |= PVS_ACTIVE; - // This is to make active scan longer (needed for Double Dragon 2, mainly) - CPUS_RUN(CYCLES_M68K_ASD); - - for (y = 0; y < lines_vis; y++) + for (y = 0; ; y++) { pv->v_counter = Pico.m.scanline = y; if ((pv->reg[12]&6) == 6) { // interlace mode 2 @@ -104,24 +108,23 @@ static int PicoFrameHints(void) pv->v_counter &= 0xff; } + if ((y == 224 && !(pv->reg[1] & 8)) || y == 240) + break; + // VDP FIFO pv->lwrite_cnt -= 12; if (pv->lwrite_cnt <= 0) { - pv->lwrite_cnt=0; - Pico.video.status|=0x200; + pv->lwrite_cnt = 0; + Pico.video.status |= SR_EMPT; } PAD_DELAY(); // H-Interrupts: - if (--hint < 0) // y <= lines_vis: Comix Zone, Golden Axe + if (--hint < 0) { - hint=pv->reg[10]; // Reload H-Int counter - pv->pending_ints|=0x10; - if (pv->reg[0]&0x10) { - elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCyclesDone()); - SekInterrupt(4); - } + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); } // decide if we draw this line @@ -163,6 +166,10 @@ static int PicoFrameHints(void) pevt_log_m68k_o(EVT_NEXT_LINE); } + lines_vis = (pv->reg[1] & 8) ? 240 : 224; + if (y == lines_vis) + pv->status &= ~PVS_ACTIVE; + if (!skip) { if (Pico.est.DrawScanline < y) @@ -172,29 +179,22 @@ static int PicoFrameHints(void) #endif } - // V-int line (224 or 240) - Pico.m.scanline = y; - pv->v_counter = 0xe0; // bad for 240 mode - if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1; - // VDP FIFO - pv->lwrite_cnt=0; - Pico.video.status|=0x200; + pv->lwrite_cnt = 0; + Pico.video.status |= SR_EMPT; memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt)); PAD_DELAY(); - // Last H-Int: + // Last H-Int (normally): if (--hint < 0) { - hint=pv->reg[10]; // Reload H-Int counter - pv->pending_ints|=0x10; - //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCyclesDone()); - if (pv->reg[0]&0x10) SekInterrupt(4); + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); } - pv->status|=0x08; // go into vblank - pv->pending_ints|=0x20; + pv->status |= SR_VB; // go into vblank + pv->pending_ints |= 0x20; // the following SekRun is there for several reasons: // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga) @@ -204,8 +204,8 @@ static int PicoFrameHints(void) if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); CPUS_RUN(CYCLES_M68K_VINT_LAG); - if (pv->reg[1]&0x20) { - elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCyclesDone()); + if (pv->reg[1] & 0x20) { + elprintf(EL_INTS, "vint: @ %06x [%u]", SekPc, SekCyclesDone()); SekInterrupt(6); } @@ -230,25 +230,39 @@ static int PicoFrameHints(void) PsndGetSamples(y); // Run scanline: - CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD); + CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG); if (PicoLineHook) PicoLineHook(); pevt_log_m68k_o(EVT_NEXT_LINE); - lines = scanlines_total; - vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens, TODO: verify + if (Pico.m.pal) { + lines = 313; + vcnt_wrap = 0x103; + vcnt_adj = 57; + } + else { + lines = 262; + vcnt_wrap = 0xEB; + vcnt_adj = 6; + } - for (y++; y < lines; y++) + for (y++; y < lines - 1; y++) { pv->v_counter = Pico.m.scanline = y; if (y >= vcnt_wrap) - pv->v_counter -= Pico.m.pal ? 56 : 6; + pv->v_counter -= vcnt_adj; if ((pv->reg[12]&6) == 6) pv->v_counter = (pv->v_counter << 1) | 1; pv->v_counter &= 0xff; PAD_DELAY(); + if ((pv->status & PVS_ACTIVE) && --hint < 0) + { + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); + } + // Run scanline: line_base_cycles = SekCyclesDone(); if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); @@ -258,6 +272,28 @@ static int PicoFrameHints(void) pevt_log_m68k_o(EVT_NEXT_LINE); } + pv->status &= ~SR_VB; + + // last scanline + Pico.m.scanline = y; + pv->v_counter = 0xff; + + PAD_DELAY(); + + if ((pv->status & PVS_ACTIVE) && --hint < 0) + { + hint = pv->reg[10]; // Reload H-Int counter + do_hint(pv); + } + + // Run scanline: + line_base_cycles = SekCyclesDone(); + if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + CPUS_RUN(CYCLES_M68K_LINE); + + if (PicoLineHook) PicoLineHook(); + pevt_log_m68k_o(EVT_NEXT_LINE); + // sync cpus cycles = SekCyclesDone(); if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) @@ -276,6 +312,8 @@ static int PicoFrameHints(void) #endif timers_cycle(); + pv->hint_cnt = hint; + return 0; } diff --git a/pico/pico_int.h b/pico/pico_int.h index f439d6af..743ecb48 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -283,6 +283,7 @@ extern SH2 sh2s[2]; #define OSC_NTSC 53693100 #define OSC_PAL 53203424 +// PicoVideo.debug_p #define PVD_KILL_A (1 << 0) #define PVD_KILL_B (1 << 1) #define PVD_KILL_S_LO (1 << 2) @@ -292,6 +293,20 @@ extern SH2 sh2s[2]; #define PVD_FORCE_B (1 << 6) #define PVD_FORCE_S (1 << 7) +// PicoVideo.status, not part of real SR +#define SR_PAL (1 << 0) +#define SR_DMA (1 << 1) +#define SR_HB (1 << 2) +#define SR_VB (1 << 3) +#define SR_ODD (1 << 4) +#define SR_C (1 << 5) +#define SR_SOVR (1 << 6) +#define SR_F (1 << 7) +#define SR_FULL (1 << 8) +#define SR_EMPT (1 << 9) +// not part of real SR +#define PVS_ACTIVE (1 << 16) + struct PicoVideo { unsigned char reg[0x20]; @@ -299,14 +314,15 @@ struct PicoVideo unsigned char pending; // 1 if waiting for second half of 32-bit command unsigned char type; // Command type (v/c/vsram read/write) unsigned short addr; // Read/Write address - int status; // Status bits + unsigned int status; // Status bits (SR) and extra flags unsigned char pending_ints; // pending interrupts: ??VH???? signed char lwrite_cnt; // VDP write count during active display line unsigned short v_counter; // V-counter unsigned short debug; // raw debug register unsigned char debug_p; // ... parsed: PVD_* - unsigned char addr_u; - unsigned char pad[0x0c]; + unsigned char addr_u; // bit16 of .addr + unsigned char hint_cnt; + unsigned char pad[0x0b]; }; struct PicoMisc @@ -684,7 +700,6 @@ extern struct Pico Pico; extern struct PicoSRAM SRam; extern int PicoPadInt[2]; extern int emustatus; -extern int scanlines_total; extern void (*PicoResetHook)(void); extern void (*PicoLineHook)(void); PICO_INTERNAL int CheckDMA(void); diff --git a/pico/sound/sound.c b/pico/sound/sound.c index 510a9aba..a67ebcca 100644 --- a/pico/sound/sound.c +++ b/pico/sound/sound.c @@ -44,7 +44,7 @@ extern int *sn76496_regs; static void dac_recalculate(void) { - int i, dac_cnt, pos, len, lines = Pico.m.pal ? 312 : 262, mid = Pico.m.pal ? 68 : 93; + int i, dac_cnt, pos, len, lines = Pico.m.pal ? 313 : 262, mid = Pico.m.pal ? 68 : 93; if (PsndLen <= lines) { @@ -169,8 +169,8 @@ PICO_INTERNAL void PsndDoDAC(int line_to) int dout = ym2612.dacout; int line_from = PsndDacLine; - if (line_to >= 312) - line_to = 311; + if (line_to >= 313) + line_to = 312; pos = dac_info[line_from]; pos1 = dac_info[line_to + 1]; @@ -198,8 +198,8 @@ PICO_INTERNAL void PsndDoPSG(int line_to) int pos, pos1, len; int stereo = 0; - if (line_to >= 312) - line_to = 311; + if (line_to >= 313) + line_to = 312; pos = dac_info[line_from]; pos1 = dac_info[line_to + 1]; diff --git a/pico/state.c b/pico/state.c index 3cd41b2b..f4e685fb 100644 --- a/pico/state.c +++ b/pico/state.c @@ -687,6 +687,7 @@ static int pico_state_internal(void *afile, int is_save) } Pico.m.dirtyPal = 1; + Pico.video.status &= ~(SR_VB | SR_F); } return ret; -- 2.39.5