X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=platform%2Fgp2x%2Femu.c;h=a9a931a68c79bba047c323353153797e0ad7c349;hb=eff55556cff77fd64cff4be32e449e0a58aed6fe;hp=074d620f6ce7eb9a857e1be49e98ecedafa05478;hpb=6cadc2da0070781cf2d8fcff84265d3ca1f423b9;p=picodrive.git diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 074d620..a9a931a 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -20,6 +20,7 @@ #include "menu.h" #include "asmutils.h" #include "cpuctrl.h" +#include "fonts.h" #include #include @@ -32,14 +33,6 @@ #define OSD_FPS_X 260 #endif -// PicoPad[] format: SACB RLDU -char *actionNames[] = { - "UP", "DOWN", "LEFT", "RIGHT", "B", "C", "A", "START", - 0, 0, 0, 0, 0, 0, 0, 0, // Z, Y, X, MODE (enabled only when needed), ?, ?, ?, ? - 0, 0, 0, 0, 0, 0, 0, "ENTER MENU", // player2_flag, ?, ?, ?, ?, ?, ?, menu - "NEXT SAVE SLOT", "PREV SAVE SLOT", "SWITCH RENDERER", "SAVE STATE", - "LOAD STATE", "VOLUME UP", "VOLUME DOWN", "DONE" -}; int engineState; int select_exits = 0; @@ -62,6 +55,7 @@ static int movie_size = 0; unsigned char *framebuff = 0; // temporary buffer for alt renderer int state_slot = 0; int reset_timing = 0; +int config_slot = 0, config_slot_current = 0; // utilities @@ -284,7 +278,7 @@ int emu_ReloadRom(void) // bios_help() ? return 0; } else { - if (PicoMCD & 1) PicoExitMCD(); + if (PicoMCD & 1) Stop_CD(); PicoMCD &= ~1; } @@ -294,6 +288,8 @@ int emu_ReloadRom(void) return 0; } + menu_romload_prepare(used_rom_name); + if(rom_data) { free(rom_data); rom_data = 0; @@ -304,9 +300,11 @@ int emu_ReloadRom(void) sprintf(menuErrorMsg, "PicoCartLoad() failed."); printf("%s\n", menuErrorMsg); pm_close(rom); + menu_romload_end(); return 0; } pm_close(rom); + menu_romload_end(); // detect wrong files (Pico crashes on very small files), also see if ROM EP is good if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || @@ -318,9 +316,9 @@ int emu_ReloadRom(void) } // load config for this ROM (do this before insert to get correct region) - ret = emu_ReadConfig(1); + ret = emu_ReadConfig(1, 1); if (!ret) - emu_ReadConfig(0); + emu_ReadConfig(0, 1); printf("PicoCartInsert(%p, %d);\n", rom_data, rom_size); if(PicoCartInsert(rom_data, rom_size)) { @@ -471,45 +469,58 @@ void scaling_update(void) } -int emu_ReadConfig(int game) +int emu_ReadConfig(int game, int no_defaults) { FILE *f; - char cfg[512]; + char cfg[512], extbuf[16]; int bread = 0; if (!game) { - // set default config - memset(¤tConfig, 0, sizeof(currentConfig)); - currentConfig.lastRomFile[0] = 0; - currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds - currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda - currentConfig.PsndRate = 22050; // 44100; - currentConfig.PicoRegion = 0; // auto - currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP - currentConfig.Frameskip = -1; // auto - currentConfig.CPUclock = 200; - currentConfig.volume = 50; - currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU - currentConfig.KeyBinds[ 4] = 1<<1; - currentConfig.KeyBinds[ 2] = 1<<2; - currentConfig.KeyBinds[ 6] = 1<<3; - currentConfig.KeyBinds[14] = 1<<4; - currentConfig.KeyBinds[13] = 1<<5; - currentConfig.KeyBinds[12] = 1<<6; - currentConfig.KeyBinds[ 8] = 1<<7; - currentConfig.KeyBinds[15] = 1<<26; // switch rend - currentConfig.KeyBinds[10] = 1<<27; // save state - currentConfig.KeyBinds[11] = 1<<28; // load state - currentConfig.KeyBinds[23] = 1<<29; // vol up - currentConfig.KeyBinds[22] = 1<<30; // vol down - currentConfig.gamma = 100; - currentConfig.PicoCDBuffers = 64; - currentConfig.scaling = 0; + if (!no_defaults) + { + // set default config + memset(¤tConfig, 0, sizeof(currentConfig)); + currentConfig.lastRomFile[0] = 0; + currentConfig.EmuOpt = 0x1f | 0x600; // | confirm_save, cd_leds + currentConfig.PicoOpt = 0x0f | 0xe00; // | use_940, cd_pcm, cd_cdda + currentConfig.PsndRate = 22050; // 44100; + currentConfig.PicoRegion = 0; // auto + currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP + currentConfig.Frameskip = -1; // auto + currentConfig.CPUclock = 200; + currentConfig.volume = 50; + currentConfig.KeyBinds[ 0] = 1<<0; // SACB RLDU + currentConfig.KeyBinds[ 4] = 1<<1; + currentConfig.KeyBinds[ 2] = 1<<2; + currentConfig.KeyBinds[ 6] = 1<<3; + currentConfig.KeyBinds[14] = 1<<4; + currentConfig.KeyBinds[13] = 1<<5; + currentConfig.KeyBinds[12] = 1<<6; + currentConfig.KeyBinds[ 8] = 1<<7; + currentConfig.KeyBinds[15] = 1<<26; // switch rend + currentConfig.KeyBinds[10] = 1<<27; // save state + currentConfig.KeyBinds[11] = 1<<28; // load state + 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); + if (config_slot != 0) + { + char *p = strrchr(cfg, '.'); + if (p == NULL) p = cfg + strlen(cfg); + sprintf(extbuf, ".%i.pbcfg", config_slot); + strncpy(p, extbuf, 511 - (p - cfg)); + } cfg[511] = 0; } else { - romfname_ext(cfg, "cfg/", ".pbcfg"); + if (config_slot != 0) + sprintf(extbuf, ".%i.pbcfg", config_slot); + else strcpy(extbuf, ".pbcfg"); + romfname_ext(cfg, "cfg/", extbuf); f = fopen(cfg, "rb"); if (!f) romfname_ext(cfg, NULL, ".pbcfg"); else fclose(f); @@ -528,10 +539,6 @@ int emu_ReadConfig(int game) 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 < 10 || currentConfig.CPUclock > 4096) currentConfig.CPUclock = 200; @@ -543,6 +550,7 @@ int emu_ReadConfig(int game) currentConfig.KeyBinds[22] = 1<<30; // vol down } + if (bread > 0) config_slot_current = config_slot; return (bread > 0); // == sizeof(currentConfig)); } @@ -550,15 +558,25 @@ int emu_ReadConfig(int game) int emu_WriteConfig(int game) { FILE *f; - char cfg[512]; + char cfg[512], extbuf[16]; int bwrite = 0; if (!game) { strncpy(cfg, PicoConfigFile, 511); + if (config_slot != 0) + { + char *p = strrchr(cfg, '.'); + if (p == NULL) p = cfg + strlen(cfg); + sprintf(extbuf, ".%i.pbcfg", config_slot); + strncpy(p, extbuf, 511 - (p - cfg)); + } cfg[511] = 0; } else { - romfname_ext(cfg, "cfg/", ".pbcfg"); + if (config_slot != 0) + sprintf(extbuf, ".%i.pbcfg", config_slot); + else strcpy(extbuf, ".pbcfg"); + romfname_ext(cfg, "cfg/", extbuf); } printf("emu_WriteConfig: %s ", cfg); @@ -578,6 +596,7 @@ int emu_WriteConfig(int game) } printf((bwrite == sizeof(currentConfig)) ? "(ok)\n" : "(failed)\n"); + if (bwrite == sizeof(currentConfig)) config_slot_current = config_slot; return (bwrite == sizeof(currentConfig)); } @@ -613,7 +632,54 @@ void emu_Deinit(void) // restore gamma if (gp2x_old_gamma != 100) - set_gamma(100); + set_gamma(100, 0); +} + +static void text_out8_builtin(int x, int y, const char *text) +{ + int i,l,len=strlen(text); + unsigned char *screen = (unsigned char *)gp2x_screen + x + y*320; + + /* always using built-in font */ + for (i = 0; i < len; i++) + { + for (l=0;l<8;l++) + { + unsigned char fd = fontdata8x8[((text[i])*8)+l]; + if (fd&0x80) screen[l*320+0]=0xf0; + if (fd&0x40) screen[l*320+1]=0xf0; + if (fd&0x20) screen[l*320+2]=0xf0; + if (fd&0x10) screen[l*320+3]=0xf0; + if (fd&0x08) screen[l*320+4]=0xf0; + if (fd&0x04) screen[l*320+5]=0xf0; + if (fd&0x02) screen[l*320+6]=0xf0; + if (fd&0x01) screen[l*320+7]=0xf0; + } + screen += 8; + } +} + +static void text_out16_builtin(int x, int y, const char *text) +{ + int i,l,len=strlen(text); + unsigned short *screen = (unsigned short *)gp2x_screen + x + y*320; + + for (i = 0; i < len; i++) + { + for (l=0;l<8;l++) + { + unsigned char fd = fontdata8x8[((text[i])*8)+l]; + if(fd&0x80) screen[l*320+0]=0xffff; + if(fd&0x40) screen[l*320+1]=0xffff; + if(fd&0x20) screen[l*320+2]=0xffff; + if(fd&0x10) screen[l*320+3]=0xffff; + if(fd&0x08) screen[l*320+4]=0xffff; + if(fd&0x04) screen[l*320+5]=0xffff; + if(fd&0x02) screen[l*320+6]=0xffff; + if(fd&0x01) screen[l*320+7]=0xffff; + } + screen += 8; + } } @@ -629,7 +695,7 @@ void osd_text(int x, int y, const char *text) p = (int *) ((unsigned char *) gp2x_screen+x+320*(y+h)); for (i = len; i; i--, p++) *p = 0xe0e0e0e0; } - gp2x_text_out8_2(x, y, text, 0xf0); + text_out8_builtin(x, y, text); } else { int *p, i, h; x &= ~1; // align x @@ -638,7 +704,7 @@ void osd_text(int x, int y, const char *text) p = (int *) ((unsigned short *) gp2x_screen+x+320*(y+h)); for (i = len; i; i--, p++) *p = (*p>>2)&0x39e7; } - gp2x_text_out15(x, y, text); + text_out16_builtin(x, y, text); } } @@ -776,7 +842,7 @@ static void vidResetMode(void) if (PicoOpt&0x10) { gp2x_video_changemode(8); } else if (currentConfig.EmuOpt&0x80) { - gp2x_video_changemode(15); + gp2x_video_changemode(16); PicoDrawSetColorFormat(1); PicoScan = EmuScan16; PicoScan(0, 0); @@ -1027,10 +1093,20 @@ static void SkipFrame(int do_audio) void emu_forced_frame(void) { int po_old = PicoOpt; + int eo_old = currentConfig.EmuOpt; + + PicoOpt &= ~0x0010; + PicoOpt |= 0x4080; // soft_scale | acc_sprites + currentConfig.EmuOpt |= 0x80; - PicoOpt |= 0x10; - PicoFrameFull(); + //vidResetMode(); + PicoDrawSetColorFormat(1); + PicoScan = EmuScan16; + PicoScan(0, 0); + Pico.m.dirtyPal = 1; + PicoFrameDrawOnly(); +/* if (!(Pico.video.reg[12]&1)) { vidCpyM2 = vidCpyM2_32col; clearArea(1); @@ -1039,8 +1115,9 @@ 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; + currentConfig.EmuOpt = eo_old; } static void simpleWait(int thissec, int lim_time) @@ -1063,11 +1140,11 @@ static void simpleWait(int thissec, int lim_time) void emu_Loop(void) { static int gp2x_old_clock = 200; - static int PsndRate_old = 0, PicoOpt_old = 0, PsndLen_real = 0, pal_old = 0; + static int PsndRate_old = 0, PicoOpt_old = 0, EmuOpt_old = 0, PsndLen_real = 0, pal_old = 0; char fpsbuff[24]; // fps count c string struct timeval tval; // timing int thissec = 0, frames_done = 0, frames_shown = 0, oldmodes = 0; - int target_fps, target_frametime, lim_time, i; + int target_fps, target_frametime, lim_time, vsync_offset, i; char *notice = 0; printf("entered emu_Loop()\n"); @@ -1079,12 +1156,19 @@ void emu_Loop(void) printf(" done\n"); } - if (gp2x_old_gamma != currentConfig.gamma) { - set_gamma(currentConfig.gamma); + if (gp2x_old_gamma != currentConfig.gamma || (EmuOpt_old&0x1000) != (currentConfig.EmuOpt&0x1000)) { + set_gamma(currentConfig.gamma, !!(currentConfig.EmuOpt&0x1000)); gp2x_old_gamma = currentConfig.gamma; - printf("updated gamma to %i\n", currentConfig.gamma); + printf("updated gamma to %i, A_SN's curve: %i\n", currentConfig.gamma, !!(currentConfig.EmuOpt&0x1000)); + } + + if ((EmuOpt_old&0x2000) != (currentConfig.EmuOpt&0x2000)) { + if (currentConfig.EmuOpt&0x2000) + set_LCD_custom_rate(Pico.m.pal ? LCDR_100 : LCDR_120); + else unset_LCD_custom_rate(); } + EmuOpt_old = currentConfig.EmuOpt; fpsbuff[0] = 0; // make sure we are in correct mode @@ -1128,6 +1212,19 @@ void emu_Loop(void) // prepare CD buffer if (PicoMCD & 1) PicoCDBufferInit(); + // calc vsync offset to sync timing code with vsync + if (currentConfig.EmuOpt&0x2000) { + 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; + // loop? while (engineState == PGS_Running) { @@ -1210,10 +1307,8 @@ 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; + + lim_time = (frames_done+1) * target_frametime + vsync_offset; if(currentConfig.Frameskip >= 0) { // frameskip enabled for(i = 0; i < currentConfig.Frameskip; i++) { updateKeys(); @@ -1309,12 +1404,18 @@ if (Pico.m.frame_count == 31563) { reset_timing = 1; else if (PsndOut != NULL || currentConfig.Frameskip < 0) { - // sleep if we are still too fast + // sleep or vsync if we are still too fast // usleep sleeps for ~20ms minimum, so it is not a solution here if(tval.tv_usec < lim_time) { // we are too fast - simpleWait(thissec, lim_time); + if (vsync_offset) { + if (lim_time - tval.tv_usec > target_frametime/2) + simpleWait(thissec, lim_time - target_frametime/4); + gp2x_video_wait_vsync(); + } else { + simpleWait(thissec, lim_time); + } } } @@ -1333,12 +1434,9 @@ if (Pico.m.frame_count == 31563) { SRam.changed = 0; } - // if in 16bit mode, generate 8it image for menu background - if (!(PicoOpt&0x10) && (currentConfig.EmuOpt&0x80)) + // if in 8bit mode, generate 16bit image for menu background + if ((PicoOpt&0x10) || !(currentConfig.EmuOpt&0x80)) emu_forced_frame(); - - // for menu bg - gp2x_memcpy_buffers((1<<2), gp2x_screen, 0, 320*240*2); } @@ -1493,6 +1591,8 @@ int emu_SaveLoadGame(int load, int sram) if (sram_size) { sramFile = fopen(saveFname, truncate ? "wb" : "r+b"); + if (!sramFile) sramFile = fopen(saveFname, "wb"); // retry + if (!sramFile) return -1; ret = fwrite(sram_data, 1, sram_size, sramFile); ret = (ret != sram_size) ? -1 : 0; fclose(sramFile);