static void ppu_vblank_starts(void) { sdl_frame(); if(p.vblank_nmi) cpu_nmi(0xFFFA); }
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 void watchdog_event(int index) { if (watchdog.control & 1) { watchdog.status = 1; if (watchdog.control & 2) { gui_console_printf("[CEmu] Watchdog reset triggered.\n"); cpuEvents |= EVENT_RESET; } if (watchdog.control & 4) { cpu_nmi(); gui_console_printf("[CEmu] Watchdog NMI triggered.\n"); } event_repeat(index, watchdog.load); } }
// 内部函数实现 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; }
void cpu_nmi_mask(cpumask_t map) { foreach_cpumask(map, cpu_nmi(i)); }