Let the SDL port choose a boot ROMs folder

This commit is contained in:
Lior Halphon 2020-12-26 15:10:11 +02:00
parent e1f797c212
commit 7fc59b5cf4
10 changed files with 197 additions and 8 deletions

View File

@ -130,7 +130,7 @@ GL_LDFLAGS := $(shell $(PKG_CONFIG) --libs gl || echo -lGL)
endif endif
ifeq ($(PLATFORM),windows32) ifeq ($(PLATFORM),windows32)
CFLAGS += -IWindows -Drandom=rand --target=i386-pc-windows CFLAGS += -IWindows -Drandom=rand --target=i386-pc-windows
LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lshell32 -lSDL2main -Wl,/MANIFESTFILE:NUL --target=i386-pc-windows LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lshell32 -lole32 -lSDL2main -Wl,/MANIFESTFILE:NUL --target=i386-pc-windows
SDL_LDFLAGS := -lSDL2 SDL_LDFLAGS := -lSDL2
GL_LDFLAGS := -lopengl32 GL_LDFLAGS := -lopengl32
else else

View File

@ -18,3 +18,21 @@ char *do_open_rom_dialog(void)
return NULL; return NULL;
} }
} }
char *do_open_folder_dialog(void)
{
@autoreleasepool {
NSWindow *key = [NSApp keyWindow];
NSOpenPanel *dialog = [NSOpenPanel openPanel];
dialog.title = @"Select Boot ROMs Folder";
dialog.canChooseDirectories = true;
dialog.canChooseFiles = false;
[dialog runModal];
[key makeKeyAndOrderFront:nil];
NSString *ret = [[[dialog URLs] firstObject] path];
if (ret) {
return strdup(ret.UTF8String);
}
return NULL;
}
}

View File

@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
#define GTK_FILE_CHOOSER_ACTION_OPEN 0 #define GTK_FILE_CHOOSER_ACTION_OPEN 0
#define GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER 2
#define GTK_RESPONSE_ACCEPT -3 #define GTK_RESPONSE_ACCEPT -3
#define GTK_RESPONSE_CANCEL -6 #define GTK_RESPONSE_CANCEL -6
@ -111,3 +112,71 @@ lazy_error:
fprintf(stderr, "Failed to display GTK dialog\n"); fprintf(stderr, "Failed to display GTK dialog\n");
return NULL; return NULL;
} }
char *do_open_folder_dialog(void)
{
static void *handle = NULL;
TRY_DLOPEN("libgtk-3.so");
TRY_DLOPEN("libgtk-3.so.0");
TRY_DLOPEN("libgtk-2.so");
TRY_DLOPEN("libgtk-2.so.0");
if (!handle) {
goto lazy_error;
}
LAZY(gtk_init_check);
LAZY(gtk_file_chooser_dialog_new);
LAZY(gtk_dialog_run);
LAZY(g_free);
LAZY(gtk_widget_destroy);
LAZY(gtk_file_chooser_get_filename);
LAZY(g_log_set_default_handler);
LAZY(gtk_file_filter_new);
LAZY(gtk_file_filter_add_pattern);
LAZY(gtk_file_filter_set_name);
LAZY(gtk_file_chooser_add_filter);
LAZY(gtk_events_pending);
LAZY(gtk_main_iteration);
/* Shut up GTK */
g_log_set_default_handler(nop, NULL);
gtk_init_check(0, 0);
void *dialog = gtk_file_chooser_dialog_new("Select Boot ROMs Folder",
0,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL );
int res = gtk_dialog_run (dialog);
char *ret = NULL;
if (res == GTK_RESPONSE_ACCEPT) {
char *filename;
filename = gtk_file_chooser_get_filename(dialog);
ret = strdup(filename);
g_free(filename);
}
while (gtk_events_pending()) {
gtk_main_iteration();
}
gtk_widget_destroy(dialog);
while (gtk_events_pending()) {
gtk_main_iteration();
}
return ret;
lazy_error:
fprintf(stderr, "Failed to display GTK dialog\n");
return NULL;
}

View File

@ -2,5 +2,5 @@
#define open_rom_h #define open_rom_h
char *do_open_rom_dialog(void); char *do_open_rom_dialog(void);
char *do_open_folder_dialog(void);
#endif /* open_rom_h */ #endif /* open_rom_h */

View File

@ -1,10 +1,11 @@
#include <windows.h> #include <windows.h>
#include <shlobj.h>
#include "open_dialog.h" #include "open_dialog.h"
char *do_open_rom_dialog(void) char *do_open_rom_dialog(void)
{ {
OPENFILENAMEW dialog; OPENFILENAMEW dialog;
wchar_t filename[MAX_PATH] = {0}; static wchar_t filename[MAX_PATH] = {0};
memset(&dialog, 0, sizeof(dialog)); memset(&dialog, 0, sizeof(dialog));
dialog.lStructSize = sizeof(dialog); dialog.lStructSize = sizeof(dialog);
@ -25,3 +26,32 @@ char *do_open_rom_dialog(void)
return NULL; return NULL;
} }
char *do_open_folder_dialog(void)
{
BROWSEINFOW dialog;
memset(&dialog, 0, sizeof(dialog));
dialog.ulFlags = BIF_USENEWUI;
dialog.lpszTitle = L"Select Boot ROMs Folder";
OleInitialize(NULL);
LPITEMIDLIST list = SHBrowseForFolderW(&dialog);
static wchar_t filename[MAX_PATH] = {0};
if (list) {
if (!SHGetPathFromIDListW(list, filename)) {
OleUninitialize();
return NULL;
}
char *ret = malloc(MAX_PATH * 4);
WideCharToMultiByte(CP_UTF8, 0, filename, sizeof(filename), ret, MAX_PATH * 4, NULL, NULL);
CoTaskMemFree(list);
OleUninitialize();
return ret;
}
OleUninitialize();
return NULL;
}

View File

@ -1033,6 +1033,26 @@ uint8_t font[] = {
_, _, _, X, X, _, _, _, _, X, X, _,
_, _, _, _, X, _, _, _, _, _, X, _,
_, _, _, _, _, _, _, _, _, _, _, _,
/* Elipsis */
_, _, _, _, _, _,
_, _, _, _, _, _,
_, _, _, _, _, _,
_, _, _, _, _, _,
_, _, _, _, _, _,
_, _, _, _, _, _,
X, _, X, _, X, _,
_, _, _, _, _, _,
/* Mojibake */
X, X, X, X, X, _,
X, _, _, _, X, _,
X, _, _, _, X, _,
X, _, _, _, X, _,
X, _, _, _, X, _,
X, _, _, _, X, _,
X, _, _, _, X, _,
X, X, X, X, X, _,
}; };
const uint8_t font_max = sizeof(font) / GLYPH_HEIGHT / GLYPH_WIDTH + ' '; const uint8_t font_max = sizeof(font) / GLYPH_HEIGHT / GLYPH_WIDTH + ' ';

View File

@ -12,5 +12,7 @@ extern const uint8_t font_max;
#define CTRL_STRING "\x80\x81\x82" #define CTRL_STRING "\x80\x81\x82"
#define SHIFT_STRING "\x83" #define SHIFT_STRING "\x83"
#define CMD_STRING "\x84\x85" #define CMD_STRING "\x84\x85"
#define ELLIPSIS_STRING "\x87"
#define MOJIBAKE_STRING "\x88"
#endif /* font_h */ #endif /* font_h */

View File

@ -442,9 +442,50 @@ const char *current_rewind_string(unsigned index)
return "Custom"; return "Custom";
} }
const char *current_bootrom_string(unsigned index)
{
if (!configuration.bootrom_path[0]) {
return "Built-in Boot ROMs";
}
size_t length = strlen(configuration.bootrom_path);
static char ret[24] = {0,};
if (length <= 23) {
strcpy(ret, configuration.bootrom_path);
}
else {
memcpy(ret, configuration.bootrom_path, 11);
memcpy(ret + 12, configuration.bootrom_path + length - 11, 11);
}
for (unsigned i = 0; i < 24; i++) {
if (ret[i] < 0) {
ret[i] = MOJIBAKE_STRING[0];
}
}
if (length > 23) {
ret[11] = ELLIPSIS_STRING[0];
}
return ret;
}
static void toggle_bootrom(unsigned index)
{
if (configuration.bootrom_path[0]) {
configuration.bootrom_path[0] = 0;
}
else {
char *folder = do_open_folder_dialog();
if (!folder) return;
if (strlen(folder) < sizeof(configuration.bootrom_path) - 1) {
strcpy(configuration.bootrom_path, folder);
}
free(folder);
}
}
static const struct menu_item emulation_menu[] = { static const struct menu_item emulation_menu[] = {
{"Emulated Model:", cycle_model, current_model_string, cycle_model_backwards}, {"Emulated Model:", cycle_model, current_model_string, cycle_model_backwards},
{"SGB Revision:", cycle_sgb_revision, current_sgb_revision_string, cycle_sgb_revision_backwards}, {"SGB Revision:", cycle_sgb_revision, current_sgb_revision_string, cycle_sgb_revision_backwards},
{"Boot ROMs Folder:", toggle_bootrom, current_bootrom_string, toggle_bootrom},
{"Rewind Length:", cycle_rewind, current_rewind_string, cycle_rewind_backwards}, {"Rewind Length:", cycle_rewind, current_rewind_string, cycle_rewind_backwards},
{"Back", return_to_root_menu}, {"Back", return_to_root_menu},
{NULL,} {NULL,}
@ -883,7 +924,7 @@ const char *current_joypad_name(unsigned index)
// SDL returns a name with repeated and trailing spaces // SDL returns a name with repeated and trailing spaces
while (*orig_name && i < sizeof(name) - 2) { while (*orig_name && i < sizeof(name) - 2) {
if (orig_name[0] != ' ' || orig_name[1] != ' ') { if (orig_name[0] != ' ' || orig_name[1] != ' ') {
name[i++] = *orig_name; name[i++] = *orig_name > 0? *orig_name : MOJIBAKE_STRING[0];
} }
orig_name++; orig_name++;
} }

View File

@ -114,6 +114,7 @@ typedef struct {
/* v0.14 */ /* v0.14 */
unsigned padding; unsigned padding;
uint8_t color_temperature; uint8_t color_temperature;
char bootrom_path[4096];
} configuration_t; } configuration_t;
extern configuration_t configuration; extern configuration_t configuration;

View File

@ -448,8 +448,6 @@ static bool handle_pending_command(void)
static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type) static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type)
{ {
bool error = false;
start_capturing_logs();
static const char *const names[] = { static const char *const names[] = {
[GB_BOOT_ROM_DMG0] = "dmg0_boot.bin", [GB_BOOT_ROM_DMG0] = "dmg0_boot.bin",
[GB_BOOT_ROM_DMG] = "dmg_boot.bin", [GB_BOOT_ROM_DMG] = "dmg_boot.bin",
@ -460,8 +458,17 @@ static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type)
[GB_BOOT_ROM_CGB] = "cgb_boot.bin", [GB_BOOT_ROM_CGB] = "cgb_boot.bin",
[GB_BOOT_ROM_AGB] = "agb_boot.bin", [GB_BOOT_ROM_AGB] = "agb_boot.bin",
}; };
bool use_built_in = true;
if (configuration.bootrom_path[0]) {
static char path[4096];
snprintf(path, sizeof(path), "%s/%s", configuration.bootrom_path, names[type]);
use_built_in = GB_load_boot_rom(gb, path);
}
if (use_built_in) {
start_capturing_logs();
GB_load_boot_rom(gb, resource_path(names[type])); GB_load_boot_rom(gb, resource_path(names[type]));
end_capturing_logs(true, error); end_capturing_logs(true, false);
}
} }
static void run(void) static void run(void)
@ -649,6 +656,7 @@ int main(int argc, char **argv)
configuration.border_mode %= GB_BORDER_ALWAYS + 1; configuration.border_mode %= GB_BORDER_ALWAYS + 1;
configuration.rumble_mode %= GB_RUMBLE_ALL_GAMES + 1; configuration.rumble_mode %= GB_RUMBLE_ALL_GAMES + 1;
configuration.color_temperature %= 21; configuration.color_temperature %= 21;
configuration.bootrom_path[sizeof(configuration.bootrom_path) - 1] = 0;
} }
if (configuration.model >= MODEL_MAX) { if (configuration.model >= MODEL_MAX) {