mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-02 14:52:52 +02:00
File associations & icons on Windows, use a manifest for themed dialogs
This commit is contained in:
3
Makefile
3
Makefile
@@ -263,7 +263,8 @@ endif
|
|||||||
|
|
||||||
ifeq ($(PLATFORM),windows32)
|
ifeq ($(PLATFORM),windows32)
|
||||||
CFLAGS += -IWindows -Drandom=rand --target=x86_64-pc-windows
|
CFLAGS += -IWindows -Drandom=rand --target=x86_64-pc-windows
|
||||||
LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lshell32 -lole32 -lSDL2main -Wl,/MANIFESTFILE:NUL --target=x86_64-pc-windows
|
LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lshell32 -lole32 -ladvapi32 -lSDL2main -Wl,/MANIFESTFILE:NUL --target=x86_64-pc-windows
|
||||||
|
|
||||||
SDL_LDFLAGS := -lSDL2
|
SDL_LDFLAGS := -lSDL2
|
||||||
GL_LDFLAGS := -lopengl32
|
GL_LDFLAGS := -lopengl32
|
||||||
ifneq ($(REDIST_XAUDIO),)
|
ifneq ($(REDIST_XAUDIO),)
|
||||||
|
@@ -143,7 +143,6 @@ typedef struct {
|
|||||||
bool osd;
|
bool osd;
|
||||||
|
|
||||||
struct __attribute__((packed, aligned(4))) {
|
struct __attribute__((packed, aligned(4))) {
|
||||||
|
|
||||||
/* v0.15 */
|
/* v0.15 */
|
||||||
bool allow_mouse_controls;
|
bool allow_mouse_controls;
|
||||||
uint8_t cgb_revision;
|
uint8_t cgb_revision;
|
||||||
@@ -155,6 +154,9 @@ typedef struct {
|
|||||||
char dmg_palette_name[25];
|
char dmg_palette_name[25];
|
||||||
hotkey_action_t hotkey_actions[2];
|
hotkey_action_t hotkey_actions[2];
|
||||||
uint16_t agb_revision;
|
uint16_t agb_revision;
|
||||||
|
|
||||||
|
/* v1.0 */
|
||||||
|
bool windows_associations_prompted; // Windows only
|
||||||
};
|
};
|
||||||
} configuration_t;
|
} configuration_t;
|
||||||
|
|
||||||
|
29
SDL/gui.c
29
SDL/gui.c
@@ -11,6 +11,10 @@
|
|||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <associations.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static const SDL_Color gui_palette[4] = {{8, 24, 16,}, {57, 97, 57,}, {132, 165, 99}, {198, 222, 140}};
|
static const SDL_Color gui_palette[4] = {{8, 24, 16,}, {57, 97, 57,}, {132, 165, 99}, {198, 222, 140}};
|
||||||
static uint32_t gui_palette_native[4];
|
static uint32_t gui_palette_native[4];
|
||||||
|
|
||||||
@@ -399,15 +403,38 @@ static void return_to_root_menu(unsigned index)
|
|||||||
recalculate_menu_height();
|
recalculate_menu_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct menu_item options_menu[] = {
|
#ifdef _WIN32
|
||||||
|
static void associate_rom_files(unsigned index);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
#ifndef _WIN32
|
||||||
|
const
|
||||||
|
#endif
|
||||||
|
struct menu_item options_menu[] = {
|
||||||
{"Emulation Options", enter_emulation_menu},
|
{"Emulation Options", enter_emulation_menu},
|
||||||
{"Graphic Options", enter_graphics_menu},
|
{"Graphic Options", enter_graphics_menu},
|
||||||
{"Audio Options", enter_audio_menu},
|
{"Audio Options", enter_audio_menu},
|
||||||
{"Control Options", enter_controls_menu},
|
{"Control Options", enter_controls_menu},
|
||||||
|
#ifdef _WIN32
|
||||||
|
{"Associate ROM Files", associate_rom_files},
|
||||||
|
#endif
|
||||||
{"Back", return_to_root_menu},
|
{"Back", return_to_root_menu},
|
||||||
{NULL,}
|
{NULL,}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static void associate_rom_files(unsigned index)
|
||||||
|
{
|
||||||
|
if (GB_do_windows_association()) {
|
||||||
|
options_menu[index].string = "ROM Files Associated";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
options_menu[index].string = "Files Association Failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void enter_options_menu(unsigned index)
|
static void enter_options_menu(unsigned index)
|
||||||
{
|
{
|
||||||
current_menu = options_menu;
|
current_menu = options_menu;
|
||||||
|
31
SDL/main.c
31
SDL/main.c
@@ -18,6 +18,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#else
|
#else
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <associations.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool stop_on_start = false;
|
static bool stop_on_start = false;
|
||||||
@@ -1253,6 +1254,36 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
update_viewport();
|
update_viewport();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!configuration.windows_associations_prompted) {
|
||||||
|
configuration.windows_associations_prompted = true;
|
||||||
|
save_configuration();
|
||||||
|
SDL_MessageBoxButtonData buttons[2] = {
|
||||||
|
{
|
||||||
|
.flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
|
||||||
|
.buttonid = 0,
|
||||||
|
.text = "No",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
|
||||||
|
.buttonid = 1,
|
||||||
|
.text = "Yes",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
SDL_MessageBoxData box = {
|
||||||
|
.title = "Associate SameBoy with Game Boy ROMs",
|
||||||
|
.message = "Would you like to associate SameBoy with Game Boy ROMs?\nThis can be also done later in the Options menu.",
|
||||||
|
.numbuttons = 2,
|
||||||
|
.buttons = buttons,
|
||||||
|
};
|
||||||
|
int button;
|
||||||
|
SDL_ShowMessageBox(&box, &button);
|
||||||
|
if (button) {
|
||||||
|
GB_do_windows_association();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
stop_on_start = false;
|
stop_on_start = false;
|
||||||
run_gui(false);
|
run_gui(false);
|
||||||
|
BIN
Windows/Cartridge.ico
Normal file
BIN
Windows/Cartridge.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 234 KiB |
BIN
Windows/ColorCartridge.ico
Normal file
BIN
Windows/ColorCartridge.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
90
Windows/associations.c
Executable file
90
Windows/associations.c
Executable file
@@ -0,0 +1,90 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "associations.h"
|
||||||
|
|
||||||
|
static bool set_registry_string(HKEY hive, const char *folder, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
HKEY hkey;
|
||||||
|
LONG status = RegCreateKeyExA(hive, folder, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
|
||||||
|
if (status != ERROR_SUCCESS || hkey == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
status = RegSetValueExA(hkey, name, 0, REG_SZ, (void *)value, strlen(value) + 1);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
return status == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool delete_registry_key(HKEY hive, const char *folder, const char *name)
|
||||||
|
{
|
||||||
|
HKEY hkey;
|
||||||
|
LONG status = RegCreateKeyExA(hive, folder, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
|
||||||
|
if (status != ERROR_SUCCESS || hkey == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
status = RegDeleteTreeA(hkey, name);
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
return status == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool set_registry_string_unicode(HKEY hive, const char *folder, const char *name, const wchar_t *value)
|
||||||
|
{
|
||||||
|
HKEY hkey;
|
||||||
|
LONG status = RegCreateKeyExA(hive, folder, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
|
||||||
|
if (status != ERROR_SUCCESS || hkey == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t wide_name[strlen(name) + 1];
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_name, sizeof(wide_name) / sizeof(wide_name[0]));
|
||||||
|
status = RegSetValueExW(hkey, wide_name, 0, REG_SZ, (void *)value, (wcslen(value) + 1) * 2);
|
||||||
|
|
||||||
|
RegCloseKey(hkey);
|
||||||
|
return status == ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool associate(const char *extension, const char *class, const char *description, signed icon)
|
||||||
|
{
|
||||||
|
char path[128] = "Software\\Classes\\";
|
||||||
|
strcat(path, extension);
|
||||||
|
if (!set_registry_string(HKEY_CURRENT_USER, path, "", class)) return false;
|
||||||
|
|
||||||
|
strcpy(path, "Software\\Classes\\");
|
||||||
|
strcat(path, class);
|
||||||
|
if (!set_registry_string(HKEY_CURRENT_USER, path, "", description)) return false;
|
||||||
|
|
||||||
|
strcat(path, "\\shell\\open\\command");
|
||||||
|
|
||||||
|
wchar_t exe[MAX_PATH];
|
||||||
|
GetModuleFileNameW(NULL, exe, MAX_PATH);
|
||||||
|
|
||||||
|
wchar_t temp[sizeof(exe) + 32];
|
||||||
|
wsprintfW(temp, L"\"\%s\" \"%%1\"", exe);
|
||||||
|
if (!set_registry_string_unicode(HKEY_CURRENT_USER, path, "", temp)) return false;
|
||||||
|
|
||||||
|
strcpy(path, "Software\\Classes\\");
|
||||||
|
strcat(path, class);
|
||||||
|
strcat(path, "\\DefaultIcon");
|
||||||
|
|
||||||
|
wsprintfW(temp, L"\%s,%d", exe, icon);
|
||||||
|
if (!set_registry_string_unicode(HKEY_CURRENT_USER, path, "", temp)) return false;
|
||||||
|
|
||||||
|
strcpy(path, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\");
|
||||||
|
strcat(path, extension);
|
||||||
|
delete_registry_key(HKEY_CURRENT_USER, path, "UserChoice"); // Might not exist, do not check return value
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GB_do_windows_association(void)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
ret &= associate(".gb", "SameBoy.gb", "Game Boy Game", 1);
|
||||||
|
ret &= associate(".gbc", "SameBoy.gbc", "Game Boy Color Game", 2);
|
||||||
|
ret &= associate(".isx", "SameBoy.isx", "Game Boy ISX File", 2);
|
||||||
|
|
||||||
|
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
2
Windows/associations.h
Executable file
2
Windows/associations.h
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#include <stdbool.h>
|
||||||
|
bool GB_do_windows_association(void);
|
22
Windows/manifest.xml
Normal file
22
Windows/manifest.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity
|
||||||
|
version="1.0.0.0"
|
||||||
|
processorArchitecture="*"
|
||||||
|
name="com.github.liji32.sameboy.windows"
|
||||||
|
type="win32"
|
||||||
|
/>
|
||||||
|
<description>SameBoy</description>
|
||||||
|
<dependency>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity
|
||||||
|
type="win32"
|
||||||
|
name="Microsoft.Windows.Common-Controls"
|
||||||
|
version="6.0.0.0"
|
||||||
|
processorArchitecture="*"
|
||||||
|
publicKeyToken="6595b64144ccf1df"
|
||||||
|
language="*"
|
||||||
|
/>
|
||||||
|
</dependentAssembly>
|
||||||
|
</dependency>
|
||||||
|
</assembly>
|
Binary file not shown.
Reference in New Issue
Block a user