CEN64_THREAD_RETURN_TYPE run_vr4300_thread(void *opaque) { struct cen64_device *device = (struct cen64_device *) opaque; while (1) { unsigned i, j; for (i = 0; i < 6250 / 10; i++) { for (j = 0; j < 10; j++) ai_cycle(&device->ai); for (j = 0; j < 15; j++) vr4300_cycle(&device->vr4300); } // Sync up with the RCP thread. cen64_mutex_lock(&device->sync_mutex); if (!device->other_thread_is_waiting) { device->other_thread_is_waiting = true; cen64_cv_wait(&device->sync_cv, &device->sync_mutex); } else { device->other_thread_is_waiting = false; cen64_mutex_unlock(&device->sync_mutex); cen64_cv_signal(&device->sync_cv); } } return CEN64_THREAD_RETURN_VAL; }
CEN64_THREAD_RETURN_TYPE run_rcp_thread(void *opaque) { struct cen64_device *device = (struct cen64_device *) opaque; if (setjmp(device->bus.unwind_data)) return CEN64_THREAD_RETURN_VAL; while (1) { unsigned i; for (i = 0; i < 6250; i++) { rsp_cycle(&device->rsp); vi_cycle(&device->vi); } // Sync up with the VR4300 thread. cen64_mutex_lock(&device->sync_mutex); if (!device->other_thread_is_waiting) { device->other_thread_is_waiting = true; cen64_cv_wait(&device->sync_cv, &device->sync_mutex); } else { device->other_thread_is_waiting = false; cen64_mutex_unlock(&device->sync_mutex); cen64_cv_signal(&device->sync_cv); } } return CEN64_THREAD_RETURN_VAL; }
// Handles events that come from Windows. bool cen64_gl_window_pump_events(struct vi_controller *vi, cen64_time *last_update_time, unsigned *frame_count) { struct bus_controller *bus; bool exit_requested = false; MSG msg; memcpy(&bus, vi, sizeof(bus)); while (1) { GetMessage(&msg, NULL, 0, 0); if (msg.message == WM_QUIT) { cen64_mutex_lock(&vi->window->event_mutex); vi->window->exit_requested = exit_requested = true; cen64_mutex_unlock(&vi->window->event_mutex); break; } else if (msg.message == WM_KEYDOWN) { cen64_mutex_lock(&vi->window->event_mutex); keyboard_press_callback(bus, msg.wParam); cen64_mutex_unlock(&vi->window->event_mutex); } else if (msg.message == WM_KEYUP) { cen64_mutex_lock(&vi->window->event_mutex); keyboard_release_callback(bus, msg.wParam); cen64_mutex_unlock(&vi->window->event_mutex); } else if (msg.message == WM_USER) { cen64_gl_window window = vi->window; cen64_mutex_lock(&window->render_mutex); gl_window_render_frame(vi, window->frame_buffer, window->frame_hres, window->frame_vres, window->frame_hskip, window->frame_type); cen64_mutex_unlock(&window->render_mutex); // Update the window title every 60 VIs // to display the current VI/s rate. if (++(*frame_count) == 60) { char title[128]; cen64_time current_time; float ns; // Compute time spent rendering last 60 frames, reset timer/counter. get_time(¤t_time); ns = compute_time_difference(¤t_time, last_update_time); *last_update_time = current_time; *frame_count = 0; sprintf(title, "CEN64 ["CEN64_COMPILER" - "CEN64_ARCH_DIR"/"CEN64_ARCH_SUPPORT"]" " - %.1f VI/s", (60 / (ns / NS_PER_SEC))); cen64_gl_window_set_title(window, title); } } else { TranslateMessage(&msg); DispatchMessage(&msg); } } return exit_requested; }