int main(int argc, char *argv[]) { //struct sound_params *sp = sg_create_sound_params(SQUARE, sg_create_square_wave_parameters(440, 0.5, SAMPLE_RATE)); struct sound_params *sp2 = sg_create_sound_params(SINE, sg_create_sine_parameters(440, SAMPLE_RATE)); //struct sound_params *sp3 = sg_create_sound_params(SQUARE, sg_create_square_wave_parameters(840, 0.5, SAMPLE_RATE)); audio_init(); audio_create_stream(SAMPLE_RATE); //sound_play_seconds(sp, 0.5); sound_play_seconds(sp2, 1.5); //sound_play_seconds(sp3, 1.5); audio_sleep(1.5*1000); //sp2 = sg_create_sound_params(SQUARE, sg_create_square_wave_parameters(440, 0.5, SAMPLE_RATE)); //sound_play_seconds(sp2, 1); //audio_sleep(1*1000); //sw1.setFrequency(300); audio_shutdown(); return 0; }
int main(int argc, char *argv[]) { video_init(0); audio_init(argc, argv); game_init(); double last = glfwGetTime(); while (running) { double current = glfwGetTime(); int delta = (current - last) * 1000; if (delta < MIN_DELTA) { glfwSleep((MIN_DELTA-delta)/1000.0); continue; } last = current; now += delta; if (delta > MAX_DELTA) continue; game_tick(delta); } audio_shutdown(); video_shutdown(); return EXIT_SUCCESS; }
/*** * Cleans up the long-lived memory we've allocated. */ void vita_cleanup() { free(pad); vita2d_fini(); audio_shutdown(); video_shutdown(); }
void quit(int sig) { if (sig != -1) { script_call("shutdown", NULL); } base_shutdown(); video_shutdown(); audio_shutdown(); common_shutdown(); exit(0); }
int audio_init(int samplerate, double framerate) { /* Shutdown first */ audio_shutdown(); /* Clear the sound data context */ memset(&snd, 0, sizeof (snd)); /* Initialize Blip Buffers */ snd.blips[0] = blip_new(samplerate / 10); if (!snd.blips[0]) { return -1; } /* Mega CD sound hardware */ if (system_hw == SYSTEM_MCD) { /* allocate blip buffers */ snd.blips[1] = blip_new(samplerate / 10); snd.blips[2] = blip_new(samplerate / 10); if (!snd.blips[1] || !snd.blips[2]) { audio_shutdown(); return -1; } } /* Initialize resampler internal rates */ audio_set_rate(samplerate, framerate); /* Set audio enable flag */ snd.enabled = 1; /* Reset audio */ audio_reset(); return (0); }
/************************************************** Shutdown everything properly ***************************************************/ void shutdown(void) { /* system shutdown */ memfile_autosave(-1,config.state_auto); system_shutdown(); audio_shutdown(); free(cart.rom); gx_audio_Shutdown(); gx_video_Shutdown(); #ifdef HW_RVL DI_Close(); #endif }
/************************************************** Shutdown everything properly ***************************************************/ void shutdown(void) { /* save current config */ config_save(); /* auto-save State file */ slot_autosave(config.s_default,config.s_device); /* shutdown emulation */ audio_shutdown(); gx_audio_Shutdown(); gx_video_Shutdown(); #ifdef HW_RVL DI_Close(); #endif }
int audio_init (int samplerate, float framerate) { /* Shutdown first */ audio_shutdown(); /* Clear the sound data context */ memset(&snd, 0, sizeof (snd)); /* Default settings */ snd.sample_rate = samplerate; snd.frame_rate = framerate; /* Calculate the sound buffer size (for one frame) */ snd.buffer_size = (int)(samplerate / framerate) + 32; /* SN76489 stream buffers */ snd.psg.buffer = (int16 *) malloc(snd.buffer_size * sizeof(int16)); if (!snd.psg.buffer) return (-1); /* YM2612 stream buffers */ snd.fm.buffer = (int32 *) malloc(snd.buffer_size * sizeof(int32) * 2); if (!snd.fm.buffer) return (-1); #ifndef NGC /* Output buffers */ snd.buffer[0] = (int16 *) malloc(snd.buffer_size * sizeof(int16)); snd.buffer[1] = (int16 *) malloc(snd.buffer_size * sizeof(int16)); if (!snd.buffer[0] || !snd.buffer[1]) return (-1); #endif /* Resampling buffer */ if (config.hq_fm && !Fir_Resampler_initialize(4096)) return (-1); /* Set audio enable flag */ snd.enabled = 1; /* Reset audio */ audio_reset(); return (0); }
int main(int argc, char **argv) { optproc(argc, argv, &opts); if(audio_init(&opts) < 0) exit(1); SDL_Surface *screen = sdl_setup(&opts, IM_SIZE); im_w = screen->w - screen->w%16; im_h = screen->h - screen->h%16; printf("running with %dx%d bufs\n", im_w, im_h); if(strcmp(opts.map_name, "rational") == 0) { map_func = soft_map_rational_interp; if(opts.quality >= 1) map_func = soft_map_rational; } else if(strcmp(opts.map_name, "butterfly") == 0) { // map_func = soft_map_butterfly_interp; // if(opts.quality >= 1) map_func = soft_map_butterfly; } else if(opts.quality >= 1) map_func = soft_map; maxsrc = maxsrc_new(im_w, im_h); struct pal_ctx *pal_ctx = pal_ctx_new(screen->format->BitsPerPixel == 8); uint16_t *map_surf[3]; void *map_surf_mem = aligned_alloc(64, 3 * im_w * im_h * sizeof(uint16_t)); for(int i=0; i<3; i++) map_surf[i] = map_surf_mem + i * im_w * im_h * sizeof(uint16_t); memset(map_surf_mem, 0, 3 * im_w * im_h * sizeof(uint16_t)); tribuf *map_tb = tribuf_new((void **)map_surf, 1); int beats = 0; int frmcnt = 0; int lastdrawn=0; SDL_Thread *map_thread = SDL_CreateThread((void *)&run_map_thread, map_tb); SDL_Delay(100); uint32_t frametimes[FPS_HIST_LEN]; for(int i=1; i<FPS_HIST_LEN; i++) frametimes[i] = 0; uint32_t totframetime = frametimes[0] = MIN(1000/opts.draw_rate, 1); Uint32 tick0 = SDL_GetTicks(); Uint32 lastpalstep, lastupdate, fps_oldtime; fps_oldtime = lastpalstep = lastupdate = tick0; SDL_Event event; while(SDL_PollEvent(&event) >= 0) { if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) { break; } else if(tribuf_check_fresh(map_tb)) { Uint32 now = SDL_GetTicks(); if(now - lastpalstep >= 2048/256) { // want pallet switch to take ~2 seconds pal_ctx_step(pal_ctx, IMIN((now - lastpalstep)*256/2048, 64)); lastpalstep = now; } pallet_blit_SDL(screen, tribuf_get_read(map_tb), im_w, im_h, pal_ctx_get_active(pal_ctx)); tribuf_finish_read(map_tb); char buf[64]; sprintf(buf,"%6.1f FPS %6.1f UPS %6.1f", map_fps, FPS_HIST_LEN*1000.0f/totframetime, maxfrms*1000.0f/(now-tick0)); DrawText(screen, buf); SDL_Flip(screen); int newbeat = beat_get_count(); if(newbeat != beats) pal_ctx_start_switch(pal_ctx, newbeat); beats = newbeat; now = SDL_GetTicks(); int delay = (tick0 + frmcnt*1000/opts.draw_rate) - now; if(delay > 0) SDL_Delay(delay); totframetime -= frametimes[frmcnt%FPS_HIST_LEN]; totframetime += (frametimes[frmcnt%FPS_HIST_LEN] = now - fps_oldtime); fps_oldtime = now; frmcnt++; } else { SDL_Delay(1000/opts.draw_rate/2); // wait half a frame and hope we get a new buffer } } running = 0; int status; SDL_WaitThread(map_thread, &status); aligned_free(map_surf_mem); audio_shutdown(); SDL_Quit(); return 0; }
int main(int argc, char **argv) { opt_data opts; optproc(argc, argv, &opts); if(audio_init(&opts) < 0) exit(1); int x = 0, y = 0, w, h; if(opts.w < 0 && opts.h < 0) opts.w = opts.h = 512; else if(opts.w < 0) opts.w = opts.h; else if(opts.h < 0) opts.h = opts.w; w = opts.w; h = opts.h; XEvent event; dpy = XOpenDisplay( NULL ); if(dpy == NULL) { printf("Error: couldn't open display %s\n", getenv("DISPLAY")); exit(EXIT_FAILURE); } int glx_major, glx_minor; if(!glXQueryVersion(dpy, &glx_major, &glx_minor)) { printf("GLX extension missing!\n"); XCloseDisplay(dpy); exit(EXIT_FAILURE); } printf("GLX version %i.%i\n", glx_major, glx_minor); int glxErrBase, glxEventBase; glXQueryExtension(dpy, &glxErrBase, &glxEventBase); printf("GLX: errorBase = %i, eventBase = %i\n", glxErrBase, glxEventBase); Window xwin, root; int numReturned; GLXFBConfig *fbConfigs; fbConfigs = glXChooseFBConfig( dpy, DefaultScreen(dpy), fbattrib, &numReturned ); if(fbConfigs == NULL) { //TODO: handle this? printf("No suitable fbconfigs!\n"); exit(EXIT_FAILURE); } XVisualInfo *vinfo = glXGetVisualFromFBConfig( dpy, fbConfigs[0] ); root = DefaultRootWindow(dpy); /* window attributes */ XSetWindowAttributes attrs; attrs.background_pixel = 0; attrs.border_pixel = 0; attrs.colormap = XCreateColormap(dpy, root, vinfo->visual, AllocNone); //attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; attrs.event_mask = StructureNotifyMask | KeyPressMask; unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; xwin = XCreateWindow(dpy, root, x, y, w, h, 0, vinfo->depth, InputOutput, vinfo->visual, mask, &attrs); XFree(vinfo); // Set hints and properties: { XSizeHints sizehints; sizehints.x = x; sizehints.y = y; sizehints.width = w; sizehints.height = h; sizehints.flags = USSize | USPosition; XSetNormalHints(dpy, xwin, &sizehints); XSetStandardProperties(dpy, xwin, "Julia-vis", "Julia-vis", None, (char **)NULL, 0, &sizehints); } /* Create a GLX context for OpenGL rendering */ GLXContext context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, NULL, True ); #if 0 GLXContext context = 0; glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); if(strstr(glXQueryExtensionsString(dpy, 0), "GLX_ARB_create_context") || !glXCreateContextAttribsARB) { printf("glXCreateContextAttribsARB() not found ... using old-style GLX context\n"); context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, 0, True); } else { const int context_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_TYPE, GLX_CONTEXT_MAJOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 1, None }; context = glXCreateContextAttribsARB(dpy, fbConfigs[0], NULL, True, context_attribs); } if(context == NULL) { printf("Failed to create context!\n"); return EXIT_FAILURE; } #endif glxWin = glXCreateWindow(dpy, fbConfigs[0], xwin, NULL ); XMapWindow(dpy, xwin); XIfEvent(dpy, &event, WaitForNotify, (XPointer) xwin); glXMakeContextCurrent(dpy, glxWin, glxWin, context); init_gl(&opts, w, h); if(strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_swap_control")) { PFNGLXSWAPINTERVALMESAPROC swap_interval = glXGetProcAddressARB("glXSwapIntervalMESA"); swap_interval(1); opts.draw_rate = 300; } if(strstr(glXQueryExtensionsString(dpy, 0), "GLX_INTEL_swap_event")) { glXSelectEvent(dpy, glxWin, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); have_intel_swap_event = GL_TRUE; } int debug_maxsrc = 0, debug_pal = 0, show_mandel = 0, show_fps_hist = 0; if(have_intel_swap_event) render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); while(1) { if(!have_intel_swap_event) render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); int clear_key = 1; while (XPending(dpy) > 0) { XNextEvent(dpy, &event); if(event.type == glxEventBase + GLX_BufferSwapComplete) { render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); continue; } switch (event.type) { case Expose: /* we'll redraw below */ break; /*case ConfigureNotify: window_w = event.xconfigure.width; window_h = event.xconfigure.height; if (surface_type == EGL_WINDOW_BIT) reshape(window_w, window_h); break;*/ case KeyPress: { clear_key = 0; char buffer[10]; int r, code; code = XLookupKeysym(&event.xkey, 0); if (code == XK_F1) { debug_maxsrc = !debug_maxsrc; } else if (code == XK_F2) { debug_pal = !debug_pal; } else if (code == XK_F3) { show_mandel = !show_mandel; } else if (code == XK_F4) { show_fps_hist = !show_fps_hist; } else { code = XLookupKeysym(&event.xkey, 1); if(code == XK_Escape) { goto glx_main_loop_quit; } } } break; default: //printf("Bar %i!\n", event.type); break; } } } glx_main_loop_quit: audio_shutdown(); XDestroyWindow(dpy, xwin); XCloseDisplay(dpy); return 0; }
int audio_init(int samplerate, double framerate) { /* Number of M-cycles executed per second. */ /* All emulated chips are kept in sync by using a common oscillator (MCLOCK) */ /* */ /* The original console would run exactly 53693175 M-cycles per sec (53203424 for PAL), */ /* 3420 M-cycles per line and 262 (313 for PAL) lines per frame, which gives an exact */ /* framerate of 59.92 (49.70 for PAL) frames per second. */ /* */ /* Since audio samples are generated at the end of the frame, to prevent audio skipping */ /* or lag between emulated frames, number of samples rendered per frame must be set to */ /* output samplerate (number of samples played per second) divided by input framerate */ /* (number of frames emulated per seconds). */ /* */ /* On some systems, we may want to achieve 100% smooth video rendering by synchronizing */ /* frame emulation with VSYNC, which frequency is generally not exactly those values. */ /* In that case, input framerate (number of frames emulated per seconds) is the same as */ /* output framerate (number of frames rendered per seconds) by the host video hardware. */ /* */ /* When no framerate is specified, base clock is set to original master clock value. */ /* Otherwise, it is set to number of M-cycles emulated per line (fixed) multiplied by */ /* number of lines per frame (VDP mode specific) multiplied by input framerate. */ /* */ double mclk = framerate ? (MCYCLES_PER_LINE * (vdp_pal ? 313 : 262) * framerate) : system_clock; /* Shutdown first */ audio_shutdown(); /* Clear the sound data context */ memset(&snd, 0, sizeof (snd)); /* Initialize audio rates */ snd.sample_rate = samplerate; snd.frame_rate = framerate; /* Initialize Blip Buffers */ snd.blips[0][0] = blip_new(samplerate / 10); snd.blips[0][1] = blip_new(samplerate / 10); if (!snd.blips[0][0] || !snd.blips[0][1]) { audio_shutdown(); return -1; } /* For maximal accuracy, sound chips are running at their original rate using common */ /* master clock timebase so they remain perfectly synchronized together, while still */ /* being synchronized with 68K and Z80 CPUs as well. Mixed sound chip output is then */ /* resampled to desired rate at the end of each frame, using Blip Buffer. */ blip_set_rates(snd.blips[0][0], mclk, samplerate); blip_set_rates(snd.blips[0][1], mclk, samplerate); /* Initialize PSG core */ SN76489_Init(snd.blips[0][0], snd.blips[0][1], (system_hw < SYSTEM_MARKIII) ? SN_DISCRETE : SN_INTEGRATED); /* Mega CD sound hardware */ if (system_hw == SYSTEM_MCD) { /* allocate blip buffers */ snd.blips[1][0] = blip_new(samplerate / 10); snd.blips[1][1] = blip_new(samplerate / 10); snd.blips[2][0] = blip_new(samplerate / 10); snd.blips[2][1] = blip_new(samplerate / 10); if (!snd.blips[1][0] || !snd.blips[1][1] || !snd.blips[2][0] || !snd.blips[2][1]) { audio_shutdown(); return -1; } /* Initialize PCM core */ pcm_init(snd.blips[1][0], snd.blips[1][1]); /* Initialize CDD core */ cdd_init(snd.blips[2][0], snd.blips[2][1]); } /* Set audio enable flag */ snd.enabled = 1; /* Reset audio */ audio_reset(); return (0); }
static void *cpu_thread(void *dummyptr) { #ifndef NDEBUG // Spamsung Galaxy Y running Gingerbread triggers this, wTf?! ASSERT_ON_CPU_THREAD(); #endif LOG("cpu_thread : initialized..."); struct timespec deltat = { 0 }; struct timespec disk_motor_time = { 0 }; struct timespec t0 = { 0 }; // the target timer struct timespec ti = { 0 }; // actual before time sample struct timespec tj = { 0 }; // actual after time sample bool negative = false; long drift_adj_nsecs = 0; // generic drift adjustment between target and actual int debugging_cycles = 0; unsigned long dbg_ticks = 0; #if DEBUG_TIMING int speaker_neg_feedback = 0; int speaker_pos_feedback = 0; unsigned long dbg_cycles_executed = 0; #endif audio_init(); speaker_init(); MB_Initialize(); run_args.emul_reinitialize = 1; cpu_runloop: do { LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", (unsigned long)cpu_thread_id); pthread_mutex_lock(&interface_mutex); if (emul_reinitialize_audio) { emul_reinitialize_audio = false; speaker_destroy(); extern void MB_SoftDestroy(void); MB_SoftDestroy(); audio_shutdown(); audio_init(); speaker_init(); extern void MB_SoftInitialize(void); MB_SoftInitialize(); } pthread_mutex_unlock(&interface_mutex); LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ..."); if (run_args.emul_reinitialize) { reinitialize(); } LOG("cpu_thread : begin main loop ..."); clock_gettime(CLOCK_MONOTONIC, &t0); do { ////SCOPE_TRACE_CPU("CPU mainloop"); // -LOCK----------------------------------------------------------------------------------------- SAMPLE ti if (UNLIKELY(emul_pause_audio)) { emul_pause_audio = false; audio_pause(); } pthread_mutex_lock(&interface_mutex); if (UNLIKELY(emul_resume_audio)) { emul_resume_audio = false; audio_resume(); } if (UNLIKELY(emul_video_dirty)) { emul_video_dirty = false; video_setDirty(A2_DIRTY_FLAG); } clock_gettime(CLOCK_MONOTONIC, &ti); deltat = timespec_diff(t0, ti, &negative); if (deltat.tv_sec) { if (!is_fullspeed) { TIMING_LOG("NOTE : serious divergence from target time ..."); } t0 = ti; deltat = timespec_diff(t0, ti, &negative); } t0 = timespec_add(t0, EXECUTION_PERIOD_NSECS); // expected interval drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec; // set up increment & decrement counters run_args.cpu65_cycles_to_execute = (cycles_persec_target / 1000); // cycles_persec_target * EXECUTION_PERIOD_NSECS / NANOSECONDS_PER_SECOND if (!is_fullspeed) { run_args.cpu65_cycles_to_execute += cycles_speaker_feedback; } if (run_args.cpu65_cycles_to_execute < 0) { run_args.cpu65_cycles_to_execute = 0; } MB_StartOfCpuExecute(); if (is_debugging) { debugging_cycles = run_args.cpu65_cycles_to_execute; } do { if (is_debugging) { run_args.cpu65_cycles_to_execute = 1; } run_args.cpu65_cycle_count = 0; cycles_checkpoint_count = 0; cpu65_run(&run_args); // run emulation for cpu65_cycles_to_execute cycles ... #if DEBUG_TIMING dbg_cycles_executed += run_args.cpu65_cycle_count; #endif if (is_debugging) { debugging_cycles -= run_args.cpu65_cycle_count; timing_checkpointCycles(); if (c_debugger_should_break() || (debugging_cycles <= 0)) { int err = 0; if ((err = pthread_cond_signal(&dbg_thread_cond))) { LOG("pthread_cond_signal : %d", err); } if ((err = pthread_cond_wait(&cpu_thread_cond, &interface_mutex))) { LOG("pthread_cond_wait : %d", err); } if (debugging_cycles <= 0) { break; } } if (run_args.emul_reinitialize) { pthread_mutex_unlock(&interface_mutex); goto cpu_runloop; } } } while (is_debugging); MB_UpdateCycles(); // TODO : modularize MB and other peripheral card cycles/interrupts ... speaker_flush(); // play audio TRACE_CPU_BEGIN("advance scanner"); video_scannerUpdate(); TRACE_CPU_END(); clock_gettime(CLOCK_MONOTONIC, &tj); pthread_mutex_unlock(&interface_mutex); // -UNLOCK--------------------------------------------------------------------------------------- SAMPLE tj if (timing_shouldAutoAdjustSpeed() && !is_fullspeed) { disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); if (UNLIKELY(negative)) { LOG("WHOA... time went backwards #1! Did you just cross a timezone?"); disk_motor_time.tv_sec = 1; } if (!speaker_isActive() && !video_isDirty(A2_DIRTY_FLAG) && (disk6.disk[disk6.drive].file_name != NULL) && !disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS) ) { TIMING_LOG("auto switching to full speed"); _timing_initialize(CPU_SCALE_FASTEST); } } if (!is_fullspeed) { deltat = timespec_diff(ti, tj, &negative); if (UNLIKELY(negative)) { LOG("WHOA... time went backwards #2! Did you just cross a timezone?"); deltat.tv_sec = 1; } long sleepfor = 0; if (LIKELY(!deltat.tv_sec)) { sleepfor = EXECUTION_PERIOD_NSECS - drift_adj_nsecs - deltat.tv_nsec; } if (sleepfor <= 0) { // lagging ... static time_t throttle_warning = 0; if (t0.tv_sec - throttle_warning > 0) { TIMING_LOG("not sleeping to catch up ... %ld . %ld", deltat.tv_sec, deltat.tv_nsec); throttle_warning = t0.tv_sec; } } else { deltat.tv_sec = 0; deltat.tv_nsec = sleepfor; ////TRACE_CPU_BEGIN("sleep"); nanosleep(&deltat, NULL); ////TRACE_CPU_END(); } #if DEBUG_TIMING // collect timing statistics if (speaker_neg_feedback > cycles_speaker_feedback) { speaker_neg_feedback = cycles_speaker_feedback; } if (speaker_pos_feedback < cycles_speaker_feedback) { speaker_pos_feedback = cycles_speaker_feedback; } if ((dbg_ticks % NANOSECONDS_PER_SECOND) == 0) { TIMING_LOG("tick:(%ld.%ld) real:(%ld.%ld) cycles exe: %d ... speaker feedback: %d/%d", t0.tv_sec, t0.tv_nsec, ti.tv_sec, ti.tv_nsec, dbg_cycles_executed, speaker_neg_feedback, speaker_pos_feedback); dbg_cycles_executed = 0; speaker_neg_feedback = 0; speaker_pos_feedback = 0; } #endif if ((dbg_ticks % NANOSECONDS_PER_SECOND) == 0) { dbg_ticks = 0; } } if (timing_shouldAutoAdjustSpeed() && is_fullspeed) { disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); if (UNLIKELY(negative)) { LOG("WHOA... time went backwards #3! Did you just cross a timezone?"); disk_motor_time.tv_sec = 1; } if (speaker_isActive() || video_isDirty(A2_DIRTY_FLAG) || (disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS)) ) { double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor; if (speed <= CPU_SCALE_FASTEST_PIVOT) { TIMING_LOG("auto switching to configured speed"); _timing_initialize(speed); } } } if (UNLIKELY(run_args.emul_reinitialize)) { break; } if (UNLIKELY(emul_reinitialize_audio)) { break; } if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); speaker_destroy(); MB_Destroy(); audio_shutdown(); cpu_thread_id = 0; cpu_pause(); disk6_eject(0); disk6_eject(1); return NULL; }
void all_shutdown(int signal) { video_shutdown(signal); audio_shutdown(signal); kill(getpid(), SIGKILL); exit(0); }
int main(int argc, char *argv[]) { struct opt_data opts; optproc(argc, argv, &opts); if(audio_init(&opts) < 0) exit(1); if(opts.w < 0 && opts.h < 0) opts.w = opts.h = 512; else if(opts.w < 0) opts.w = opts.h; else if(opts.h < 0) opts.h = opts.w; int ret; ret = init_drm(&opts, 512); if (ret) { printf("failed to initialize DRM\n"); return ret; } ret = init_gbm(); if (ret) { printf("failed to initialize GBM\n"); return ret; } ret = init_egl(); if (ret) { printf("failed to initialize EGL\n"); return ret; } // call init_gl //init_gl(&opts, drm.mode->hdisplay, drm.mode->vdisplay); init_gl(&opts, opts.w, opts.h); //TODO: better dealing with our great big screen eglSwapBuffers(gl.display, gl.surface); struct gbm_bo *bo = gbm_surface_lock_front_buffer(gbm.surface); fb = drm_fb_get_from_bo(bo); /* set mode: */ ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0, &drm.connector_id, 1, drm.mode); if (ret) { printf("failed to set mode: %s\n", strerror(errno)); return ret; } // turn off line buffering on input and echoing of characters struct termios term; tcgetattr(STDIN_FILENO, &save_term); tcgetattr(STDIN_FILENO, &term); term.c_lflag &= ~(ICANON|ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &term); atexit(shutdown_cleanup); drmVBlank vbl; /* Get current count first hopefully also sync up with blank too*/ vbl.request.type = DRM_VBLANK_RELATIVE; vbl.request.sequence = 1; ret = drmWaitVBlank(drm.fd, &vbl); if (ret != 0) { printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret); return -1; } printf("starting msc: %d\n", vbl.request.sequence); /* Queue an event for frame + 1 */ vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; vbl.request.sequence = 1; vbl.request.signal = NULL; ret = drmWaitVBlank(drm.fd, &vbl); if (ret != 0) { printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret); return -1; } struct pollfd pfds[] = { {drm.fd, POLLIN | POLLPRI, 0 }, {STDIN_FILENO, POLLIN, 0 }, }; int debug_maxsrc = 0, debug_pal = 0, show_mandel = 0, show_fps_hist = 0; bool done = false; while (!done) { render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist); while (waiting_for_flip) { // TODO: input handling ret = poll(pfds, 2, -1); if (ret < 0) { printf("poll err: %s\n", strerror(errno)); return ret; } else if (ret == 0) { printf("poll timeout!\n"); done = true; break; } if (pfds[1].revents) { char buf[128]; int cnt = read(STDIN_FILENO, buf, sizeof(buf)); if(buf[0] == 27) done = true; else if(buf[0] == '1') debug_maxsrc = !debug_maxsrc; else if(buf[0] == '2') debug_pal = !debug_pal; else if(buf[0] == '3') show_mandel = !show_mandel; else if(buf[0] == '4') show_fps_hist = !show_fps_hist; //continue; } if(pfds[0].revents) drmHandleEvent(drm.fd, &evctx); } /* release last buffer to render on again: */ gbm_surface_release_buffer(gbm.surface, bo); bo = next_bo; } audio_shutdown(); return ret; }
void TrashMachine(void) { audio_shutdown(); }
int main (int argc, const char **argv) { #ifdef WIN32 { // set the console to accept escape sequences (Win10+) HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); if (console != INVALID_HANDLE_VALUE) { DWORD consoleMode = 0; GetConsoleMode(console, &consoleMode); consoleMode |= 4; // ENABLE_VIRTUAL_TERMINAL_PROCESSING; but that isn't available in our current SDK target SetConsoleMode(console, consoleMode); } } #endif int exit_code = EXIT_SUCCESS; try { // Experiment with floating point masks. // #ifdef FE_NOMASK_ENV // feenableexcept(FE_INVALID); // feenableexcept(FE_DIVBYZERO | FE_INVALID); // #endif bgl = new BackgroundLoader(); size_t winid = gfx_init(cb); debug_drawer = new BulletDebugDrawer(ogre_sm); // FIXME: hack #ifdef WIN32 mouse = new MouseDirectInput8(winid); bool use_dinput = getenv("GRIT_DINPUT")!=NULL; keyboard = use_dinput ? (Keyboard *)new KeyboardDirectInput8(winid) : (Keyboard *)new KeyboardWinAPI(winid); #else mouse = new MouseX11(winid); keyboard = new KeyboardX11(winid); #endif clipboard_init(); physics_init(); net_init(); core_option_init(); streamer_init(); navigation_init(); // audio_init(getenv("GRIT_AUDIO_DEV")); audio_init(NULL); std::vector<std::string> args; for (int i=0 ; i<argc ; i++) { args.push_back(argv[i]); } try { const char *init_file = getenv("GRIT_INIT"); if (init_file == nullptr) init_file = "/system/init.lua"; init_lua(init_file, args, core_L); } catch (Exception &e) { CERR << "Fatal error: " << e << std::endl; exit_code = EXIT_FAILURE; } // Lua returns - we quit. CVERB << "Shutting down Lua net subsystem..." << std::endl; net_shutdown(core_L); navigation_shutdown(); object_all_del(core_L); // Will remove all demands from background loader. CVERB << "Shutting down Lua graphics subsystem..." << std::endl; gfx_shutdown_lua(core_L); CVERB << "Shutting down Background Loader..." << std::endl; bgl->shutdown(); CVERB << "Shutting down Mouse & Keyboard..." << std::endl; if (mouse) delete mouse; if (keyboard) delete keyboard; CVERB << "Shutting down clipboard..." << std::endl; clipboard_shutdown(); CVERB << "Shutting down Lua VM..." << std::endl; if (core_L) shutdown_lua(core_L); CVERB << "Shutting down audio subsystem..." << std::endl; audio_shutdown(); //close AL device CVERB << "Shutting down physics subsystem..." << std::endl; physics_shutdown(); CVERB << "Shutting down the physics debug drawer..." << std::endl; if (debug_drawer) delete debug_drawer; CVERB << "Shutting down the Graphics subsystem..." << std::endl; gfx_shutdown(); delete bgl; } catch (Exception &e) { std::cerr << "TOP LEVEL ERROR: " << e << std::endl; return EXIT_FAILURE; } return exit_code; }
static void *cpu_thread(void *dummyptr) { assert(pthread_self() == cpu_thread_id); LOG("cpu_thread : initialized..."); struct timespec deltat; #if !MOBILE_DEVICE struct timespec disk_motor_time; #endif struct timespec t0; // the target timer struct timespec ti, tj; // actual time samples bool negative = false; long drift_adj_nsecs = 0; // generic drift adjustment between target and actual int debugging_cycles0 = 0; int debugging_cycles = 0; #if DEBUG_TIMING unsigned long dbg_ticks = 0; int speaker_neg_feedback = 0; int speaker_pos_feedback = 0; unsigned int dbg_cycles_executed = 0; #endif do { #ifdef AUDIO_ENABLED LOG("CPUTHREAD %lu LOCKING FOR MAYBE INITIALIZING AUDIO ...", cpu_thread_id); pthread_mutex_lock(&interface_mutex); if (emul_reinitialize_audio) { emul_reinitialize_audio = false; speaker_destroy(); MB_Destroy(); audio_shutdown(); audio_init(); speaker_init(); MB_Initialize(); } pthread_mutex_unlock(&interface_mutex); LOG("UNLOCKING FOR MAYBE INITIALIZING AUDIO ..."); #endif if (emul_reinitialize) { reinitialize(); } LOG("cpu_thread : begin main loop ..."); clock_gettime(CLOCK_MONOTONIC, &t0); do { SCOPE_TRACE_CPU("CPU mainloop"); // -LOCK----------------------------------------------------------------------------------------- SAMPLE ti #ifdef AUDIO_ENABLED if (UNLIKELY(emul_pause_audio)) { emul_pause_audio = false; audio_pause(); } #endif pthread_mutex_lock(&interface_mutex); #ifdef AUDIO_ENABLED if (UNLIKELY(emul_resume_audio)) { emul_resume_audio = false; audio_resume(); } #endif clock_gettime(CLOCK_MONOTONIC, &ti); deltat = timespec_diff(t0, ti, &negative); if (deltat.tv_sec) { if (!is_fullspeed) { TIMING_LOG("NOTE : serious divergence from target time ..."); } t0 = ti; deltat = timespec_diff(t0, ti, &negative); } t0 = timespec_add(t0, EXECUTION_PERIOD_NSECS); // expected interval drift_adj_nsecs = negative ? ~deltat.tv_nsec : deltat.tv_nsec; // set up increment & decrement counters cpu65_cycles_to_execute = (cycles_persec_target / 1000); // cycles_persec_target * EXECUTION_PERIOD_NSECS / NANOSECONDS_PER_SECOND if (!is_fullspeed) { cpu65_cycles_to_execute += cycles_speaker_feedback; } if (cpu65_cycles_to_execute < 0) { cpu65_cycles_to_execute = 0; } #ifdef AUDIO_ENABLED MB_StartOfCpuExecute(); #endif if (is_debugging) { debugging_cycles0 = cpu65_cycles_to_execute; debugging_cycles = cpu65_cycles_to_execute; } do { if (is_debugging) { cpu65_cycles_to_execute = 1; } cpu65_cycle_count = 0; cycles_checkpoint_count = 0; cpu65_run(); // run emulation for cpu65_cycles_to_execute cycles ... if (is_debugging) { debugging_cycles -= cpu65_cycle_count; if (c_debugger_should_break() || (debugging_cycles <= 0)) { int err = 0; if ((err = pthread_cond_signal(&dbg_thread_cond))) { ERRLOG("pthread_cond_signal : %d", err); } if ((err = pthread_cond_wait(&cpu_thread_cond, &interface_mutex))) { ERRLOG("pthread_cond_wait : %d", err); } if (debugging_cycles <= 0) { cpu65_cycle_count = debugging_cycles0 - debugging_cycles/*<=0*/; break; } } } if (emul_reinitialize) { reinitialize(); } } while (is_debugging); #if DEBUG_TIMING dbg_cycles_executed += cpu65_cycle_count; #endif g_dwCyclesThisFrame += cpu65_cycle_count; #ifdef AUDIO_ENABLED MB_UpdateCycles(); // update 6522s (NOTE: do this before updating cycles_count_total) #endif timing_checkpoint_cycles(); #if CPU_TRACING cpu65_trace_checkpoint(); #endif #ifdef AUDIO_ENABLED speaker_flush(); // play audio #endif if (g_dwCyclesThisFrame >= dwClksPerFrame) { g_dwCyclesThisFrame -= dwClksPerFrame; #ifdef AUDIO_ENABLED MB_EndOfVideoFrame(); #endif } clock_gettime(CLOCK_MONOTONIC, &tj); pthread_mutex_unlock(&interface_mutex); // -UNLOCK--------------------------------------------------------------------------------------- SAMPLE tj #if !MOBILE_DEVICE if (timing_shouldAutoAdjustSpeed()) { disk_motor_time = timespec_diff(disk6.motor_time, tj, &negative); assert(!negative); if (!is_fullspeed && #ifdef AUDIO_ENABLED !speaker_isActive() && #endif !video_isDirty() && (!disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS)) ) { TIMING_LOG("auto switching to full speed"); _timing_initialize(CPU_SCALE_FASTEST); } } #endif if (!is_fullspeed) { deltat = timespec_diff(ti, tj, &negative); assert(!negative); long sleepfor = 0; if (!deltat.tv_sec) { sleepfor = EXECUTION_PERIOD_NSECS - drift_adj_nsecs - deltat.tv_nsec; } if (sleepfor <= 0) { // lagging ... static time_t throttle_warning = 0; if (t0.tv_sec - throttle_warning > 0) { TIMING_LOG("not sleeping to catch up ... %ld . %ld", deltat.tv_sec, deltat.tv_nsec); throttle_warning = t0.tv_sec; } } else { deltat.tv_sec = 0; deltat.tv_nsec = sleepfor; TRACE_CPU_BEGIN("sleep"); nanosleep(&deltat, NULL); TRACE_CPU_END(); } #if DEBUG_TIMING // collect timing statistics if (speaker_neg_feedback > cycles_speaker_feedback) { speaker_neg_feedback = cycles_speaker_feedback; } if (speaker_pos_feedback < cycles_speaker_feedback) { speaker_pos_feedback = cycles_speaker_feedback; } dbg_ticks += EXECUTION_PERIOD_NSECS; if ((dbg_ticks % NANOSECONDS_PER_SECOND) == 0) { TIMING_LOG("tick:(%ld.%ld) real:(%ld.%ld) cycles exe: %d ... speaker feedback: %d/%d", t0.tv_sec, t0.tv_nsec, ti.tv_sec, ti.tv_nsec, dbg_cycles_executed, speaker_neg_feedback, speaker_pos_feedback); dbg_cycles_executed = 0; dbg_ticks = 0; speaker_neg_feedback = 0; speaker_pos_feedback = 0; } #endif } #if !MOBILE_DEVICE if (timing_shouldAutoAdjustSpeed()) { if (is_fullspeed && ( #ifdef AUDIO_ENABLED speaker_isActive() || #endif video_isDirty() || (disk6.motor_off && (disk_motor_time.tv_sec || disk_motor_time.tv_nsec > DISK_MOTOR_QUIET_NSECS))) ) { double speed = alt_speed_enabled ? cpu_altscale_factor : cpu_scale_factor; if (speed < CPU_SCALE_FASTEST) { TIMING_LOG("auto switching to configured speed"); _timing_initialize(speed); } } } #endif if (UNLIKELY(emul_reinitialize)) { break; } #ifdef AUDIO_ENABLED if (UNLIKELY(emul_reinitialize_audio)) { break; } #endif if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); if (UNLIKELY(cpu_shutting_down)) { break; } } while (1); #ifdef AUDIO_ENABLED speaker_destroy(); MB_Destroy(); audio_shutdown(); #endif return NULL; }