frontend: new sync code

should fix video drift/desync on pandora
This commit is contained in:
notaz 2013-08-30 03:54:48 +03:00
parent cfae1ae179
commit b59172e3d4
5 changed files with 77 additions and 94 deletions

View file

@ -308,11 +308,6 @@ static int custom_read(menu_entry *me, const char *var, const char *val)
return 0; return 0;
return 1; return 1;
case MA_OPT2_GAMMA:
if (strcasecmp(var, "Gamma correction") != 0) return 0;
currentConfig.gamma = (int) (atof(val) * 100.0);
return 1;
case MA_CDOPT_READAHEAD: case MA_CDOPT_READAHEAD:
if (strcasecmp(var, "ReadAhead buffer") != 0) return 0; if (strcasecmp(var, "ReadAhead buffer") != 0) return 0;
PicoCDBuffers = atoi(val) / 2; PicoCDBuffers = atoi(val) / 2;

View file

@ -43,7 +43,7 @@ void *g_screen_ptr;
int g_screen_width = 320; int g_screen_width = 320;
int g_screen_height = 240; int g_screen_height = 240;
char *PicoConfigFile = "config.cfg"; const char *PicoConfigFile = "config2.cfg";
currentConfig_t currentConfig, defaultConfig; currentConfig_t currentConfig, defaultConfig;
int state_slot = 0; int state_slot = 0;
int config_slot = 0, config_slot_current = 0; int config_slot = 0, config_slot_current = 0;
@ -1276,31 +1276,26 @@ static void emu_loop_prep(void)
filter_old = currentConfig.filter; filter_old = currentConfig.filter;
} }
printf("-- gamma %d\n", currentConfig.gamma);
plat_target_gamma_set(currentConfig.gamma, 0); plat_target_gamma_set(currentConfig.gamma, 0);
pemu_loop_prep(); pemu_loop_prep();
} }
static void skip_frame(int do_audio)
{
PicoSkipFrame = do_audio ? 1 : 2;
PicoFrame();
PicoSkipFrame = 0;
}
/* our tick here is 1 us right now */ /* our tick here is 1 us right now */
#define ms_to_ticks(x) (unsigned int)(x * 1000) #define ms_to_ticks(x) (unsigned int)(x * 1000)
#define get_ticks() plat_get_ticks_us() #define get_ticks() plat_get_ticks_us()
void emu_loop(void) void emu_loop(void)
{ {
int pframes_done; /* "period" frames, used for sync */
int frames_done, frames_shown; /* actual frames for fps counter */ int frames_done, frames_shown; /* actual frames for fps counter */
int target_fps, target_frametime; int target_frametime_x3;
unsigned int timestamp_base = 0, timestamp_fps; unsigned int timestamp_x3 = 0;
unsigned int timestamp_aim_x3 = 0;
unsigned int timestamp_fps_x3 = 0;
char *notice_msg = NULL; char *notice_msg = NULL;
char fpsbuff[24]; char fpsbuff[24];
int i; int fskip_cnt = 0;
fpsbuff[0] = 0; fpsbuff[0] = 0;
@ -1315,45 +1310,47 @@ void emu_loop(void)
pemu_sound_start(); pemu_sound_start();
/* number of ticks per frame */ /* number of ticks per frame */
if (Pico.m.pal) { if (Pico.m.pal)
target_fps = 50; target_frametime_x3 = 3 * ms_to_ticks(1000) / 50;
target_frametime = ms_to_ticks(1000) / 50; else
} else { target_frametime_x3 = 3 * ms_to_ticks(1000) / 60;
target_fps = 60;
target_frametime = ms_to_ticks(1000) / 60 + 1;
}
timestamp_fps = get_ticks();
reset_timing = 1; reset_timing = 1;
frames_done = frames_shown = 0;
frames_done = frames_shown = pframes_done = 0;
plat_video_wait_vsync();
/* loop with resync every 1 sec. */ /* loop with resync every 1 sec. */
while (engineState == PGS_Running) while (engineState == PGS_Running)
{ {
unsigned int timestamp; int skip = 0;
int diff, diff_lim; int diff;
pprof_start(main); pprof_start(main);
timestamp = get_ticks();
if (reset_timing) { if (reset_timing) {
reset_timing = 0; reset_timing = 0;
timestamp_base = timestamp; plat_video_wait_vsync();
pframes_done = 0; timestamp_aim_x3 = get_ticks() * 3;
timestamp_fps_x3 = timestamp_aim_x3;
fskip_cnt = 0;
} }
else if (currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) {
timestamp_aim_x3 = get_ticks() * 3;
}
timestamp_x3 = get_ticks() * 3;
// show notice_msg message? // show notice_msg message?
if (notice_msg_time != 0) if (notice_msg_time != 0)
{ {
static int noticeMsgSum; static int noticeMsgSum;
if (timestamp - ms_to_ticks(notice_msg_time) > ms_to_ticks(STATUS_MSG_TIMEOUT)) { if (timestamp_x3 - ms_to_ticks(notice_msg_time) * 3
> ms_to_ticks(STATUS_MSG_TIMEOUT) * 3)
{
notice_msg_time = 0; notice_msg_time = 0;
plat_status_msg_clear(); plat_status_msg_clear();
notice_msg = NULL; notice_msg = NULL;
} else { }
else {
int sum = noticeMsg[0] + noticeMsg[1] + noticeMsg[2]; int sum = noticeMsg[0] + noticeMsg[1] + noticeMsg[2];
if (sum != noticeMsgSum) { if (sum != noticeMsgSum) {
plat_status_msg_clear(); plat_status_msg_clear();
@ -1364,7 +1361,7 @@ void emu_loop(void)
} }
// second changed? // second changed?
if (timestamp - timestamp_fps >= ms_to_ticks(1000)) if (timestamp_x3 - timestamp_fps_x3 >= ms_to_ticks(1000) * 3)
{ {
#ifdef BENCHMARK #ifdef BENCHMARK
static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4];
@ -1382,86 +1379,79 @@ void emu_loop(void)
sprintf(fpsbuff, "%02i/%02i ", frames_shown, frames_done); sprintf(fpsbuff, "%02i/%02i ", frames_shown, frames_done);
#endif #endif
frames_shown = frames_done = 0; frames_shown = frames_done = 0;
timestamp_fps += ms_to_ticks(1000); timestamp_fps_x3 += ms_to_ticks(1000) * 3;
} }
#ifdef PFRAMES #ifdef PFRAMES
sprintf(fpsbuff, "%i", Pico.m.frame_count); sprintf(fpsbuff, "%i", Pico.m.frame_count);
#endif #endif
if (timestamp - timestamp_base >= ms_to_ticks(1000)) diff = timestamp_aim_x3 - timestamp_x3;
if (currentConfig.Frameskip >= 0) // frameskip enabled (or 0)
{ {
if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && currentConfig.Frameskip >= 0) if (fskip_cnt < currentConfig.Frameskip) {
pframes_done = 0; fskip_cnt++;
else skip = 1;
pframes_done -= target_fps;
if (pframes_done < -2) {
/* don't drag more than 2 frames behind */
pframes_done = -2;
timestamp_base = timestamp - 2 * target_frametime;
} }
else else {
timestamp_base += ms_to_ticks(1000); fskip_cnt = 0;
}
diff = timestamp - timestamp_base;
diff_lim = (pframes_done + 1) * target_frametime;
if (currentConfig.Frameskip >= 0) // frameskip enabled
{
for (i = 0; i < currentConfig.Frameskip; i++) {
emu_update_input();
skip_frame(1);
pframes_done++; frames_done++;
diff_lim += target_frametime;
if (!(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) {
timestamp = get_ticks();
diff = timestamp - timestamp_base;
if (!reset_timing && diff < diff_lim) // we are too fast
plat_wait_till_us(timestamp_base + diff_lim);
}
} }
} }
else if (diff > diff_lim) else if (diff < -target_frametime_x3)
{ {
/* no time left for this frame - skip */ /* no time left for this frame - skip */
/* limit auto frameskip to 8 */ /* limit auto frameskip to 8 */
if (frames_done / 8 <= frames_shown) { if (frames_done / 8 <= frames_shown)
emu_update_input(); skip = 1;
skip_frame(diff < diff_lim + target_frametime * 16); }
pframes_done++; frames_done++;
continue; // don't go in debt too much
} while (diff < -target_frametime_x3 * 3) {
timestamp_aim_x3 += target_frametime_x3;
diff = timestamp_aim_x3 - timestamp_x3;
} }
emu_update_input(); emu_update_input();
PicoFrame(); if (skip) {
pemu_finalize_frame(fpsbuff, notice_msg); int do_audio = diff > -target_frametime_x3 * 2;
PicoSkipFrame = do_audio ? 1 : 2;
PicoFrame();
PicoSkipFrame = 0;
}
else {
PicoFrame();
pemu_finalize_frame(fpsbuff, notice_msg);
frames_shown++;
}
frames_done++;
timestamp_aim_x3 += target_frametime_x3;
if (!flip_after_sync) if (!skip && !flip_after_sync)
plat_video_flip(); plat_video_flip();
/* frame limiter */ /* frame limiter */
if (!reset_timing && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT))) if (!skip && !reset_timing
&& !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT)))
{ {
timestamp = get_ticks(); unsigned int timestamp = get_ticks();
diff = timestamp - timestamp_base; diff = timestamp_aim_x3 - timestamp * 3;
// sleep or vsync if we are still too fast // sleep or vsync if we are still too fast
if (diff < diff_lim) if (diff > target_frametime_x3 && (currentConfig.EmuOpt & EOPT_VSYNC)) {
{
// we are too fast // we are too fast
plat_wait_till_us(timestamp_base + diff_lim - target_frametime / 4); plat_video_wait_vsync();
if (currentConfig.EmuOpt & EOPT_VSYNC) timestamp = get_ticks();
plat_video_wait_vsync(); diff = timestamp * 3 - timestamp_aim_x3;
}
if (diff > target_frametime_x3) {
// still too fast
plat_wait_till_us(timestamp + (diff - target_frametime_x3) / 3);
} }
} }
if (flip_after_sync) if (!skip && flip_after_sync)
plat_video_flip(); plat_video_flip();
pframes_done++; frames_done++; frames_shown++;
pprof_end(main); pprof_end(main);
} }

View file

@ -77,7 +77,7 @@ typedef struct _currentConfig_t {
} currentConfig_t; } currentConfig_t;
extern currentConfig_t currentConfig, defaultConfig; extern currentConfig_t currentConfig, defaultConfig;
extern char *PicoConfigFile; extern const char *PicoConfigFile;
extern int state_slot; extern int state_slot;
extern int config_slot, config_slot_current; extern int config_slot, config_slot_current;
extern unsigned char *movie_data; extern unsigned char *movie_data;

View file

@ -19,7 +19,6 @@
#include <cpu/debug.h> #include <cpu/debug.h>
extern char *PicoConfigFile;
static int load_state_slot = -1; static int load_state_slot = -1;
char **g_argv; char **g_argv;

View file

@ -927,7 +927,7 @@ static void debug_menu_loop(void)
// ------------ main menu ------------ // ------------ main menu ------------
static const char credits[] = static const char credits[] =
"PicoDrive v" VERSION " (c) notaz, 2006-2011\n\n\n" "PicoDrive v" VERSION " (c) notaz, 2006-2013\n\n\n"
"Credits:\n" "Credits:\n"
"fDave: Cyclone 68000 core,\n" "fDave: Cyclone 68000 core,\n"
" base code of PicoDrive\n" " base code of PicoDrive\n"
@ -935,7 +935,6 @@ static const char credits[] =
"MAME devs: YM2612 and SN76496 cores\n" "MAME devs: YM2612 and SN76496 cores\n"
"Inder, ketchupgun: graphics\n" "Inder, ketchupgun: graphics\n"
#ifdef __GP2X__ #ifdef __GP2X__
"rlyeh and others: minimal SDK\n"
"Squidge: mmuhack\n" "Squidge: mmuhack\n"
"Dzz: ARM940 sample\n" "Dzz: ARM940 sample\n"
#endif #endif
@ -944,7 +943,7 @@ static const char credits[] =
" Charles MacDonald, Haze,\n" " Charles MacDonald, Haze,\n"
" Stephane Dallongeville,\n" " Stephane Dallongeville,\n"
" Lordus, Exophase, Rokas,\n" " Lordus, Exophase, Rokas,\n"
" Nemesis, Tasco Deluxe"; " Eke, Nemesis, Tasco Deluxe";
static void menu_main_draw_status(void) static void menu_main_draw_status(void)
{ {