Ejemplo n.º 1
0
// Funções:
//===========================================================================
void ContinueExecution ()
{
	static   DWORD dwVideoUpdateTick = 0;
	static   BOOL pageflipping    = 0; //?
	int      nNumCyclesPerFrame = 23191;
	DWORD    nCyclesToExecute;
	DWORD    executedcycles;
	DWORD    CLKS_PER_MS;
	BOOL     diskspinning;
	BOOL     screenupdated;
	BOOL     systemidle;

	fullspeed = ( (speed == SPEED_MAX) || 
				 (GetKeyState(VK_SCROLL) < 0) ||
				 (ColarRapido && KeybIsPasting()) ||
				 (DiskIsSpinning() && enhancedisk));

	if(fullspeed)
	{
		Timer_StopTimer();
	}
	else
	{
		Timer_StartTimer((ULONG)((double)nNumCyclesPerFrame / g_fMHz));
	}

	nCyclesToExecute = nNumCyclesPerFrame + g_nCpuCyclesFeedback;
	executedcycles = CpuExecute(nCyclesToExecute);

	cyclenum = executedcycles;
	
	// Atualizações:
	KeybAtualiza(executedcycles);
	DiskUpdatePosition(executedcycles);
	JoyUpdatePosition(executedcycles);
//	VideoUpdateVbl(executedcycles, 0);  /* TO DO: nearrefresh */
//	HDAtualiza(executedcycles);
//	IDEAtualiza(executedcycles);
//	TKClockAtualiza(executedcycles);
	TapeAtualiza(executedcycles);
//	CommUpdate(executedcycles);
	ImpressoraAtualiza(executedcycles);
	SpkrUpdate(executedcycles);
	
	CLKS_PER_MS = (DWORD)g_fCurrentCLK6502 / 1000;

	emulmsec_frac += executedcycles;
	if(emulmsec_frac > CLKS_PER_MS)
	{
		emulmsec += emulmsec_frac / CLKS_PER_MS;
		emulmsec_frac %= CLKS_PER_MS;
	}

	//
	// DETERMINE WHETHER THE SCREEN WAS UPDATED, THE DISK WAS SPINNING,
	// OR THE KEYBOARD I/O PORTS WERE BEING EXCESSIVELY QUERIED THIS CLOCKTICK
	VideoCheckPage(0);
	diskspinning  = DiskIsSpinning();
	screenupdated = VideoHasRefreshed();
	systemidle    = 0;

	if(screenupdated)
		pageflipping = 3;

	//
	// IF A TWENTIETH OF A SECOND HAS ELAPSED AND THE SCREEN HAS NOT BEEN
	// UPDATED BUT IT APPEARS TO NEED UPDATING, THEN REFRESH IT
	if(mode != MODE_LOGO)
	{
		const DWORD _50ms = 50;	// 50ms == 20Hz
		DWORD dwCyclesPerScreenUpdate = _50ms * (DWORD) (g_fCurrentCLK6502 / 1000.0);

		if((GetTickCount() - dwVideoUpdateTick) > _50ms)
		{
			static BOOL  anyupdates     = 0;
			static DWORD lastcycles     = 0;
			static BOOL  lastupdates[2] = {0,0};

			dwVideoUpdateTick = GetTickCount();

			anyupdates |= screenupdated;

			if ((cumulativecycles-lastcycles) >= dwCyclesPerScreenUpdate)
			{
				lastcycles = cumulativecycles;
				if ((!anyupdates) && (!lastupdates[0]) && (!lastupdates[1]) &&
					VideoApparentlyDirty())
				{
					static DWORD lasttime = 0;
					DWORD currtime = GetTickCount();

					VideoCheckPage(1);
					if ((!fullspeed) ||
						(currtime-lasttime >= (DWORD)((graphicsmode || !systemidle) ? 100 : 25)))
					{
						VideoRefreshScreen();
						lasttime = currtime;
					}
					screenupdated = 1;
				}

				lastupdates[1] = lastupdates[0];
				lastupdates[0] = anyupdates;
				anyupdates     = 0;

				if (pageflipping)
					pageflipping--;
			}
		}
	}
	if(!fullspeed)
	{
		Timer_WaitTimer();
	}
}
Ejemplo n.º 2
0
void ContinueExecution()
{
	static BOOL pageflipping    = 0; //?

	const double fUsecPerSec        = 1.e6;
#if 1
	const UINT nExecutionPeriodUsec = 1000;		// 1.0ms
//	const UINT nExecutionPeriodUsec = 100;		// 0.1ms
	const double fExecutionPeriodClks = g_fCurrentCLK6502 * ((double)nExecutionPeriodUsec / fUsecPerSec);
#else
	const double fExecutionPeriodClks = 1800.0;
	const UINT nExecutionPeriodUsec = (UINT) (fUsecPerSec * (fExecutionPeriodClks / g_fCurrentCLK6502));
#endif

	//

	bool bScrollLock_FullSpeed = g_uScrollLockToggle
									? g_bScrollLock_FullSpeed
									: (GetKeyState(VK_SCROLL) < 0);

	g_bFullSpeed = ( (g_dwSpeed == SPEED_MAX) || 
					 bScrollLock_FullSpeed ||
					 (DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) );

	if(g_bFullSpeed)
	{
		// Don't call Spkr_Mute() - will get speaker clicks
		MB_Mute();
		SysClk_StopTimer();

		g_nCpuCyclesFeedback = 0;	// For the case when this is a big -ve number
	}
	else
	{
		// Don't call Spkr_Demute()
		MB_Demute();
		SysClk_StartTimerUsec(nExecutionPeriodUsec);
	}

	//

	int nCyclesToExecute = (int) fExecutionPeriodClks + g_nCpuCyclesFeedback;
	if(nCyclesToExecute < 0)
		nCyclesToExecute = 0;

	DWORD dwExecutedCycles = CpuExecute(nCyclesToExecute);

	g_dwCyclesThisFrame += dwExecutedCycles;

	//

	cyclenum = dwExecutedCycles;

	DiskUpdatePosition(dwExecutedCycles);
	JoyUpdatePosition();
	VideoUpdateVbl(g_dwCyclesThisFrame);

	SpkrUpdate(cyclenum);
	sg_SSC.CommUpdate(cyclenum);
	PrintUpdate(cyclenum);

	//

	const DWORD CLKS_PER_MS = (DWORD)g_fCurrentCLK6502 / 1000;

	emulmsec_frac += dwExecutedCycles;
	if(emulmsec_frac > CLKS_PER_MS)
	{
		emulmsec += emulmsec_frac / CLKS_PER_MS;
		emulmsec_frac %= CLKS_PER_MS;
	}

	//
	// DETERMINE WHETHER THE SCREEN WAS UPDATED, THE DISK WAS SPINNING,
	// OR THE KEYBOARD I/O PORTS WERE BEING EXCESSIVELY QUERIED THIS CLOCKTICK
	VideoCheckPage(0);
	BOOL screenupdated = VideoHasRefreshed();
	BOOL systemidle    = 0;	//(KeybGetNumQueries() > (clockgran << 2));	//  && (!ranfinegrain);	// TO DO

	if(screenupdated)
		pageflipping = 3;

	//

	if(g_dwCyclesThisFrame >= dwClksPerFrame)
	{
		g_dwCyclesThisFrame -= dwClksPerFrame;

		if(g_nAppMode != MODE_LOGO)
		{
			VideoUpdateFlash();

			static BOOL  anyupdates     = 0;
			static DWORD lastcycles     = 0;
			static BOOL  lastupdates[2] = {0,0};

			anyupdates |= screenupdated;

			//

			lastcycles = cumulativecycles;
			if ((!anyupdates) && (!lastupdates[0]) && (!lastupdates[1]) && VideoApparentlyDirty())
			{
				VideoCheckPage(1);
				static DWORD lasttime = 0;
				DWORD currtime = GetTickCount();
				if ((!g_bFullSpeed) ||
					(currtime-lasttime >= (DWORD)((graphicsmode || !systemidle) ? 100 : 25)))
				{
					VideoRefreshScreen();
					lasttime = currtime;
				}
				screenupdated = 1;
			}

			lastupdates[1] = lastupdates[0];
			lastupdates[0] = anyupdates;
			anyupdates     = 0;

			if (pageflipping)
				pageflipping--;
		}

		MB_EndOfVideoFrame();
	}

	//

	if(!g_bFullSpeed)
	{
		SysClk_WaitTimer();

#if DBG_CALC_FREQ
		if(g_nPerfFreq)
		{
			QueryPerformanceCounter((LARGE_INTEGER*)&nTime1);
			LONGLONG nTimeDiff = nTime1 - nTime0;
			double fTime = (double)nTimeDiff / (double)(LONGLONG)g_nPerfFreq;

			g_fDbg[g_nIdx] = fTime;
			g_nIdx = (g_nIdx+1) & (MAX_CNT-1);
			g_fMeanPeriod = 0.0;
			for(UINT n=0; n<MAX_CNT; n++)
				g_fMeanPeriod += g_fDbg[n];
			g_fMeanPeriod /= (double)MAX_CNT;
			g_fMeanFreq = 1.0 / g_fMeanPeriod;
		}
#endif
	}
}
Ejemplo n.º 3
0
void EmulatorThread::run()
{
    // Load PC from Reset Vector
    CpuInitialize();
    lcdoffshift0flag = false;
    //g_stp = 1; // test
#ifndef FAKENMI
    unsigned int nmistart = GetTickCount();
#endif
    gThreadFlags &= 0xFFFEu; // Remove 0x01 from gThreadFlags (stack related)
#ifdef AUTOTEST
    unsigned totalline = 0; // TODO: long long
    enablelogging = false;
#endif
    while(fKeeping) {
#if 1
        const unsigned spdc1016freq = GlobalSetting.SPDC1016Frequency;
#endif
#ifdef FAMENMI
        twohznmicycle = spdc1016freq / 2;
#endif
        while (batchcount >= 0 && fKeeping) {
#ifdef AUTOTEST
            totalline++;
            TryTest(totalline);
#endif // AUTOTEST
#ifdef LOGASM
#ifdef AUTOTEST
            if (enablelogging) {
#endif
#ifdef HANDYPSP
                LogDisassembly(mPC, NULL);
#else
                LogDisassembly(regs.pc, NULL);
#endif // HANDYPSP
#ifdef AUTOTEST
            }
#endif // AUTOTEST
#endif // LOGASM
            if (matrixupdated) {
                matrixupdated = false;
                AppendLog("keypadmatrix updated.");
            }

            nmicount++; // MERGEASM
            // 2Hz NMI
            // TODO: use batchcount as NMI source
#ifdef FAKENMI
            if (nmicount % 400000 == 0) {
                nmicount = 0; // MERGEASM
            //if (twohznmicycle < 0) {
            //    twohznmicycle = spdc1016freq / 2; // reset
#else
            // in CC800 hardware, NMI is generated by 32.768k crystal, but spdc1016 use RC oscillator so cycle/NMI can be mismatched.
            unsigned int dummynow = GetTickCount();
            if (dummynow - nmistart >= 500) {
                nmistart += 500;
#endif
                //g_nmi = 0; // next CpuExecute will execute two instructions
                gThreadFlags |= 0x08; // Add NMIFlag
            }

            // NMI > IRQ
            if ((gThreadFlags & 0x08) != 0) {
                gThreadFlags &= 0xFFF7u; // remove 0x08 NMI Flag
                // FIXME: NO MORE REVERSE
                g_nmi = TRUE; // next CpuExecute will execute two instructions
                qDebug("ggv wanna NMI.");
                //fprintf(stderr, "ggv wanna NMI.\n");
                gDeadlockCounter--; // wrong behavior of wqxsim
#ifdef HANDYPSP
            } else if (((PS() & AF_INTERRUPT) == 0) && ((gThreadFlags & TF_IRQFLAG) != 0)) {
#else
            } else if (((regs.ps & 0x4) == 0) && ((gThreadFlags & 0x10) != 0)) {
#endif
                gThreadFlags &= 0xFFEFu; // remove 0x10 IRQ Flag
                g_irq = TRUE; // B flag (AF_BREAK) will remove in CpuExecute
                qDebug("ggv wanna IRQ.");
                gDeadlockCounter--; // wrong behavior of wqxsim
            }

            DWORD CpuTicks = CpuExecute();
            totalcycle += CpuTicks;
            twohznmicycle -= CpuTicks;
            // add checks for reset, IRQ, NMI, and other pin signals
            if (lastTicket == 0) {
                lastTicket = GetTickCount();
            }

            gDeadlockCounter++;
            if (gDeadlockCounter == 6000) {
                // overflowed
                gDeadlockCounter = 0;
                if ((gThreadFlags & 0x80u) == 0) {
                    // CheckTimerbaseAndEnableIRQnEXIE1
                    CheckTimebaseAndEnableIRQnEXIE1();
                    if (timer0started) {
                        // mayDestAddr == 5 in ReadRegister
                        // mayBaseTable have 0x100 elements?
                        //increment = mayBasetable[mayDestAddr];  // mayBaseTable[5] == 3
                        //t0overflow = (unsigned int)(increment + mayPreviousTimer0Value) < 0xFF;
                        //mayPreviousTimer0Value += increment;
                        //if ( !t0overflow )
                        //{
                        //    mayPreviousTimer0Value = 0;
                        //    Turnoff2HzNMIMaskAddIRQFlag();
                        //}
                        int increment = 3;
                        prevtimer0value += increment;
                        if (prevtimer0value >= 0xFFu) {
                            prevtimer0value = 0;
                            Turnoff2HzNMIMaskAddIRQFlag();
                        }
                    }
                } else {
                    // RESET
                    fixedram0000[io01_int_enable] |= 0x1; // TIMER A INTERRUPT ENABLE
                    fixedram0000[io02_timer0_val] |= 0x1; // [io01+1] Timer0 bit1 = 1
                    gThreadFlags &= 0xFF7F;      // remove 0x80 | 0x10
#ifdef HANDYPSP
                    mPC = *(unsigned short*)&pmemmap[mapE000][0x1FFC];
#else
                    regs.pc = *(unsigned short*)&pmemmap[mapE000][0x1FFC];
#endif
                }
            } else {
                if (timer0started) {
                    // mayDestAddr == 5 in ReadRegister
                    // mayBaseTable have 0x100 elements?
                    int increment = 3;
                    prevtimer0value += increment;
                    if (prevtimer0value >= 0xFFu) {
                        prevtimer0value = 0;
                        Turnoff2HzNMIMaskAddIRQFlag();
                    }
                }
            }
            

            //if (timer0started) {
            //    fixedram0000[io02_timer0_val] = fixedram0000[io02_timer0_val] + 1;
            //}
            //if (timer1started) {
            //    fixedram0000[io03_timer1_val] = fixedram0000[io03_timer1_val] + 1;
            //}

            // TODO: dynamic re-measure
            if (measured == false && totalcycle % spdc1016freq < 10 && totalcycle > spdc1016freq) {
                measured = true;
#if 0
                // fixed rate on device
                // realworld time = 106
#ifdef HANDYPSP
                batchlimiter = spdc1016freq / 88; // 12*10=120ms
#else
                batchlimiter = spdc1016freq / 4;
#endif
                batchcount = batchlimiter;
#else
                if (totalcycle < spdc1016freq * 2) {
                    // first loop check!
                    // spdc1016 executed one second in fullspeed virtual timeline
                    unsigned long long realworldtime = GetTickCount() - lastTicket; // should less than 1000ms
                    lastTicket = GetTickCount();
                    //double virtual100ms = realworldtime / 100.0;
                    qDebug("realworldtime:%llu", realworldtime);
                    fprintf(stderr, "realworldtime:%llu\n", realworldtime);
                    if (realworldtime > 1000) {
                        // TODO: device may slower than simulator
                        // in my test iPad I get 3528/3779/3630 msec to finish one sdpc1016freq loop
                        // we should make screen refresh at least twice per real world second or screen will never been updated
                        // 1000->500 2000->250 4000->125
                        batchlimiter = 500 * spdc1016freq / realworldtime;
                        if (remeasure) {
                            qDebug("remeasure on batchlimiter: %u", batchlimiter);
                            fprintf(stderr, "remeasure on batchlimiter: %u\n", batchlimiter);
                            measured = false;
                            totalcycle = 0;
                            remeasure--;
                        }
                        batchcount = batchlimiter;
                    } else if (batchlimiter == 0) {
                        // 1000 - realworldtime = overflow time, overflow time / 10 = sleepcount, freq / sleepcount = batchcount
                        //batchlimiter = spdc1016freq / ((1000 - realworldtime) / 10);
                        sleepcount = (1000 - realworldtime) / sleepgap;
                        batchlimiter = spdc1016freq * sleepgap / (1000 - realworldtime);
                    } else {
                        // wrong path?
                        // sleep(0) is less than 10ms, but we'd never go here
                    }
                    batchcount = batchlimiter;
                } else {
                    // totalcycle > spdc1016freq * 2
                    // TODO:  check once more
                }
#endif // TARGET_IPHONE_SIMULATOR
            } // measured == false && totalcycle % spdc1016freq < 10 && totalcycle > spdc1016freq 
            if (totalcycle % spdc1016freq > 10 && totalcycle > spdc1016freq) {
                // FIXME: bug on slow device
                //measured = false;
            }

            if (batchlimiter != 0) {
                batchcount -= CpuTicks;
            }

            //usleep(10);
            //Sleep(0);
        }

        if (memcmp(&fixedram0000[0x9C0], fLCDBuffer, 160*80/8) != 0) {
            memcpy(fLCDBuffer, &fixedram0000[0x9C0], 160*80/8);
            qDebug("lcdBufferChanged");
            fprintf(stderr, "lcdBufferChanged\n");
            emit lcdBufferChanged(new QByteArray((const char*)fLCDBuffer, 160*80/8));
        }

        Sleep(10); // SleepGap. 10ms = 10us
        if (batchlimiter > 0) {
            batchcount = batchlimiter;
        } else {
            batchcount = spdc1016freq * 2; // dirty fix
        }
    }
    //this->deleteLater();
}

void EmulatorThread::StopKeeping()
{
    fKeeping = false;
}

#ifdef AUTOTEST
void EmulatorThread::TryTest( unsigned line )
{
    // Network
    if (line == 1024000) {
        keypadmatrix[1][6] = 1;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }
    if (line == 1064000) {
        keypadmatrix[1][6] = 0;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }
    // Down
    if (line == 1224000) {
        keypadmatrix[6][3] = 1;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }
    if (line == 1264000) {
        keypadmatrix[6][3] = 0;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }
    // Enter
    if (line == 1424000) {
        keypadmatrix[6][5] = 1;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
        enablelogging = true;
    }
    if (line == 1524000) {
        keypadmatrix[6][5] = 0;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }
    // Splash
    if (line == 4724000) {
        keypadmatrix[6][5] = 1;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }
    if (line == 4764000) {
        keypadmatrix[6][5] = 0;
        CheckLCDOffShift0HotkeyAndEnableWatchDog();
    }

}
#endif

void CheckLCDOffShift0HotkeyAndEnableWatchDog()
{
    //// may check hotkey press
    //if ( gLcdoffShift0Flag )
    //{
    //    if ( keypadmatrix1[6] || keypadmatrix1[7] )
    //    {
    //        // Line6 Dict Card
    //        // Line7 on/off
    //        EnableWatchDogFlag();               // 0x80
    //        gLcdoffShift0Flag = 0;
    //    }
    //}
    //else
    //{
    //    // Set lcdoffshift0flag only when keypadmatrix3 == 0xFB
    //    if ( keypadmatrix1[7] == 0xFBu )
    //        gLcdoffShift0Flag = 1;
    //}
    matrixupdated = true;
    if (lcdoffshift0flag) {
        // we don't have invert bit for row6,7
        //bool row67down = false;
        for (int y = 0; y < 2; y++) {
            for (int x = 0; x < 8; x++) {
                if (keypadmatrix[y][x] == 1) {
                    //row6,7down = true;
                    EnableWatchDogFlag();
                    lcdoffshift0flag = false;
                    return;
                }
            }
        }
    } else {
        if (keypadmatrix[0][2] == 1) {
            lcdoffshift0flag = true; // this flag is used for UI? (IO05_ClockControl)
        }
    }
}
Ejemplo n.º 4
0
void ContinueExecution()
{
	static BOOL pageflipping    = 0; //?

	const double fUsecPerSec        = 1.e6;
#if 1
	const UINT nExecutionPeriodUsec = 1000;		// 1.0ms
//	const UINT nExecutionPeriodUsec = 100;		// 0.1ms
	const double fExecutionPeriodClks = g_fCurrentCLK6502 * ((double)nExecutionPeriodUsec / fUsecPerSec);
#else
	const double fExecutionPeriodClks = 1800.0;
	const UINT nExecutionPeriodUsec = (UINT) (fUsecPerSec * (fExecutionPeriodClks / g_fCurrentCLK6502));
#endif

	//

	bool bScrollLock_FullSpeed = g_uScrollLockToggle
									? g_bScrollLock_FullSpeed
									: (GetKeyState(VK_SCROLL) < 0);

	g_bFullSpeed = ( (g_dwSpeed == SPEED_MAX) || 
					 bScrollLock_FullSpeed ||
					 (DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) );

	if(g_bFullSpeed)
	{
		// Don't call Spkr_Mute() - will get speaker clicks
		MB_Mute();
		SysClk_StopTimer();
#ifdef USE_SPEECH_API
		g_Speech.Reset();			// TODO: Put this on a timer (in emulated cycles)... otherwise CATALOG cuts out
#endif

		g_nCpuCyclesFeedback = 0;	// For the case when this is a big -ve number

		// Switch to normal priority so that APPLEWIN process doesn't hog machine!
		//. EG: No disk in Drive-1, and boot Apple: Windows will start to crawl!
		SetPriorityNormal();
	}
	else
	{
		// Don't call Spkr_Demute()
		MB_Demute();
		SysClk_StartTimerUsec(nExecutionPeriodUsec);

		// Switch to higher priority, eg. for audio (BUG #015394)
		SetPriorityAboveNormal();
	}

#ifdef WS_VIDEO
	wsVideoNewDirtyRect.ulx = FRAMEBUFFER_W;
	wsVideoNewDirtyRect.uly = FRAMEBUFFER_H;
	wsVideoNewDirtyRect.lrx = 0;
	wsVideoNewDirtyRect.lry = 0;
#endif

	//

	int nCyclesToExecute = (int) fExecutionPeriodClks + g_nCpuCyclesFeedback;
	if(nCyclesToExecute < 0)
		nCyclesToExecute = 0;

	DWORD dwExecutedCycles = CpuExecute(nCyclesToExecute);
	g_dwCyclesThisFrame += dwExecutedCycles;

	//

	cyclenum = dwExecutedCycles;

	DiskUpdatePosition(dwExecutedCycles);
	JoyUpdatePosition();

	SpkrUpdate(cyclenum);
	sg_SSC.CommUpdate(cyclenum);
	PrintUpdate(cyclenum);

	//

	const DWORD CLKS_PER_MS = (DWORD)g_fCurrentCLK6502 / 1000;

	emulmsec_frac += dwExecutedCycles;
	if(emulmsec_frac > CLKS_PER_MS)
	{
		emulmsec += emulmsec_frac / CLKS_PER_MS;
		emulmsec_frac %= CLKS_PER_MS;
	}

#ifdef WS_VIDEO
	if (wsVideoNewDirtyRect.lrx > wsVideoNewDirtyRect.ulx)
	  {
	    if (wsVideoNewDirtyRect.ulx < wsVideoAllDirtyRect.ulx) wsVideoAllDirtyRect.ulx = wsVideoNewDirtyRect.ulx;
	    if (wsVideoNewDirtyRect.uly < wsVideoAllDirtyRect.uly) wsVideoAllDirtyRect.uly = wsVideoNewDirtyRect.uly;
	    if (wsVideoNewDirtyRect.lrx > wsVideoAllDirtyRect.lrx) wsVideoAllDirtyRect.lrx = wsVideoNewDirtyRect.lrx;
	    if (wsVideoNewDirtyRect.lry > wsVideoAllDirtyRect.lry) wsVideoAllDirtyRect.lry = wsVideoNewDirtyRect.lry;
	  }

	if(g_dwCyclesThisFrame >= dwClksPerFrame)
	{
		g_dwCyclesThisFrame -= dwClksPerFrame;
		wsVideoRefresh();
	}	
#else
	//
	// DETERMINE WHETHER THE SCREEN WAS UPDATED, THE DISK WAS SPINNING,
	// OR THE KEYBOARD I/O PORTS WERE BEING EXCESSIVELY QUERIED THIS CLOCKTICK
	VideoCheckPage(0);
	BOOL screenupdated = VideoHasRefreshed();
	BOOL systemidle    = 0;	//(KeybGetNumQueries() > (clockgran << 2));	//  && (!ranfinegrain);	// TO DO

	if(screenupdated)
		pageflipping = 3;

	//

	if(g_dwCyclesThisFrame >= dwClksPerFrame)
	{
		g_dwCyclesThisFrame -= dwClksPerFrame;

		if(g_nAppMode != MODE_LOGO)
		{
			VideoUpdateFlash();

			static BOOL  anyupdates     = 0;
			static DWORD lastcycles     = 0;
			static BOOL  lastupdates[2] = {0,0};

			anyupdates |= screenupdated;

			//

			lastcycles = cumulativecycles;
			if ((!anyupdates) && (!lastupdates[0]) && (!lastupdates[1]) && VideoApparentlyDirty())
			{
				VideoCheckPage(1);
				static DWORD lasttime = 0;
				DWORD currtime = GetTickCount();
				if ((!g_bFullSpeed) ||
					(currtime-lasttime >= (DWORD)((g_bGraphicsMode || !systemidle) ? 100 : 25)))
				{
					VideoRefreshScreen();
					lasttime = currtime;
				}
				screenupdated = 1;
			}

			lastupdates[1] = lastupdates[0];
			lastupdates[0] = anyupdates;
			anyupdates     = 0;

			if (pageflipping)
				pageflipping--;
		}

		MB_EndOfVideoFrame();
	}

	//
#endif // ifndef WS_VIDEO

	if(!g_bFullSpeed)
	{
		SysClk_WaitTimer();

#if DBG_CALC_FREQ
		if(g_nPerfFreq)
		{
			QueryPerformanceCounter((LARGE_INTEGER*)&nTime1);
			LONGLONG nTimeDiff = nTime1 - nTime0;
			double fTime = (double)nTimeDiff / (double)(LONGLONG)g_nPerfFreq;

			g_fDbg[g_nIdx] = fTime;
			g_nIdx = (g_nIdx+1) & (MAX_CNT-1);
			g_fMeanPeriod = 0.0;
			for(UINT n=0; n<MAX_CNT; n++)
				g_fMeanPeriod += g_fDbg[n];
			g_fMeanPeriod /= (double)MAX_CNT;
			g_fMeanFreq = 1.0 / g_fMeanPeriod;
		}
#endif
	}
}
Ejemplo n.º 5
0
void ContinueExecution(void)
{
	const double fUsecPerSec        = 1.e6;
#if 1
	const UINT nExecutionPeriodUsec = 1000;		// 1.0ms
//	const UINT nExecutionPeriodUsec = 100;		// 0.1ms
	const double fExecutionPeriodClks = g_fCurrentCLK6502 * ((double)nExecutionPeriodUsec / fUsecPerSec);
#else
	const double fExecutionPeriodClks = 1800.0;
	const UINT nExecutionPeriodUsec = (UINT) (fUsecPerSec * (fExecutionPeriodClks / g_fCurrentCLK6502));
#endif

	//

	bool bScrollLock_FullSpeed = sg_PropertySheet.GetScrollLockToggle()
									? g_bScrollLock_FullSpeed
									: (GetKeyState(VK_SCROLL) < 0);

	g_bFullSpeed = ( (g_dwSpeed == SPEED_MAX) || 
					 bScrollLock_FullSpeed ||
					 (DiskIsSpinning() && enhancedisk && !Spkr_IsActive() && !MB_IsActive()) );

	if (g_bFullSpeed)
	{
		// Don't call Spkr_Mute() - will get speaker clicks
		MB_Mute();
		SysClk_StopTimer();
#ifdef USE_SPEECH_API
		g_Speech.Reset();			// TODO: Put this on a timer (in emulated cycles)... otherwise CATALOG cuts out
#endif

		g_nCpuCyclesFeedback = 0;	// For the case when this is a big -ve number

		// Switch to normal priority so that APPLEWIN process doesn't hog machine!
		//. EG: No disk in Drive-1, and boot Apple: Windows will start to crawl!
		SetPriorityNormal();
	}
	else
	{
		// Don't call Spkr_Demute()
		MB_Demute();
		SysClk_StartTimerUsec(nExecutionPeriodUsec);

		// Switch to higher priority, eg. for audio (BUG #015394)
		SetPriorityAboveNormal();
	}

	//

	int nCyclesToExecute = (int) fExecutionPeriodClks + g_nCpuCyclesFeedback;
	if (nCyclesToExecute < 0)
		nCyclesToExecute = 0;

	DWORD dwExecutedCycles = CpuExecute(nCyclesToExecute);
	g_dwCyclesThisFrame += dwExecutedCycles;

	//

	cyclenum = dwExecutedCycles;

	DiskUpdatePosition(dwExecutedCycles);
	JoyUpdatePosition();

	SpkrUpdate(cyclenum);
	sg_SSC.CommUpdate(cyclenum);
	PrintUpdate(cyclenum);

	//

	const DWORD CLKS_PER_MS = (DWORD)g_fCurrentCLK6502 / 1000;

	emulmsec_frac += dwExecutedCycles;
	if (emulmsec_frac > CLKS_PER_MS)
	{
		emulmsec += emulmsec_frac / CLKS_PER_MS;
		emulmsec_frac %= CLKS_PER_MS;
	}

	// DETERMINE WHETHER THE SCREEN WAS UPDATED THIS CLOCKTICK
	static BOOL anyupdates = 0;
	VideoCheckPage(0);								// force=0
	anyupdates |= VideoHasRefreshed();				// Only called from here. Returns & clears 'hasrefreshed' flag

	//

	if (g_dwCyclesThisFrame >= dwClksPerFrame)
	{
		g_dwCyclesThisFrame -= dwClksPerFrame;
		VideoUpdateFlash();

		static BOOL lastupdates[2] = {0,0};
		if (!anyupdates && !lastupdates[0] && !lastupdates[1] && VideoApparentlyDirty())
		{
			VideoCheckPage(1);						// force=1
			static DWORD lasttime = 0;
			DWORD currtime = GetTickCount();
			if ((!g_bFullSpeed) ||
				(currtime-lasttime >= (DWORD)(g_bGraphicsMode ? 100 : 25)))
			{
				VideoRefreshScreen();
				lasttime = currtime;
			}
		}

		lastupdates[1] = lastupdates[0];
		lastupdates[0] = anyupdates;
		anyupdates     = 0;

		MB_EndOfVideoFrame();
	}

	//

	if (!g_bFullSpeed)
	{
		SysClk_WaitTimer();

#if DBG_CALC_FREQ
		if (g_nPerfFreq)
		{
			QueryPerformanceCounter((LARGE_INTEGER*)&nTime1);
			LONGLONG nTimeDiff = nTime1 - nTime0;
			double fTime = (double)nTimeDiff / (double)(LONGLONG)g_nPerfFreq;

			g_fDbg[g_nIdx] = fTime;
			g_nIdx = (g_nIdx+1) & (MAX_CNT-1);
			g_fMeanPeriod = 0.0;
			for(UINT n=0; n<MAX_CNT; n++)
				g_fMeanPeriod += g_fDbg[n];
			g_fMeanPeriod /= (double)MAX_CNT;
			g_fMeanFreq = 1.0 / g_fMeanPeriod;
		}
#endif
	}
}