Added open dialog to the SDL GUI, misc fixes

This commit is contained in:
Lior Halphon 2019-06-01 14:29:46 +03:00
parent f9cc7a3b46
commit cdc36f329e
10 changed files with 227 additions and 29 deletions

View File

@ -82,9 +82,9 @@ Start:
.sendCommand .sendCommand
xor a xor a
ldh [c], a ld [c], a
ld a, $30 ld a, $30
ldh [c], a ld [c], a
ldh a, [$80] ldh a, [$80]
call SendByte call SendByte
@ -112,9 +112,9 @@ Start:
; Done bit ; Done bit
ld a, $20 ld a, $20
ldh [c], a ld [c], a
ld a, $30 ld a, $30
ldh [c], a ld [c], a
; Update command ; Update command
ldh a, [$80] ldh a, [$80]
@ -128,10 +128,10 @@ Start:
; Write to sound registers for DMG compatibility ; Write to sound registers for DMG compatibility
ld c, $13 ld c, $13
ld a, $c1 ld a, $c1
ldh [c], a ld [c], a
inc c inc c
ld a, 7 ld a, 7
ldh [c], a ld [c], a
; Init BG palette ; Init BG palette
ld a, $fc ld a, $fc
@ -168,9 +168,9 @@ SendByte:
jr c, .zeroBit jr c, .zeroBit
add a ; 10 -> 20 add a ; 10 -> 20
.zeroBit .zeroBit
ldh [c], a ld [c], a
ld a, $30 ld a, $30
ldh [c], a ld [c], a
dec d dec d
ret z ret z
jr .loop jr .loop

View File

@ -606,7 +606,7 @@ static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode)
cycle_write(gb, gb->registers[GB_REGISTER_HL], data); cycle_write(gb, gb->registers[GB_REGISTER_HL], data);
} }
uint8_t get_src_value(GB_gameboy_t *gb, uint8_t opcode) static uint8_t get_src_value(GB_gameboy_t *gb, uint8_t opcode)
{ {
uint8_t src_register_id; uint8_t src_register_id;
uint8_t src_low; uint8_t src_low;

View File

@ -65,14 +65,25 @@ endif
# Set compilation and linkage flags based on target, platform and configuration # Set compilation and linkage flags based on target, platform and configuration
OPEN_DIALOG = OpenDialog/gtk.c
ifeq ($(PLATFORM),windows32)
OPEN_DIALOG = OpenDialog/windows.c
endif
ifeq ($(PLATFORM),Darwin)
OPEN_DIALOG = OpenDialog/cocoa.m
endif
CFLAGS += -Werror -Wall -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES CFLAGS += -Werror -Wall -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES
SDL_LDFLAGS := -lSDL2 -lGL SDL_LDFLAGS := -lSDL2 -lGL
ifeq ($(PLATFORM),windows32) ifeq ($(PLATFORM),windows32)
CFLAGS += -IWindows CFLAGS += -IWindows -Drandom=rand
LDFLAGS += -lmsvcrt -lSDL2main -Wl,/MANIFESTFILE:NUL LDFLAGS += -lmsvcrt -lcomdlg32 -lSDL2main -Wl,/MANIFESTFILE:NUL
SDL_LDFLAGS := -lSDL2 -lopengl32 SDL_LDFLAGS := -lSDL2 -lopengl32
else else
LDFLAGS += -lc -lm LDFLAGS += -lc -lm -ldl
endif endif
ifeq ($(PLATFORM),Darwin) ifeq ($(PLATFORM),Darwin)
@ -120,7 +131,7 @@ all: cocoa sdl tester libretro
# Get a list of our source files and their respective object file targets # Get a list of our source files and their respective object file targets
CORE_SOURCES := $(shell ls Core/*.c) CORE_SOURCES := $(shell ls Core/*.c)
SDL_SOURCES := $(shell ls SDL/*.c) SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG)
TESTER_SOURCES := $(shell ls Tester/*.c) TESTER_SOURCES := $(shell ls Tester/*.c)
ifeq ($(PLATFORM),Darwin) ifeq ($(PLATFORM),Darwin)

20
OpenDialog/cocoa.m Normal file
View File

@ -0,0 +1,20 @@
#import <AppKit/AppKit.h>
#include "open_dialog.h"
char *do_open_rom_dialog(void)
{
@autoreleasepool {
NSWindow *key = [NSApp keyWindow];
NSOpenPanel *dialog = [NSOpenPanel openPanel];
dialog.title = @"Open ROM";
dialog.allowedFileTypes = @[@"gb", @"gbc", @"sgb"];
[dialog runModal];
[key makeKeyAndOrderFront:nil];
NSString *ret = [[[dialog URLs] firstObject] path];
if (ret) {
return strdup(ret.UTF8String);
}
return NULL;
}
}

96
OpenDialog/gtk.c Normal file
View File

@ -0,0 +1,96 @@
#include "open_dialog.h"
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdbool.h>
#include <string.h>
#define GTK_FILE_CHOOSER_ACTION_OPEN 0
void *_gtk_file_chooser_dialog_new (const char *title,
void *parent,
int action,
const char *first_button_text,
...);
bool _gtk_init_check (int *argc, char ***argv);
int _gtk_dialog_run(void *);
void _g_free(void *);
void _g_object_unref(void *);
char *_gtk_file_chooser_get_filename(void *);
void _g_log_set_default_handler (void *function, void *data);
void *_gtk_file_filter_new(void);
void _gtk_file_filter_add_pattern(void *filter, const char *pattern);
void _gtk_file_filter_set_name(void *filter, const char *name);
void _gtk_file_chooser_add_filter(void *dialog, void *filter);
#define LAZY(symbol) static typeof(_##symbol) *symbol = NULL;\
if (symbol == NULL) symbol = dlsym(handle, #symbol);\
if (symbol == NULL) goto lazy_error
#define TRY_DLOPEN(name) handle = handle? handle : dlopen(name, RTLD_NOW)
void nop(){}
char *do_open_rom_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(g_object_unref);
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);
/* Shut up GTK */
g_log_set_default_handler(nop, NULL);
gtk_init_check(0, 0);
void *dialog = gtk_file_chooser_dialog_new("Open ROM",
0,
GTK_FILE_CHOOSER_ACTION_OPEN,
"Open", 0, NULL);
void *filter = gtk_file_filter_new();
gtk_file_filter_add_pattern(filter, "*.gb");
gtk_file_filter_add_pattern(filter, "*.gbc");
gtk_file_filter_add_pattern(filter, "*.sgb");
gtk_file_filter_set_name(filter, "Game Boy ROMs");
gtk_file_chooser_add_filter(dialog, filter);
int res = gtk_dialog_run (dialog);
char *ret = NULL;
if (res == 0)
{
char *filename;
filename = gtk_file_chooser_get_filename(dialog);
ret = strdup(filename);
g_free(filename);
}
g_object_unref(dialog);
return ret;
lazy_error:
fprintf(stderr, "Failed to display GTK dialog\n");
return NULL;
}

6
OpenDialog/open_dialog.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef open_rom_h
#define open_rom_h
char *do_open_rom_dialog(void);
#endif /* open_rom_h */

28
OpenDialog/windows.c Normal file
View File

@ -0,0 +1,28 @@
#include <windows.h>
#include "open_dialog.h"
char *do_open_rom_dialog(void)
{
OPENFILENAMEW dialog;
wchar_t filename[MAX_PATH] = {0};
memset(&dialog, 0, sizeof(dialog));
dialog.lStructSize = sizeof(dialog);
dialog.lpstrFile = filename;
dialog.nMaxFile = sizeof(filename);
dialog.lpstrFilter = L"Game Boy ROMs\0*.gb;*.gbc;*.sgb\0All files\0*.*\0\0";
dialog.nFilterIndex = 1;
dialog.lpstrFileTitle = NULL;
dialog.nMaxFileTitle = 0;
dialog.lpstrInitialDir = NULL;
dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileNameW(&dialog) == TRUE)
{
char *ret = malloc(MAX_PATH * 4);
WideCharToMultiByte(CP_UTF8, 0, filename, sizeof(filename), ret, MAX_PATH * 4, NULL, NULL);
return ret;
}
return NULL;
}

View File

@ -1,4 +1,5 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <OpenDialog/open_dialog.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -97,11 +98,11 @@ configuration_t configuration =
static const char *help[] ={ static const char *help[] ={
"Drop a GB or GBC ROM\n" "Drop a ROM to play.\n"
"file to play.\n"
"\n" "\n"
"Keyboard Shortcuts:\n" "Keyboard Shortcuts:\n"
" Open Menu: Escape\n" " Open Menu: Escape\n"
" Open ROM: " MODIFIER_NAME "+O\n"
" Reset: " MODIFIER_NAME "+R\n" " Reset: " MODIFIER_NAME "+R\n"
" Pause: " MODIFIER_NAME "+P\n" " Pause: " MODIFIER_NAME "+P\n"
" Save state: " MODIFIER_NAME "+(0-9)\n" " Save state: " MODIFIER_NAME "+(0-9)\n"
@ -267,8 +268,19 @@ static void enter_controls_menu(unsigned index);
static void enter_joypad_menu(unsigned index); static void enter_joypad_menu(unsigned index);
static void enter_audio_menu(unsigned index); static void enter_audio_menu(unsigned index);
extern void set_filename(const char *new_filename, typeof(free) *new_free_function);
static void open_rom(unsigned index)
{
char *filename = do_open_rom_dialog();
if (filename) {
set_filename(filename, free);
pending_command = GB_SDL_NEW_FILE_COMMAND;
}
}
static const struct menu_item paused_menu[] = { static const struct menu_item paused_menu[] = {
{"Resume", NULL}, {"Resume", NULL},
{"Open ROM", open_rom},
{"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},
@ -778,7 +790,6 @@ void connect_joypad(void)
} }
} }
extern void set_filename(const char *new_filename, bool new_should_free);
void run_gui(bool is_running) void run_gui(bool is_running)
{ {
connect_joypad(); connect_joypad();
@ -818,6 +829,9 @@ void run_gui(bool is_running)
/* Convert Joypad and mouse events (We only generate down events) */ /* Convert Joypad and mouse events (We only generate down events) */
if (gui_state != WAITING_FOR_KEY && gui_state != WAITING_FOR_JBUTTON) { if (gui_state != WAITING_FOR_KEY && gui_state != WAITING_FOR_JBUTTON) {
switch (event.type) { switch (event.type) {
case SDL_WINDOWEVENT:
should_render = true;
break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
if (gui_state == SHOWING_HELP) { if (gui_state == SHOWING_HELP) {
event.type = SDL_KEYDOWN; event.type = SDL_KEYDOWN;
@ -957,7 +971,7 @@ void run_gui(bool is_running)
break; break;
} }
case SDL_DROPFILE: { case SDL_DROPFILE: {
set_filename(event.drop.file, true); set_filename(event.drop.file, SDL_free);
pending_command = GB_SDL_NEW_FILE_COMMAND; pending_command = GB_SDL_NEW_FILE_COMMAND;
return; return;
} }
@ -995,7 +1009,17 @@ void run_gui(bool is_running)
} }
case SDL_KEYDOWN: case SDL_KEYDOWN:
if (event.key.keysym.scancode == SDL_SCANCODE_RETURN && gui_state == WAITING_FOR_JBUTTON) { if (event.key.keysym.scancode == SDL_SCANCODE_O) {
if (event.key.keysym.mod & MODIFIER) {
char *filename = do_open_rom_dialog();
if (filename) {
set_filename(filename, free);
pending_command = GB_SDL_NEW_FILE_COMMAND;
return;
}
}
}
else if (event.key.keysym.scancode == SDL_SCANCODE_RETURN && gui_state == WAITING_FOR_JBUTTON) {
should_render = true; should_render = true;
if (joypad_configuration_progress != JOYPAD_BUTTONS_MAX) { if (joypad_configuration_progress != JOYPAD_BUTTONS_MAX) {
configuration.joypad_configuration[joypad_configuration_progress] = -1; configuration.joypad_configuration[joypad_configuration_progress] = -1;

View File

@ -9,6 +9,12 @@
#define JOYSTICK_HIGH 0x4000 #define JOYSTICK_HIGH 0x4000
#define JOYSTICK_LOW 0x3800 #define JOYSTICK_LOW 0x3800
#ifdef __APPLE__
#define MODIFIER KMOD_GUI
#else
#define MODIFIER KMOD_CTRL
#endif
extern GB_gameboy_t gb; extern GB_gameboy_t gb;
extern SDL_Window *window; extern SDL_Window *window;

View File

@ -1,6 +1,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include <OpenDialog/open_dialog.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <Core/gb.h> #include <Core/gb.h>
#include "utils.h" #include "utils.h"
@ -30,18 +31,18 @@ static bool underclock_down = false, rewind_down = false, do_rewind = false, rew
static double clock_mutliplier = 1.0; static double clock_mutliplier = 1.0;
static char *filename = NULL; static char *filename = NULL;
static bool should_free_filename = false; static typeof(free) *free_function = NULL;
static char *battery_save_path_ptr; static char *battery_save_path_ptr;
SDL_AudioDeviceID device_id; SDL_AudioDeviceID device_id;
void set_filename(const char *new_filename, bool new_should_free) void set_filename(const char *new_filename, typeof(free) *new_free_function)
{ {
if (filename && should_free_filename) { if (filename && free_function) {
SDL_free(filename); free_function(filename);
} }
filename = (char *) new_filename; filename = (char *) new_filename;
should_free_filename = new_should_free; free_function = new_free_function;
} }
static SDL_AudioSpec want_aspec, have_aspec; static SDL_AudioSpec want_aspec, have_aspec;
@ -101,11 +102,6 @@ static void open_menu(void)
static void handle_events(GB_gameboy_t *gb) static void handle_events(GB_gameboy_t *gb)
{ {
#ifdef __APPLE__
#define MODIFIER KMOD_GUI
#else
#define MODIFIER KMOD_CTRL
#endif
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
@ -115,7 +111,7 @@ static void handle_events(GB_gameboy_t *gb)
break; break;
case SDL_DROPFILE: { case SDL_DROPFILE: {
set_filename(event.drop.file, true); set_filename(event.drop.file, SDL_free);
pending_command = GB_SDL_NEW_FILE_COMMAND; pending_command = GB_SDL_NEW_FILE_COMMAND;
break; break;
} }
@ -227,6 +223,17 @@ static void handle_events(GB_gameboy_t *gb)
} }
break; break;
case SDL_SCANCODE_O: {
if (event.key.keysym.mod & MODIFIER) {
char *filename = do_open_rom_dialog();
if (filename) {
set_filename(filename, free);
pending_command = GB_SDL_NEW_FILE_COMMAND;
}
}
break;
}
case SDL_SCANCODE_P: case SDL_SCANCODE_P:
if (event.key.keysym.mod & MODIFIER) { if (event.key.keysym.mod & MODIFIER) {
paused = !paused; paused = !paused;