vsync bugfix + refactoring
[libpicofe.git] / common / emu.c
index 5bd34e8..118dc38 100644 (file)
@@ -25,6 +25,8 @@
 #include <zlib/zlib.h>\r
 \r
 \r
+#define STATUS_MSG_TIMEOUT 2000\r
+\r
 void *g_screen_ptr;\r
 \r
 #if !SCREEN_SIZE_FIXED\r
@@ -78,9 +80,9 @@ static int try_rfn_cut(char *fname)
        return 0;\r
 }\r
 \r
-static void get_ext(char *file, char *ext)\r
+static void get_ext(const char *file, char *ext)\r
 {\r
-       char *p;\r
+       const char *p;\r
 \r
        p = file + strlen(file) - 4;\r
        if (p < file) p = file;\r
@@ -92,23 +94,29 @@ static void get_ext(char *file, char *ext)
 void emu_status_msg(const char *format, ...)\r
 {\r
        va_list vl;\r
+       int ret;\r
 \r
        va_start(vl, format);\r
-       vsnprintf(noticeMsg, sizeof(noticeMsg), format, vl);\r
+       ret = vsnprintf(noticeMsg, sizeof(noticeMsg), format, vl);\r
        va_end(vl);\r
 \r
+       /* be sure old text gets overwritten */\r
+       for (; ret < 28; ret++)\r
+               noticeMsg[ret] = ' ';\r
+       noticeMsg[ret] = 0;\r
+\r
        notice_msg_time = plat_get_ticks_ms();\r
 }\r
 \r
-static const char *biosfiles_us[] = { "us_scd1_9210", "us_scd2_9306", "SegaCDBIOS9303" };\r
-static const char *biosfiles_eu[] = { "eu_mcd1_9210", "eu_mcd2_9306", "eu_mcd2_9303"   };\r
-static const char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" };\r
+static const char * const biosfiles_us[] = { "us_scd1_9210", "us_scd2_9306", "SegaCDBIOS9303" };\r
+static const char * const biosfiles_eu[] = { "eu_mcd1_9210", "eu_mcd2_9306", "eu_mcd2_9303"   };\r
+static const char * const biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" };\r
 \r
 static int find_bios(int region, char **bios_file)\r
 {\r
        static char bios_path[1024];\r
        int i, count;\r
-       const char **files;\r
+       const char * const *files;\r
        FILE *f = NULL;\r
 \r
        if (region == 4) { // US\r
@@ -169,12 +177,13 @@ static unsigned char id_header[0x100];
 \r
 /* checks if fname points to valid MegaCD image\r
  * if so, checks for suitable BIOS */\r
-int emu_cd_check(int *pregion, char *fname_in)\r
+static int emu_cd_check(int *pregion, const char *fname_in)\r
 {\r
+       const char *fname = fname_in;\r
        unsigned char buf[32];\r
        pm_file *cd_f;\r
        int region = 4; // 1: Japan, 4: US, 8: Europe\r
-       char ext[5], *fname = fname_in;\r
+       char ext[5];\r
        cue_track_type type = CT_UNKNOWN;\r
        cue_data_t *cue_data = NULL;\r
 \r
@@ -523,6 +532,24 @@ fail:
        return 0;\r
 }\r
 \r
+int emu_swap_cd(const char *fname)\r
+{\r
+       cd_img_type cd_type;\r
+       int ret = -1;\r
+\r
+       cd_type = emu_cd_check(NULL, fname);\r
+       if (cd_type != CIT_NOT_CD)\r
+               ret = Insert_CD(fname, cd_type);\r
+       if (ret != 0) {\r
+               me_update_msg("Load failed, invalid CD image?");\r
+               return 0;\r
+       }\r
+\r
+       strncpy(rom_fname_loaded, fname, sizeof(rom_fname_loaded)-1);\r
+       rom_fname_loaded[sizeof(rom_fname_loaded)-1] = 0;\r
+       return 1;\r
+}\r
+\r
 static void romfname_ext(char *dst, const char *prefix, const char *ext)\r
 {\r
        char *p;\r
@@ -616,7 +643,8 @@ int emu_read_config(int game, int no_defaults)
                        // read global config, and apply game_def.cfg on top\r
                        make_config_cfg(cfg);\r
                        config_readsect(cfg, NULL);\r
-                       ret = config_readsect("game_def.cfg", sect);\r
+                       emu_make_path(cfg, "game_def.cfg", sizeof(cfg));\r
+                       ret = config_readsect(cfg, sect);\r
                }\r
 \r
                if (ret == 0)\r
@@ -924,7 +952,7 @@ int emu_save_load_game(int load, int sram)
                }\r
                else    ret = -1;\r
                if (!ret)\r
-                       emu_status_msg(load ? "GAME LOADED" : "GAME SAVED");\r
+                       emu_status_msg(load ? "STATE LOADED" : "STATE SAVED");\r
                else\r
                {\r
                        emu_status_msg(load ? "LOAD FAILED" : "SAVE FAILED");\r
@@ -1086,7 +1114,7 @@ static void run_events_ui(unsigned int which)
                        in_set_blocking(0);\r
                }\r
                if (do_it) {\r
-                       plat_status_msg_busy_first((which & PEV_STATE_LOAD) ? "LOADING GAME" : "SAVING GAME");\r
+                       plat_status_msg_busy_first((which & PEV_STATE_LOAD) ? "LOADING STATE" : "SAVING STATE");\r
                        PicoStateProgressCB = plat_status_msg_busy_next;\r
                        emu_save_load_game((which & PEV_STATE_LOAD) ? 1 : 0, 0);\r
                        PicoStateProgressCB = NULL;\r
@@ -1248,9 +1276,6 @@ void emu_loop(void)
        if (PicoAHW & PAHW_MCD)\r
                PicoCDBufferInit();\r
 \r
-       if (currentConfig.EmuOpt & EOPT_PSYNC)\r
-               plat_video_wait_vsync();\r
-\r
        pemu_loop_prep();\r
 \r
        timestamp_fps = get_ticks();\r
@@ -1258,6 +1283,8 @@ void emu_loop(void)
 \r
        frames_done = frames_shown = pframes_done = 0;\r
 \r
+       plat_video_wait_vsync();\r
+\r
        /* loop with resync every 1 sec. */\r
        while (engineState == PGS_Running)\r
        {\r
@@ -1276,7 +1303,7 @@ void emu_loop(void)
                if (notice_msg_time != 0)\r
                {\r
                        static int noticeMsgSum;\r
-                       if (timestamp - ms_to_ticks(notice_msg_time) > ms_to_ticks(2000)) {\r
+                       if (timestamp - ms_to_ticks(notice_msg_time) > ms_to_ticks(STATUS_MSG_TIMEOUT)) {\r
                                notice_msg_time = 0;\r
                                plat_status_msg_clear();\r
                                notice_msg = NULL;\r
@@ -1325,10 +1352,18 @@ void emu_loop(void)
 \r
                if (timestamp - timestamp_base >= ms_to_ticks(1000))\r
                {\r
-                       if (PsndOut == 0 && currentConfig.Frameskip >= 0)\r
+                       if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && currentConfig.Frameskip >= 0)\r
                                pframes_done = 0;\r
-                       else\r
+                       else {\r
                                pframes_done -= target_fps;\r
+                               /* don't allow it to drift during heavy slowdowns */\r
+                               if (pframes_done < -5) {\r
+                                       reset_timing = 1;\r
+                                       continue;\r
+                               }\r
+                               if (pframes_done < -2)\r
+                                       pframes_done = -2;\r
+                       }\r
                        timestamp_base += ms_to_ticks(1000);\r
                }\r
 \r
@@ -1343,7 +1378,7 @@ void emu_loop(void)
                                pframes_done++; frames_done++;\r
                                diff_lim += target_frametime;\r
 \r
-                               if (PsndOut && !reset_timing) { // do framelimitting if sound is enabled\r
+                               if (!(currentConfig.EmuOpt & EOPT_NO_FRMLIMIT)) {\r
                                        timestamp = get_ticks();\r
                                        diff = timestamp - timestamp_base;\r
                                        if (diff < diff_lim) // we are too fast\r
@@ -1354,7 +1389,7 @@ void emu_loop(void)
                else if (diff > diff_lim)\r
                {\r
                        /* no time left for this frame - skip */\r
-                       if (diff - diff_lim >= ms_to_ticks(300)) {\r
+                       if (diff - diff_lim >= ms_to_ticks(200)) {\r
                                /* if too much behind, reset instead */\r
                                reset_timing = 1;\r
                                continue;\r
@@ -1369,7 +1404,7 @@ void emu_loop(void)
                PicoFrame();\r
 \r
                /* frame limiter */\r
-               if (!reset_timing && (PsndOut != NULL || currentConfig.Frameskip < 0))\r
+               if (!reset_timing && !(currentConfig.EmuOpt & EOPT_NO_FRMLIMIT))\r
                {\r
                        timestamp = get_ticks();\r
                        diff = timestamp - timestamp_base;\r
@@ -1378,12 +1413,9 @@ void emu_loop(void)
                        if (diff < diff_lim)\r
                        {\r
                                // we are too fast\r
-                               if (currentConfig.EmuOpt & EOPT_PSYNC) {\r
-                                       if (diff_lim - diff > target_frametime/2)\r
-                                               plat_wait_till_us(timestamp_base + target_frametime/4);\r
+                               plat_wait_till_us(timestamp_base + diff_lim - target_frametime / 4);\r
+                               if (currentConfig.EmuOpt & EOPT_VSYNC)\r
                                        plat_video_wait_vsync();\r
-                               } else\r
-                                       plat_wait_till_us(timestamp_base + diff_lim);\r
                        }\r
                }\r
 \r
@@ -1394,9 +1426,6 @@ void emu_loop(void)
 \r
        emu_set_fastforward(0);\r
 \r
-       if (PicoAHW & PAHW_MCD)\r
-               PicoCDBufferFree();\r
-\r
        // save SRAM\r
        if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && SRam.changed) {\r
                plat_status_msg_busy_first("Writing SRAM/BRAM...");\r
@@ -1404,9 +1433,11 @@ void emu_loop(void)
                SRam.changed = 0;\r
        }\r
 \r
-       // do menu background to be sure it's right\r
-       pemu_forced_frame(POPT_EN_SOFTSCALE);\r
-\r
        pemu_loop_end();\r
+\r
+       // pemu_loop_end() might want to do 1 frame for bg image,\r
+       // so free CD buffer here\r
+       if (PicoAHW & PAHW_MCD)\r
+               PicoCDBufferFree();\r
 }\r
 \r