From b5bfb86438216d502f1f9ed14b923d3b0107c07d Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 31 Jul 2009 22:01:03 +0000 Subject: [PATCH] move emu loop to common; redo timing; add pollux timer git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@721 be3aeb3a-fb24-0410-a615-afba39da0efa --- common/emu.c | 244 ++++++++++++++++++++++++++++++++-- common/emu.h | 2 + common/main.c | 2 +- common/plat.h | 19 ++- gp2x/emu.c | 328 ++++++++++------------------------------------ gp2x/soc.c | 3 + gp2x/soc.h | 3 + gp2x/soc_mmsp2.c | 6 + gp2x/soc_pollux.c | 36 +++++ linux/plat.c | 21 ++- pandora/emu.c | 12 -- psp/emu.c | 21 +-- 12 files changed, 385 insertions(+), 312 deletions(-) diff --git a/common/emu.c b/common/emu.c index 1c7d1b7..5bd34e8 100644 --- a/common/emu.c +++ b/common/emu.c @@ -5,6 +5,7 @@ #include #include +#include #ifndef NO_SYNC #include #endif @@ -44,6 +45,8 @@ char rom_fname_reload[512] = { 0, }; char rom_fname_loaded[512] = { 0, }; int rom_loaded = 0; int reset_timing = 0; +static unsigned int notice_msg_time; /* when started showing */ +static char noticeMsg[40]; unsigned char *movie_data = NULL; static int movie_size = 0; @@ -86,6 +89,17 @@ static void get_ext(char *file, char *ext) strlwr_(ext); } +void emu_status_msg(const char *format, ...) +{ + va_list vl; + + va_start(vl, format); + vsnprintf(noticeMsg, sizeof(noticeMsg), format, vl); + va_end(vl); + + notice_msg_time = plat_get_ticks_ms(); +} + static const char *biosfiles_us[] = { "us_scd1_9210", "us_scd2_9306", "SegaCDBIOS9303" }; static const char *biosfiles_eu[] = { "eu_mcd1_9210", "eu_mcd2_9306", "eu_mcd2_9303" }; static const char *biosfiles_jp[] = { "jp_mcd1_9112", "jp_mcd1_9111" }; @@ -485,12 +499,12 @@ int emu_reload_rom(char *rom_fname) // TODO: bits 6 & 5 } movie_data[0x18+30] = 0; - plat_status_msg("MOVIE: %s", (char *) &movie_data[0x18]); + emu_status_msg("MOVIE: %s", (char *) &movie_data[0x18]); } else { PicoOpt &= ~POPT_DIS_VDP_FIFO; - plat_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS"); + emu_status_msg(Pico.m.pal ? "PAL SYSTEM / 50 FPS" : "NTSC SYSTEM / 60 FPS"); } // load SRAM for this ROM @@ -702,7 +716,7 @@ void update_movie(void) if (offs+3 > movie_size) { free(movie_data); movie_data = 0; - plat_status_msg("END OF MOVIE."); + emu_status_msg("END OF MOVIE."); lprintf("END OF MOVIE.\n"); } else { // MXYZ SACB RLDU @@ -824,7 +838,7 @@ int emu_save_load_game(int load, int sram) saveFname = emu_get_save_fname(load, sram, state_slot); if (saveFname == NULL) { if (!sram) - plat_status_msg(load ? "LOAD FAILED (missing file)" : "SAVE FAILED"); + emu_status_msg(load ? "LOAD FAILED (missing file)" : "SAVE FAILED"); return -1; } @@ -910,10 +924,10 @@ int emu_save_load_game(int load, int sram) } else ret = -1; if (!ret) - plat_status_msg(load ? "GAME LOADED" : "GAME SAVED"); + emu_status_msg(load ? "GAME LOADED" : "GAME SAVED"); else { - plat_status_msg(load ? "LOAD FAILED" : "SAVE FAILED"); + emu_status_msg(load ? "LOAD FAILED" : "SAVE FAILED"); ret = -1; } @@ -935,7 +949,7 @@ void emu_set_fastforward(int set_on) currentConfig.EmuOpt &= ~4; currentConfig.EmuOpt |= 0x40000; is_on = 1; - plat_status_msg("FAST FORWARD"); + emu_status_msg("FAST FORWARD"); } else if (!set_on && is_on) { PsndOut = set_PsndOut; @@ -948,7 +962,7 @@ void emu_set_fastforward(int set_on) static void emu_msg_tray_open(void) { - plat_status_msg("CD tray opened"); + emu_status_msg("CD tray opened"); } void emu_reset_game(void) @@ -966,9 +980,9 @@ void run_events_pico(unsigned int events) if (pico_inp_mode > 2) pico_inp_mode = 0; switch (pico_inp_mode) { - case 2: plat_status_msg("Input: Pen on Pad"); break; - case 1: plat_status_msg("Input: Pen on Storyware"); break; - case 0: plat_status_msg("Input: Joystick"); + case 2: emu_status_msg("Input: Pen on Pad"); break; + case 1: emu_status_msg("Input: Pen on Storyware"); break; + case 0: emu_status_msg("Input: Joystick"); PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000; break; } @@ -977,13 +991,13 @@ void run_events_pico(unsigned int events) PicoPicohw.page--; if (PicoPicohw.page < 0) PicoPicohw.page = 0; - plat_status_msg("Page %i", PicoPicohw.page); + emu_status_msg("Page %i", PicoPicohw.page); } if (events & PEV_PICO_PNEXT) { PicoPicohw.page++; if (PicoPicohw.page > 6) PicoPicohw.page = 6; - plat_status_msg("Page %i", PicoPicohw.page); + emu_status_msg("Page %i", PicoPicohw.page); } if (pico_inp_mode == 0) @@ -1094,7 +1108,7 @@ static void run_events_ui(unsigned int which) 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"); } if (which & PEV_MENU) @@ -1194,3 +1208,205 @@ void emu_finish(void) PicoExit(); } +static void skip_frame(int do_audio) +{ + PicoSkipFrame = do_audio ? 1 : 2; + PicoFrame(); + PicoSkipFrame = 0; +} + +/* our tick here is 1 us right now */ +#define ms_to_ticks(x) (unsigned int)(x * 1000) +#define get_ticks() plat_get_ticks_us() + +void emu_loop(void) +{ + int pframes_done; /* "period" frames, used for sync */ + int frames_done, frames_shown; /* actual frames for fps counter */ + int oldmodes, target_fps, target_frametime; + unsigned int timestamp_base = 0, timestamp_fps; + char *notice_msg = NULL; + char fpsbuff[24]; + int i; + + fpsbuff[0] = 0; + + /* make sure we are in correct mode */ + oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc; + Pico.m.dirtyPal = 1; + + /* number of ticks per frame */ + if (Pico.m.pal) { + target_fps = 50; + target_frametime = ms_to_ticks(1000) / 50; + } else { + target_fps = 60; + target_frametime = ms_to_ticks(1000) / 60 + 1; + } + + // prepare CD buffer + if (PicoAHW & PAHW_MCD) + PicoCDBufferInit(); + + if (currentConfig.EmuOpt & EOPT_PSYNC) + plat_video_wait_vsync(); + + pemu_loop_prep(); + + timestamp_fps = get_ticks(); + reset_timing = 1; + + frames_done = frames_shown = pframes_done = 0; + + /* loop with resync every 1 sec. */ + while (engineState == PGS_Running) + { + unsigned int timestamp; + int diff, diff_lim; + int modes; + + timestamp = get_ticks(); + if (reset_timing) { + reset_timing = 0; + timestamp_base = timestamp; + pframes_done = 0; + } + + // show notice_msg message? + if (notice_msg_time != 0) + { + static int noticeMsgSum; + if (timestamp - ms_to_ticks(notice_msg_time) > ms_to_ticks(2000)) { + notice_msg_time = 0; + plat_status_msg_clear(); + notice_msg = NULL; + } else { + int sum = noticeMsg[0] + noticeMsg[1] + noticeMsg[2]; + if (sum != noticeMsgSum) { + plat_status_msg_clear(); + noticeMsgSum = sum; + } + notice_msg = noticeMsg; + } + } + + // check for mode changes + modes = ((Pico.video.reg[12]&1)<<2) | (Pico.video.reg[1]&8); + if (modes != oldmodes) { + oldmodes = modes; + pemu_video_mode_change(!(modes & 4), (modes & 8)); + } + + // second changed? + if (timestamp - timestamp_fps >= ms_to_ticks(1000)) + { +#ifdef BENCHMARK + static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; + if (++bench == 10) { + bench = 0; + bench_fps_s = bench_fps; + bf[bfp++ & 3] = bench_fps; + bench_fps = 0; + } + bench_fps += frames_shown; + sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2); +#else + if (currentConfig.EmuOpt & EOPT_SHOW_FPS) { + sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done); + if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; } + } +#endif + frames_shown = frames_done = 0; + timestamp_fps += ms_to_ticks(1000); + } +#ifdef PFRAMES + sprintf(fpsbuff, "%i", Pico.m.frame_count); +#endif + + if (timestamp - timestamp_base >= ms_to_ticks(1000)) + { + if (PsndOut == 0 && currentConfig.Frameskip >= 0) + pframes_done = 0; + else + pframes_done -= target_fps; + timestamp_base += ms_to_ticks(1000); + } + + 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 (PsndOut && !reset_timing) { // do framelimitting if sound is enabled + timestamp = get_ticks(); + diff = timestamp - timestamp_base; + if (diff < diff_lim) // we are too fast + plat_wait_till_us(timestamp_base + diff_lim); + } + } + } + else if (diff > diff_lim) + { + /* no time left for this frame - skip */ + if (diff - diff_lim >= ms_to_ticks(300)) { + /* if too much behind, reset instead */ + reset_timing = 1; + continue; + } + emu_update_input(); + skip_frame(diff < diff_lim + target_frametime * 2); + pframes_done++; frames_done++; + continue; + } + + emu_update_input(); + PicoFrame(); + + /* frame limiter */ + if (!reset_timing && (PsndOut != NULL || currentConfig.Frameskip < 0)) + { + timestamp = get_ticks(); + diff = timestamp - timestamp_base; + + // sleep or vsync if we are still too fast + if (diff < diff_lim) + { + // we are too fast + if (currentConfig.EmuOpt & EOPT_PSYNC) { + if (diff_lim - diff > target_frametime/2) + plat_wait_till_us(timestamp_base + target_frametime/4); + plat_video_wait_vsync(); + } else + plat_wait_till_us(timestamp_base + diff_lim); + } + } + + pemu_update_display(fpsbuff, notice_msg); + + pframes_done++; frames_done++; frames_shown++; + } + + emu_set_fastforward(0); + + if (PicoAHW & PAHW_MCD) + PicoCDBufferFree(); + + // save SRAM + if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && SRam.changed) { + plat_status_msg_busy_first("Writing SRAM/BRAM..."); + emu_save_load_game(0, 1); + SRam.changed = 0; + } + + // do menu background to be sure it's right + pemu_forced_frame(POPT_EN_SOFTSCALE); + + pemu_loop_end(); +} + diff --git a/common/emu.h b/common/emu.h index 28aed4f..ecd9ba1 100644 --- a/common/emu.h +++ b/common/emu.h @@ -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" diff --git a/common/main.c b/common/main.c index d43aabc..bdcdc14 100644 --- a/common/main.c +++ b/common/main.c @@ -117,7 +117,7 @@ int main(int argc, char *argv[]) engineState = PGS_Running; case PGS_Running: - pemu_loop(); + emu_loop(); break; case PGS_Quit: diff --git a/common/plat.h b/common/plat.h index ccdfa79..a453431 100644 --- a/common/plat.h +++ b/common/plat.h @@ -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 diff --git a/gp2x/emu.c b/gp2x/emu.c index f17e53a..372ce56 100644 --- a/gp2x/emu.c +++ b/gp2x/emu.c @@ -5,8 +5,6 @@ #include #include -#include -#include #include "plat_gp2x.h" #include "soc.h" @@ -36,25 +34,12 @@ extern int crashed_940; static short __attribute__((aligned(4))) sndBuffer[2*44100/50]; -static struct timeval noticeMsgTime = { 0, 0 }; // when started showing -static char noticeMsg[40]; static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)]; unsigned char *PicoDraw2FB = PicoDraw2FB_; static int osd_fps_x; extern void *gp2x_screens[4]; -void plat_status_msg(const char *format, ...) -{ - va_list vl; - - va_start(vl, format); - vsnprintf(noticeMsg, sizeof(noticeMsg), format, vl); - va_end(vl); - - gettimeofday(¬iceMsgTime, 0); -} - int plat_get_root_dir(char *dst, int len) { extern char **g_argv; @@ -289,7 +274,7 @@ static int EmuScanEnd8_rot(unsigned int num) int localPal[0x100]; static void (*vidcpyM2)(void *dest, void *src, int m32col, int with_32c_border) = NULL; -static void blit(const char *fps, const char *notice) +void pemu_update_display(const char *fps, const char *notice) { int emu_opt = currentConfig.EmuOpt; @@ -360,11 +345,42 @@ static void blit(const char *fps, const char *notice) gp2x_video_flip(); } -// clears whole screen or just the notice area (in all buffers) -static void clearArea(int full) +/* XXX */ +#ifdef __GP2X__ +unsigned int plat_get_ticks_ms(void) +{ + return gp2x_get_ticks_ms(); +} + +unsigned int plat_get_ticks_us(void) +{ + return gp2x_get_ticks_us(); +} +#endif + +void plat_wait_till_us(unsigned int us_to) +{ + unsigned int now; + + spend_cycles(1024); + now = plat_get_ticks_us(); + + while ((signed int)(us_to - now) > 512) + { + spend_cycles(1024); + now = plat_get_ticks_us(); + } +} + +void plat_video_wait_vsync(void) +{ + gp2x_video_wait_vsync(); +} + +void plat_status_msg_clear(void) { int is_8bit = (PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP); - if (!full && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) { + if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) { /* ugh.. */ int i, u, *p; if (is_8bit) { @@ -383,21 +399,16 @@ static void clearArea(int full) return; } - if (is_8bit) { - // 8-bit renderers - if (full) gp2x_memset_all_buffers(0, 0xe0, 320*240); - else gp2x_memset_all_buffers(320*232, 0xe0, 320*8); - } else { - // 16bit accurate renderer - if (full) gp2x_memset_all_buffers(0, 0, 320*240*2); - else gp2x_memset_all_buffers(320*232*2, 0, 320*8*2); - } + if (is_8bit) + gp2x_memset_all_buffers(320*232, 0xe0, 320*8); + else + gp2x_memset_all_buffers(320*232*2, 0, 320*8*2); } void plat_status_msg_busy_next(const char *msg) { - clearArea(0); - blit("", msg); + plat_status_msg_clear(); + pemu_update_display("", msg); /* assumption: msg_busy_next gets called only when * something slow is about to happen */ @@ -494,11 +505,11 @@ void plat_video_toggle_renderer(int is_next, int is_menu) vidResetMode(); if (PicoOpt & POPT_ALT_RENDERER) { - plat_status_msg(" 8bit fast renderer"); + emu_status_msg(" 8bit fast renderer"); } else if (currentConfig.EmuOpt & EOPT_16BPP) { - plat_status_msg("16bit accurate renderer"); + emu_status_msg("16bit accurate renderer"); } else { - plat_status_msg(" 8bit accurate renderer"); + emu_status_msg(" 8bit accurate renderer"); } } @@ -560,7 +571,7 @@ void plat_update_volume(int has_changed, int is_up) sndout_oss_setvol(vol, vol); currentConfig.volume = vol; } - plat_status_msg("VOL: %02i", vol); + emu_status_msg("VOL: %02i", vol); prev_frame = Pico.m.frame_count; } @@ -576,10 +587,10 @@ void plat_update_volume(int has_changed, int is_up) } } - static void updateSound(int len) { - if (PicoOpt&8) len<<=1; + if (PicoOpt & POPT_EN_STEREO) + len <<= 1; /* avoid writing audio when lagging behind to prevent audio lag */ if (PicoSkipFrame != 2) @@ -626,14 +637,6 @@ void pemu_sound_wait(void) } -static void SkipFrame(int do_audio) -{ - PicoSkipFrame=do_audio ? 1 : 2; - PicoFrame(); - PicoSkipFrame=0; -} - - void pemu_forced_frame(int opts) { int po_old = PicoOpt; @@ -657,23 +660,27 @@ void plat_debug_cat(char *str) { } -static void simpleWait(int thissec, int lim_time) +void pemu_video_mode_change(int is_32col, int is_240_lines) { - struct timeval tval; - - spend_cycles(1024); - gettimeofday(&tval, 0); - if (thissec != tval.tv_sec) tval.tv_usec+=1000000; - - while (tval.tv_usec < lim_time) - { - spend_cycles(1024); - gettimeofday(&tval, 0); - if (thissec != tval.tv_sec) tval.tv_usec+=1000000; + int scalex = 320; + osd_fps_x = OSD_FPS_X; + if (is_32col && (PicoOpt & POPT_DIS_32C_BORDER)) { + scalex = 256; + osd_fps_x = OSD_FPS_X - 64; } + /* want vertical scaling and game is not in 240 line mode */ + if (currentConfig.scaling == EOPT_SCALE_HW_HV && !is_240_lines) + gp2x_video_RGB_setscaling(8, scalex, 224); + else + gp2x_video_RGB_setscaling(0, scalex, 240); + + // clear whole screen in all buffers + if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) + gp2x_memset_all_buffers(0, 0xe0, 320*240); + else + gp2x_memset_all_buffers(0, 0, 320*240*2); } - #if 0 static void tga_dump(void) { @@ -722,19 +729,10 @@ static void tga_dump(void) } #endif - -void pemu_loop(void) +void pemu_loop_prep(void) { static int gp2x_old_clock = -1, EmuOpt_old = 0, pal_old = 0; static int gp2x_old_gamma = 100; - char fpsbuff[24]; // fps count c string - struct timeval tval; // timing - int pframes_done, pframes_shown, pthissec; // "period" frames, used for sync - int frames_done, frames_shown, thissec; // actual frames - int oldmodes = 0, target_fps, target_frametime, lim_time, vsync_offset, i; - char *notice = 0; - - printf("entered emu_Loop()\n"); if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_RAM_TIMINGS) { if (currentConfig.EmuOpt & EOPT_RAM_TIMINGS) @@ -770,206 +768,16 @@ void pemu_loop(void) EmuOpt_old = currentConfig.EmuOpt; pal_old = Pico.m.pal; - fpsbuff[0] = 0; // make sure we are in correct mode vidResetMode(); scaling_update(); - Pico.m.dirtyPal = 1; - oldmodes = ((Pico.video.reg[12]&1)<<2) ^ 0xc; - - // pal/ntsc might have changed, reset related stuff - target_fps = Pico.m.pal ? 50 : 60; - target_frametime = 1000000/target_fps; - reset_timing = 1; pemu_sound_start(); +} - // prepare CD buffer - if (PicoAHW & PAHW_MCD) PicoCDBufferInit(); - - // calc vsync offset to sync timing code with vsync - if (currentConfig.EmuOpt & EOPT_PSYNC) { - gettimeofday(&tval, 0); - gp2x_video_wait_vsync(); - gettimeofday(&tval, 0); - vsync_offset = tval.tv_usec; - while (vsync_offset >= target_frametime) - vsync_offset -= target_frametime; - if (!vsync_offset) vsync_offset++; - printf("vsync_offset: %i\n", vsync_offset); - } else - vsync_offset = 0; - - frames_done = frames_shown = thissec = - pframes_done = pframes_shown = pthissec = 0; - - // loop - while (engineState == PGS_Running) - { - int modes; - - gettimeofday(&tval, 0); - if (reset_timing) { - reset_timing = 0; - pthissec = tval.tv_sec; - pframes_shown = pframes_done = tval.tv_usec/target_frametime; - } - - // show notice message? - if (noticeMsgTime.tv_sec) - { - static int noticeMsgSum; - if((tval.tv_sec*1000000+tval.tv_usec) - (noticeMsgTime.tv_sec*1000000+noticeMsgTime.tv_usec) > 2000000) { // > 2.0 sec - noticeMsgTime.tv_sec = noticeMsgTime.tv_usec = 0; - clearArea(0); - notice = 0; - } else { - int sum = noticeMsg[0]+noticeMsg[1]+noticeMsg[2]; - if (sum != noticeMsgSum) { clearArea(0); noticeMsgSum = sum; } - notice = noticeMsg; - } - } - - // check for mode changes - modes = ((Pico.video.reg[12]&1)<<2)|(Pico.video.reg[1]&8); - if (modes != oldmodes) - { - int scalex = 320; - osd_fps_x = OSD_FPS_X; - if (!(modes & 4) && (PicoOpt & POPT_DIS_32C_BORDER)) { - scalex = 256; - osd_fps_x = OSD_FPS_X - 64; - } - /* want vertical scaling and game is not in 240 line mode */ - if (currentConfig.scaling == EOPT_SCALE_HW_HV && !(modes&8)) - gp2x_video_RGB_setscaling(8, scalex, 224); - else gp2x_video_RGB_setscaling(0, scalex, 240); - oldmodes = modes; - clearArea(1); - } - - // second changed? - if (thissec != tval.tv_sec) - { -#ifdef BENCHMARK - static int bench = 0, bench_fps = 0, bench_fps_s = 0, bfp = 0, bf[4]; - if (++bench == 10) { - bench = 0; - bench_fps_s = bench_fps; - bf[bfp++ & 3] = bench_fps; - bench_fps = 0; - } - bench_fps += frames_shown; - sprintf(fpsbuff, "%02i/%02i/%02i", frames_shown, bench_fps_s, (bf[0]+bf[1]+bf[2]+bf[3])>>2); -#else - if (currentConfig.EmuOpt & 2) { - sprintf(fpsbuff, "%02i/%02i", frames_shown, frames_done); - if (fpsbuff[5] == 0) { fpsbuff[5] = fpsbuff[6] = ' '; fpsbuff[7] = 0; } - } -#endif - frames_shown = frames_done = 0; - thissec = tval.tv_sec; - } -#ifdef PFRAMES - sprintf(fpsbuff, "%i", Pico.m.frame_count); -#endif - - if (pthissec != tval.tv_sec) - { - if (PsndOut == 0 && currentConfig.Frameskip >= 0) { - pframes_done = pframes_shown = 0; - } else { - // it is quite common for this implementation to leave 1 fame unfinished - // when second changes, but we don't want buffer to starve. - if (PsndOut && pframes_done < target_fps && pframes_done > target_fps-5) { - emu_update_input(); - SkipFrame(1); pframes_done++; - } - - pframes_done -= target_fps; if (pframes_done < 0) pframes_done = 0; - pframes_shown -= target_fps; if (pframes_shown < 0) pframes_shown = 0; - if (pframes_shown > pframes_done) pframes_shown = pframes_done; - } - pthissec = tval.tv_sec; - } - - lim_time = (pframes_done+1) * target_frametime + vsync_offset; - if (currentConfig.Frameskip >= 0) // frameskip enabled - { - for(i = 0; i < currentConfig.Frameskip; i++) { - emu_update_input(); - SkipFrame(1); pframes_done++; frames_done++; - if (PsndOut && !reset_timing) { // do framelimitting if sound is enabled - gettimeofday(&tval, 0); - if (pthissec != tval.tv_sec) tval.tv_usec+=1000000; - if (tval.tv_usec < lim_time) { // we are too fast - simpleWait(pthissec, lim_time); - } - } - lim_time += target_frametime; - } - } - else if (tval.tv_usec > lim_time) // auto frameskip - { - // no time left for this frame - skip - if (tval.tv_usec - lim_time >= 300000) { - /* something caused a slowdown for us (disk access? cache flush?) - * try to recover by resetting timing... */ - reset_timing = 1; - continue; - } - emu_update_input(); - SkipFrame(tval.tv_usec < lim_time+target_frametime*2); pframes_done++; frames_done++; - continue; - } - - emu_update_input(); - PicoFrame(); - - // check time - gettimeofday(&tval, 0); - if (pthissec != tval.tv_sec) tval.tv_usec+=1000000; - - if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 300000) // slowdown detection - reset_timing = 1; - else if (PsndOut != NULL || currentConfig.Frameskip < 0) - { - // sleep or vsync if we are still too fast - // usleep sleeps for ~20ms minimum, so it is not a solution here - if (!reset_timing && tval.tv_usec < lim_time) - { - // we are too fast - if (vsync_offset) { - if (lim_time - tval.tv_usec > target_frametime/2) - simpleWait(pthissec, lim_time - target_frametime/4); - gp2x_video_wait_vsync(); - } else { - simpleWait(pthissec, lim_time); - } - } - } - - blit(fpsbuff, notice); - - pframes_done++; pframes_shown++; - frames_done++; frames_shown++; - } - - emu_set_fastforward(0); - - if (PicoAHW & PAHW_MCD) - PicoCDBufferFree(); - - // save SRAM - if ((currentConfig.EmuOpt & EOPT_EN_SRAM) && SRam.changed) { - plat_status_msg_busy_first("Writing SRAM/BRAM..."); - emu_save_load_game(0, 1); - SRam.changed = 0; - } - - // do menu background to be sure it's right - pemu_forced_frame(POPT_EN_SOFTSCALE); +void pemu_loop_end(void) +{ } const char *plat_get_credits(void) diff --git a/gp2x/soc.c b/gp2x/soc.c index d5326be..ee421df 100644 --- a/gp2x/soc.c +++ b/gp2x/soc.c @@ -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) { diff --git a/gp2x/soc.h b/gp2x/soc.h index 1396f24..b645e8b 100644 --- a/gp2x/soc.h +++ b/gp2x/soc.h @@ -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); diff --git a/gp2x/soc_mmsp2.c b/gp2x/soc_mmsp2.c index 00eb0a2..5217dda 100644 --- a/gp2x/soc_mmsp2.c +++ b/gp2x/soc_mmsp2.c @@ -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) diff --git a/gp2x/soc_pollux.c b/gp2x/soc_pollux.c index 7b71324..b6ec9ab 100644 --- a/gp2x/soc_pollux.c +++ b/gp2x/soc_pollux.c @@ -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) diff --git a/linux/plat.c b/linux/plat.c index 751d97a..166b4d6 100644 --- a/linux/plat.c +++ b/linux/plat.c @@ -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); diff --git a/pandora/emu.c b/pandora/emu.c index d409b57..a9a2119 100644 --- a/pandora/emu.c +++ b/pandora/emu.c @@ -34,7 +34,6 @@ static short __attribute__((aligned(4))) sndBuffer[2*44100/50]; -static struct timeval noticeMsgTime = { 0, 0 }; // when started showing static int osd_fps_x; unsigned char *PicoDraw2FB = NULL; // temporary buffer for alt renderer @@ -43,17 +42,6 @@ unsigned char *PicoDraw2FB = NULL; // temporary buffer for alt renderer static int pico_pen_x = 0, pico_pen_y = 240/2; -void plat_status_msg(const char *format, ...) -{ - va_list vl; - - va_start(vl, format); - vsnprintf(noticeMsg, sizeof(noticeMsg), fmt, vl); - va_end(vl); - - gettimeofday(¬iceMsgTime, 0); -} - int plat_get_root_dir(char *dst, int len) { extern char **g_argv; diff --git a/psp/emu.c b/psp/emu.c index 929c608..e0e1ca1 100644 --- a/psp/emu.c +++ b/psp/emu.c @@ -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"); } } -- 2.39.2