int video_screen_get_vpos(int scrnum) { mame_time delta = sub_mame_times(mame_timer_get_time(), scrinfo[scrnum].vblank_time); int vpos; assert(delta.seconds == 0); vpos = delta.subseconds / scrinfo[scrnum].scantime; return (Machine->screen[scrnum].visarea.max_y + 1 + vpos) % Machine->screen[scrnum].height; }
int video_screen_get_hpos(int scrnum) { mame_time delta = sub_mame_times(mame_timer_get_time(), scrinfo[scrnum].vblank_time); int vpos, hpos; assert(delta.seconds == 0); vpos = delta.subseconds / scrinfo[scrnum].scantime; hpos = (delta.subseconds - (vpos * scrinfo[scrnum].scantime)) / scrinfo[scrnum].pixeltime; return hpos; }
void video_vblank_start(void) { mame_time curtime = mame_timer_get_time(); int scrnum; /* kludge: we get called at time 0 to reset, but at that point, the time of last VBLANK is actually -vblank_duration */ if (curtime.seconds == 0 && curtime.subseconds == 0) curtime = sub_mame_times(time_zero, double_to_mame_time(Machine->screen[0].vblank)); /* reset VBLANK timers for each screen -- fix me */ for (scrnum = 0; scrnum < MAX_SCREENS; scrnum++) scrinfo[scrnum].vblank_time = curtime; }
mame_time video_screen_get_time_until_pos(int scrnum, int vpos, int hpos) { mame_time curdelta = sub_mame_times(mame_timer_get_time(), scrinfo[scrnum].vblank_time); subseconds_t targetdelta; assert(curdelta.seconds == 0); /* since we measure time relative to VBLANK, compute the scanline offset from VBLANK */ vpos += Machine->screen[scrnum].height - (Machine->screen[scrnum].visarea.max_y + 1); vpos %= Machine->screen[scrnum].height; /* compute the delta for the given X,Y position */ targetdelta = (subseconds_t)vpos * scrinfo[scrnum].scantime + (subseconds_t)hpos * scrinfo[scrnum].pixeltime; /* if we're past that time, head to the next frame */ if (targetdelta <= curdelta.subseconds) targetdelta += DOUBLE_TO_SUBSECONDS(TIME_IN_HZ(Machine->screen[scrnum].refresh)); /* return the difference */ return make_mame_time(0, targetdelta - curdelta.subseconds); }
int video_init(running_machine *machine) { int scrnum; add_exit_callback(machine, video_exit); /* reset globals */ memset(scrinfo, 0, sizeof(scrinfo)); /* configure all of the screens */ for (scrnum = 0; scrnum < MAX_SCREENS; scrnum++) if (machine->drv->screen[scrnum].tag != NULL) { internal_screen_info *info = &scrinfo[scrnum]; screen_state *state = &machine->screen[scrnum]; /* configure the screen with the default parameters */ video_screen_configure(scrnum, state->width, state->height, &state->visarea, state->refresh); /* reset VBLANK timing */ info->vblank_time = sub_mame_times(time_zero, double_to_mame_time(Machine->screen[0].vblank)); /* register for save states */ state_save_register_item("video", scrnum, info->vblank_time.seconds); state_save_register_item("video", scrnum, info->vblank_time.subseconds); } /* create spriteram buffers if necessary */ if (machine->drv->video_attributes & VIDEO_BUFFERS_SPRITERAM) init_buffered_spriteram(); /* convert the gfx ROMs into character sets. This is done BEFORE calling the driver's */ /* palette_init() routine because it might need to check the machine->gfx[] data */ if (machine->drv->gfxdecodeinfo != NULL) allocate_graphics(machine->drv->gfxdecodeinfo); /* configure the palette */ palette_config(machine); /* actually decode the graphics */ if (machine->drv->gfxdecodeinfo != NULL) decode_graphics(machine->drv->gfxdecodeinfo); /* reset performance data */ last_fps_time = osd_ticks(); rendered_frames_since_last_fps = frames_since_last_fps = 0; performance.game_speed_percent = 100; performance.frames_per_second = machine->screen[0].refresh; performance.vector_updates_last_second = 0; /* reset video statics and get out of here */ pdrawgfx_shadow_lowpri = 0; leds_status = 0; /* initialize tilemaps */ if (tilemap_init(machine) != 0) fatalerror("tilemap_init failed"); /* create a render target for snapshots */ if (Machine->drv->screen[0].tag != NULL) { snap_bitmap = NULL; snap_target = render_target_alloc(layout_snap, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN); assert(snap_target != NULL); if (snap_target == NULL) return 1; render_target_set_layer_config(snap_target, 0); } /* create crosshairs */ crosshair_init(); return 0; }
static void handle_load(running_machine *machine) { mame_private *mame = machine->mame_data; mame_file_error filerr; mame_file *file; /* if no name, bail */ if (mame->saveload_pending_file == NULL) { mame->saveload_schedule_callback = NULL; return; } /* if there are anonymous timers, we can't load just yet because the timers might */ /* overwrite data we have loaded */ if (timer_count_anonymous() > 0) { /* if more than a second has passed, we're probably screwed */ if (sub_mame_times(mame_timer_get_time(), mame->saveload_schedule_time).seconds > 0) { popmessage("Unable to load due to pending anonymous timers. See error.log for details."); goto cancel; } return; } /* open the file */ filerr = mame_fopen(SEARCHPATH_STATE, mame->saveload_pending_file, OPEN_FLAG_READ, &file); if (filerr == FILERR_NONE) { /* start loading */ if (state_save_load_begin(file) == 0) { int cpunum; /* read tag 0 */ state_save_push_tag(0); state_save_load_continue(); state_save_pop_tag(); /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { cpuintrf_push_context(cpunum); /* make sure banking is set */ activecpu_reset_banking(); /* load the CPU data */ state_save_push_tag(cpunum + 1); state_save_load_continue(); state_save_pop_tag(); /* make sure banking is set */ activecpu_reset_banking(); cpuintrf_pop_context(); } /* finish and close */ state_save_load_finish(); popmessage("State successfully loaded."); } else popmessage("Error: Failed to load state"); mame_fclose(file); } else popmessage("Error: Failed to load state"); cancel: /* unschedule the load */ free(mame->saveload_pending_file); mame->saveload_pending_file = NULL; mame->saveload_schedule_callback = NULL; }
static void handle_save(running_machine *machine) { mame_private *mame = machine->mame_data; mame_file_error filerr; mame_file *file; /* if no name, bail */ if (mame->saveload_pending_file == NULL) { mame->saveload_schedule_callback = NULL; return; } /* if there are anonymous timers, we can't save just yet */ if (timer_count_anonymous() > 0) { /* if more than a second has passed, we're probably screwed */ if (sub_mame_times(mame_timer_get_time(), mame->saveload_schedule_time).seconds > 0) { popmessage("Unable to save due to pending anonymous timers. See error.log for details."); goto cancel; } return; } /* open the file */ filerr = mame_fopen(SEARCHPATH_STATE, mame->saveload_pending_file, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file); if (filerr == FILERR_NONE) { int cpunum; /* write the save state */ if (state_save_save_begin(file) != 0) { popmessage("Error: Unable to save state due to illegal registrations. See error.log for details."); mame_fclose(file); goto cancel; } /* write the default tag */ state_save_push_tag(0); state_save_save_continue(); state_save_pop_tag(); /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { cpuintrf_push_context(cpunum); /* make sure banking is set */ activecpu_reset_banking(); /* save the CPU data */ state_save_push_tag(cpunum + 1); state_save_save_continue(); state_save_pop_tag(); cpuintrf_pop_context(); } /* finish and close */ state_save_save_finish(); mame_fclose(file); /* pop a warning if the game doesn't support saves */ if (!(machine->gamedrv->flags & GAME_SUPPORTS_SAVE)) popmessage("State successfully saved.\nWarning: Save states are not officially supported for this game."); else popmessage("State successfully saved."); } else popmessage("Error: Failed to save state"); cancel: /* unschedule the save */ free(mame->saveload_pending_file); mame->saveload_pending_file = NULL; mame->saveload_schedule_callback = NULL; }
static void update_throttle(mame_time emutime) { static double ticks_per_sleep_msec = 0; osd_ticks_t target, curr, cps, diffticks; int allowed_to_sleep; subseconds_t subsecs_per_cycle; int paused = mame_is_paused(Machine); // if we're only syncing to the refresh, bail now if (video_config.syncrefresh) return; // if we're paused, emutime will not advance; explicitly resync and set us backwards // 1/60th of a second if (paused) throttle_realtime = throttle_emutime = sub_subseconds_from_mame_time(emutime, MAX_SUBSECONDS / PAUSED_REFRESH_RATE); // if time moved backwards (reset), or if it's been more than 1 second in emulated time, resync if (compare_mame_times(emutime, throttle_emutime) < 0 || sub_mame_times(emutime, throttle_emutime).seconds > 0) goto resync; // get the current realtime; if it's been more than 1 second realtime, just resync cps = osd_ticks_per_second(); diffticks = osd_ticks() - throttle_last_ticks; throttle_last_ticks += diffticks; if (diffticks >= cps) goto resync; // add the time that has passed to the real time subsecs_per_cycle = MAX_SUBSECONDS / cps; throttle_realtime = add_subseconds_to_mame_time(throttle_realtime, diffticks * subsecs_per_cycle); // update the emulated time throttle_emutime = emutime; // if we're behind, just sync if (compare_mame_times(throttle_emutime, throttle_realtime) <= 0) goto resync; // determine our target ticks value target = throttle_last_ticks + sub_mame_times(throttle_emutime, throttle_realtime).subseconds / subsecs_per_cycle; // initialize the ticks per sleep if (ticks_per_sleep_msec == 0) ticks_per_sleep_msec = (double)(cps / 1000); // this counts as idle time profiler_mark(PROFILER_IDLE); // determine whether or not we are allowed to sleep allowed_to_sleep = video_config.sleep && (!effective_autoframeskip() || effective_frameskip() == 0); // sync for (curr = osd_ticks(); curr - target < 0; curr = osd_ticks()) { // if we have enough time to sleep, do it // ...but not if we're autoframeskipping and we're behind if (paused || (allowed_to_sleep && (target - curr) > (osd_ticks_t)(ticks_per_sleep_msec * 1.1))) { osd_ticks_t next; // keep track of how long we actually slept Sleep(1); next = osd_ticks(); ticks_per_sleep_msec = (ticks_per_sleep_msec * 0.90) + ((double)(next - curr) * 0.10); } } // idle time done profiler_mark(PROFILER_END); // update realtime diffticks = osd_ticks() - throttle_last_ticks; throttle_last_ticks += diffticks; throttle_realtime = add_subseconds_to_mame_time(throttle_realtime, diffticks * subsecs_per_cycle); return; resync: // reset realtime and emutime to the same value throttle_realtime = throttle_emutime = emutime; }
mame_time mame_timer_timeleft(mame_timer *which) { return sub_mame_times(which->expire, get_current_time()); }
mame_time mame_timer_timeelapsed(mame_timer *which) { return sub_mame_times(get_current_time(), which->start); }