static void* nes_thread_proc(void *param) { NES *nes = (NES*)param; int totalpclk, nmi, irq; while (!nes->thread_exit) { //++ for run/pause ++// if (!nes->isrunning) { nes->ispaused = 1; nes->ppu.vdev->dequeue(nes->ppu.vctxt, NULL, NULL); nes->ppu.vdev->enqueue(nes->ppu.vctxt); continue; } //-- for run/pause --// //++ for replay playing ++// if (!replay_progress(&(nes->replay)) && nes->request_reset == 0) { nes->ppu.vdev->dequeue(nes->ppu.vctxt, NULL, NULL); nes->ppu.vdev->enqueue(nes->ppu.vctxt); continue; } //-- for replay playing --// //++ for nes reset ++// if (nes->request_reset == 1) { nes->request_reset = 0; nes_do_reset(nes); } //-- for nes reset --// //++ run cpu & apu & ppu do { cpu_run_pclk(&(nes->cpu)); // run cpu ppu_run_pclk(&(nes->ppu)); // run ppu apu_run_pclk(&(nes->apu)); // run apu //+ for cpu nmi & irq nmi = nes->ppu.pinvbl; irq = !(nes->apu.regs[0x0015] & 0xC0); cpu_nmi(&(nes->cpu), nmi); cpu_irq(&(nes->cpu), irq); //- for cpu nmi & irq } while (nes->ppu.pclk_frame != NES_HTOTAL * 241 + 2); // at frame clk (241, 2) the frame buffer will be enqueued //-- run cpu & apu & ppu // run joypad for turbo key function joypad_run(&(nes->pad)); } return NULL; }
// 内部函数实现 static DWORD WINAPI nes_thread_proc(LPVOID lpParam) { NES *nes = (NES*)lpParam; DWORD dwTickLast = 0; DWORD dwTickCur = 0; DWORD dwTickDiff = 0; DWORD dwTickSleep = 0; int scanline = 0; while (1) { WaitForSingleObject(nes->hNesEvent, -1); if (nes->bExitThread) break; // run cpu & ppu for (scanline=0; scanline<NES_VTOTAL; scanline++) { cpu_run_pclk(&(nes->cpu), NES_HTOTAL); ppu_run(&(nes->ppu), scanline ); cpu_nmi(&(nes->cpu), nes->ppu.pin_vbl); } // apu render frame apu_run_pclk(&(nes->apu), NES_HTOTAL * NES_VTOTAL); //++ framerate control ++// dwTickCur = GetTickCount(); dwTickDiff = dwTickCur - dwTickLast; dwTickLast = dwTickCur; if (dwTickDiff > 16) { if (dwTickSleep > 0) dwTickSleep--; } else if (dwTickDiff < 16) { dwTickSleep++; } if (dwTickSleep) Sleep(dwTickSleep); //-- framerate control --// log_printf("%d, %d\n", dwTickDiff, dwTickSleep); } return 0; }