frontend options hooked up (except Max FF Speed)

since i haven't implemented fast forward yet 😅
This commit is contained in:
Shaun Inman 2023-01-26 22:46:00 -05:00
parent 3cfd1313c6
commit 9c72a4f261
4 changed files with 210 additions and 68 deletions

View file

@ -19,7 +19,6 @@ CPU_PATH="/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
cd $(dirname "$0")
keymon.elf & # &> /mnt/sdcard/keymon.txt &
# ./batmon.sh &> /mnt/sdcard/batmon.txt &
export EXEC_PATH=/tmp/minui_exec

View file

@ -48,6 +48,11 @@ static SDL_Surface* screen;
static int quit;
static int show_menu;
static int show_scanlines;
static int optimize_text = 1;
static int show_debug;
static int max_ff_speed = 3; // 4x
///////////////////////////////////////
static struct Game {
@ -320,20 +325,140 @@ typedef struct Option {
char* var;
int default_value;
int value;
int count;
int count; // TODO: drop this
int visible;
char** values;
char** labels;
} Option;
static struct {
typedef struct OptionList {
int count;
int changed;
Option* items;
} options;
} OptionList;
static OptionList options;
static Option* frontend_options = (Option[]){
// TODO:
{NULL}
static char* onoff_values[] = {
"0",
"1",
NULL,
};
static char* onoff_labels[] = {
"OFF",
"ON",
NULL
};
static char* tearing_labels[] = {
"OFF",
"LENIENT",
"STRICT",
NULL
};
static char* max_ff_labels[] = {
"NONE",
"2X",
"3X",
"4X",
"5X",
"6X",
"7X",
"8X",
NULL,
};
enum {
FE_OPT_SCANLINES,
FE_OPT_TEXT,
FE_OPT_TEARING,
FE_OPT_DEBUG,
FE_OPT_MAXFF,
FE_OPT_COUNT,
};
static OptionList frontend_options = {
.count = FE_OPT_COUNT,
.items = (Option[]){
[FE_OPT_SCANLINES] = {
.key = "minarch_scanlines_grid",
.name = "Scanlines/Grid",
.desc = "Simulate scanlines (or a pixel grid at odd scales). Darkens\nthe overall image by about 50%. Reduces CPU load.",
.default_value = 0,
.value = 0,
.count = 2,
.values = onoff_values,
.labels = onoff_labels,
},
[FE_OPT_TEXT] = {
.key = "minarch_optimize_text",
.name = "Optimize Text",
.desc = "Prioritize a consistent stroke width when upscaling single\npixel lines using nearest neighbor scaler. Increases CPU load.",
.default_value = 1,
.value = 1,
.count = 2,
.values = onoff_values,
.labels = onoff_labels,
},
[FE_OPT_TEARING] = {
.key = "minarch_prevent_tearing",
.name = "Prevent Tearing",
.desc = "Wait for vsync before drawing the next frame. Lenient\nonly waits when within frame budget. Strict always waits\nand may cause audio stutter or crackling in some games.",
.default_value = 1,
.value = 1,
.count = 3,
.values = (char* []){
"off",
"lenient",
"strict",
NULL
},
.labels = (char* []){
"OFF",
"LENIENT",
"STRICT",
NULL
},
},
[FE_OPT_DEBUG] = {
.key = "minarch_debug_hud",
.name = "Debug HUD",
.desc = "Show frames per second, cpu load,\nresolution, and scaler information.",
.default_value = 0,
.value = 0,
.count = 2,
.values = onoff_values,
.labels = onoff_labels,
},
[FE_OPT_MAXFF] = {
.key = "minarch_max_ff_speed",
.name = "Max FF Speed",
.desc = "Fast forward will not exceed the selected speed\n(but may be less than depending on game and emulator).",
.default_value = 3,
.value = 3,
.count = 8,
.values = (char* []){
"none",
"2x",
"3x",
"4x",
"5x",
"6x",
"7x",
"8x",
NULL,
},
.labels = (char* []){
"NONE",
"2X",
"3X",
"4X",
"5X",
"6X",
"7X",
"8X",
NULL,
},
},
[FE_OPT_COUNT] = {NULL}
}
};
static int Option_getValueIndex(Option* item, const char* value) {
@ -598,7 +723,6 @@ static const char* device_button_names[RETRO_BUTTON_COUNT] = {
static const char* core_button_names[RETRO_BUTTON_COUNT];
static uint32_t buttons = 0; // RETRO_DEVICE_ID_JOYPAD_* buttons
static int ignore_menu = 0;
static int show_debug = 0;
static void input_poll_callback(void) {
PAD_poll();
@ -1013,7 +1137,7 @@ static double use_double = 0;
static uint32_t sec_start = 0;
static struct {
void* src;
// void* src;
int src_w;
int src_h;
int src_p;
@ -1516,7 +1640,7 @@ static void selectScaler(int width, int height, int pitch) {
int scale_y = SCREEN_HEIGHT / height;
int scale = MIN(scale_x,scale_y);
// TODO: carry this fix over to MiniUI/picoarch?
// TODO: carry this fix over to MiniUI/picoarch? or just port MinUI/minarch itself? :sweat_smile:
// this is not an aspect ratio but rather the ratio between
// the proposed aspect ratio and the target aspect ratio
@ -1616,12 +1740,11 @@ static void selectScaler(int width, int height, int pitch) {
renderer.dst_offset = (oy * SCREEN_PITCH) + (ox * SCREEN_BPP);
if (use_nearest)
renderer.scaler = scaleNN_text;
// renderer.scaler = scaleNN_text_scanline;
// renderer.scaler = scaleNN; // better for Tekken 3, Colin McRae Rally 2
if (show_scanlines) renderer.scaler = optimize_text ? scaleNN_text_scanline : scaleNN_scanline;
else renderer.scaler = optimize_text ? scaleNN_text : scaleNN;
else {
sprintf(scaler_name, "%ix", scale);
if (0) {
if (show_scanlines) {
switch (scale) {
case 4: renderer.scaler = scale4x_scanline; break;
case 3: renderer.scaler = scale3x_scanline; break;
@ -1666,11 +1789,11 @@ static void video_refresh_callback(const void *data, unsigned width, unsigned he
selectScaler(width,height,pitch);
GFX_clearAll();
if (renderer.src) {
free(renderer.src);
renderer.src = NULL;
}
renderer.src = malloc(height * pitch);
// if (renderer.src) {
// free(renderer.src);
// renderer.src = NULL;
// }
// renderer.src = malloc(height * pitch);
}
static int top_width = 0;
@ -2076,8 +2199,8 @@ int Menu_options(MenuList* list) {
}
dirty = 1;
}
else if (type!=MENU_INPUT) {
if (PAD_justPressed(BTN_LEFT)) {
else if (type!=MENU_INPUT && type!=MENU_LIST) {
if (PAD_justRepeated(BTN_LEFT)) {
MenuItem* item = &items[selected];
if (item->value>0) item->value -= 1;
else {
@ -2091,7 +2214,7 @@ int Menu_options(MenuList* list) {
dirty = 1;
}
else if (PAD_justPressed(BTN_RIGHT)) {
else if (PAD_justRepeated(BTN_RIGHT)) {
MenuItem* item = &items[selected];
if (item->values[item->value+1]) item->value += 1;
else item->value = 0;
@ -2231,7 +2354,18 @@ int Menu_options(MenuList* list) {
mw,
SCALE1(BUTTON_SIZE)
});
}
if (item->value>=0) {
text = TTF_RenderUTF8_Blended(font.tiny, item->values[item->value], COLOR_WHITE); // always white
SDL_BlitSurface(text, NULL, screen, &(SDL_Rect){
ox + mw - text->w - SCALE1(OPTION_PADDING),
oy+SCALE1((j*BUTTON_SIZE)+3)
});
SDL_FreeSurface(text);
}
if (j==selected_row) {
// white pill
int w = 0;
TTF_SizeUTF8(font.small, item->name, &w, NULL);
@ -2252,15 +2386,6 @@ int Menu_options(MenuList* list) {
oy+SCALE1((j*BUTTON_SIZE)+1)
});
SDL_FreeSurface(text);
if (item->value>=0) {
text = TTF_RenderUTF8_Blended(font.tiny, item->values[item->value], COLOR_WHITE); // always white
SDL_BlitSurface(text, NULL, screen, &(SDL_Rect){
ox + mw - text->w - SCALE1(OPTION_PADDING),
oy+SCALE1((j*BUTTON_SIZE)+3)
});
SDL_FreeSurface(text);
}
}
}
else if (type==MENU_VAR || type==MENU_INPUT) {
@ -2516,40 +2641,49 @@ static char* shortcut_labels[] = {
"MENU+R2",
NULL,
};
static char* onoff_labels[] = {
"OFF",
"ON",
NULL
};
static char* tearing_labels[] = {
"OFF",
"LENIENT",
"STRICT",
NULL
};
static char* max_ff_labels[] = {
"NONE",
"2X",
"3X",
"4X",
"5X",
"6X",
"7X",
"8X",
NULL,
};
static int options_frontend_change(MenuList* list, int i) {
MenuItem* item = &list->items[i];
Option* option = &frontend_options.items[i];
LOG_info("%s (%s) changed from `%s` (%s) to `%s` (%s)\n", item->name, item->key,
item->values[option->value], option->values[option->value],
item->values[item->value], option->values[item->value]
);
option->value = item->value;
switch (i) {
case FE_OPT_SCANLINES: show_scanlines = item->value; renderer.src_w = 0; break;
case FE_OPT_TEXT: optimize_text = item->value; renderer.src_w = 0; break;
case FE_OPT_TEARING: GFX_setVsync(item->value); break;
case FE_OPT_DEBUG: show_debug = item->value; break;
case FE_OPT_MAXFF: max_ff_speed = item->value; break;
}
// Options_setOptionRawValue(item->key, item->value);
}
static MenuList options_frontend_menu = {
.type = MENU_VAR,
.items = (MenuItem[]){
{"Scanlines/Grid", .values=onoff_labels, .desc="Simulate scanlines (or a pixel grid at odd scales). Darkens\nthe overall image by about 50%. Reduces CPU load."},
{"Optimize Text", .values=onoff_labels,.value=1, .desc="Prioritize a consistent stroke width when upscaling single\npixel lines using nearest neighbor scaler. Increases CPU load."},
{"Prevent Tearing", .values=tearing_labels,.value=1, .desc="Wait for vsync before drawing the next frame. Lenient\nonly waits when within frame budget. Strict always waits\nand may cause audio stutter or crackling in some games."},
{"Debug HUD", .values=onoff_labels,.desc="Show frames per second, cpu load,\nresolution, and scaler information."},
{"Max FF Speed", .values=max_ff_labels,.value=3,.desc="Fast forward will not exceed the selected speed\n(but may be less than depending on game and emulator)."},
{NULL},
}
.on_change = options_frontend_change,
.items = NULL,
};
static int options_frontend_confirm(MenuList* list, int i) {
if (options_frontend_menu.items==NULL) {
// TODO: where do I free this?
options_frontend_menu.items = calloc(frontend_options.count+1, sizeof(MenuItem));
for (int j=0; j<frontend_options.count; j++) {
Option* option = &frontend_options.items[j];
MenuItem* item = &options_frontend_menu.items[j];
item->key = option->key;
item->name = option->name;
item->desc = option->desc;
item->value = option->value;
// TODO: these need to be uppercased so we'll want to copy instead of reference or do it at the source?
item->values = option->labels;
}
}
Menu_options(&options_frontend_menu);
return MENU_CALLBACK_NOP;
}
static int options_emulator_change(MenuList* list, int i) {
MenuItem* item = &list->items[i];
@ -2560,7 +2694,6 @@ static int options_emulator_change(MenuList* list, int i) {
);
Options_setOptionRawValue(item->key, item->value);
}
static MenuList options_emulator_menu = {
.type = MENU_FIXED,
.on_change = options_emulator_change,
@ -2573,8 +2706,10 @@ static int options_emulator_confirm(MenuList* list, int i) {
for (int j=0; j<options.count; j++) {
Option* option = &options.items[j];
MenuItem* item = &options_emulator_menu.items[j];
item->name = option->name;
item->key = option->key;
item->name = option->name;
item->desc = NULL; // gambatte crashes if this isn't set to NULL :thinking_face:
// item->desc = option->desc; // TODO: these need to be copyfit/truncated
item->value = option->value;
// TODO: these need to be uppercased so we'll want to copy instead of reference
item->values = option->labels;
@ -2632,7 +2767,7 @@ static MenuList options_save_menu = {
static MenuList options_menu = {
.type = MENU_LIST,
.items = (MenuItem[]){
{"Frontend", "MinUI / " BUILD_DATE " / " COMMIT_HASH,.submenu=&options_frontend_menu}, // TODO: build submenu from frontend options
{"Frontend", "MinUI (" BUILD_DATE " " COMMIT_HASH ")",.on_confirm=options_frontend_confirm}, // TODO: build submenu from frontend options
{"Emulator",.on_confirm=options_emulator_confirm}, // TODO: build submenu from core options
{"Controls",.submenu=&options_controls_menu}, // TODO: build submenu from core buttons using callback then open the submenu manually
{"Shortcuts",.submenu=&options_shortcuts_menu},
@ -3046,6 +3181,13 @@ int main(int argc , char* argv[]) {
Core_open(core_path, tag_name);
Core_init();
// TODO: find a better place to do this, mixing static and loaded data is messy
// char core_desc[MAX_PATH];
// sprintf(core_desc, "%s / %s", core.tag, core.version);
// options_menu.items[1].desc = core_desc;
options_menu.items[1].desc = (char*)core.version;
Game_open(rom_path);
Core_load();
SND_init(core.sample_rate, core.fps);

View file

@ -4,7 +4,7 @@
typedef struct OptionOverride {
char* key;
char* value;
int disable; // hides from user
int disable; // TODO: hide option from user
} OptionOverride;
typedef struct ButtonMapping {
@ -13,9 +13,8 @@ typedef struct ButtonMapping {
int local;
} ButtonMapping;
// TODO: not strictly overrides anymore...
typedef struct CoreOverrides {
char* core_name;
char* core_name; // cannot be NULL
OptionOverride* option_overrides;
ButtonMapping* button_mapping;
} CoreOverrides;

View file

@ -3,6 +3,8 @@
static CoreOverrides pokemini_overrides = {
.core_name = "pokemini",
.option_overrides = (OptionOverride[]){
{"pokemini_video_scale", "6x",1},
{"pokemini_60hz_mode", "enabled",1},
{"pokemini_palette", "Old"},
{"pokemini_piezofilter", "disabled"},
{"pokemini_lowpass_filter", "enabled"},