move emu loop to common; redo timing; add pollux timer
authornotaz <notasas@gmail.com>
Fri, 31 Jul 2009 22:01:03 +0000 (22:01 +0000)
committernotaz <notasas@gmail.com>
Fri, 31 Jul 2009 22:01:03 +0000 (22:01 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@721 be3aeb3a-fb24-0410-a615-afba39da0efa

13 files changed:
platform/common/emu.c
platform/common/emu.h
platform/common/main.c
platform/common/plat.h
platform/gizmondo/emu.c
platform/gp2x/emu.c
platform/gp2x/soc.c
platform/gp2x/soc.h
platform/gp2x/soc_mmsp2.c
platform/gp2x/soc_pollux.c
platform/linux/plat.c
platform/pandora/emu.c
platform/psp/emu.c

index 1c7d1b7..5bd34e8 100644 (file)
@@ -5,6 +5,7 @@
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
+#include <stdarg.h>\r
 #ifndef NO_SYNC\r
 #include <unistd.h>\r
 #endif\r
@@ -44,6 +45,8 @@ char rom_fname_reload[512] = { 0, };
 char rom_fname_loaded[512] = { 0, };\r
 int rom_loaded = 0;\r
 int reset_timing = 0;\r
+static unsigned int notice_msg_time;   /* when started showing */\r
+static char noticeMsg[40];\r
 \r
 unsigned char *movie_data = NULL;\r
 static int movie_size = 0;\r
@@ -86,6 +89,17 @@ static void get_ext(char *file, char *ext)
        strlwr_(ext);\r
 }\r
 \r
+void emu_status_msg(const char *format, ...)\r
+{\r
+       va_list vl;\r
+\r
+       va_start(vl, format);\r
+       vsnprintf(noticeMsg, sizeof(noticeMsg), format, vl);\r
+       va_end(vl);\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
@@ -485,12 +499,12 @@ int emu_reload_rom(char *rom_fname)
                        // TODO: bits 6 & 5\r
                }\r
                movie_data[0x18+30] = 0;\r
-               plat_status_msg("MOVIE: %s", (char *) &movie_data[0x18]);\r
+               emu_status_msg("MOVIE: %s", (char *) &movie_data[0x18]);\r
        }\r
        else\r
        {\r
                PicoOpt &= ~POPT_DIS_VDP_FIFO;\r
-               plat_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS");\r
+               emu_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS");\r
        }\r
 \r
        // load SRAM for this ROM\r
@@ -702,7 +716,7 @@ void update_movie(void)
        if (offs+3 > movie_size) {\r
                free(movie_data);\r
                movie_data = 0;\r
-               plat_status_msg("END OF MOVIE.");\r
+               emu_status_msg("END OF MOVIE.");\r
                lprintf("END OF MOVIE.\n");\r
        } else {\r
                // MXYZ SACB RLDU\r
@@ -824,7 +838,7 @@ int emu_save_load_game(int load, int sram)
        saveFname = emu_get_save_fname(load, sram, state_slot);\r
        if (saveFname == NULL) {\r
                if (!sram)\r
-                       plat_status_msg(load ? "LOAD FAILED (missing file)" : "SAVE FAILED");\r
+                       emu_status_msg(load ? "LOAD FAILED (missing file)" : "SAVE FAILED");\r
                return -1;\r
        }\r
 \r
@@ -910,10 +924,10 @@ int emu_save_load_game(int load, int sram)
                }\r
                else    ret = -1;\r
                if (!ret)\r
-                       plat_status_msg(load ? "GAME LOADED" : "GAME SAVED");\r
+                       emu_status_msg(load ? "GAME LOADED" : "GAME SAVED");\r
                else\r
                {\r
-                       plat_status_msg(load ? "LOAD FAILED" : "SAVE FAILED");\r
+                       emu_status_msg(load ? "LOAD FAILED" : "SAVE FAILED");\r
                        ret = -1;\r
                }\r
 \r
@@ -935,7 +949,7 @@ void emu_set_fastforward(int set_on)
                currentConfig.EmuOpt &= ~4;\r
                currentConfig.EmuOpt |= 0x40000;\r
                is_on = 1;\r
-               plat_status_msg("FAST FORWARD");\r
+               emu_status_msg("FAST FORWARD");\r
        }\r
        else if (!set_on && is_on) {\r
                PsndOut = set_PsndOut;\r
@@ -948,7 +962,7 @@ void emu_set_fastforward(int set_on)
 \r
 static void emu_msg_tray_open(void)\r
 {\r
-       plat_status_msg("CD tray opened");\r
+       emu_status_msg("CD tray opened");\r
 }\r
 \r
 void emu_reset_game(void)\r
@@ -966,9 +980,9 @@ void run_events_pico(unsigned int events)
                if (pico_inp_mode > 2)\r
                        pico_inp_mode = 0;\r
                switch (pico_inp_mode) {\r
-                       case 2: plat_status_msg("Input: Pen on Pad"); break;\r
-                       case 1: plat_status_msg("Input: Pen on Storyware"); break;\r
-                       case 0: plat_status_msg("Input: Joystick");\r
+                       case 2: emu_status_msg("Input: Pen on Pad"); break;\r
+                       case 1: emu_status_msg("Input: Pen on Storyware"); break;\r
+                       case 0: emu_status_msg("Input: Joystick");\r
                                PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000;\r
                                break;\r
                }\r
@@ -977,13 +991,13 @@ void run_events_pico(unsigned int events)
                PicoPicohw.page--;\r
                if (PicoPicohw.page < 0)\r
                        PicoPicohw.page = 0;\r
-               plat_status_msg("Page %i", PicoPicohw.page);\r
+               emu_status_msg("Page %i", PicoPicohw.page);\r
        }\r
        if (events & PEV_PICO_PNEXT) {\r
                PicoPicohw.page++;\r
                if (PicoPicohw.page > 6)\r
                        PicoPicohw.page = 6;\r
-               plat_status_msg("Page %i", PicoPicohw.page);\r
+               emu_status_msg("Page %i", PicoPicohw.page);\r
        }\r
 \r
        if (pico_inp_mode == 0)\r
@@ -1094,7 +1108,7 @@ static void run_events_ui(unsigned int which)
                                state_slot = 0;\r
                }\r
 \r
-               plat_status_msg("SAVE SLOT %i [%s]", state_slot,\r
+               emu_status_msg("SAVE SLOT %i [%s]", state_slot,\r
                        emu_check_save_file(state_slot) ? "USED" : "FREE");\r
        }\r
        if (which & PEV_MENU)\r
@@ -1194,3 +1208,205 @@ void emu_finish(void)
        PicoExit();\r
 }\r
 \r
+static void skip_frame(int do_audio)\r
+{\r
+       PicoSkipFrame = do_audio ? 1 : 2;\r
+       PicoFrame();\r
+       PicoSkipFrame = 0;\r
+}\r
+\r
+/* our tick here is 1 us right now */\r
+#define ms_to_ticks(x) (unsigned int)(x * 1000)\r
+#define get_ticks() plat_get_ticks_us()\r
+\r
+void emu_loop(void)\r
+{\r
+       int pframes_done;               /* "period" frames, used for sync */\r
+       int frames_done, frames_shown;  /* actual frames for fps counter */\r
+       int oldmodes, target_fps, target_frametime;\r
+       unsigned int timestamp_base = 0, timestamp_fps;\r
+       char *notice_msg = NULL;\r
+       char fpsbuff[24];\r
+       int i;\r
+\r
+       fpsbuff[0] = 0;\r
+\r
+       /* make sure we are in correct mode */\r
+       oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc;\r
+       Pico.m.dirtyPal = 1;\r
+\r
+       /* number of ticks per frame */\r
+       if (Pico.m.pal) {\r
+               target_fps = 50;\r
+               target_frametime = ms_to_ticks(1000) / 50;\r
+       } else {\r
+               target_fps = 60;\r
+               target_frametime = ms_to_ticks(1000) / 60 + 1;\r
+       }\r
+\r
+       // prepare CD buffer\r
+       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
+       reset_timing = 1;\r
+\r
+       frames_done = frames_shown = pframes_done = 0;\r
+\r
+       /* loop with resync every 1 sec. */\r
+       while (engineState == PGS_Running)\r
+       {\r
+               unsigned int timestamp;\r
+               int diff, diff_lim;\r
+               int modes;\r
+\r
+               timestamp = get_ticks();\r
+               if (reset_timing) {\r
+                       reset_timing = 0;\r
+                       timestamp_base = timestamp;\r
+                       pframes_done = 0;\r
+               }\r
+\r
+               // show notice_msg message?\r
+               if (notice_msg_time != 0)\r
+               {\r
+                       static int noticeMsgSum;\r
+                       if (timestamp - ms_to_ticks(notice_msg_time) > ms_to_ticks(2000)) {\r
+                               notice_msg_time = 0;\r
+                               plat_status_msg_clear();\r
+                               notice_msg = NULL;\r
+                       } else {\r
+                               int sum = noticeMsg[0] + noticeMsg[1] + noticeMsg[2];\r
+                               if (sum != noticeMsgSum) {\r
+                                       plat_status_msg_clear();\r
+                                       noticeMsgSum = sum;\r
+                               }\r
+                               notice_msg = noticeMsg;\r
+                       }\r
+               }\r
+\r
+               // check for mode changes\r
+               modes = ((Pico.video.reg[12]&1)<<2) | (Pico.video.reg[1]&8);\r
+               if (modes != oldmodes) {\r
+                       oldmodes = modes;\r
+                       pemu_video_mode_change(!(modes & 4), (modes & 8));\r
+               }\r
+\r
+               // second changed?\r
+               if (timestamp - timestamp_fps >= ms_to_ticks(1000))\r
+               {\r
+#ifdef BENCHMARK\r
+                       static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4];\r
+                       if (++bench == 10) {\r
+                               bench = 0;\r
+                               bench_fps_s = bench_fps;\r
+                               bf[bfp++ & 3] = bench_fps;\r
+                               bench_fps = 0;\r
+                       }\r
+                       bench_fps += frames_shown;\r
+                       sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2);\r
+#else\r
+                       if (currentConfig.EmuOpt & EOPT_SHOW_FPS) {\r
+                               sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done);\r
+                               if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; }\r
+                       }\r
+#endif\r
+                       frames_shown = frames_done = 0;\r
+                       timestamp_fps += ms_to_ticks(1000);\r
+               }\r
+#ifdef PFRAMES\r
+               sprintf(fpsbuff, "%i", Pico.m.frame_count);\r
+#endif\r
+\r
+               if (timestamp - timestamp_base >= ms_to_ticks(1000))\r
+               {\r
+                       if (PsndOut == 0 && currentConfig.Frameskip >= 0)\r
+                               pframes_done = 0;\r
+                       else\r
+                               pframes_done -= target_fps;\r
+                       timestamp_base += ms_to_ticks(1000);\r
+               }\r
+\r
+               diff = timestamp - timestamp_base;\r
+               diff_lim = (pframes_done + 1) * target_frametime;\r
+\r
+               if (currentConfig.Frameskip >= 0) // frameskip enabled\r
+               {\r
+                       for (i = 0; i < currentConfig.Frameskip; i++) {\r
+                               emu_update_input();\r
+                               skip_frame(1);\r
+                               pframes_done++; frames_done++;\r
+                               diff_lim += target_frametime;\r
+\r
+                               if (PsndOut && !reset_timing) { // do framelimitting if sound is enabled\r
+                                       timestamp = get_ticks();\r
+                                       diff = timestamp - timestamp_base;\r
+                                       if (diff < diff_lim) // we are too fast\r
+                                               plat_wait_till_us(timestamp_base + diff_lim);\r
+                               }\r
+                       }\r
+               }\r
+               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 too much behind, reset instead */\r
+                               reset_timing = 1;\r
+                               continue;\r
+                       }\r
+                       emu_update_input();\r
+                       skip_frame(diff < diff_lim + target_frametime * 2);\r
+                       pframes_done++; frames_done++;\r
+                       continue;\r
+               }\r
+\r
+               emu_update_input();\r
+               PicoFrame();\r
+\r
+               /* frame limiter */\r
+               if (!reset_timing && (PsndOut != NULL || currentConfig.Frameskip < 0))\r
+               {\r
+                       timestamp = get_ticks();\r
+                       diff = timestamp - timestamp_base;\r
+\r
+                       // sleep or vsync if we are still too fast\r
+                       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_video_wait_vsync();\r
+                               } else\r
+                                       plat_wait_till_us(timestamp_base + diff_lim);\r
+                       }\r
+               }\r
+\r
+               pemu_update_display(fpsbuff, notice_msg);\r
+\r
+               pframes_done++; frames_done++; frames_shown++;\r
+       }\r
+\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
+               emu_save_load_game(0, 1);\r
+               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
+\r
index 28aed4f..ecd9ba1 100644 (file)
@@ -99,6 +99,7 @@ enum TPicoGameState {
 
 void  emu_init(void);
 void  emu_finish(void);
+void  emu_loop(void);
 
 int   emu_reload_rom(char *rom_fname);
 int   emu_save_load_game(int load, int sram);
@@ -122,6 +123,7 @@ void  emu_update_input(void);
 void  emu_get_game_name(char *str150);
 void  emu_set_fastforward(int set_on);
 int   emu_cd_check(int *pregion, char *fname_in);
+void  emu_status_msg(const char *format, ...);
 
 #ifdef __cplusplus
 } // extern "C"
index d43aabc..bdcdc14 100644 (file)
@@ -117,7 +117,7 @@ int main(int argc, char *argv[])
                                engineState = PGS_Running;\r
 \r
                        case PGS_Running:\r
-                               pemu_loop();\r
+                               emu_loop();\r
                                break;\r
 \r
                        case PGS_Quit:\r
index ccdfa79..a453431 100644 (file)
@@ -6,8 +6,12 @@ extern "C" {
 extern char cpu_clk_name[];
 
 void pemu_prep_defconfig(void);
-void pemu_loop(void);
+void pemu_loop_prep(void);
+void pemu_loop_end(void);
 void pemu_forced_frame(int opts);
+void pemu_video_mode_change(int is_32col, int is_240_lines);
+void pemu_update_display(const char *fps, const char *notice_msg);
+
 void pemu_sound_start(void);
 void pemu_sound_stop(void);
 void pemu_sound_wait(void);
@@ -22,18 +26,17 @@ void plat_finish(void);
 /* return the dir/ where configs, saves, bios, etc. are found */
 int  plat_get_root_dir(char *dst, int len);
 
-/* to be used while emulation is starting or running */
-void plat_status_msg(const char *format, ...);
-
 /* used before things blocking for a while (these funcs redraw on return) */
 void plat_status_msg_busy_first(const char *msg);
 void plat_status_msg_busy_next(const char *msg);
+void plat_status_msg_clear(void);
 
 /* menu: enter (switch bpp, etc), begin/end drawing */
 void plat_video_menu_enter(int is_rom_loaded);
 void plat_video_menu_begin(void);
 void plat_video_menu_end(void);
 
+void plat_video_wait_vsync(void);
 void plat_video_toggle_renderer(int is_next, int is_menu);
 void plat_validate_config(void);
 void plat_update_volume(int has_changed, int is_up);
@@ -42,10 +45,12 @@ int  plat_is_dir(const char *path);
 int  plat_wait_event(int *fds_hnds, int count, int timeout_ms);
 void plat_sleep_ms(int ms);
 
-/* ms counter, to be used for time diff */
-unsigned int  plat_get_ticks_ms(void);
+/* timers, to be used for time diff and must refet to the same clock */
+unsigned int plat_get_ticks_ms(void);
+unsigned int plat_get_ticks_us(void);
+void plat_wait_till_us(unsigned int us);
 
-const char   *plat_get_credits(void);
+const char  *plat_get_credits(void);
 void plat_debug_cat(char *str);
 
 #ifdef __cplusplus
index f602db7..fea424f 100644 (file)
@@ -28,7 +28,6 @@
 unsigned char gfx_buffer[321*240*2*2];
 unsigned char *PicoDraw2FB = gfx_buffer;  // temporary buffer for alt renderer ( (8+320)*(8+240+8) )
 
-static DWORD noticeMsgTime = 0;
 static short *snd_cbuff = NULL;
 static int snd_cbuf_samples = 0, snd_all_samples = 0;
 
@@ -36,12 +35,6 @@ static int snd_cbuf_samples = 0, snd_all_samples = 0;
 static void blit(const char *fps, const char *notice);
 static void clearArea(int full);
 
-void plat_status_msg(const char *format, ...)
-{
-       /* TODO */
-       noticeMsgTime = GetTickCount();
-}
-
 int plat_get_root_dir(char *dst, int len)
 {
        if (len > 0) *dst = 0;
index f17e53a..372ce56 100644 (file)
@@ -5,8 +5,6 @@
 \r
 #include <stdio.h>\r
 #include <stdlib.h>\r
-#include <sys/time.h>\r
-#include <stdarg.h>\r
 \r
 #include "plat_gp2x.h"\r
 #include "soc.h"\r
 extern int crashed_940;\r
 \r
 static short __attribute__((aligned(4))) sndBuffer[2*44100/50];\r
-static struct timeval noticeMsgTime = { 0, 0 };        // when started showing\r
-static char noticeMsg[40];\r
 static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)];\r
 unsigned char *PicoDraw2FB = PicoDraw2FB_;\r
 static int osd_fps_x;\r
 \r
 extern void *gp2x_screens[4];\r
 \r
-void plat_status_msg(const char *format, ...)\r
-{\r
-       va_list vl;\r
-\r
-       va_start(vl, format);\r
-       vsnprintf(noticeMsg, sizeof(noticeMsg), format, vl);\r
-       va_end(vl);\r
-\r
-       gettimeofday(&noticeMsgTime, 0);\r
-}\r
-\r
 int plat_get_root_dir(char *dst, int len)\r
 {\r
        extern char **g_argv;\r
@@ -289,7 +274,7 @@ static int EmuScanEnd8_rot(unsigned int num)
 int localPal[0x100];\r
 static void (*vidcpyM2)(void *dest, void *src, int m32col, int with_32c_border) = NULL;\r
 \r
-static void blit(const char *fps, const char *notice)\r
+void pemu_update_display(const char *fps, const char *notice)\r
 {\r
        int emu_opt = currentConfig.EmuOpt;\r
 \r
@@ -360,11 +345,42 @@ static void blit(const char *fps, const char *notice)
        gp2x_video_flip();\r
 }\r
 \r
-// clears whole screen or just the notice area (in all buffers)\r
-static void clearArea(int full)\r
+/* XXX */\r
+#ifdef __GP2X__\r
+unsigned int plat_get_ticks_ms(void)\r
+{\r
+       return gp2x_get_ticks_ms();\r
+}\r
+\r
+unsigned int plat_get_ticks_us(void)\r
+{\r
+       return gp2x_get_ticks_us();\r
+}\r
+#endif\r
+\r
+void plat_wait_till_us(unsigned int us_to)\r
+{\r
+       unsigned int now;\r
+\r
+       spend_cycles(1024);\r
+       now = plat_get_ticks_us();\r
+\r
+       while ((signed int)(us_to - now) > 512)\r
+       {\r
+               spend_cycles(1024);\r
+               now = plat_get_ticks_us();\r
+       }\r
+}\r
+\r
+void plat_video_wait_vsync(void)\r
+{\r
+       gp2x_video_wait_vsync();\r
+}\r
+\r
+void plat_status_msg_clear(void)\r
 {\r
        int is_8bit = (PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP);\r
-       if (!full && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) {\r
+       if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {\r
                /* ugh.. */\r
                int i, u, *p;\r
                if (is_8bit) {\r
@@ -383,21 +399,16 @@ static void clearArea(int full)
                return;\r
        }\r
 \r
-       if (is_8bit) {\r
-               // 8-bit renderers\r
-               if (full) gp2x_memset_all_buffers(0, 0xe0, 320*240);\r
-               else      gp2x_memset_all_buffers(320*232, 0xe0, 320*8);\r
-       } else {\r
-               // 16bit accurate renderer\r
-               if (full) gp2x_memset_all_buffers(0, 0, 320*240*2);\r
-               else      gp2x_memset_all_buffers(320*232*2, 0, 320*8*2);\r
-       }\r
+       if (is_8bit)\r
+               gp2x_memset_all_buffers(320*232, 0xe0, 320*8);\r
+       else\r
+               gp2x_memset_all_buffers(320*232*2, 0, 320*8*2);\r
 }\r
 \r
 void plat_status_msg_busy_next(const char *msg)\r
 {\r
-       clearArea(0);\r
-       blit("", msg);\r
+       plat_status_msg_clear();\r
+       pemu_update_display("", msg);\r
 \r
        /* assumption: msg_busy_next gets called only when\r
         * something slow is about to happen */\r
@@ -494,11 +505,11 @@ void plat_video_toggle_renderer(int is_next, int is_menu)
        vidResetMode();\r
 \r
        if (PicoOpt & POPT_ALT_RENDERER) {\r
-               plat_status_msg(" 8bit fast renderer");\r
+               emu_status_msg(" 8bit fast renderer");\r
        } else if (currentConfig.EmuOpt & EOPT_16BPP) {\r
-               plat_status_msg("16bit accurate renderer");\r
+               emu_status_msg("16bit accurate renderer");\r
        } else {\r
-               plat_status_msg(" 8bit accurate renderer");\r
+               emu_status_msg(" 8bit accurate renderer");\r
        }\r
 }\r
 \r
@@ -560,7 +571,7 @@ void plat_update_volume(int has_changed, int is_up)
                        sndout_oss_setvol(vol, vol);\r
                        currentConfig.volume = vol;\r
                }\r
-               plat_status_msg("VOL: %02i", vol);\r
+               emu_status_msg("VOL: %02i", vol);\r
                prev_frame = Pico.m.frame_count;\r
        }\r
 \r
@@ -576,10 +587,10 @@ void plat_update_volume(int has_changed, int is_up)
        }\r
 }\r
 \r
-\r
 static void updateSound(int len)\r
 {\r
-       if (PicoOpt&8) len<<=1;\r
+       if (PicoOpt & POPT_EN_STEREO)\r
+               len <<= 1;\r
 \r
        /* avoid writing audio when lagging behind to prevent audio lag */\r
        if (PicoSkipFrame != 2)\r
@@ -626,14 +637,6 @@ void pemu_sound_wait(void)
 }\r
 \r
 \r
-static void SkipFrame(int do_audio)\r
-{\r
-       PicoSkipFrame=do_audio ? 1 : 2;\r
-       PicoFrame();\r
-       PicoSkipFrame=0;\r
-}\r
-\r
-\r
 void pemu_forced_frame(int opts)\r
 {\r
        int po_old = PicoOpt;\r
@@ -657,23 +660,27 @@ void plat_debug_cat(char *str)
 {\r
 }\r
 \r
-static void simpleWait(int thissec, int lim_time)\r
+void pemu_video_mode_change(int is_32col, int is_240_lines)\r
 {\r
-       struct timeval tval;\r
-\r
-       spend_cycles(1024);\r
-       gettimeofday(&tval, 0);\r
-       if (thissec != tval.tv_sec) tval.tv_usec+=1000000;\r
-\r
-       while (tval.tv_usec < lim_time)\r
-       {\r
-               spend_cycles(1024);\r
-               gettimeofday(&tval, 0);\r
-               if (thissec != tval.tv_sec) tval.tv_usec+=1000000;\r
+       int scalex = 320;\r
+       osd_fps_x = OSD_FPS_X;\r
+       if (is_32col && (PicoOpt & POPT_DIS_32C_BORDER)) {\r
+               scalex = 256;\r
+               osd_fps_x = OSD_FPS_X - 64;\r
        }\r
+       /* want vertical scaling and game is not in 240 line mode */\r
+       if (currentConfig.scaling == EOPT_SCALE_HW_HV && !is_240_lines)\r
+               gp2x_video_RGB_setscaling(8, scalex, 224);\r
+       else\r
+               gp2x_video_RGB_setscaling(0, scalex, 240);\r
+\r
+       // clear whole screen in all buffers\r
+       if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP))\r
+               gp2x_memset_all_buffers(0, 0xe0, 320*240);\r
+       else\r
+               gp2x_memset_all_buffers(0, 0, 320*240*2);\r
 }\r
 \r
-\r
 #if 0\r
 static void tga_dump(void)\r
 {\r
@@ -722,19 +729,10 @@ static void tga_dump(void)
 }\r
 #endif\r
 \r
-\r
-void pemu_loop(void)\r
+void pemu_loop_prep(void)\r
 {\r
        static int gp2x_old_clock = -1, EmuOpt_old = 0, pal_old = 0;\r
        static int gp2x_old_gamma = 100;\r
-       char fpsbuff[24]; // fps count c string\r
-       struct timeval tval; // timing\r
-       int pframes_done, pframes_shown, pthissec; // "period" frames, used for sync\r
-       int  frames_done,  frames_shown,  thissec; // actual frames\r
-       int oldmodes = 0, target_fps, target_frametime, lim_time, vsync_offset, i;\r
-       char *notice = 0;\r
-\r
-       printf("entered emu_Loop()\n");\r
 \r
        if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_RAM_TIMINGS) {\r
                if (currentConfig.EmuOpt & EOPT_RAM_TIMINGS)\r
@@ -770,206 +768,16 @@ void pemu_loop(void)
 \r
        EmuOpt_old = currentConfig.EmuOpt;\r
        pal_old = Pico.m.pal;\r
-       fpsbuff[0] = 0;\r
 \r
        // make sure we are in correct mode\r
        vidResetMode();\r
        scaling_update();\r
-       Pico.m.dirtyPal = 1;\r
-       oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc;\r
-\r
-       // pal/ntsc might have changed, reset related stuff\r
-       target_fps = Pico.m.pal ? 50 : 60;\r
-       target_frametime = 1000000/target_fps;\r
-       reset_timing = 1;\r
 \r
        pemu_sound_start();\r
+}\r
 \r
-       // prepare CD buffer\r
-       if (PicoAHW & PAHW_MCD) PicoCDBufferInit();\r
-\r
-       // calc vsync offset to sync timing code with vsync\r
-       if (currentConfig.EmuOpt & EOPT_PSYNC) {\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
-       frames_done = frames_shown = thissec =\r
-       pframes_done = pframes_shown = pthissec = 0;\r
-\r
-       // loop\r
-       while (engineState == PGS_Running)\r
-       {\r
-               int modes;\r
-\r
-               gettimeofday(&tval, 0);\r
-               if (reset_timing) {\r
-                       reset_timing = 0;\r
-                       pthissec = tval.tv_sec;\r
-                       pframes_shown = pframes_done = tval.tv_usec/target_frametime;\r
-               }\r
-\r
-               // show notice message?\r
-               if (noticeMsgTime.tv_sec)\r
-               {\r
-                       static int noticeMsgSum;\r
-                       if((tval.tv_sec*1000000+tval.tv_usec) - (noticeMsgTime.tv_sec*1000000+noticeMsgTime.tv_usec) > 2000000) { // > 2.0 sec\r
-                               noticeMsgTime.tv_sec = noticeMsgTime.tv_usec = 0;\r
-                               clearArea(0);\r
-                               notice = 0;\r
-                       } else {\r
-                               int sum = noticeMsg[0]+noticeMsg[1]+noticeMsg[2];\r
-                               if (sum != noticeMsgSum) { clearArea(0); noticeMsgSum = sum; }\r
-                               notice = noticeMsg;\r
-                       }\r
-               }\r
-\r
-               // check for mode changes\r
-               modes = ((Pico.video.reg[12]&1)<<2)|(Pico.video.reg[1]&8);\r
-               if (modes != oldmodes)\r
-               {\r
-                       int scalex = 320;\r
-                       osd_fps_x = OSD_FPS_X;\r
-                       if (!(modes & 4) && (PicoOpt & POPT_DIS_32C_BORDER)) {\r
-                               scalex = 256;\r
-                               osd_fps_x = OSD_FPS_X - 64;\r
-                       }\r
-                       /* want vertical scaling and game is not in 240 line mode */\r
-                       if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(modes&8))\r
-                            gp2x_video_RGB_setscaling(8, scalex, 224);\r
-                       else gp2x_video_RGB_setscaling(0, scalex, 240);\r
-                       oldmodes = modes;\r
-                       clearArea(1);\r
-               }\r
-\r
-               // second changed?\r
-               if (thissec != tval.tv_sec)\r
-               {\r
-#ifdef BENCHMARK\r
-                       static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4];\r
-                       if (++bench == 10) {\r
-                               bench = 0;\r
-                               bench_fps_s = bench_fps;\r
-                               bf[bfp++ & 3] = bench_fps;\r
-                               bench_fps = 0;\r
-                       }\r
-                       bench_fps += frames_shown;\r
-                       sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2);\r
-#else\r
-                       if (currentConfig.EmuOpt & 2) {\r
-                               sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done);\r
-                               if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; }\r
-                       }\r
-#endif\r
-                       frames_shown = frames_done = 0;\r
-                       thissec = tval.tv_sec;\r
-               }\r
-#ifdef PFRAMES\r
-               sprintf(fpsbuff, "%i", Pico.m.frame_count);\r
-#endif\r
-\r
-               if (pthissec != tval.tv_sec)\r
-               {\r
-                       if (PsndOut == 0 && currentConfig.Frameskip >= 0) {\r
-                               pframes_done = pframes_shown = 0;\r
-                       } else {\r
-                               // it is quite common for this implementation to leave 1 fame unfinished\r
-                               // when second changes, but we don't want buffer to starve.\r
-                               if (PsndOut && pframes_done < target_fps && pframes_done > target_fps-5) {\r
-                                       emu_update_input();\r
-                                       SkipFrame(1); pframes_done++;\r
-                               }\r
-\r
-                               pframes_done  -= target_fps; if (pframes_done  < 0) pframes_done  = 0;\r
-                               pframes_shown -= target_fps; if (pframes_shown < 0) pframes_shown = 0;\r
-                               if (pframes_shown > pframes_done) pframes_shown = pframes_done;\r
-                       }\r
-                       pthissec = tval.tv_sec;\r
-               }\r
-\r
-               lim_time = (pframes_done+1) * target_frametime + vsync_offset;\r
-               if (currentConfig.Frameskip >= 0) // frameskip enabled\r
-               {\r
-                       for(i = 0; i < currentConfig.Frameskip; i++) {\r
-                               emu_update_input();\r
-                               SkipFrame(1); pframes_done++; frames_done++;\r
-                               if (PsndOut && !reset_timing) { // do framelimitting if sound is enabled\r
-                                       gettimeofday(&tval, 0);\r
-                                       if (pthissec != tval.tv_sec) tval.tv_usec+=1000000;\r
-                                       if (tval.tv_usec < lim_time) { // we are too fast\r
-                                               simpleWait(pthissec, lim_time);\r
-                                       }\r
-                               }\r
-                               lim_time += target_frametime;\r
-                       }\r
-               }\r
-               else if (tval.tv_usec > lim_time) // auto frameskip\r
-               {\r
-                       // no time left for this frame - skip\r
-                       if (tval.tv_usec - lim_time >= 300000) {\r
-                               /* something caused a slowdown for us (disk access? cache flush?)\r
-                                * try to recover by resetting timing... */\r
-                               reset_timing = 1;\r
-                               continue;\r
-                       }\r
-                       emu_update_input();\r
-                       SkipFrame(tval.tv_usec < lim_time+target_frametime*2); pframes_done++; frames_done++;\r
-                       continue;\r
-               }\r
-\r
-               emu_update_input();\r
-               PicoFrame();\r
-\r
-               // check time\r
-               gettimeofday(&tval, 0);\r
-               if (pthissec != tval.tv_sec) tval.tv_usec+=1000000;\r
-\r
-               if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 300000) // slowdown detection\r
-                       reset_timing = 1;\r
-               else if (PsndOut != NULL || currentConfig.Frameskip < 0)\r
-               {\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 (!reset_timing && tval.tv_usec < lim_time)\r
-                       {\r
-                               // we are too fast\r
-                               if (vsync_offset) {\r
-                                       if (lim_time - tval.tv_usec > target_frametime/2)\r
-                                               simpleWait(pthissec, lim_time - target_frametime/4);\r
-                                       gp2x_video_wait_vsync();\r
-                               } else {\r
-                                       simpleWait(pthissec, lim_time);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               blit(fpsbuff, notice);\r
-\r
-               pframes_done++; pframes_shown++;\r
-                frames_done++;  frames_shown++;\r
-       }\r
-\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
-               emu_save_load_game(0, 1);\r
-               SRam.changed = 0;\r
-       }\r
-\r
-       // do menu background to be sure it's right\r
-       pemu_forced_frame(POPT_EN_SOFTSCALE);\r
+void pemu_loop_end(void)\r
+{\r
 }\r
 \r
 const char *plat_get_credits(void)\r
index d5326be..ee421df 100644 (file)
@@ -25,6 +25,9 @@ void (*set_ram_timings)(void);
 void (*unset_ram_timings)(void);
 int  (*gp2x_read_battery)(void);
 
+unsigned int (*gp2x_get_ticks_ms)(void);
+unsigned int (*gp2x_get_ticks_us)(void);
+
 
 gp2x_soc_t soc_detect(void)
 {
index 1396f24..b645e8b 100644 (file)
@@ -30,3 +30,6 @@ extern void (*set_ram_timings)(void);
 extern void (*unset_ram_timings)(void);
 extern int  (*gp2x_read_battery)(void);
 
+/* gettimeofday is not suitable for Wiz, at least fw 1.1 or lower */
+extern unsigned int (*gp2x_get_ticks_ms)(void);
+extern unsigned int (*gp2x_get_ticks_us)(void);
index 00eb0a2..5217dda 100644 (file)
@@ -12,6 +12,7 @@
 #include "soc_mmsp2.h"
 #include "plat_gp2x.h"
 #include "../common/emu.h"
+#include "../common/plat.h"
 #include "../common/arm_utils.h"
 #include "940ctl.h"
 
@@ -40,6 +41,8 @@ static unsigned short gp2x_screenaddr_old[4];
 static unsigned short memtimex_old[2];
 static unsigned short reg0910;
 
+extern unsigned int plat_get_ticks_ms_gtod(void);
+extern unsigned int plat_get_ticks_us_gtod(void);
 
 /* video stuff */
 static void gp2x_video_flip_(void)
@@ -508,6 +511,9 @@ void mmsp2_init(void)
        set_ram_timings = set_ram_timings_;
        unset_ram_timings = unset_ram_timings_;
        gp2x_read_battery = gp2x_read_battery_;
+
+       gp2x_get_ticks_ms = plat_get_ticks_ms_gtod;
+       gp2x_get_ticks_us = plat_get_ticks_us_gtod;
 }
 
 void mmsp2_finish(void)
index 7b71324..b6ec9ab 100644 (file)
@@ -208,6 +208,31 @@ static int gp2x_read_battery_(void)
        }
 }
 
+#define TIMER_BASE3 0x1980
+#define TIMER_REG(x) memregl[(TIMER_BASE3 + x) >> 2]
+
+unsigned int gp2x_get_ticks_us_(void)
+{
+       TIMER_REG(0x08) = 0x4b;  /* run timer, latch value */
+       return TIMER_REG(0);
+}
+
+unsigned int gp2x_get_ticks_ms_(void)
+{
+       unsigned long long v64;
+       v64 = (unsigned long long)gp2x_get_ticks_us_() * 4195;
+       return v64 >> 22;
+}
+
+static void timer_cleanup(void)
+{
+       TIMER_REG(0x40) = 0x0c; /* be sure clocks are on */
+       TIMER_REG(0x08) = 0x23; /* stop the timer, clear irq in case it's pending */
+       TIMER_REG(0x00) = 0;    /* clear counter */
+       TIMER_REG(0x40) = 0;    /* clocks off */
+       TIMER_REG(0x44) = 0;    /* dividers back to default */
+}
+
 void pollux_init(void)
 {
        struct fb_fix_screeninfo fbfix;
@@ -264,6 +289,14 @@ void pollux_init(void)
        if (battdev < 0)
                perror("Warning: could't open pollux_batt");
 
+       /* setup timer */
+       if (TIMER_REG(0x08) & 8)
+               timer_cleanup();
+
+       TIMER_REG(0x44) = 0x922; /* using PLL1, divider value 147 */
+       TIMER_REG(0x40) = 0x0c;  /* clocks on */
+       TIMER_REG(0x08) = 0x6b;  /* run timer, clear irq, latch value */
+
        pllsetreg0 = memregl[0xf004>>2];
        memtimex_old[0] = memregs[0x14802>>1];
        memtimex_old[1] = memregs[0x14804>>1];
@@ -284,6 +317,9 @@ void pollux_init(void)
        set_ram_timings = set_ram_timings_;
        unset_ram_timings = unset_ram_timings_;
        gp2x_read_battery = gp2x_read_battery_;
+
+       gp2x_get_ticks_ms = gp2x_get_ticks_ms_;
+       gp2x_get_ticks_us = gp2x_get_ticks_us_;
 }
 
 void pollux_finish(void)
index 751d97a..166b4d6 100644 (file)
@@ -17,6 +17,12 @@ int plat_is_dir(const char *path)
        return 0;
 }
 
+#ifdef __GP2X__
+/* Wiz has a borked gettimeofday().. */
+#define plat_get_ticks_ms plat_get_ticks_ms_gtod
+#define plat_get_ticks_us plat_get_ticks_us_gtod
+#endif
+
 unsigned int plat_get_ticks_ms(void)
 {
        struct timeval tv;
@@ -25,12 +31,25 @@ unsigned int plat_get_ticks_ms(void)
        gettimeofday(&tv, NULL);
 
        ret = (unsigned)tv.tv_sec * 1000;
-       /* approximate division */
+       /* approximate /= 1000 */
        ret += ((unsigned)tv.tv_usec * 4195) >> 22;
 
        return ret;
 }
 
+unsigned int plat_get_ticks_us(void)
+{
+       struct timeval tv;
+       unsigned int ret;
+
+       gettimeofday(&tv, NULL);
+
+       ret = (unsigned)tv.tv_sec * 1000000;
+       ret += (unsigned)tv.tv_usec;
+
+       return ret;
+}
+
 void plat_sleep_ms(int ms)
 {
        usleep(ms * 1000);
index d409b57..a9a2119 100644 (file)
@@ -34,7 +34,6 @@
 \r
 \r
 static short __attribute__((aligned(4))) sndBuffer[2*44100/50];\r
-static struct timeval noticeMsgTime = { 0, 0 };        // when started showing\r
 static int osd_fps_x;\r
 unsigned char *PicoDraw2FB = NULL;  // temporary buffer for alt renderer\r
 \r
@@ -43,17 +42,6 @@ unsigned char *PicoDraw2FB = NULL;  // temporary buffer for alt renderer
 static int pico_pen_x = 0, pico_pen_y = 240/2;\r
 \r
 \r
-void plat_status_msg(const char *format, ...)\r
-{\r
-       va_list vl;\r
-\r
-       va_start(vl, format);\r
-       vsnprintf(noticeMsg, sizeof(noticeMsg), fmt, vl);\r
-       va_end(vl);\r
-\r
-       gettimeofday(&noticeMsgTime, 0);\r
-}\r
-\r
 int plat_get_root_dir(char *dst, int len)\r
 {\r
        extern char **g_argv;\r
index 929c608..e0e1ca1 100644 (file)
@@ -36,8 +36,6 @@ int sceAudioOutput2GetRestSample();
 unsigned char *PicoDraw2FB = (unsigned char *)VRAM_CACHED_STUFF + 8; // +8 to be able to skip border with 1 quadword..
 int engineStateSuspend;
 
-static unsigned int noticeMsgTime = 0;
-
 #define PICO_PEN_ADJUST_X 4
 #define PICO_PEN_ADJUST_Y 2
 static int pico_pen_x = 320/2, pico_pen_y = 240/2;
@@ -47,17 +45,6 @@ static void sound_deinit(void);
 static void blit2(const char *fps, const char *notice, int lagging_behind);
 static void clearArea(int full);
 
-void plat_status_msg(const char *format, ...)
-{
-       va_list vl;
-
-       va_start(vl, format);
-       vsnprintf(noticeMsg, sizeof(noticeMsg), fmt, vl);
-       va_end(vl);
-
-       noticeMsgTime = sceKernelGetSystemTimeLow();
-}
-
 int plat_get_root_dir(char *dst, int len)
 {
        if (len > 0) *dst = 0;
@@ -610,7 +597,7 @@ void pemu_sound_start(void)
        ret = sceAudio_38553111(samples_block/2, PsndRate, 2); // seems to not need that stupid 64byte alignment
        if (ret < 0) {
                lprintf("sceAudio_38553111() failed: %i\n", ret);
-               plat_status_msg("sound init failed (%i), snd disabled", ret);
+               emu_status_msg("sound init failed (%i), snd disabled", ret);
                currentConfig.EmuOpt &= ~EOPT_EN_SOUND;
        } else {
                PicoWriteSound = writeSound;
@@ -782,9 +769,9 @@ static void RunEvents(unsigned int which)
                vidResetMode();
 
                if (PicoOpt & POPT_ALT_RENDERER)
-                       plat_status_msg("fast renderer");
+                       emu_status_msg("fast renderer");
                else if (currentConfig.EmuOpt&0x80)
-                       plat_status_msg("accurate renderer");
+                       emu_status_msg("accurate renderer");
        }
        if (which & 0x0300)
        {
@@ -795,7 +782,7 @@ static void RunEvents(unsigned int which)
                        state_slot += 1;
                        if(state_slot > 9) state_slot = 0;
                }
-               plat_status_msg("SAVE SLOT %i [%s]", state_slot,
+               emu_status_msg("SAVE SLOT %i [%s]", state_slot,
                        emu_check_save_file(state_slot) ? "USED" : "FREE");
        }
 }