From: Shamus Hammons Date: Thu, 17 Nov 2011 16:30:31 +0000 (+0000) Subject: Video rendering now has correct timing per frame, in both NTSC and PAL mode. X-Git-Tag: 2.0.2~9 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=253f7b2713969c4982a3149c55e378db51d7791d;p=virtualjaguar Video rendering now has correct timing per frame, in both NTSC and PAL mode. --- diff --git a/src/event.h b/src/event.h index 35f8446..9014dfb 100644 --- a/src/event.h +++ b/src/event.h @@ -9,11 +9,11 @@ #include "types.h" -// Note that these are NTSC timings: +#define RISC_CYCLE_IN_USEC 0.03760684198 +#define M68K_CYCLE_IN_USEC (RISC_CYCLE_IN_USEC * 2) -#define RISC_CYCLE_IN_USEC 0.03760684198 -#define M68K_CYCLE_IN_USEC (RISC_CYCLE_IN_USEC * 2) -#define HORIZ_PERIOD_IN_USEC 63.5555 +#define HORIZ_PERIOD_IN_USEC_NTSC 63.555555555 +#define HORIZ_PERIOD_IN_USEC_PAL 64.0 #define USEC_TO_RISC_CYCLES(u) (uint32)(((u) / RISC_CYCLE_IN_USEC) + 0.5) #define USEC_TO_M68K_CYCLES(u) (uint32)(((u) / M68K_CYCLE_IN_USEC) + 0.5) diff --git a/src/gui/mainwin.cpp b/src/gui/mainwin.cpp index 7abc8c7..af1dab1 100644 --- a/src/gui/mainwin.cpp +++ b/src/gui/mainwin.cpp @@ -185,6 +185,10 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit( useCDAct->setCheckable(true); connect(useCDAct, SIGNAL(triggered()), this, SLOT(ToggleCDUsage())); + frameAdvanceAct = new QAction(QIcon(":/res/generic.png"), tr("&Frame Advance"), this); + frameAdvanceAct->setShortcut(QKeySequence(tr("F7"))); + connect(frameAdvanceAct, SIGNAL(triggered()), this, SLOT(FrameAdvance())); + // Misc. connections... connect(filePickWin, SIGNAL(RequestLoad(QString)), this, SLOT(LoadSoftware(QString))); connect(filePickWin, SIGNAL(FilePickerHiding()), this, SLOT(Unpause())); @@ -194,6 +198,7 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit( fileMenu = menuBar()->addMenu(tr("&Jaguar")); fileMenu->addAction(powerAct); fileMenu->addAction(pauseAct); + fileMenu->addAction(frameAdvanceAct); fileMenu->addAction(filePickAct); fileMenu->addAction(useCDAct); fileMenu->addAction(configAct); @@ -640,6 +645,14 @@ void MainWin::ToggleCDUsage(void) #endif } +void MainWin::FrameAdvance(void) +{ +//printf("Frame Advance...\n"); + // Execute 1 frame, then exit (only useful in Pause mode) + JaguarExecuteNew(); + videoWidget->updateGL(); +} + void MainWin::ResizeMainWindow(void) { videoWidget->setFixedSize(zoomLevel * 320, zoomLevel * (vjs.hardwareTypeNTSC ? 240 : 256)); diff --git a/src/gui/mainwin.h b/src/gui/mainwin.h index c69c478..30d9eb2 100644 --- a/src/gui/mainwin.h +++ b/src/gui/mainwin.h @@ -48,6 +48,7 @@ class MainWin: public QMainWindow void Unpause(void); void LoadSoftware(QString); void ToggleCDUsage(void); + void FrameAdvance(void); private: void HandleKeys(QKeyEvent *, bool); @@ -92,6 +93,7 @@ class MainWin: public QMainWindow QAction * filePickAct; QAction * configAct; QAction * useCDAct; + QAction * frameAdvanceAct; QIcon powerGreen; QIcon powerRed; diff --git a/src/jaguar.cpp b/src/jaguar.cpp index 75ece20..0cd8411 100644 --- a/src/jaguar.cpp +++ b/src/jaguar.cpp @@ -1814,8 +1814,8 @@ void JaguarDone(void) JaguarDasm(0x802000, 6000); WriteLog("\n");//*/ #endif -/* WriteLog("\n\nM68000 disassembly at $802000...\n"); - JaguarDasm(0x802000, 10000); +/* WriteLog("\n\nM68000 disassembly at $4000...\n"); + JaguarDasm(0x4000, 10000); WriteLog("\n");//*/ } @@ -1843,6 +1843,8 @@ void JaguarExecute(uint32 * backbuffer, bool render) //seem to indicate the refresh rate is *half* the above... // uint16 refreshRate = (vjs.hardwareTypeNTSC ? 30 : 25); // Should these be hardwired or read from VP? Yes, from VP! + // Err, actually, they should be hardwired, and hardwired to a set # of + // lines as well... uint32 M68KCyclesPerScanline = m68kClockRate / (vp * refreshRate); uint32 RISCCyclesPerScanline = m68kClockRate / (vp * refreshRate); @@ -1951,15 +1953,68 @@ void JaguarExecuteNew(void) while (!frameDone); } +/* +BIG NOTE: NEED TO FIX THIS TO RUN ON ABSOLUTE TIMINGS BASED ON SCANLINES, + *NOT* ON THE VERTICAL PERIOD!!! + + scanlines are 64 µs in PAL + and 63.5555... µs in NTSC + +Also: 625 lines per frame in PAL, 525 in NTSC + +So... can use +#define RISC_CYCLE_IN_USEC 0.03760684198 +#define M68K_CYCLE_IN_USEC (RISC_CYCLE_IN_USEC * 2) + +#define HORIZ_PERIOD_IN_USEC_NTSC 63.555555555 +#define HORIZ_PERIOD_IN_USEC_PAL 64.0 + +#define USEC_TO_RISC_CYCLES(u) (uint32)(((u) / RISC_CYCLE_IN_USEC) + 0.5) +#define USEC_TO_M68K_CYCLES(u) (uint32)(((u) / M68K_CYCLE_IN_USEC) + 0.5) + +to figure cycles per half-line... + +USEC_TO_RISC_CYCLES(HORIZ_PERIOD_IN_USEC_NTSC) / 2 +USEC_TO_M68K_CYCLES(HORIZ_PERIOD_IN_USEC_NTSC) / 2 +USEC_TO_RISC_CYCLES(HORIZ_PERIOD_IN_USEC_PAL) / 2 +USEC_TO_M68K_CYCLES(HORIZ_PERIOD_IN_USEC_PAL) / 2 + +// Full lines here, divide by two for half-lines... +which gives the following: 1690, 845 (NTSC), 1702, 851 (PAL) +So, for a full frame, that would yield: +887250 (NTSC), 1063750 (PAL) +one second: +26617500 (NTSC), 26593750 (PAL) + +Which is off a little bit for NTSC... +#define M68K_CLOCK_RATE_PAL 13296950 +#define M68K_CLOCK_RATE_NTSC 13295453 +#define RISC_CLOCK_RATE_PAL 26593900 +#define RISC_CLOCK_RATE_NTSC 26590906 + +*/ + +#define USE_CORRECT_PAL_TIMINGS void ScanlineCallback(void) { +//OK, this is hardwired to run in NTSC, and for who knows how long. +//Need to fix this so that it does a half-line in the correct amount of time +//and number of lines, depending on which mode we're in. [FIXED] uint16 vc = TOMReadWord(0xF00006, JAGUAR); uint16 vp = TOMReadWord(0xF0003E, JAGUAR) + 1; uint16 vi = TOMReadWord(0xF0004E, JAGUAR); // uint16 vbb = TOMReadWord(0xF00040, JAGUAR); vc++; +#ifdef USE_CORRECT_PAL_TIMINGS + // Each # of lines is for a full frame == 1/30s (NTSC), 1/25s (PAL). + // So we cut the number of half-lines in a frame in half. :-P + uint16 numHalfLines = ((vjs.hardwareTypeNTSC ? 525 : 625) * 2) / 2; + + if (vc >= numHalfLines) +#else if (vc >= vp) +#endif vc = 0; //WriteLog("SLC: Currently on line %u (VP=%u)...\n", vc, vp); @@ -1986,8 +2041,12 @@ void ScanlineCallback(void) frameDone = true; }//*/ +#ifdef USE_CORRECT_PAL_TIMINGS + SetCallbackTime(ScanlineCallback, (vjs.hardwareTypeNTSC ? 31.777777777 : 32.0)); +#else // SetCallbackTime(ScanlineCallback, 63.5555); SetCallbackTime(ScanlineCallback, 31.77775); +#endif } // This isn't currently used, but maybe it should be... diff --git a/src/tom.cpp b/src/tom.cpp index 08832a8..82062bd 100644 --- a/src/tom.cpp +++ b/src/tom.cpp @@ -780,10 +780,18 @@ void TOMExecScanline(uint16 scanline, bool render) // to do a scanline render in the non-display area... [DONE] //this seems to cause a regression in certain games, like rayman //which means I have to dig thru the asic nets to see what's wrong... +/* +No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the +HALF line that the OP starts on--which means that it needs to start at VDB / 2!!! + +Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames. +*/ #if 1 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman +// if (scanline >= ((uint16)GET16(tomRam8, VDB) / 2) && scanline < ((uint16)GET16(tomRam8, VDE) / 2)) if (scanline >= (uint16)GET16(tomRam8, VDB) && scanline < (uint16)GET16(tomRam8, VDE)) -// if (scanline >= ((uint16)GET16(tomRam8, VDB) - 32) && scanline < (uint16)GET16(tomRam8, VDE)) +// if (scanline >= ((uint16)GET16(tomRam8, VDB) - 16) && scanline < (uint16)GET16(tomRam8, VDE)) +// if (scanline >= 20 && scanline < (uint16)GET16(tomRam8, VDE)) { if (render) {