X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=platform%2Fgp2x%2Femu.c;h=f3b4c02a118673a1fc8dbb35c10b08aaea5cd06a;hb=4696954094ca11200b8b08e8a9bfb231cf21fb86;hp=3d6cd3a2ca94d1959a1ab500b549a9e5eaec985c;hpb=83bd0b76aba19ff62368cfee76089e15579e3b7c;p=picodrive.git diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 3d6cd3a..f3b4c02 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -54,29 +54,16 @@ extern int crashed_940; static short sndBuffer[2*44100/50]; static char noticeMsg[64]; // notice msg to draw static struct timeval noticeMsgTime = { 0, 0 }; // when started showing -static int reset_timing, osd_fps_x; +static int osd_fps_x; static int combo_keys = 0, combo_acts = 0; // keys and actions which need button combos static int gp2x_old_gamma = 100; static unsigned char *movie_data = NULL; static int movie_size = 0; unsigned char *framebuff = 0; // temporary buffer for alt renderer int state_slot = 0; +int reset_timing = 0; -/* -// tmp -static FILE *logf = NULL; -void pprintf(char *texto, ...) -{ - va_list args; - - va_start(args,texto); - vfprintf(logf,texto,args); - va_end(args); - fflush(logf); - sync(); -} -*/ // utilities static void strlwr(char* string) { @@ -169,7 +156,7 @@ int find_bios(int region, char **bios_file) /* checks if romFileName points to valid MegaCD image * if so, checks for suitable BIOS */ -static int cd_check(char **bios_file) +int emu_cd_check(char **bios_file) { unsigned char buf[32]; pm_file *cd_f; @@ -190,7 +177,7 @@ static int cd_check(char **bios_file) return 0; } - /* it seems we have a CD image here. Try to detect region and load a suitable BIOS now.. */ + /* it seems we have a CD image here. Try to detect region now.. */ pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); pm_read(buf, 1, cd_f); pm_close(cd_f); @@ -206,7 +193,9 @@ static int cd_check(char **bios_file) printf("overrided region to %s\n", region != 4 ? (region == 8 ? "EU" : "JAP") : "USA"); } - if(find_bios(region, bios_file)) + if (bios_file == NULL) return type; + + if (find_bios(region, bios_file)) return type; // CD and BIOS detected return -1; // CD detected but load failed @@ -283,8 +272,11 @@ int emu_ReloadRom(void) get_ext(romFileName, ext); } + if ((PicoMCD & 1) && Pico_mcd != NULL) + Stop_CD(); + // check for MegaCD image - cd_state = cd_check(&used_rom_name); + cd_state = emu_cd_check(&used_rom_name); if (cd_state > 0) { PicoMCD |= 1; get_ext(used_rom_name, ext); @@ -393,6 +385,9 @@ int emu_ReloadRom(void) } +static void emu_msg_cb(const char *msg); +static void emu_msg_tray_open(void); + void emu_Init(void) { // make temp buffer for alt renderer @@ -409,8 +404,9 @@ void emu_Init(void) mkdir("cfg", 0777); PicoInit(); - -// logf = fopen("log.txt", "w"); + PicoMessage = emu_msg_cb; + PicoMCDopenTray = emu_msg_tray_open; + PicoMCDcloseTray = menu_loop_tray; } @@ -463,6 +459,18 @@ static void find_combos(void) } +void scaling_update(void) +{ + PicoOpt &= ~0x4100; + switch (currentConfig.scaling) { + default: break; // off + case 1: // hw hor + case 2: PicoOpt |= 0x0100; break; // hw hor+vert + case 3: PicoOpt |= 0x4000; break; // sw hor + } +} + + int emu_ReadConfig(int game) { FILE *f; @@ -496,6 +504,8 @@ int emu_ReadConfig(int game) currentConfig.KeyBinds[23] = 1<<29; // vol up currentConfig.KeyBinds[22] = 1<<30; // vol down currentConfig.gamma = 100; + currentConfig.PicoCDBuffers = 64; + currentConfig.scaling = 0; strncpy(cfg, PicoConfigFile, 511); cfg[511] = 0; } else { @@ -511,26 +521,29 @@ int emu_ReadConfig(int game) bread = fread(¤tConfig, 1, sizeof(currentConfig), f); fclose(f); } - printf((bread == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); + printf(bread > 0 ? "(ok)\n" : "(failed)\n"); PicoOpt = currentConfig.PicoOpt; PsndRate = currentConfig.PsndRate; PicoRegionOverride = currentConfig.PicoRegion; PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder; + PicoCDBuffers = currentConfig.PicoCDBuffers; if (PicoOpt & 0x20) { actionNames[ 8] = "Z"; actionNames[ 9] = "Y"; actionNames[10] = "X"; actionNames[11] = "MODE"; } + scaling_update(); // some sanity checks - if (currentConfig.CPUclock < 1 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; + if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; if (currentConfig.gamma < 10 || currentConfig.gamma > 300) currentConfig.gamma = 100; + if (currentConfig.volume < 0 || currentConfig.volume > 99) currentConfig.volume = 50; // if volume keys are unbound, bind them to volume control if (!currentConfig.KeyBinds[23] && !currentConfig.KeyBinds[22]) { currentConfig.KeyBinds[23] = 1<<29; // vol up currentConfig.KeyBinds[22] = 1<<30; // vol down } - return (bread == sizeof(currentConfig)); + return (bread > 0); // == sizeof(currentConfig)); } @@ -545,7 +558,7 @@ int emu_WriteConfig(int game) strncpy(cfg, PicoConfigFile, 511); cfg[511] = 0; } else { - romfname_ext(cfg, "cfg", ".pbcfg"); + romfname_ext(cfg, "cfg/", ".pbcfg"); } printf("emu_WriteConfig: %s ", cfg); @@ -555,10 +568,13 @@ int emu_WriteConfig(int game) currentConfig.PsndRate = PsndRate; currentConfig.PicoRegion = PicoRegionOverride; currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder; + currentConfig.PicoCDBuffers = PicoCDBuffers; bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f); fflush(f); fclose(f); +#ifndef NO_SYNC sync(); +#endif } printf((bwrite == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); @@ -574,12 +590,26 @@ void emu_Deinit(void) SRam.changed = 0; } - if (!(currentConfig.EmuOpt & 0x20)) - emu_WriteConfig(0); + if (!(currentConfig.EmuOpt & 0x20)) { + FILE *f = fopen(PicoConfigFile, "r+b"); + if (!f) emu_WriteConfig(0); + else { + // if we already have config, reload it, except last ROM + fseek(f, sizeof(currentConfig.lastRomFile), SEEK_SET); + fread(¤tConfig.EmuOpt, 1, sizeof(currentConfig) - sizeof(currentConfig.lastRomFile), f); + fseek(f, 0, SEEK_SET); + fwrite(¤tConfig, 1, sizeof(currentConfig), f); + fflush(f); + fclose(f); +#ifndef NO_SYNC + sync(); +#endif + } + } + free(framebuff); PicoExit(); -// fclose(logf); // restore gamma if (gp2x_old_gamma != 100) @@ -699,9 +729,13 @@ static void blit(const char *fps, const char *notice) } } - if (notice) osd_text(4, 232, notice); - if (emu_opt & 2) - osd_text(osd_fps_x, 232, fps); + if (notice || (emu_opt & 2)) { + int h = 232; + if (currentConfig.scaling == 2 && !(Pico.video.reg[1]&8)) h -= 8; + if (notice) osd_text(4, h, notice); + if (emu_opt & 2) + osd_text(osd_fps_x, h, fps); + } if ((emu_opt & 0x400) && (PicoMCD & 1)) cd_leds(); @@ -764,23 +798,53 @@ static void vidResetMode(void) } Pico.m.dirtyPal = 1; // reset scaling - gp2x_video_RGB_setscaling((PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 240); + if (currentConfig.scaling == 2 && !(Pico.video.reg[1]&8)) + gp2x_video_RGB_setscaling(8, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 224); + else gp2x_video_RGB_setscaling(0, (PicoOpt&0x100)&&!(Pico.video.reg[12]&1) ? 256 : 320, 240); } +static void emu_msg_cb(const char *msg) +{ + if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) { + // 8-bit renderers + gp2x_memset_all_buffers(320*232, 0xe0, 320*8); + osd_text(4, 232, msg); + gp2x_memcpy_all_buffers((char *)gp2x_screen+320*232, 320*232, 320*8); + } else { + // 16bit accurate renderer + gp2x_memset_all_buffers(320*232*2, 0, 320*8*2); + osd_text(4, 232, msg); + gp2x_memcpy_all_buffers((char *)gp2x_screen+320*232*2, 320*232*2, 320*8*2); + } + gettimeofday(¬iceMsgTime, 0); + noticeMsgTime.tv_sec -= 2; + + /* assumption: emu_msg_cb gets called only when something slow is about to happen */ + reset_timing = 1; +} + static void emu_state_cb(const char *str) { clearArea(0); blit("", str); } +static void emu_msg_tray_open(void) +{ + strcpy(noticeMsg, "CD tray opened"); + gettimeofday(¬iceMsgTime, 0); +} + static void RunEvents(unsigned int which) { if(which & 0x1800) { // save or load (but not both) int do_it = 1; - if (!(which & 0x1000) && (currentConfig.EmuOpt & 0x200) && emu_check_save_file(state_slot)) { + if ( emu_check_save_file(state_slot) && + (( (which & 0x1000) && (currentConfig.EmuOpt & 0x800)) || // load + (!(which & 0x1000) && (currentConfig.EmuOpt & 0x200))) ) { // save unsigned long keys; - blit("", "OVERWRITE SAVE? (Y=yes, X=no)"); + blit("", (which & 0x1000) ? "LOAD STATE? (Y=yes, X=no)" : "OVERWRITE SAVE? (Y=yes, X=no)"); while( !((keys = gp2x_joystick_read(1)) & (GP2X_X|GP2X_Y)) ) usleep(50*1024); if (keys & GP2X_X) do_it = 0; @@ -924,7 +988,7 @@ static void updateKeys(void) if(events & 0x6000) { int vol = currentConfig.volume; if (events & 0x2000) { - if (vol < 90) vol++; + if (vol < 99) vol++; } else { if (vol > 0) vol--; } @@ -946,25 +1010,17 @@ static void updateSound(int len) { if (PicoOpt&8) len<<=1; - gp2x_sound_write(PsndOut, len<<1); + /* avoid writing audio when lagging behind to prevent audio lag */ + if (PicoSkipFrame != 2) + gp2x_sound_write(PsndOut, len<<1); } -static void SkipFrame(int do_sound) +static void SkipFrame(int do_audio) { - void *sndbuff_tmp = 0; - if (PsndOut && !do_sound) { - sndbuff_tmp = PsndOut; - PsndOut = 0; - } - - PicoSkipFrame=1; + PicoSkipFrame=do_audio ? 1 : 2; PicoFrame(); PicoSkipFrame=0; - - if (sndbuff_tmp && !do_sound) { - PsndOut = sndbuff_tmp; - } } @@ -974,7 +1030,6 @@ void emu_forced_frame(void) PicoOpt |= 0x10; PicoFrameFull(); - PicoOpt = po_old; if (!(Pico.video.reg[12]&1)) { vidCpyM2 = vidCpyM2_32col; @@ -984,6 +1039,8 @@ void emu_forced_frame(void) vidCpyM2((unsigned char *)gp2x_screen+320*8, framebuff+328*8); vidConvCpyRGB32(localPal, Pico.cram, 0x40); gp2x_video_setpalette(localPal, 0x40); + + PicoOpt = po_old; } static void simpleWait(int thissec, int lim_time) @@ -1068,6 +1125,9 @@ void emu_Loop(void) PsndOut = 0; } + // prepare CD buffer + if (PicoMCD & 1) PicoCDBufferInit(); + // loop? while (engineState == PGS_Running) { @@ -1110,7 +1170,9 @@ void emu_Loop(void) vidCpyM2 = vidCpyM2_32col; } } - gp2x_video_RGB_setscaling(scalex, 240); + if (currentConfig.scaling == 2 && !(modes&8)) // want vertical scaling and game is not in 240 line mode + gp2x_video_RGB_setscaling(8, scalex, 224); + else gp2x_video_RGB_setscaling(0, scalex, 240); oldmodes = modes; clearArea(1); } @@ -1148,7 +1210,9 @@ void emu_Loop(void) if (frames_shown > frames_done) frames_shown = frames_done; } } - +#if 0 + sprintf(fpsbuff, "%05i", Pico.m.frame_count); +#endif lim_time = (frames_done+1) * target_frametime; if(currentConfig.Frameskip >= 0) { // frameskip enabled for(i = 0; i < currentConfig.Frameskip; i++) { @@ -1165,8 +1229,14 @@ void emu_Loop(void) } } else if(tval.tv_usec > lim_time) { // auto frameskip // no time left for this frame - skip + if (tval.tv_usec - lim_time >= 0x300000) { + /* something caused a slowdown for us (disk access? cache flush?) + * try to recover by resetting timing... */ + reset_timing = 1; + continue; + } updateKeys(); - SkipFrame(tval.tv_usec < lim_time+target_frametime); frames_done++; + SkipFrame(tval.tv_usec < lim_time+target_frametime*2); frames_done++; continue; } @@ -1233,14 +1303,14 @@ if (Pico.m.frame_count == 31563) { // check time gettimeofday(&tval, 0); - if(thissec != tval.tv_sec) tval.tv_usec+=1000000; + if (thissec != tval.tv_sec) tval.tv_usec+=1000000; - // sleep if we are still too fast - if(PsndOut != 0 || currentConfig.Frameskip < 0) + if (currentConfig.Frameskip < 0 && tval.tv_usec - lim_time >= 0x300000) // slowdown detection + reset_timing = 1; + else if (PsndOut != NULL || currentConfig.Frameskip < 0) { + // sleep if we are still too fast // usleep sleeps for ~20ms minimum, so it is not a solution here - gettimeofday(&tval, 0); - if(thissec != tval.tv_sec) tval.tv_usec+=1000000; if(tval.tv_usec < lim_time) { // we are too fast @@ -1253,6 +1323,9 @@ if (Pico.m.frame_count == 31563) { frames_done++; frames_shown++; } + + if (PicoMCD & 1) PicoCDBufferFree(); + // save SRAM if((currentConfig.EmuOpt & 1) && SRam.changed) { osd_text(4, 232, "Writing SRAM/BRAM.."); @@ -1412,7 +1485,9 @@ int emu_SaveLoadGame(int load, int sram) ret = fwrite(sram_data, 1, sram_size, sramFile); ret = (ret != sram_size) ? -1 : 0; fclose(sramFile); +#ifndef NO_SYNC sync(); +#endif } } return ret; @@ -1436,8 +1511,10 @@ int emu_SaveLoadGame(int load, int sram) ret = PmovState(load ? 6 : 5, PmovFile); areaClose(PmovFile); PmovFile = 0; - if (!load) sync(); - else Pico.m.dirtyPal=1; + if (load) Pico.m.dirtyPal=1; +#ifndef NO_SYNC + else sync(); +#endif } else ret = -1; if (!ret)