perfect vsync
[picodrive.git] / platform / gp2x / emu.c
index eca0dc4..36d956a 100644 (file)
@@ -1063,11 +1063,11 @@ static void simpleWait(int thissec, int lim_time)
 void emu_Loop(void)\r
 {\r
        static int gp2x_old_clock = 200;\r
-       static int PsndRate_old = 0, PicoOpt_old = 0, PsndLen_real = 0, pal_old = 0;\r
+       static int PsndRate_old = 0, PicoOpt_old = 0, EmuOpt_old = 0, PsndLen_real = 0, pal_old = 0;\r
        char fpsbuff[24]; // fps count c string\r
        struct timeval tval; // timing\r
        int thissec = 0, frames_done = 0, frames_shown = 0, oldmodes = 0;\r
-       int target_fps, target_frametime, lim_time, i;\r
+       int target_fps, target_frametime, lim_time, vsync_offset, i;\r
        char *notice = 0;\r
 \r
        printf("entered emu_Loop()\n");\r
@@ -1085,6 +1085,13 @@ void emu_Loop(void)
                printf("updated gamma to %i\n", currentConfig.gamma);\r
        }\r
 \r
+       if ((EmuOpt_old&0x2000) != (currentConfig.EmuOpt&0x2000)) {\r
+               if (currentConfig.EmuOpt&0x2000)\r
+                    set_LCD_custom_rate(Pico.m.pal ? LCDR_100 : LCDR_120);\r
+               else unset_LCD_custom_rate();\r
+       }\r
+\r
+       EmuOpt_old = currentConfig.EmuOpt;\r
        fpsbuff[0] = 0;\r
 \r
        // make sure we are in correct mode\r
@@ -1128,6 +1135,19 @@ void emu_Loop(void)
        // prepare CD buffer\r
        if (PicoMCD & 1) PicoCDBufferInit();\r
 \r
+       // calc vsync offset to sync timing code with vsync\r
+       if (currentConfig.EmuOpt&0x2000) {\r
+               gettimeofday(&tval, 0);\r
+               gp2x_video_wait_vsync();\r
+               gettimeofday(&tval, 0);\r
+               vsync_offset = tval.tv_usec;\r
+               while (vsync_offset >= target_frametime)\r
+                       vsync_offset -= target_frametime;\r
+               if (!vsync_offset) vsync_offset++;\r
+               printf("vsync_offset: %i\n", vsync_offset);\r
+       } else\r
+               vsync_offset = 0;\r
+\r
        // loop?\r
        while (engineState == PGS_Running)\r
        {\r
@@ -1210,10 +1230,8 @@ void emu_Loop(void)
                                if (frames_shown > frames_done) frames_shown = frames_done;\r
                        }\r
                }\r
-#if 0\r
-               sprintf(fpsbuff, "%05i", Pico.m.frame_count);\r
-#endif\r
-               lim_time = (frames_done+1) * target_frametime;\r
+\r
+               lim_time = (frames_done+1) * target_frametime + vsync_offset;\r
                if(currentConfig.Frameskip >= 0) { // frameskip enabled\r
                        for(i = 0; i < currentConfig.Frameskip; i++) {\r
                                updateKeys();\r
@@ -1309,12 +1327,18 @@ if (Pico.m.frame_count == 31563) {
                        reset_timing = 1;\r
                else if (PsndOut != NULL || currentConfig.Frameskip < 0)\r
                {\r
-                       // sleep if we are still too fast\r
+                       // sleep or vsync if we are still too fast\r
                        // usleep sleeps for ~20ms minimum, so it is not a solution here\r
                        if(tval.tv_usec < lim_time)\r
                        {\r
                                // we are too fast\r
-                               simpleWait(thissec, lim_time);\r
+                               if (vsync_offset) {\r
+                                       if (lim_time - tval.tv_usec > target_frametime/2)\r
+                                               simpleWait(thissec, lim_time - target_frametime/4);\r
+                                       gp2x_video_wait_vsync();\r
+                               } else {\r
+                                       simpleWait(thissec, lim_time);\r
+                               }\r
                        }\r
                }\r
 \r