diff --git a/skeleton/.system/rg35xx/paks/MinUI.pak/launch.sh b/skeleton/.system/rg35xx/paks/MinUI.pak/launch.sh index 6c60003..11a0df1 100755 --- a/skeleton/.system/rg35xx/paks/MinUI.pak/launch.sh +++ b/skeleton/.system/rg35xx/paks/MinUI.pak/launch.sh @@ -1,5 +1,9 @@ #!/bin/sh +# disable MicroSD card powersaving (should help reduce load stutter, test) +echo on > /sys/devices/b0238000.mmc/mmc_host/mmc0/power/control +echo on > /sys/devices/b0230000.mmc/mmc_host/mmc1/power/control + export SDCARD_PATH="/mnt/sdcard" export BIOS_PATH="$SDCARD_PATH/Bios" export SAVES_PATH="$SDCARD_PATH/Saves" @@ -14,7 +18,11 @@ export LD_LIBRARY_PATH=$SYSTEM_PATH/lib:$LD_LIBRARY_PATH mkdir -p "$LOGS_PATH" mkdir -p "$USERDATA_PATH/.minui" -CPU_PATH="/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" +echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor +export CPU_SPEED_MENU=504000 +export CPU_SPEED_GAME=1296000 +export CPU_SPEED_PERF=1488000 # improves binary launch times +export CPU_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed cd $(dirname "$0") @@ -25,11 +33,10 @@ export EXEC_PATH=/tmp/minui_exec touch "$EXEC_PATH" && sync while [ -f "$EXEC_PATH" ]; do - echo ondemand > "$CPU_PATH" - ./minui.elf &> $LOGS_PATH/minui.txt - echo performance > "$CPU_PATH" + # overclock to speedup binary launch time + echo $CPU_SPEED_PERF > "$CPU_PATH" sync NEXT="/tmp/next" diff --git a/src/clock/main.c b/src/clock/main.c index 7550bb2..05d238b 100644 --- a/src/clock/main.c +++ b/src/clock/main.c @@ -22,6 +22,8 @@ enum { }; int main(int argc , char* argv[]) { + POW_setCPUSpeed(CPU_SPEED_MENU); + SDL_Surface* screen = GFX_init(MODE_MAIN); InitSettings(); diff --git a/src/common/api.c b/src/common/api.c index dfa01ba..facdc3a 100644 --- a/src/common/api.c +++ b/src/common/api.c @@ -1099,26 +1099,33 @@ void POW_powerOff(void) { } #define BACKLIGHT_PATH "/sys/class/backlight/backlight.2/bl_power" -#define GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" -static char governor[128]; + +#define CPU_SPEED_SET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed" +#define CPU_SPEED_GET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" +static int previous_speed = CPU_SPEED_NORMAL; + +void POW_setCPUSpeed(int speed) { + putInt(CPU_SPEED_SET_PATH, speed); + sync(); +} static void POW_enterSleep(void) { SetRawVolume(0); putInt(BACKLIGHT_PATH, FB_BLANK_POWERDOWN); - // save current governor (either ondemand or performance) - getFile(GOVERNOR_PATH, governor, 128); - trimTrailingNewlines(governor); - - putFile(GOVERNOR_PATH, "powersave"); + // TODO: not sure this is necessary + // previous_speed = getInt(CPU_SPEED_GET_PATH); + // POW_setCPUSpeed(CPU_SPEED_MENU); + sync(); } static void POW_exitSleep(void) { putInt(BACKLIGHT_PATH, FB_BLANK_UNBLANK); SetVolume(GetVolume()); - // restore previous governor - putFile(GOVERNOR_PATH, governor); + // TODO: not sure this is necessary + // POW_setCPUSpeed(previous_speed); + sync(); } static void POW_waitForWake(void) { diff --git a/src/common/api.h b/src/common/api.h index 6abfdff..37b5585 100644 --- a/src/common/api.h +++ b/src/common/api.h @@ -192,6 +192,12 @@ int POW_isCharging(void); int POW_getBattery(void); void POW_setRumble(int strength); // 0-100 +#define CPU_SPEED_MENU 504000 // 240000 was having latency issues +#define CPU_SPEED_POWERSAVE 1104000 +#define CPU_SPEED_NORMAL 1296000 +#define CPU_SPEED_PERFORMANCE 1488000 +void POW_setCPUSpeed(int speed); + /////////////////////////////// #endif diff --git a/src/minarch/main.c b/src/minarch/main.c index 5f3953e..7bcbfe6 100644 --- a/src/minarch/main.c +++ b/src/minarch/main.c @@ -54,6 +54,7 @@ static int optimize_text = 1; static int show_debug = 0; static int max_ff_speed = 3; // 4x static int fast_forward = 0; +static int overclock = 1; // normal static struct Renderer { int src_w; @@ -384,6 +385,7 @@ enum { FE_OPT_SCANLINES, FE_OPT_TEXT, FE_OPT_TEARING, + FE_OPT_OVERCLOCK, FE_OPT_DEBUG, FE_OPT_MAXFF, FE_OPT_COUNT, @@ -485,10 +487,16 @@ static char* shortcut_labels[] = { "MENU+R2", NULL, }; +static char* overclock_labels[] = { + "Powersave", + "Normal", + "Performance", + NULL, +}; enum { CONFIG_NONE, - CONFIG_GLOBAL, + CONFIG_CONSOLE, CONFIG_GAME, }; @@ -532,6 +540,16 @@ static struct Config { .values = tearing_labels, .labels = tearing_labels, }, + [FE_OPT_OVERCLOCK] = { + .key = "minarch_cpu_speed", + .name = "CPU Speed", + .desc = "Over- or underclock the CPU to prioritize\npure performance or power savings.", + .default_value = 1, + .value = 1, + .count = 3, + .values = overclock_labels, + .labels = overclock_labels, + }, [FE_OPT_DEBUG] = { .key = "minarch_debug_hud", .name = "Debug HUD", @@ -579,11 +597,21 @@ static void Config_getValue(char* cfg, const char* key, char* out_value) { if (!tmp) tmp = strchr(out_value, '\r'); if (tmp) *tmp = '\0'; } + +static void setOverclock(int i) { + overclock = i; + switch (i) { + case 0: POW_setCPUSpeed(CPU_SPEED_POWERSAVE); break; + case 1: POW_setCPUSpeed(CPU_SPEED_NORMAL); break; + case 2: POW_setCPUSpeed(CPU_SPEED_PERFORMANCE); break; + } +} static void Config_syncFrontend(int i, int value) { switch (i) { case FE_OPT_SCANLINES: show_scanlines = value; renderer.src_w = 0; break; case FE_OPT_TEXT: optimize_text = value; renderer.src_w = 0; break; case FE_OPT_TEARING: GFX_setVsync(value); break; + case FE_OPT_OVERCLOCK: setOverclock(value); break; case FE_OPT_DEBUG: show_debug = value; break; case FE_OPT_MAXFF: max_ff_speed = value; break; } @@ -609,7 +637,7 @@ static void Config_read(void) { char* cfg = allocFile(path); if (!cfg) return; - config.loaded = override ? CONFIG_GAME : CONFIG_GLOBAL; + config.loaded = override ? CONFIG_GAME : CONFIG_CONSOLE; char key[256]; char value[256]; @@ -676,7 +704,7 @@ static void Config_write(int override) { if (config.loaded==CONFIG_GAME) unlink(path); Config_getPath(path, CONFIG_WRITE_ALL); } - config.loaded = override ? CONFIG_GAME : CONFIG_GLOBAL; + config.loaded = override ? CONFIG_GAME : CONFIG_CONSOLE; FILE *file = fopen(path, "wb"); if (!file) return; @@ -711,7 +739,7 @@ static void Config_restore(void) { sprintf(path, "%s/%s.cfg", core.config_dir, game.name); unlink(path); } - else if (config.loaded==CONFIG_GLOBAL) { + else if (config.loaded==CONFIG_CONSOLE) { sprintf(path, "%s/minarch.cfg", core.config_dir); unlink(path); } @@ -2427,9 +2455,12 @@ void Menu_quit(void) { void Menu_beforeSleep(void) { State_autosave(); putFile(AUTO_RESUME_PATH, game.path + strlen(SDCARD_PATH)); + POW_setCPUSpeed(CPU_SPEED_MENU); } void Menu_afterSleep(void) { unlink(AUTO_RESUME_PATH); + setOverclock(overclock); + // POW_setCPUSpeed(CPU_SPEED_NORMAL); } typedef struct MenuList MenuList; @@ -2658,9 +2689,9 @@ static MenuList OptionShortcuts_menu = { }; static char* getSaveDesc(void) { switch (config.loaded) { - case CONFIG_NONE: return "Using defaults."; break; - case CONFIG_GLOBAL: return "Using global config."; break; - case CONFIG_GAME: return "Using game config."; break; + case CONFIG_NONE: return "Using defaults."; break; + case CONFIG_CONSOLE: return "Using console config."; break; + case CONFIG_GAME: return "Using game config."; break; } } static int OptionShortcuts_openMenu(MenuList* list, int i) { @@ -2697,17 +2728,18 @@ static int OptionSaveChanges_onConfirm(MenuList* list, int i) { switch (i) { case 0: { Config_write(CONFIG_WRITE_ALL); - message = "Saved for all games."; + message = "Saved for console."; break; } case 1: { Config_write(CONFIG_WRITE_GAME); - message = "Saved for this game."; + message = "Saved for game."; break; } default: { Config_restore(); - message = "Restored defaults."; + if (config.loaded) message = "Restored console defaults."; + else message = "Restored defaults."; break; } } @@ -2739,8 +2771,8 @@ static MenuList OptionSaveChanges_menu = { .type = MENU_LIST, .on_confirm = OptionSaveChanges_onConfirm, .items = (MenuItem[]){ - {"Save for all games"}, - {"Save for this game"}, + {"Save for console"}, + {"Save for game"}, {"Restore defaults"}, {NULL}, } @@ -3146,6 +3178,8 @@ static int Menu_options(MenuList* list) { return 0; } static void Menu_loop(void) { + POW_setCPUSpeed(CPU_SPEED_MENU); // set Hz directly + fast_forward = 0; POW_enableAutosleep(); PAD_reset(); @@ -3504,6 +3538,8 @@ static void Menu_loop(void) { GFX_flip(screen); POW_disableAutosleep(); + + if (!quit) setOverclock(overclock); // restore overclock value } // TODO: move to POW_*? @@ -3561,7 +3597,11 @@ static void limitFF(void) { uint64_t ff_frame_time = 1000000 / (core.fps * (max_ff_speed + 1)); // TODO: define this only when max_ff_speed changes if (elapsed0) SDL_Delay(delay); + if (delay>0) { + // TODO: huh, this isn't causing the Tekken 3 hangs... + // printf("limitFF delay: %i\n", delay); fflush(stdout); + SDL_Delay(delay); + } } last_time += ff_frame_time; return; @@ -3571,6 +3611,7 @@ static void limitFF(void) { } int main(int argc , char* argv[]) { + setOverclock(overclock); // default to normal // force a stack overflow to ensure asan is linked and actually working // char tmp[2]; // tmp[2] = 'a'; diff --git a/src/minui/main.c b/src/minui/main.c index 96e1e0c..e776e5f 100644 --- a/src/minui/main.c +++ b/src/minui/main.c @@ -1233,6 +1233,7 @@ int main (int argc, char *argv[]) { if (autoResume()) return 0; // nothing to do dump("MinUI"); + POW_setCPUSpeed(CPU_SPEED_MENU); SDL_Surface* screen = GFX_init(MODE_MAIN); InitSettings();