Gtk: Switch codebase to gtkmm.

GTK: Remove support for GTK+ 2.0.

GTK 3 is stable and widespread enough now.

GTK: Rearrange headers to eliminate gtk_s9xcore.h

Gtk: Initial gtkmm conversion work.

Gtk: More gtkmm conversion and bug fixing.

Gtk: More gtkmm fixes.

Gtk: More Fixes

OpenGL no longer creates a second window.
Accelerators are fixed.

Gtk: More fixes

Removed GLX context dependency on Gtk.

Gtk: Fix formatting.

Gtk: Remove a #pragma once
This commit is contained in:
Brandon Wright 2020-07-04 17:53:38 -05:00
parent 3c3ea985ef
commit e17ff69533
51 changed files with 3069 additions and 4720 deletions

View File

@ -23,12 +23,9 @@ args += [ '-DDATADIR="' + appdatadir + '"', '-DSNES9XLOCALEDIR="' + localedir +
subdir('data') subdir('data')
subdir('po') subdir('po')
glib_dep = dependency('glib-2.0', version: '> 2.28')
gthread_dep = dependency('gthread-2.0', version: '>= 2.6')
gobject_dep = dependency('gobject-2.0', version: '>= 2.6')
sdl2_dep = dependency('sdl2') sdl2_dep = dependency('sdl2')
deps += [ glib_dep, gthread_dep, gobject_dep, sdl2_dep ] deps += sdl2_dep
c_compiler = meson.get_compiler('c') c_compiler = meson.get_compiler('c')
@ -36,16 +33,7 @@ if c_compiler.version().version_compare('>=7.0.0') and c_compiler.get_id() == 'g
args += '-Wno-format-truncation' args += '-Wno-format-truncation'
endif endif
if get_option('gtk3') and not get_option('gtk2') gtk_dep = dependency('gtkmm-3.0', version: '>= 3.22')
message('Building with GTK+-3.0')
gtk_dep = dependency('gtk+-3.0', version: '>= 3.22')
gtk_ver = 3
else
message('Building with GTK+-2.0')
gtk_dep = dependency('gtk+-2.0', version: '>= 2.16')
gtk_ver = 2
endif
deps += gtk_dep deps += gtk_dep
x11_dep = c_compiler.find_library('X11') x11_dep = c_compiler.find_library('X11')
@ -125,7 +113,7 @@ if slang and opengl
endif endif
wayland = get_option('wayland') wayland = get_option('wayland')
if wayland and gtk_ver == 3 if wayland
wayland_dep = dependency('wayland-egl', required: false) wayland_dep = dependency('wayland-egl', required: false)
if wayland_dep.found() if wayland_dep.found()
@ -320,7 +308,7 @@ srcs += [
'../filter/snes_ntsc.h', '../filter/snes_ntsc.h',
'../filter/snes_ntsc_impl.h', '../filter/snes_ntsc_impl.h',
'../filter/snes_ntsc.c', '../filter/snes_ntsc.c',
'src/gtk_2_3_compat.h', 'src/gtk_compat.h',
'src/gtk_sound_driver_sdl.h', 'src/gtk_sound_driver_sdl.h',
'src/gtk_sound_driver_sdl.cpp', 'src/gtk_sound_driver_sdl.cpp',
'../fxinst.cpp', '../fxinst.cpp',
@ -405,7 +393,7 @@ libjma_srcs = [
libjma = static_library('jma', libjma = static_library('jma',
libjma_srcs, libjma_srcs,
c_args: args, c_args: args,
cpp_args: [args, '-fexceptions'], cpp_args: args,
include_directories: include_directories(includes)) include_directories: include_directories(includes))
sourcify = executable('sourcify', 'src/sourcify.c', native: true) sourcify = executable('sourcify', 'src/sourcify.c', native: true)
@ -418,7 +406,7 @@ snes9x_gtk = executable('snes9x-gtk',
srcs, srcs,
gtk_snes9x_ui_cpp, gtk_snes9x_ui_cpp,
c_args: args, c_args: args,
cpp_args: [args, '-fno-exceptions', '-fno-rtti'], cpp_args: args,
dependencies: deps, dependencies: deps,
include_directories: include_directories(includes), include_directories: include_directories(includes),
link_with: libjma, link_with: libjma,
@ -431,7 +419,6 @@ summary = [
' appdatadir: ' + appdatadir, ' appdatadir: ' + appdatadir,
' localedir: ' + localedir, ' localedir: ' + localedir,
'[Options] Build type: ' + get_option('buildtype'), '[Options] Build type: ' + get_option('buildtype'),
' GTK+ version: ' + gtk_ver.to_string(),
' Wayland: ' + wayland.to_string(), ' Wayland: ' + wayland.to_string(),
' OpenGL: ' + opengl.to_string(), ' OpenGL: ' + opengl.to_string(),
' slang shaders: ' + slang.to_string(), ' slang shaders: ' + slang.to_string(),

View File

@ -11,8 +11,6 @@ option('xbrz', type: 'boolean', value: true, description: 'Enable th
option('zlib', type: 'boolean', value: true, description: 'Enable gzip compression') option('zlib', type: 'boolean', value: true, description: 'Enable gzip compression')
option('system-zip', type: 'boolean', value: true, description: 'Build using system minizip library') option('system-zip', type: 'boolean', value: true, description: 'Build using system minizip library')
option('screenshot', type: 'boolean', value: true, description: 'Enable screenshots') option('screenshot', type: 'boolean', value: true, description: 'Enable screenshots')
option('gtk3', type: 'boolean', value: true, description: 'Build with GTK+ 3.0 as the toolkit')
option('wayland', type: 'boolean', value: true, description: 'Build support for Wayland') option('wayland', type: 'boolean', value: true, description: 'Build support for Wayland')
option('gtk2', type: 'boolean', value: false, description: 'Build with GTK+ 2.0 as the toolkit')
option('dangerous-hacks', type: 'boolean', value: false, description: 'Allow dangerous hacks to be enabled') option('dangerous-hacks', type: 'boolean', value: false, description: 'Allow dangerous hacks to be enabled')
option('appdatadir', type: 'string' , value: '', description: 'Snes9x-only data directory (default: datadir/snes9x)') option('appdatadir', type: 'string' , value: '', description: 'Snes9x-only data directory (default: datadir/snes9x)')

View File

@ -1,4 +1,5 @@
#pragma once #ifndef __BACKGROUND_PARTICLES_H
#define __BACKGROUND_PARTICLES_H
#include <vector> #include <vector>
#include <list> #include <list>
#include <cstdint> #include <cstdint>
@ -50,3 +51,4 @@ class Particles
}; };
} // namespace Background } // namespace Background
#endif // __BACKGROUND_PARTICLES_H

View File

@ -1,60 +0,0 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#ifndef __GTK_2_3_COMPAT_H
#define __GTK_2_3_COMPAT_H
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#if GTK_MAJOR_VERSION >= 3
#include <gdk/gdkkeysyms-compat.h>
#ifndef USE_WAYLAND
#undef GDK_WINDOWING_WAYLAND
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
#else // GTK+ 2.0
#define GDK_WINDOWING_X11
#define GDK_IS_X11_WINDOW(window) true
#define GDK_IS_X11_DISPLAY(display) true
#define gdk_x11_window_get_xid(window) GDK_WINDOW_XWINDOW (window)
inline void gdk_x11_display_error_trap_push(GdkDisplay *dpy)
{
gdk_error_trap_push();
}
inline void gdk_x11_display_error_trap_pop_ignored(GdkDisplay *dpy)
{
if (gdk_error_trap_pop())
{
}
}
inline void gdk_window_get_geometry (GdkWindow *window,
gint *x,
gint *y,
gint *width,
gint *height)
{
gdk_window_get_geometry (window, x, y, width, height, NULL);
}
#endif
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#endif

View File

@ -10,22 +10,22 @@
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_binding.h" #include "gtk_binding.h"
Binding::Binding () Binding::Binding()
{ {
value = 0; value = 0;
} }
Binding::Binding (GdkEventKey *event) Binding::Binding(GdkEventKey *event)
{ {
event->keyval = gdk_keyval_to_lower (event->keyval); event->keyval = gdk_keyval_to_lower(event->keyval);
value = BINDING_KEY | (event->keyval & BINDING_KEY_MASK); value = BINDING_KEY | (event->keyval & BINDING_KEY_MASK);
/* Strip modifiers from modifiers */ /* Strip modifiers from modifiers */
if (event->keyval == GDK_Control_L || if (event->keyval == GDK_Control_L ||
event->keyval == GDK_Control_R || event->keyval == GDK_Control_R ||
event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_L ||
event->keyval == GDK_Shift_R || event->keyval == GDK_Shift_R ||
event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_L ||
event->keyval == GDK_Alt_R) event->keyval == GDK_Alt_R)
{ {
return; return;
@ -41,7 +41,7 @@ Binding::Binding (GdkEventKey *event)
value |= BINDING_ALT; value |= BINDING_ALT;
} }
Binding::Binding (unsigned int key, bool ctrl, bool shift, bool alt) Binding::Binding(unsigned int key, bool ctrl, bool shift, bool alt)
{ {
value = BINDING_KEY; value = BINDING_KEY;
@ -54,23 +54,21 @@ Binding::Binding (unsigned int key, bool ctrl, bool shift, bool alt)
value |= BINDING_ALT; value |= BINDING_ALT;
} }
Binding::Binding (unsigned int device, Binding::Binding(unsigned int device, unsigned int button, unsigned int threshold)
unsigned int button,
unsigned int threshold)
{ {
value = BINDING_JOY; value = BINDING_JOY;
value |= JOY_DEVICE_MASK (device + 1); value |= JOY_DEVICE_MASK(device + 1);
value |= BINDING_KEY_MASK & button; value |= BINDING_KEY_MASK & button;
if (button >= 512) if (button >= 512)
value |= THRESHOLD_MASK (threshold); value |= THRESHOLD_MASK(threshold);
} }
Binding::Binding (unsigned int val) Binding::Binding(unsigned int val)
{ {
value = val; value = val;
} }
Binding::Binding (const Binding& binding) Binding::Binding(const Binding &binding)
{ {
this->value = binding.value; this->value = binding.value;
} }
@ -83,88 +81,75 @@ Binding &Binding::operator=(const Binding &binding)
bool Binding::operator==(const Binding &binding) bool Binding::operator==(const Binding &binding)
{ {
if ((value & ~BINDING_THRESHOLD_MASK) == if ((value & ~BINDING_THRESHOLD_MASK) == (binding.value & ~BINDING_THRESHOLD_MASK))
(binding.value & ~BINDING_THRESHOLD_MASK))
return true; return true;
return false; return false;
} }
void void Binding::clear()
Binding::clear ()
{ {
value = 0; value = 0;
} }
unsigned int unsigned int Binding::hex()
Binding::hex ()
{ {
return value; return value;
} }
unsigned int unsigned int Binding::base_hex()
Binding::base_hex ()
{ {
return (value & ~BINDING_THRESHOLD_MASK); return (value & ~BINDING_THRESHOLD_MASK);
} }
bool bool Binding::is_joy()
Binding::is_joy ()
{ {
return (value & BINDING_JOY); return (value & BINDING_JOY);
} }
bool bool Binding::is_key()
Binding::is_key ()
{ {
return (value & BINDING_KEY); return (value & BINDING_KEY);
} }
unsigned int unsigned int Binding::get_key()
Binding::get_key ()
{ {
return (value & BINDING_KEY_MASK); return (value & BINDING_KEY_MASK);
} }
unsigned int unsigned int Binding::get_device()
Binding::get_device ()
{ {
return JOY_DEVICE_UNMASK (value); return JOY_DEVICE_UNMASK(value);
} }
unsigned int unsigned int Binding::get_threshold()
Binding::get_threshold ()
{ {
return THRESHOLD_UNMASK (value); return THRESHOLD_UNMASK(value);
} }
unsigned int unsigned int Binding::get_axis()
Binding::get_axis ()
{ {
return JOY_AXIS_UNMASK (value); return JOY_AXIS_UNMASK(value);
} }
GdkModifierType Gdk::ModifierType Binding::get_gdk_modifiers()
Binding::get_gdk_modifiers ()
{ {
return (GdkModifierType) (((BINDING_CTRL & value) ? GDK_CONTROL_MASK : 0) | return (Gdk::ModifierType)(((BINDING_CTRL & value) ? Gdk::CONTROL_MASK : 0) |
((BINDING_ALT & value) ? GDK_MOD1_MASK : 0) | ((BINDING_ALT & value) ? Gdk::MOD1_MASK : 0) |
((BINDING_SHIFT & value) ? GDK_SHIFT_MASK : 0)); ((BINDING_SHIFT & value) ? Gdk::SHIFT_MASK : 0));
} }
bool bool Binding::is_positive()
Binding::is_positive ()
{ {
return JOY_DIRECTION_UNMASK (value) == AXIS_POS; return JOY_DIRECTION_UNMASK(value) == AXIS_POS;
} }
bool bool Binding::is_negative()
Binding::is_negative ()
{ {
return JOY_DIRECTION_UNMASK (value) == AXIS_NEG; return JOY_DIRECTION_UNMASK(value) == AXIS_NEG;
} }
Binding::Binding (const char *raw_string) Binding::Binding(const char *raw_string)
{ {
value = 0; value = 0;
@ -172,33 +157,33 @@ Binding::Binding (const char *raw_string)
return; return;
char substr[80]; char substr[80];
if (sscanf (raw_string, "Keyboard %79s", substr) == 1) if (sscanf(raw_string, "Keyboard %79s", substr) == 1)
{ {
bool ctrl = false; bool ctrl = false;
bool shift = false; bool shift = false;
bool alt= false; bool alt = false;
bool direct = false; bool direct = false;
unsigned int keyval = 0; unsigned int keyval = 0;
char *key; char *key;
if (!strchr (substr, '+')) if (!strchr(substr, '+'))
direct = true; direct = true;
key = strtok (substr, "+"); key = strtok(substr, "+");
while (key) while (key)
{ {
if (strstr (key, "Alt") && !direct) if (strstr(key, "Alt") && !direct)
alt = true; alt = true;
else if (strstr (key, "Ctrl") && !direct) else if (strstr(key, "Ctrl") && !direct)
ctrl = true; ctrl = true;
else if (strstr (key, "Shift") && !direct) else if (strstr(key, "Shift") && !direct)
shift = true; shift = true;
else else
{ {
keyval = gdk_keyval_from_name (key); keyval = gdk_keyval_from_name(key);
} }
key = strtok (NULL, "+"); key = strtok(NULL, "+");
} }
if (keyval != GDK_KEY_VoidSymbol) if (keyval != GDK_KEY_VoidSymbol)
@ -206,7 +191,7 @@ Binding::Binding (const char *raw_string)
else else
value = 0; value = 0;
} }
else if (!strncmp (raw_string, "Joystick", 8)) else if (!strncmp(raw_string, "Joystick", 8))
{ {
unsigned int axis; unsigned int axis;
unsigned int button; unsigned int button;
@ -215,15 +200,14 @@ Binding::Binding (const char *raw_string)
char posneg; char posneg;
const char *substr = &raw_string[8]; const char *substr = &raw_string[8];
if (sscanf (substr, "%u Axis %u %c %u", &device, &axis, &posneg, &percent) == 4) if (sscanf(substr, "%u Axis %u %c %u", &device, &axis, &posneg, &percent) == 4)
{ {
value = Binding(device - 1, JOY_AXIS (axis, posneg == '+' ? AXIS_POS : AXIS_NEG), percent).value; value = Binding(device - 1, JOY_AXIS(axis, posneg == '+' ? AXIS_POS : AXIS_NEG), percent).value;
} }
else if (sscanf (substr, "%u Button %u", &device, &button) == 2) else if (sscanf(substr, "%u Button %u", &device, &button) == 2)
{ {
value = Binding(device - 1, button, 0).value; value = Binding(device - 1, button, 0).value;
} }
} }
} }
@ -234,8 +218,7 @@ std::string Binding::as_string()
return std::string(buf); return std::string(buf);
} }
void void Binding::to_string(char *str, bool translate)
Binding::to_string (char *str, bool translate)
{ {
char buf[256]; char buf[256];
@ -244,22 +227,22 @@ Binding::to_string (char *str, bool translate)
str[0] = '\0'; str[0] = '\0';
if (is_key ()) if (is_key())
{ {
char *keyval_name = NULL; char *keyval_name = NULL;
unsigned int keyval = gdk_keyval_to_lower (get_key ()); unsigned int keyval = gdk_keyval_to_lower(get_key());
keyval_name = gdk_keyval_name (keyval); keyval_name = gdk_keyval_name(keyval);
if (keyval_name == NULL) if (keyval_name == NULL)
{ {
sprintf (buf, _("Unknown")); sprintf(buf, _("Unknown"));
} }
else else
{ {
memset (buf, 0, 256); memset(buf, 0, 256);
strncpy (buf, strncpy(buf,
keyval_name, keyval_name,
255); 255);
} }
if (translate) if (translate)
@ -267,29 +250,29 @@ Binding::to_string (char *str, bool translate)
if (buf[i] == '_') if (buf[i] == '_')
buf[i] = ' '; buf[i] = ' ';
sprintf (str, _("Keyboard %s%s%s%s"), sprintf(str, _("Keyboard %s%s%s%s"),
(value & BINDING_SHIFT) ? "Shift+" : "", (value & BINDING_SHIFT) ? "Shift+" : "",
(value & BINDING_CTRL) ? "Ctrl+" : "", (value & BINDING_CTRL) ? "Ctrl+" : "",
(value & BINDING_ALT) ? "Alt+" : "", (value & BINDING_ALT) ? "Alt+" : "",
buf); buf);
} }
else if (is_joy ()) else if (is_joy())
{ {
if ((get_key ()) >= 512) if ((get_key()) >= 512)
sprintf (buf, sprintf(buf,
_("Axis %u %s %u%%"), _("Axis %u %s %u%%"),
get_axis (), get_axis(),
is_positive () ? "+" : "-", is_positive() ? "+" : "-",
get_threshold ()); get_threshold());
else else
sprintf (buf, _("Button %u"), get_key ()); sprintf(buf, _("Button %u"), get_key());
sprintf (str, _("Joystick %u %s"), get_device (), buf); sprintf(str, _("Joystick %u %s"), get_device(), buf);
} }
else else
{ {
sprintf (str, _("Unset")); sprintf(str, _("Unset"));
} }
} }

View File

@ -7,7 +7,7 @@
#ifndef __GTK_BINDING_H #ifndef __GTK_BINDING_H
#define __GTK_BINDING_H #define __GTK_BINDING_H
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include <string> #include <string>
#define AXIS_POS 1 #define AXIS_POS 1
@ -34,34 +34,34 @@
class Binding class Binding
{ {
public: public:
Binding (unsigned int key, bool ctrl, bool shift, bool alt); Binding(unsigned int key, bool ctrl, bool shift, bool alt);
Binding (unsigned int device, unsigned int button, unsigned int threshold); Binding(unsigned int device, unsigned int button, unsigned int threshold);
Binding (const Binding &binding); Binding(const Binding &binding);
Binding &operator=(const Binding &binding); Binding &operator=(const Binding &binding);
bool operator==(const Binding &binding); bool operator==(const Binding &binding);
Binding (GdkEventKey *event); Binding(GdkEventKey *event);
Binding (unsigned int); Binding(unsigned int);
Binding (); Binding();
Binding (const char *str); Binding(const char *str);
void to_string (char *str, bool translate = true); void to_string(char *str, bool translate = true);
std::string as_string(); std::string as_string();
unsigned int hex (); unsigned int hex();
unsigned int base_hex (); unsigned int base_hex();
void clear (); void clear();
bool is_joy (); bool is_joy();
bool is_key (); bool is_key();
bool is_mouse (); bool is_mouse();
bool is_positive (); bool is_positive();
bool is_negative (); bool is_negative();
unsigned int get_key (); unsigned int get_key();
unsigned int get_device (); unsigned int get_device();
unsigned int get_threshold (); unsigned int get_threshold();
unsigned int get_axis (); unsigned int get_axis();
GdkModifierType get_gdk_modifiers (); Gdk::ModifierType get_gdk_modifiers();
private: private:
unsigned int value; unsigned int value;
}; };
#endif /* __GTK_BINDING_H_ */ #endif /* __GTK_BINDING_H_ */

View File

@ -9,242 +9,147 @@
#include "gtk_builder_window.h" #include "gtk_builder_window.h"
extern const unsigned char snes9x_ui[]; extern const unsigned char snes9x_ui[];
extern const int snes9x_ui_size; extern const int snes9x_ui_size;
GtkBuilderWindow::GtkBuilderWindow (const char *root) Glib::RefPtr<Gtk::Builder> global_builder;
bool global_builder_created = false;
GtkBuilderWindow::GtkBuilderWindow(const char *root)
{ {
builder = gtk_builder_new (); if (!global_builder_created)
gtk_builder_add_from_string (builder,
(const gchar *) snes9x_ui,
snes9x_ui_size,
NULL);
window = get_widget (root);
}
GtkBuilderWindow::~GtkBuilderWindow ()
{
gtk_widget_destroy (window);
g_object_unref (builder);
}
GtkWidget *
GtkBuilderWindow::get_widget (const char *name)
{
return GTK_WIDGET (gtk_builder_get_object (builder, name));
}
void
GtkBuilderWindow::signal_connection_func (GtkBuilder *builder,
GObject *object,
const gchar *signal_name,
const char *handler_name,
GObject *connect_object,
GConnectFlags flags,
gpointer data)
{
GCallback function = NULL;
GtkBuilderWindow *window = (GtkBuilderWindow *) data;
GtkBuilderWindowCallbacks *callbacks = window->callbacks;
for (int i = 0; callbacks[i].signal; i++)
{ {
if (!strcmp (handler_name, callbacks[i].signal)) global_builder = Gtk::Builder::create();
{ global_builder->add_from_string((const gchar *)snes9x_ui, snes9x_ui_size);
function = callbacks[i].function; global_builder_created = true;
break;
}
} }
if (function) window = get_object<Gtk::Window>(root);
{
if (connect_object)
{
fprintf (stderr, "Error: found a persistent object signal.\n");
g_signal_connect_object (object,
signal_name,
function,
connect_object,
flags);
}
else
{
g_signal_connect_data (object,
signal_name,
function,
data,
NULL,
flags);
}
}
else
{
}
} }
void GtkBuilderWindow::~GtkBuilderWindow()
GtkBuilderWindow::signal_connect (GtkBuilderWindowCallbacks *callbacks)
{ {
if (!callbacks)
return;
this->callbacks = callbacks;
gtk_builder_connect_signals_full (builder,
signal_connection_func,
(gpointer) this);
this->callbacks = NULL;
} }
void void GtkBuilderWindow::enable_widget(const char *name, bool state)
GtkBuilderWindow::enable_widget (const char *name, bool state)
{ {
gtk_widget_set_sensitive (get_widget (name), state); auto widget = get_object<Gtk::Widget>(name);
widget->set_sensitive(state);
} }
void void GtkBuilderWindow::show_widget(const char *name, bool state)
GtkBuilderWindow::resize (int width, int height)
{ {
if (width > 0 && height > 0) auto widget = get_object<Gtk::Widget>(name);
gtk_window_resize (GTK_WINDOW (window), width, height); widget->set_visible(state);
} }
void void GtkBuilderWindow::resize(int width, int height)
GtkBuilderWindow::refresh ()
{ {
gtk_widget_queue_draw (GTK_WIDGET (window)); window->resize(width, height);
} }
int void GtkBuilderWindow::refresh()
GtkBuilderWindow::get_width ()
{ {
int width, height; window->queue_draw();
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
return width;
} }
int int GtkBuilderWindow::get_width()
GtkBuilderWindow::get_height ()
{ {
int width, height; return window->get_width();
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
return height;
} }
void int GtkBuilderWindow::get_height()
GtkBuilderWindow::set_button_label (const char *name, const char *label)
{ {
gtk_button_set_label (GTK_BUTTON (get_widget (name)), label); return window->get_height();
} }
unsigned char void GtkBuilderWindow::set_button_label(const char *name, const char *label)
GtkBuilderWindow::get_check (const char *name)
{ {
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (get_widget (name)))) get_object<Gtk::Button>(name)->set_label(label);
return 1; }
return 0;
bool GtkBuilderWindow::get_check(const char *name)
{
return get_object<Gtk::ToggleButton>(name)->get_active();
} }
int GtkBuilderWindow::get_entry_value(const char *name) int GtkBuilderWindow::get_entry_value(const char *name)
{ {
return atoi (gtk_entry_get_text (GTK_ENTRY (get_widget (name))));; auto text = get_object<Gtk::Entry>(name)->get_text();
return std::stoi(text);
} }
const char * std::string GtkBuilderWindow::get_entry_text(const char *name)
GtkBuilderWindow::get_entry_text (const char *name)
{ {
return gtk_entry_get_text (GTK_ENTRY (get_widget (name))); return get_object<Gtk::Entry>(name)->get_text();
} }
float void GtkBuilderWindow::set_entry_value(const char *name, unsigned int value)
GtkBuilderWindow::get_slider (const char *name)
{ {
return (float) gtk_range_get_value (GTK_RANGE (get_widget (name))); get_object<Gtk::Entry>(name)->set_text(std::to_string(value));
} }
unsigned char void GtkBuilderWindow::set_entry_text(const char *name, const char *text)
GtkBuilderWindow::get_combo (const char *name)
{ {
return gtk_combo_box_get_active (GTK_COMBO_BOX (get_widget (name))); get_object<Gtk::Entry>(name)->set_text(text);
} }
void float GtkBuilderWindow::get_slider(const char *name)
GtkBuilderWindow::set_slider (const char *name, float value)
{ {
gtk_range_set_value (GTK_RANGE (get_widget (name)), (double) value); return get_object<Gtk::Range>(name)->get_value();
} }
void int GtkBuilderWindow::get_combo(const char *name)
GtkBuilderWindow::set_check (const char *name, bool value)
{ {
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (get_widget (name)), return get_object<Gtk::ComboBox>(name)->get_active_row_number();
value);
} }
void void GtkBuilderWindow::set_slider(const char *name, float value)
GtkBuilderWindow::set_entry_value (const char *name, unsigned int value)
{ {
char text[80]; get_object<Gtk::Range>(name)->set_value(value);
snprintf (text, 80, "%u", value);
gtk_entry_set_text (GTK_ENTRY (get_widget (name)), text);
} }
void void GtkBuilderWindow::set_check(const char *name, bool value)
GtkBuilderWindow::set_entry_text (const char *name, const char *text)
{ {
gtk_entry_set_text (GTK_ENTRY (get_widget (name)), text); get_object<Gtk::ToggleButton>(name)->set_active(value);
} }
void void GtkBuilderWindow::set_combo(const char *name, unsigned char value)
GtkBuilderWindow::set_combo (const char *name, unsigned char value)
{ {
gtk_combo_box_set_active (GTK_COMBO_BOX (get_widget (name)), value); get_object<Gtk::ComboBox>(name)->set_active(value);
} }
void void GtkBuilderWindow::set_spin(const char *name, double value)
GtkBuilderWindow::set_spin (const char *name, double value)
{ {
gtk_spin_button_set_value (GTK_SPIN_BUTTON (get_widget (name)), get_object<Gtk::SpinButton>(name)->set_value(value);
(double) value);
} }
void double GtkBuilderWindow::get_spin(const char *name)
GtkBuilderWindow::combo_box_append (const char *name, const char *value)
{ {
combo_box_append (GTK_COMBO_BOX (get_widget (name)), value); return get_object<Gtk::SpinButton>(name)->get_value();
} }
void void GtkBuilderWindow::combo_box_append(const char *name, const char *value)
GtkBuilderWindow::combo_box_append (GtkComboBox *combo, const char *value) {
return combo_box_append(get_object<Gtk::ComboBox>(name).get(), value);
}
void GtkBuilderWindow::combo_box_append(Gtk::ComboBox *combo, const char *value)
{ {
GtkListStore *store; GtkListStore *store;
GtkTreeIter iter; GtkTreeIter iter;
store = GTK_LIST_STORE (gtk_combo_box_get_model (combo)); store = GTK_LIST_STORE(combo->get_model()->gobj());
gtk_list_store_append (store, &iter); gtk_list_store_append(store, &iter);
gtk_list_store_set (store, &iter, 0, value, -1); gtk_list_store_set(store, &iter, 0, value, -1);
} }
GtkWindow * GtkWindow *GtkBuilderWindow::get_window()
GtkBuilderWindow::get_window ()
{ {
return GTK_WINDOW (window); return window->gobj();
}
double
GtkBuilderWindow::get_spin (const char *name)
{
return gtk_spin_button_get_value (GTK_SPIN_BUTTON (get_widget (name)));
} }
bool GtkBuilderWindow::has_focus(const char *widget) bool GtkBuilderWindow::has_focus(const char *widget)
{ {
return gtk_widget_is_focus (get_widget (widget)); return get_object<Gtk::Widget>(widget)->is_focus();
} }

View File

@ -7,51 +7,54 @@
#ifndef __GTK_BUILDER_WINDOW_H #ifndef __GTK_BUILDER_WINDOW_H
#define __GTK_BUILDER_WINDOW_H #define __GTK_BUILDER_WINDOW_H
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
typedef struct extern Glib::RefPtr<Gtk::Builder> global_builder;
{
const char *signal;
GCallback function;
} GtkBuilderWindowCallbacks;
class GtkBuilderWindow class GtkBuilderWindow
{ {
public: public:
GtkBuilderWindow (const char *root); GtkBuilderWindow(const char *root);
~GtkBuilderWindow (); ~GtkBuilderWindow();
GtkWidget *get_widget (const char *name);
void resize (int width, int height);
GtkWindow *get_window ();
void refresh ();
int get_width ();
int get_height ();
void signal_connect (GtkBuilderWindowCallbacks *callbacks); template <typename T>
void enable_widget (const char *name, bool state); Glib::RefPtr<T> get_object(const char *name)
void set_button_label (const char *name, const char *label); {
unsigned char get_check (const char *name); auto object = global_builder->get_object(name);
int get_entry_value (const char *name); if (!object)
const char *get_entry_text (const char *name); {
unsigned char get_combo (const char *name); printf("No object named %s\n", name);
void combo_box_append (const char *name, const char *value); exit(1);
void combo_box_append (GtkComboBox *combo, const char *value); }
double get_spin (const char *name); return Glib::RefPtr<T>::cast_static(object);
float get_slider (const char *name); }
void set_check (const char *name, bool value);
void set_entry_value (const char *name, unsigned int value);
void set_entry_text (const char *name, const char *text);
void set_combo (const char *name, unsigned char value);
void set_spin (const char *name, double value);
void set_slider (const char *name, float value);
bool has_focus (const char *widget);
protected: void resize(int width, int height);
static void signal_connection_func (GtkBuilder *, GObject *, const gchar *, const char *, GObject *, GConnectFlags, gpointer); GtkWindow *get_window();
void refresh();
int get_width();
int get_height();
GtkWidget *window; void enable_widget(const char *name, bool state);
GtkBuilder *builder; void show_widget(const char *name, bool state);
GtkBuilderWindowCallbacks *callbacks; void set_button_label(const char *name, const char *label);
bool get_check(const char *name);
int get_entry_value(const char *name);
std::string get_entry_text(const char *name);
int get_combo(const char *name);
void combo_box_append(const char *name, const char *value);
void combo_box_append(Gtk::ComboBox *combo, const char *value);
double get_spin(const char *name);
float get_slider(const char *name);
void set_check(const char *name, bool value);
void set_entry_value(const char *name, unsigned int value);
void set_entry_text(const char *name, const char *text);
void set_combo(const char *name, unsigned char value);
void set_spin(const char *name, double value);
void set_slider(const char *name, float value);
bool has_focus(const char *widget);
Glib::RefPtr<Gtk::Window> window;
}; };
#endif /* __GTK_BUILDER_WINDOW_H */ #endif /* __GTK_BUILDER_WINDOW_H */

View File

@ -4,13 +4,12 @@
For further information, consult the LICENSE file in the root directory. For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_s9xcore.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_cheat.h" #include "gtk_cheat.h"
#include "cheats.h"
#include "display.h"
enum enum {
{
COLUMN_ENABLED = 0, COLUMN_ENABLED = 0,
COLUMN_DESCRIPTION = 1, COLUMN_DESCRIPTION = 1,
COLUMN_CHEAT = 2, COLUMN_CHEAT = 2,
@ -19,225 +18,128 @@ enum
extern SCheatData Cheat; extern SCheatData Cheat;
static void static void display_errorbox(const char *error)
display_errorbox (const char *error)
{ {
GtkWidget *dialog = gtk_message_dialog_new (NULL, auto dialog = Gtk::MessageDialog(error, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
GTK_DIALOG_MODAL, dialog.set_title(_("Error"));
GTK_MESSAGE_ERROR, dialog.run();
GTK_BUTTONS_OK, dialog.hide();
"%s",
error);
gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
} }
static void static Snes9xCheats *cheats_dialog = nullptr;
event_add_code (GtkButton *button, gpointer data) void open_snes9x_cheats_dialog()
{ {
((Snes9xCheats *) data)->add_code (); if (!cheats_dialog)
cheats_dialog = new Snes9xCheats;
cheats_dialog->show();
} }
static void Snes9xCheats::Snes9xCheats()
event_update_code (GtkButton *button, gpointer data) : GtkBuilderWindow("cheat_window")
{ {
((Snes9xCheats *) data)->update_code ();
}
static void
event_disable_all (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->disable_all ();
}
static void
event_remove_code (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->remove_code ();
}
static void
event_search_database (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->search_database ();
}
static void
event_delete_all_cheats (GtkButton *button, gpointer data)
{
((Snes9xCheats *) data)->delete_all_cheats ();
}
static void
event_code_toggled (GtkCellRendererToggle *cell_renderer,
gchar *path,
gpointer data)
{
int enabled = !gtk_cell_renderer_toggle_get_active (cell_renderer);
((Snes9xCheats *) data)->toggle_code (path, enabled);
}
static void
event_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer data)
{
((Snes9xCheats *) data)->row_activated (path);
}
static void
event_row_inserted (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data)
{
int *indices = gtk_tree_path_get_indices (path);
((Snes9xCheats *) data)->row_inserted (indices[0]);
}
static void
event_row_deleted (GtkTreeModel *tree_model,
GtkTreePath *path,
gpointer data)
{
int *indices = gtk_tree_path_get_indices (path);
((Snes9xCheats *) data)->row_deleted (indices[0]);
}
void
event_enabled_column_clicked (GtkTreeViewColumn *treeviewcolumn,
gpointer data)
{
((Snes9xCheats *) data)->sort_cheats ();
}
Snes9xCheats::Snes9xCheats ()
: GtkBuilderWindow ("cheat_window")
{
GtkTreeView *view;
GtkCellRenderer *renderer;
GtkBuilderWindowCallbacks callbacks[] =
{
{ "add_code", G_CALLBACK (event_add_code) },
{ "update_code", G_CALLBACK (event_update_code) },
{ "remove_code", G_CALLBACK (event_remove_code) },
{ "search_database", G_CALLBACK (event_search_database) },
{ "disable_all", G_CALLBACK (event_disable_all) },
{ "delete_all_cheats", G_CALLBACK (event_delete_all_cheats) },
{ NULL, NULL}
};
dst_row = -1; dst_row = -1;
view = GTK_TREE_VIEW (get_widget ("cheat_treeview")); auto view = get_object<Gtk::TreeView>("cheat_treeview");
view->signal_row_activated().connect(sigc::mem_fun(*this, &Snes9xCheats::row_activated));
view->set_reorderable();
g_signal_connect (view, "row-activated", G_CALLBACK (event_row_activated), (gpointer) this); auto toggle_renderer = new Gtk::CellRendererToggle();
toggle_renderer->set_activatable();
toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &Snes9xCheats::toggle_code));
gtk_tree_view_set_reorderable (view, true); view->insert_column("\xe2\x86\x91", *toggle_renderer, COLUMN_ENABLED);
auto column = view->get_column(COLUMN_ENABLED);
column->set_clickable();
column->set_alignment(0.5);
column->add_attribute(*toggle_renderer, "active", COLUMN_ENABLED);
column->signal_clicked().connect([&] {
sort_cheats();
});
renderer = gtk_cell_renderer_toggle_new (); auto text_renderer = new Gtk::CellRendererText();
gtk_cell_renderer_toggle_set_activatable (GTK_CELL_RENDERER_TOGGLE (renderer), true); view->insert_column(_("Description"), *text_renderer, COLUMN_DESCRIPTION);
gtk_tree_view_insert_column_with_attributes (view, column = view->get_column(COLUMN_DESCRIPTION);
-1, column->set_resizable();
"\xe2\x86\x91", column->set_min_width(40);
renderer, column->add_attribute(*text_renderer, "text", COLUMN_DESCRIPTION);
"active", COLUMN_ENABLED,
NULL);
GtkTreeViewColumn *column = gtk_tree_view_get_column (view, 0);
gtk_tree_view_column_set_clickable (column, true);
gtk_tree_view_column_set_alignment (column, 0.5f);
g_signal_connect (column, "clicked", G_CALLBACK (event_enabled_column_clicked), (gpointer) this);
g_signal_connect (renderer, view->insert_column(_("Cheat"), *text_renderer, COLUMN_CHEAT);
"toggled", column = view->get_column(COLUMN_CHEAT);
G_CALLBACK (event_code_toggled), column->set_resizable();
(gpointer) this); column->set_min_width(40);
column->add_attribute(*text_renderer, "text", COLUMN_CHEAT);
renderer = gtk_cell_renderer_text_new (); Gtk::TreeModelColumn<bool> column1;
gtk_tree_view_insert_column_with_attributes (view, Gtk::TreeModelColumn<Glib::ustring> column2;
-1, Gtk::TreeModelColumn<Glib::ustring> column3;
_("Description"), Gtk::TreeModelColumnRecord record;
renderer, record.add(column1);
"text", COLUMN_DESCRIPTION, record.add(column2);
NULL); record.add(column3);
column = gtk_tree_view_get_column (view, 1);
gtk_tree_view_column_set_resizable (column, true);
gtk_tree_view_column_set_min_width (column, 40);
renderer = gtk_cell_renderer_text_new (); store = Gtk::ListStore::create(record);
gtk_tree_view_insert_column_with_attributes (view, view->set_model(store);
-1,
_("Cheat"),
renderer,
"text", COLUMN_CHEAT,
NULL);
column = gtk_tree_view_get_column (view, 2);
gtk_tree_view_column_set_resizable (column, true);
gtk_tree_view_column_set_min_width (column, 40);
store = gtk_list_store_new (NUM_COLS, delete_id = store->signal_row_deleted().connect([&](const Gtk::TreeModel::Path &path) {
G_TYPE_BOOLEAN, row_deleted(get_index_from_path(path));
G_TYPE_STRING, });
G_TYPE_STRING);
gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); insert_id = store->signal_row_inserted().connect([&](const Gtk::TreeModel::Path &path, const Gtk::TreeModel::iterator &iter) {
delete_id = g_signal_connect (store, "row-deleted", G_CALLBACK (event_row_deleted), (gpointer) this); row_inserted(get_index_from_path(path));
insert_id = g_signal_connect (store, "row-inserted", G_CALLBACK (event_row_inserted), (gpointer) this); });
gtk_widget_realize (window); get_object<Gtk::Button>("add_code")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::add_code));
get_object<Gtk::Button>("remove_code")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::remove_code));
get_object<Gtk::Button>("update_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::update_code));
get_object<Gtk::Button>("disable_all_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::disable_all));
get_object<Gtk::Button>("delete_all_cheats_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::delete_all_cheats));
get_object<Gtk::Button>("cheat_search_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::search_database));
get_object<Gtk::Button>("update_button")->signal_clicked().connect(sigc::mem_fun(*this, &Snes9xCheats::update_code));
signal_connect (callbacks); gtk_widget_realize(GTK_WIDGET(window->gobj()));
} }
Snes9xCheats::~Snes9xCheats () Snes9xCheats::~Snes9xCheats()
{ {
gtk_widget_destroy (window);
g_object_unref (store);
} }
void void Snes9xCheats::enable_dnd(bool enable)
Snes9xCheats::enable_dnd (bool enable)
{ {
if (enable) if (enable)
{ {
g_signal_handler_unblock (G_OBJECT (store), delete_id); delete_id.unblock();
g_signal_handler_unblock (G_OBJECT (store), insert_id); insert_id.unblock();
} }
else else
{ {
g_signal_handler_block (G_OBJECT (store), delete_id); delete_id.block();
g_signal_handler_block (G_OBJECT (store), insert_id); insert_id.unblock();
} }
} }
void void Snes9xCheats::show()
Snes9xCheats::show ()
{ {
top_level->pause_from_focus_change (); top_level->pause_from_focus_change();
gtk_window_set_transient_for (GTK_WINDOW (window), window->set_transient_for(*top_level->window.get());
top_level->get_window ());
refresh_tree_view (); refresh_tree_view();
Glib::RefPtr<Gtk::Dialog>::cast_static(window)->run();
window->hide();
gtk_dialog_run (GTK_DIALOG (window)); top_level->unpause_from_focus_change();
top_level->unpause_from_focus_change ();
} }
static void cheat_move (int src, int dst) static void cheat_move(int src, int dst)
{ {
Cheat.g.insert (Cheat.g.begin() + dst, Cheat.g[src]); Cheat.g.insert(Cheat.g.begin() + dst, Cheat.g[src]);
if (dst < src) if (dst < src)
src++; src++;
Cheat.g.erase (Cheat.g.begin() + src); Cheat.g.erase(Cheat.g.begin() + src);
} }
static void cheat_gather_enabled () static void cheat_gather_enabled()
{ {
unsigned int enabled = 0; unsigned int enabled = 0;
@ -251,311 +153,259 @@ static void cheat_gather_enabled ()
} }
} }
void void Snes9xCheats::row_deleted(int src_row)
Snes9xCheats::row_deleted (int src_row)
{ {
if (dst_row >= 0) if (dst_row >= 0)
{ {
if (src_row >= dst_row) if (src_row >= dst_row)
src_row--; src_row--;
cheat_move (src_row, dst_row); cheat_move(src_row, dst_row);
dst_row = -1; dst_row = -1;
} }
} }
void void Snes9xCheats::row_inserted(int new_row)
Snes9xCheats::row_inserted (int new_row)
{ {
dst_row = new_row; dst_row = new_row;
} }
int int Snes9xCheats::get_selected_index()
Snes9xCheats::get_selected_index ()
{ {
GtkTreeSelection *selection; auto selection = get_object<Gtk::TreeView>("cheat_treeview")->get_selection();
GList *rows; auto rows = selection->get_selected_rows();
gint *indices; if (rows.empty())
int index; return -1;
GtkTreeModel *model = GTK_TREE_MODEL (store); auto indices = gtk_tree_path_get_indices(rows[0].gobj());
return indices[0];
}
selection = int Snes9xCheats::get_index_from_path(Gtk::TreeModel::Path path)
gtk_tree_view_get_selection ( {
GTK_TREE_VIEW (get_widget ("cheat_treeview"))); gint *indices = gtk_tree_path_get_indices(path.gobj());
int index = indices[0];
rows = gtk_tree_selection_get_selected_rows (selection,
&model);
if (rows)
{
indices = gtk_tree_path_get_indices ((GtkTreePath *) (rows->data));
index = indices[0];
for (GList *i = rows; i; i = i->next)
gtk_tree_path_free ((GtkTreePath *)(i->data));
g_list_free (rows);
}
else
index = -1;
return index; return index;
} }
int int Snes9xCheats::get_index_from_path(const Glib::ustring &path)
Snes9xCheats::get_index_from_path (const gchar *path)
{ {
GtkTreePath *tree_path = gtk_tree_path_new_from_string (path); return get_index_from_path(Gtk::TreeModel::Path(path));
gint *indices = gtk_tree_path_get_indices (tree_path);
int index = indices[0];
gtk_tree_path_free (tree_path);
return index;
} }
void void Snes9xCheats::refresh_tree_view()
Snes9xCheats::refresh_tree_view ()
{ {
GtkTreeIter iter; enable_dnd(false);
unsigned int list_size;
enable_dnd (false); auto list_size = store->children().size();
list_size = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL);
if (Cheat.g.size () == 0) if (Cheat.g.size() == 0)
return; return;
for (unsigned int i = 0; i < Cheat.g.size() - list_size; i++) for (unsigned int i = 0; i < Cheat.g.size() - list_size; i++)
gtk_list_store_append (store, &iter); store->append();
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
auto iter = store->children().begin();
for (unsigned int i = 0; i < Cheat.g.size (); i++) for (unsigned int i = 0; i < Cheat.g.size (); i++)
{ {
char *str = S9xCheatGroupToText (i); char *str = S9xCheatGroupToText(i);
Glib::ustring description = Cheat.g[i].name[0] == '\0' ? "" :Cheat.g[i].name;
if (i > 0) iter->set_value(COLUMN_ENABLED, Cheat.g[i].enabled);
gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); iter->set_value(COLUMN_DESCRIPTION, description);
iter->set_value(COLUMN_CHEAT, Glib::ustring(str));
gtk_list_store_set (store, &iter, iter++;
COLUMN_DESCRIPTION,
!strcmp (Cheat.g [i].name, "") ? _("No description")
: Cheat.g [i].name,
COLUMN_CHEAT, str,
COLUMN_ENABLED, Cheat.g [i].enabled,
-1);
delete[] str; delete[] str;
} }
enable_dnd (true); enable_dnd(true);
} }
void void Snes9xCheats::add_code()
Snes9xCheats::add_code ()
{ {
const char *description; std::string code = get_entry_text("code_entry");
const gchar *code = get_entry_text ("code_entry"); std::string description = get_entry_text("description_entry");
description = get_entry_text ("description_entry"); if (description.empty())
if (description[0] == '\0')
description = _("No description"); description = _("No description");
if (S9xAddCheatGroup (description, code) < 0) if (S9xAddCheatGroup(description.c_str(), code.c_str()) < 0)
{ {
display_errorbox (_("Couldn't find any cheat codes in input.")); display_errorbox(_("Couldn't find any cheat codes in input."));
return; return;
} }
code = (const gchar *) S9xCheatGroupToText (Cheat.g.size () - 1); auto parsed_code = S9xCheatGroupToText(Cheat.g.size() - 1);
set_entry_text ("code_entry", code); set_entry_text("code_entry", parsed_code);
delete[] code; delete[] parsed_code;
gtk_widget_grab_focus (get_widget ("code_entry")); get_object<Gtk::Entry>("code_entry")->grab_focus();
refresh_tree_view (); refresh_tree_view();
while (gtk_events_pending ()) while (Gtk::Main::events_pending())
gtk_main_iteration (); Gtk::Main::iteration(false);
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (get_widget ("cheat_treeview"))); auto selection = get_object<Gtk::TreeView>("cheat_treeview")->get_selection();
GtkTreePath *path = gtk_tree_path_new_from_indices (Cheat.g.size () - 1, -1); Gtk::TreePath path;
gtk_tree_selection_select_path (selection, path); path.push_back(Cheat.g.size() - 1);
gtk_tree_path_free (path); selection->select(path);
GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW (get_widget ("cheat_scrolledwindow")); auto adj = get_object<Gtk::ScrolledWindow>("cheat_scrolledwindow")->get_vadjustment();
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment (scroll); adj->set_value(adj->get_upper());
gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj));
} }
void void Snes9xCheats::remove_code()
Snes9xCheats::remove_code ()
{ {
int index = get_selected_index (); int index = get_selected_index();
GtkTreeIter iter;
if (index < 0) if (index < 0)
return; return;
enable_dnd (false); enable_dnd(false);
gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, NULL, index);
gtk_list_store_remove (store, &iter);
enable_dnd (true);
S9xDeleteCheatGroup (index); Gtk::TreePath path;
path.push_back(index);
auto iter = store->get_iter(path);
store->erase(iter);
enable_dnd(true);
S9xDeleteCheatGroup(index);
} }
void void Snes9xCheats::delete_all_cheats()
Snes9xCheats::delete_all_cheats ()
{ {
enable_dnd (false); enable_dnd(false);
S9xDeleteCheats (); S9xDeleteCheats();
gtk_list_store_clear (store); store->clear();
enable_dnd (true); enable_dnd(true);
} }
void void Snes9xCheats::search_database()
Snes9xCheats::search_database ()
{ {
std::string filename; std::string filename;
int result; int result;
int reason = 0; int reason = 0;
filename = S9xGetDirectory (CHEAT_DIR); filename = S9xGetDirectory(CHEAT_DIR);
filename += "/cheats.bml"; filename += "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{ {
refresh_tree_view (); refresh_tree_view();
return; return;
} }
if (result < reason) if (result < reason)
reason = result; reason = result;
filename = get_config_dir () + "/cheats.bml"; filename = get_config_dir() + "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{ {
refresh_tree_view (); refresh_tree_view();
return; return;
} }
if (result < reason) if (result < reason)
reason = result; reason = result;
filename = std::string (DATADIR) + "/cheats.bml"; filename = std::string(DATADIR) + "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{ {
refresh_tree_view (); refresh_tree_view();
return; return;
} }
if (result < reason) if (result < reason)
reason = result; reason = result;
filename = S9xGetDirectory (ROM_DIR); filename = S9xGetDirectory(ROM_DIR);
filename += "/cheats.bml"; filename += "/cheats.bml";
if (!(result = S9xImportCheatsFromDatabase (filename.c_str ()))) if (!(result = S9xImportCheatsFromDatabase(filename.c_str())))
{ {
refresh_tree_view (); refresh_tree_view();
return; return;
} }
if (result < reason) if (result < reason)
reason = result; reason = result;
GtkMessageDialog *dialog; auto dialog = Gtk::MessageDialog(*window.get(), reason == -1 ? _("Couldn't Find Cheats Database") : _("No Matching Game Found"), true);
GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT; dialog.set_secondary_text(reason == -1 ? _("The database file <b>cheats.bml</b> was not found. It is normally installed with "
dialog = GTK_MESSAGE_DIALOG (gtk_message_dialog_new (get_window (), "Snes9x, but you may also place a custom copy in your configuration or cheats directory.")
flags, : _("No matching game was found in the databases. If you are using a non-official "
GTK_MESSAGE_INFO, "translation or modified copy, you may be able to find and manually enter the codes."));
GTK_BUTTONS_CLOSE, dialog.run();
reason == -1 ? _("Couldn't Find Cheats Database") : dialog.hide();
_("No Matching Game Found")));
gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG (dialog),
reason == -1 ?
_("The database file <b>cheats.bml</b> was not found. It is normally installed with "
"Snes9x, but you may also place a custom copy in your configuration or cheats directory.") :
_("No matching game was found in the databases. If you are using a non-official "
"translation or modified copy, you may be able to find and manually enter the codes."));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
} }
void void Snes9xCheats::sort_cheats()
Snes9xCheats::sort_cheats ()
{ {
cheat_gather_enabled (); cheat_gather_enabled();
refresh_tree_view (); refresh_tree_view();
} }
void void Snes9xCheats::row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column)
Snes9xCheats::row_activated (GtkTreePath *path)
{ {
gint *indices = gtk_tree_path_get_indices (path); int index = get_index_from_path(path);
char *cheat_text; char *cheat_text;
cheat_text = S9xCheatGroupToText (indices[0]); cheat_text = S9xCheatGroupToText(index);
set_entry_text ("code_entry", cheat_text); set_entry_text("code_entry", cheat_text);
delete[] cheat_text; delete[] cheat_text;
set_entry_text ("description_entry", Cheat.g[indices[0]].name); set_entry_text("description_entry", Cheat.g[index].name);
} }
void void Snes9xCheats::toggle_code(const Glib::ustring &path)
Snes9xCheats::toggle_code (const gchar *path, int enabled)
{ {
GtkTreeIter iter; int index = get_index_from_path(path);
int index = get_index_from_path (path); auto iter = store->get_iter(path);
bool enabled;
GtkTreePath *treepath = gtk_tree_path_new_from_string (path); iter->get_value(COLUMN_ENABLED, enabled);
gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, treepath); enabled = !enabled;
gtk_list_store_set (store, &iter, COLUMN_ENABLED, enabled, -1); iter->set_value(COLUMN_ENABLED, enabled);
if (enabled) if (enabled)
S9xEnableCheatGroup (index); S9xEnableCheatGroup(index);
else else
S9xDisableCheatGroup (index); S9xDisableCheatGroup(index);
} }
void void Snes9xCheats::update_code()
Snes9xCheats::update_code ()
{ {
int index = get_selected_index (); int index = get_selected_index();
if (index < 0) if (index < 0)
return; return;
const char *description; std::string code = get_entry_text("code_entry");
char *code = (char *) get_entry_text ("code_entry"); std::string description = get_entry_text("description_entry");
if (description.empty())
description = get_entry_text ("description_entry");
if (description[0] == '\0')
description = _("No description"); description = _("No description");
code = S9xCheatValidate (code); auto parsed_code = S9xCheatValidate(code.c_str());
if (!code) if (!parsed_code)
{ {
display_errorbox (_("Couldn't find any cheat codes in input.")); display_errorbox(_("Couldn't find any cheat codes in input."));
return; return;
} }
S9xModifyCheatGroup (index, description, code); S9xModifyCheatGroup(index, description.c_str(), parsed_code);
set_entry_text ("code_entry", code); set_entry_text("code_entry", parsed_code);
delete[] code; delete[] parsed_code;
gtk_widget_grab_focus (get_widget ("code_entry")); get_object<Gtk::Entry>("code_entry")->grab_focus();
refresh_tree_view (); refresh_tree_view();
} }
void void Snes9xCheats::disable_all()
Snes9xCheats::disable_all ()
{ {
for (unsigned int i = 0; i < Cheat.g.size(); i++) for (unsigned int i = 0; i < Cheat.g.size(); i++)
{ {
if (Cheat.g[i].enabled) if (Cheat.g[i].enabled)
S9xDisableCheatGroup (i); S9xDisableCheatGroup(i);
} }
refresh_tree_view (); refresh_tree_view();
} }

View File

@ -9,41 +9,43 @@
#include "gtk_builder_window.h" #include "gtk_builder_window.h"
enum void open_snes9x_cheats_dialog();
{
TYPE_GAME_GENIE = 0, enum {
TYPE_GAME_GENIE = 0,
TYPE_ACTION_REPLAY = 1, TYPE_ACTION_REPLAY = 1,
TYPE_GOLDFINGER = 2 TYPE_GOLDFINGER = 2
}; };
class Snes9xCheats : public GtkBuilderWindow class Snes9xCheats : public GtkBuilderWindow
{ {
public: public:
Snes9xCheats (); Snes9xCheats();
~Snes9xCheats (); ~Snes9xCheats();
void show (); void show();
void add_code (); void add_code();
void remove_code (); void remove_code();
void search_database (); void search_database();
void delete_all_cheats (); void delete_all_cheats();
void toggle_code (const gchar *path, int enabled); void toggle_code(const Glib::ustring &path);
void row_activated (GtkTreePath *path); void row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column);
void row_deleted (int src_row); void row_deleted(int src_row);
void row_inserted (int row); void row_inserted(int row);
void enable_dnd (bool); void enable_dnd(bool);
void sort_cheats (); void sort_cheats();
void update_code (); void update_code();
void disable_all (); void disable_all();
private: private:
void refresh_tree_view (); void refresh_tree_view();
int get_selected_index (); int get_selected_index();
int get_index_from_path (const gchar *path); int get_index_from_path(const Glib::ustring &path);
int get_index_from_path(Gtk::TreeModel::Path path);
unsigned long insert_id; sigc::connection insert_id;
unsigned long delete_id; sigc::connection delete_id;
int dst_row; int dst_row;
GtkListStore *store; Glib::RefPtr<Gtk::ListStore> store;
}; };
#endif /* __GTK_CHEAT_H */ #endif /* __GTK_CHEAT_H */

29
gtk/src/gtk_compat.h Normal file
View File

@ -0,0 +1,29 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#ifndef __GTK_COMPAT_H
#define __GTK_COMPAT_H
#include <gtkmm.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkkeysyms-compat.h>
#ifndef USE_WAYLAND
#undef GDK_WINDOWING_WAYLAND
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#endif

View File

@ -14,6 +14,10 @@
#include "gtk_sound.h" #include "gtk_sound.h"
#include "gtk_display.h" #include "gtk_display.h"
#include "conffile.h" #include "conffile.h"
#include "cheats.h"
#include "apu/apu.h"
#include "netplay.h"
#include "controls.h"
static bool directory_exists(std::string str) static bool directory_exists(std::string str)
{ {
@ -38,7 +42,7 @@ std::string get_config_dir()
if (!env_home && !env_xdg_config_home) if (!env_home && !env_xdg_config_home)
{ {
return std::string(".snes9x"); return std::string{".snes9x"};
} }
std::string config; std::string config;
@ -70,7 +74,6 @@ void S9xParsePortConfig(ConfigFile &conf, int pass)
Snes9xConfig::Snes9xConfig() Snes9xConfig::Snes9xConfig()
{ {
joystick = NULL;
joystick_threshold = 40; joystick_threshold = 40;
} }
@ -103,8 +106,8 @@ int Snes9xConfig::load_defaults()
default_esc_behavior = 1; default_esc_behavior = 1;
prevent_screensaver = false; prevent_screensaver = false;
sound_driver = 0; sound_driver = 0;
sound_buffer_size = 32; sound_buffer_size = 48;
sound_playback_rate = 5; sound_playback_rate = 7;
sound_input_rate = 31950; sound_input_rate = 31950;
auto_input_rate = true; auto_input_rate = true;
last_directory.clear(); last_directory.clear();
@ -149,7 +152,7 @@ int Snes9xConfig::load_defaults()
sync_to_vblank = true; sync_to_vblank = true;
use_pbos = true; use_pbos = true;
pbo_format = 0; pbo_format = 0;
npot_textures = false; npot_textures = true;
use_shaders = false; use_shaders = false;
shader_filename.clear(); shader_filename.clear();
use_glfinish = false; use_glfinish = false;
@ -206,26 +209,26 @@ int Snes9xConfig::load_defaults()
void Snes9xConfig::joystick_register_centers() void Snes9xConfig::joystick_register_centers()
{ {
for (int i = 0; joystick[i] != NULL; i++) for (auto &j : joystick)
joystick[i]->register_centers(); j.register_centers();
} }
void Snes9xConfig::flush_joysticks() void Snes9xConfig::flush_joysticks()
{ {
for (int i = 0; joystick[i] != NULL; i++) for (auto &j : joystick)
joystick[i]->flush(); j.flush();
} }
void Snes9xConfig::set_joystick_mode(int mode) void Snes9xConfig::set_joystick_mode(int mode)
{ {
for (int i = 0; joystick[i] != NULL; i++) for (auto &j : joystick)
joystick[i]->mode = mode; j.mode = mode;
} }
int Snes9xConfig::save_config_file() int Snes9xConfig::save_config_file()
{ {
ConfigFile cf; ConfigFile cf;
std::string section = ""; std::string section;
auto outbool = [&](std::string name, bool b, std::string comment = "") { auto outbool = [&](std::string name, bool b, std::string comment = "") {
cf.SetBool((section + "::" + name).c_str(), b, "true", "false", comment.c_str()); cf.SetBool((section + "::" + name).c_str(), b, "true", "false", comment.c_str());

View File

@ -7,14 +7,14 @@
#ifndef __GTK_CONFIG_H #ifndef __GTK_CONFIG_H
#define __GTK_CONFIG_H #define __GTK_CONFIG_H
#include "gtk_control.h"
#include "filter/snes_ntsc.h"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <string> #include <string>
#include <array> #include <array>
#include "gtk_control.h"
#include "filter/snes_ntsc.h"
enum { enum {
HWA_NONE = 0, HWA_NONE = 0,
HWA_OPENGL = 1, HWA_OPENGL = 1,
@ -53,14 +53,14 @@ enum {
class Snes9xConfig class Snes9xConfig
{ {
public: public:
Snes9xConfig (); Snes9xConfig();
int load_config_file (); int load_config_file();
int save_config_file (); int save_config_file();
int load_defaults (); int load_defaults();
void rebind_keys (); void rebind_keys();
void flush_joysticks (); void flush_joysticks();
void set_joystick_mode (int mode); void set_joystick_mode(int mode);
void joystick_register_centers (); void joystick_register_centers();
/* Screen options */ /* Screen options */
bool full_screen_on_open; bool full_screen_on_open;
@ -167,11 +167,11 @@ class Snes9xConfig
bool use_sync_control; bool use_sync_control;
#endif #endif
JoyDevice **joystick; std::vector<JoyDevice> joystick;
int joystick_threshold; int joystick_threshold;
}; };
std::string get_config_dir (); std::string get_config_dir();
std::string get_config_file_name (); std::string get_config_file_name();
#endif /* __GTK_CONFIG_H */ #endif /* __GTK_CONFIG_H */

View File

@ -6,12 +6,17 @@
#include <fcntl.h> #include <fcntl.h>
#include "gtk_s9xcore.h" #include "SDL_joystick.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_config.h" #include "gtk_config.h"
#include "gtk_control.h" #include "gtk_control.h"
#include "gtk_file.h" #include "gtk_file.h"
#include "snes9x.h"
#include "controls.h"
#include "display.h"
#include "gfx.h"
const BindingLink b_links[] = const BindingLink b_links[] =
{ {
/* Joypad-specific bindings. "Joypad# " will be prepended */ /* Joypad-specific bindings. "Joypad# " will be prepended */
@ -122,17 +127,17 @@ const int b_breaks[] =
static int joystick_lock = 0; static int joystick_lock = 0;
bool S9xPollButton (uint32 id, bool *pressed) bool S9xPollButton(uint32 id, bool *pressed)
{ {
return true; return true;
} }
bool S9xPollAxis (uint32 id, int16 *value) bool S9xPollAxis(uint32 id, int16 *value)
{ {
return true; return true;
} }
bool S9xPollPointer (uint32 id, int16 *x, int16 *y) bool S9xPollPointer(uint32 id, int16 *x, int16 *y)
{ {
*x = top_level->snes_mouse_x; *x = top_level->snes_mouse_x;
*y = top_level->snes_mouse_y; *y = top_level->snes_mouse_y;
@ -140,14 +145,14 @@ bool S9xPollPointer (uint32 id, int16 *x, int16 *y)
return true; return true;
} }
bool S9xIsMousePluggedIn () bool S9xIsMousePluggedIn()
{ {
enum controllers ctl; enum controllers ctl;
int8 id1, id2, id3, id4; int8 id1, id2, id3, id4;
for (int i = 0; i <= 1; i++) for (int i = 0; i <= 1; i++)
{ {
S9xGetController (i, &ctl, &id1, &id2, &id3, &id4); S9xGetController(i, &ctl, &id1, &id2, &id3, &id4);
if (ctl == CTL_MOUSE || ctl == CTL_SUPERSCOPE) if (ctl == CTL_MOUSE || ctl == CTL_SUPERSCOPE)
return true; return true;
} }
@ -155,7 +160,7 @@ bool S9xIsMousePluggedIn ()
return false; return false;
} }
bool S9xGrabJoysticks () bool S9xGrabJoysticks()
{ {
if (joystick_lock) if (joystick_lock)
return false; return false;
@ -165,12 +170,12 @@ bool S9xGrabJoysticks ()
return true; return true;
} }
void S9xReleaseJoysticks () void S9xReleaseJoysticks()
{ {
joystick_lock--; joystick_lock--;
} }
static void swap_controllers_1_2 () static void swap_controllers_1_2()
{ {
JoypadBinding interrim; JoypadBinding interrim;
@ -178,10 +183,10 @@ static void swap_controllers_1_2 ()
gui_config->pad[0] = gui_config->pad[1]; gui_config->pad[0] = gui_config->pad[1];
gui_config->pad[1] = interrim; gui_config->pad[1] = interrim;
gui_config->rebind_keys (); gui_config->rebind_keys();
} }
static void change_slot (int difference) static void change_slot(int difference)
{ {
static char buf[256]; static char buf[256];
@ -192,12 +197,12 @@ static void change_slot (int difference)
if (!gui_config->rom_loaded) if (!gui_config->rom_loaded)
return; return;
snprintf (buf, 256, "State Slot: %d", gui_config->current_save_slot); snprintf(buf, 256, "State Slot: %d", gui_config->current_save_slot);
S9xSetInfoString (buf); S9xSetInfoString(buf);
GFX.InfoStringTimeout = 60; GFX.InfoStringTimeout = 60;
} }
void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2)
{ {
static bool quit_binding_down = false; static bool quit_binding_down = false;
@ -215,109 +220,93 @@ void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2)
{ {
quit_binding_down = false; quit_binding_down = false;
} }
if (cmd.port[0] == PORT_COMMAND_FULLSCREEN) if (cmd.port[0] == PORT_COMMAND_FULLSCREEN)
{ {
top_level->toggle_fullscreen_mode (); top_level->toggle_fullscreen_mode();
} }
else if (cmd.port[0] == PORT_COMMAND_SAVE_SPC) else if (cmd.port[0] == PORT_COMMAND_SAVE_SPC)
{ {
top_level->save_spc_dialog (); top_level->save_spc_dialog();
} }
else if (cmd.port[0] == PORT_OPEN_ROM) else if (cmd.port[0] == PORT_OPEN_ROM)
{ {
top_level->open_rom_dialog (); top_level->open_rom_dialog();
} }
else if (cmd.port[0] == PORT_PAUSE) else if (cmd.port[0] == PORT_PAUSE)
{ {
if (!(top_level->user_pause)) if (!(top_level->user_pause))
top_level->pause_from_user (); top_level->pause_from_user();
else else
top_level->unpause_from_user (); top_level->unpause_from_user();
} }
else if (cmd.port[0] == PORT_REWIND) else if (cmd.port[0] == PORT_REWIND)
{ {
Settings.Rewinding = false; Settings.Rewinding = false;
} }
else if (cmd.port[0] == PORT_SEEK_TO_FRAME) else if (cmd.port[0] == PORT_SEEK_TO_FRAME)
{ {
top_level->movie_seek_dialog (); top_level->movie_seek_dialog();
} }
else if (cmd.port[0] == PORT_SWAP_CONTROLLERS) else if (cmd.port[0] == PORT_SWAP_CONTROLLERS)
{ {
swap_controllers_1_2 (); swap_controllers_1_2();
} }
else if (cmd.port[0] == PORT_QUIT) else if (cmd.port[0] == PORT_QUIT)
{ {
if (quit_binding_down) if (quit_binding_down)
S9xExit (); S9xExit();
} }
else if (cmd.port[0] >= PORT_QUICKLOAD0 && cmd.port[0] <= PORT_QUICKLOAD9) else if (cmd.port[0] >= PORT_QUICKLOAD0 && cmd.port[0] <= PORT_QUICKLOAD9)
{ {
S9xQuickLoadSlot (cmd.port[0] - PORT_QUICKLOAD0); S9xQuickLoadSlot(cmd.port[0] - PORT_QUICKLOAD0);
} }
else if (cmd.port[0] == PORT_SAVESLOT) else if (cmd.port[0] == PORT_SAVESLOT)
{ {
S9xQuickSaveSlot (gui_config->current_save_slot); S9xQuickSaveSlot(gui_config->current_save_slot);
} }
else if (cmd.port[0] == PORT_LOADSLOT) else if (cmd.port[0] == PORT_LOADSLOT)
{ {
S9xQuickLoadSlot (gui_config->current_save_slot); S9xQuickLoadSlot(gui_config->current_save_slot);
} }
else if (cmd.port[0] == PORT_INCREMENTSAVESLOT) else if (cmd.port[0] == PORT_INCREMENTSAVESLOT)
{ {
change_slot (1); change_slot(1);
S9xQuickSaveSlot (gui_config->current_save_slot); S9xQuickSaveSlot(gui_config->current_save_slot);
} }
else if (cmd.port[0] == PORT_DECREMENTLOADSLOT) else if (cmd.port[0] == PORT_DECREMENTLOADSLOT)
{ {
change_slot (-1); change_slot(-1);
S9xQuickLoadSlot (gui_config->current_save_slot); S9xQuickLoadSlot(gui_config->current_save_slot);
} }
else if (cmd.port[0] == PORT_INCREMENTSLOT) else if (cmd.port[0] == PORT_INCREMENTSLOT)
{ {
change_slot (1); change_slot(1);
} }
else if (cmd.port[0] == PORT_DECREMENTSLOT) else if (cmd.port[0] == PORT_DECREMENTSLOT)
{ {
change_slot (-1); change_slot(-1);
} }
else if (cmd.port[0] == PORT_GRABMOUSE) else if (cmd.port[0] == PORT_GRABMOUSE)
{ {
top_level->toggle_grab_mouse (); top_level->toggle_grab_mouse();
} }
} }
} }
Binding S9xGetBindingByName (const char *name) Binding S9xGetBindingByName(const char *name)
{ {
for (int i = 0; i < NUM_EMU_LINKS; i++) for (int i = 0; i < NUM_EMU_LINKS; i++)
{ {
if (!strcasecmp (b_links[i + NUM_JOYPAD_LINKS].snes9x_name, name)) if (!strcasecmp(b_links[i + NUM_JOYPAD_LINKS].snes9x_name, name))
{ {
return gui_config->shortcut[i]; return gui_config->shortcut[i];
} }
} }
return Binding (); return Binding();
} }
s9xcommand_t S9xGetPortCommandT (const char *name) s9xcommand_t S9xGetPortCommandT(const char *name)
{ {
s9xcommand_t cmd; s9xcommand_t cmd;
@ -329,248 +318,214 @@ s9xcommand_t S9xGetPortCommandT (const char *name)
cmd.port[2] = 0; cmd.port[2] = 0;
cmd.port[3] = 0; cmd.port[3] = 0;
if (!strcasecmp (name, "GTK_fullscreen")) if (!strcasecmp(name, "GTK_fullscreen"))
{ {
cmd.port[0] = PORT_COMMAND_FULLSCREEN; cmd.port[0] = PORT_COMMAND_FULLSCREEN;
} }
else if (!strcasecmp(name, "GTK_save_spc"))
else if (!strcasecmp (name, "GTK_save_spc"))
{ {
cmd.port[0] = PORT_COMMAND_SAVE_SPC; cmd.port[0] = PORT_COMMAND_SAVE_SPC;
} }
else if (!strcasecmp(name, "GTK_open_rom"))
else if (!strcasecmp (name, "GTK_open_rom"))
{ {
cmd.port[0] = PORT_OPEN_ROM; cmd.port[0] = PORT_OPEN_ROM;
} }
else if (!strcasecmp(name, "GTK_pause"))
else if (!strcasecmp (name, "GTK_pause"))
{ {
cmd.port[0] = PORT_PAUSE; cmd.port[0] = PORT_PAUSE;
} }
else if (!strcasecmp(name, "GTK_seek_to_frame"))
else if (!strcasecmp (name, "GTK_seek_to_frame"))
{ {
cmd.port[0] = PORT_SEEK_TO_FRAME; cmd.port[0] = PORT_SEEK_TO_FRAME;
} }
else if (!strcasecmp(name, "GTK_quit"))
else if (!strcasecmp (name, "GTK_quit"))
{ {
cmd.port[0] = PORT_QUIT; cmd.port[0] = PORT_QUIT;
} }
else if (!strcasecmp(name, "GTK_swap_controllers"))
else if (!strcasecmp (name, "GTK_swap_controllers"))
{ {
cmd.port[0] = PORT_SWAP_CONTROLLERS; cmd.port[0] = PORT_SWAP_CONTROLLERS;
} }
else if (!strcasecmp(name, "GTK_rewind"))
else if (!strcasecmp (name, "GTK_rewind"))
{ {
cmd.port[0] = PORT_REWIND; cmd.port[0] = PORT_REWIND;
} }
else if (strstr(name, "QuickLoad000"))
else if (strstr (name, "QuickLoad000"))
{ {
cmd.port[0] = PORT_QUICKLOAD0; cmd.port[0] = PORT_QUICKLOAD0;
} }
else if (strstr(name, "QuickLoad001"))
else if (strstr (name, "QuickLoad001"))
{ {
cmd.port[0] = PORT_QUICKLOAD1; cmd.port[0] = PORT_QUICKLOAD1;
} }
else if (strstr(name, "QuickLoad002"))
else if (strstr (name, "QuickLoad002"))
{ {
cmd.port[0] = PORT_QUICKLOAD2; cmd.port[0] = PORT_QUICKLOAD2;
} }
else if (strstr(name, "QuickLoad003"))
else if (strstr (name, "QuickLoad003"))
{ {
cmd.port[0] = PORT_QUICKLOAD3; cmd.port[0] = PORT_QUICKLOAD3;
} }
else if (strstr(name, "QuickLoad004"))
else if (strstr (name, "QuickLoad004"))
{ {
cmd.port[0] = PORT_QUICKLOAD4; cmd.port[0] = PORT_QUICKLOAD4;
} }
else if (strstr(name, "QuickLoad005"))
else if (strstr (name, "QuickLoad005"))
{ {
cmd.port[0] = PORT_QUICKLOAD5; cmd.port[0] = PORT_QUICKLOAD5;
} }
else if (strstr(name, "QuickLoad006"))
else if (strstr (name, "QuickLoad006"))
{ {
cmd.port[0] = PORT_QUICKLOAD6; cmd.port[0] = PORT_QUICKLOAD6;
} }
else if (strstr(name, "QuickLoad007"))
else if (strstr (name, "QuickLoad007"))
{ {
cmd.port[0] = PORT_QUICKLOAD7; cmd.port[0] = PORT_QUICKLOAD7;
} }
else if (strstr(name, "QuickLoad008"))
else if (strstr (name, "QuickLoad008"))
{ {
cmd.port[0] = PORT_QUICKLOAD8; cmd.port[0] = PORT_QUICKLOAD8;
} }
else if (strstr(name, "QuickLoad009"))
else if (strstr (name, "QuickLoad009"))
{ {
cmd.port[0] = PORT_QUICKLOAD9; cmd.port[0] = PORT_QUICKLOAD9;
} }
else if (strstr(name, "GTK_state_save_current"))
else if (strstr (name, "GTK_state_save_current"))
{ {
cmd.port[0] = PORT_SAVESLOT; cmd.port[0] = PORT_SAVESLOT;
} }
else if (strstr(name, "GTK_state_load_current"))
else if (strstr (name, "GTK_state_load_current"))
{ {
cmd.port[0] = PORT_LOADSLOT; cmd.port[0] = PORT_LOADSLOT;
} }
else if (strstr(name, "GTK_state_increment_save"))
else if (strstr (name, "GTK_state_increment_save"))
{ {
cmd.port[0] = PORT_INCREMENTSAVESLOT; cmd.port[0] = PORT_INCREMENTSAVESLOT;
} }
else if (strstr(name, "GTK_state_decrement_load"))
else if (strstr (name, "GTK_state_decrement_load"))
{ {
cmd.port[0] = PORT_DECREMENTLOADSLOT; cmd.port[0] = PORT_DECREMENTLOADSLOT;
} }
else if (strstr(name, "GTK_state_increment"))
else if (strstr (name, "GTK_state_increment"))
{ {
cmd.port[0] = PORT_INCREMENTSLOT; cmd.port[0] = PORT_INCREMENTSLOT;
} }
else if (strstr(name, "GTK_state_decrement"))
else if (strstr (name, "GTK_state_decrement"))
{ {
cmd.port[0] = PORT_DECREMENTSLOT; cmd.port[0] = PORT_DECREMENTSLOT;
} }
else if (strstr(name, "GTK_grab_mouse"))
else if (strstr (name, "GTK_grab_mouse"))
{ {
cmd.port[0] = PORT_GRABMOUSE; cmd.port[0] = PORT_GRABMOUSE;
} }
else else
{ {
cmd = S9xGetCommandT (name); cmd = S9xGetCommandT(name);
} }
return cmd; return cmd;
} }
void S9xProcessEvents (bool8 block) void S9xProcessEvents(bool8 block)
{ {
JoyEvent event; JoyEvent event;
Binding binding; Binding binding;
if (S9xGrabJoysticks ()) if (S9xGrabJoysticks())
{ {
for (int i = 0; gui_config->joystick[i]; i++) for (size_t i = 0; i < gui_config->joystick.size(); i++)
{ {
while (gui_config->joystick[i]->get_event (&event)) while (gui_config->joystick[i].get_event(&event))
{ {
binding = Binding (i, event.parameter, 0); binding = Binding(i, event.parameter, 0);
S9xReportButton (binding.hex (), event.state == JOY_PRESSED ? 1 : 0); S9xReportButton(binding.hex(), event.state == JOY_PRESSED ? 1 : 0);
gui_config->screensaver_needs_reset = true; gui_config->screensaver_needs_reset = true;
} }
} }
S9xReleaseJoysticks (); S9xReleaseJoysticks();
} }
} }
static void poll_joystick_events () static void poll_joystick_events()
{ {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent (&event)) while (SDL_PollEvent(&event))
{ {
if (event.type == SDL_JOYAXISMOTION) if (event.type == SDL_JOYAXISMOTION)
{ {
gui_config->joystick[event.jaxis.which]->handle_event (&event); gui_config->joystick[event.jaxis.which].handle_event(&event);
} }
else if (event.type == SDL_JOYHATMOTION) else if (event.type == SDL_JOYHATMOTION)
{ {
gui_config->joystick[event.jhat.which]->handle_event (&event); gui_config->joystick[event.jhat.which].handle_event(&event);
} }
else if (event.type == SDL_JOYBUTTONUP || else if (event.type == SDL_JOYBUTTONUP ||
event.type == SDL_JOYBUTTONDOWN) event.type == SDL_JOYBUTTONDOWN)
{ {
gui_config->joystick[event.jbutton.which]->handle_event (&event); gui_config->joystick[event.jbutton.which].handle_event(&event);
} }
} }
} }
void S9xInitInputDevices () void S9xInitInputDevices()
{ {
SDL_Init (SDL_INIT_JOYSTICK); SDL_Init(SDL_INIT_JOYSTICK);
size_t num_joysticks = SDL_NumJoysticks();
gui_config->joystick.resize(num_joysticks);
for (int i = 0; ; i++) for (size_t i = 0; i < num_joysticks; i++)
{ {
gui_config->joystick = (JoyDevice **) gui_config->joystick[i].set_sdl_joystick_num(i);
realloc (gui_config->joystick,
sizeof (JoyDevice *) * (i + 1));
gui_config->joystick[i] = new JoyDevice (i);
if (!gui_config->joystick[i]->enabled)
{
delete gui_config->joystick[i];
gui_config->joystick[i] = NULL;
break;
}
else
{
gui_config->joystick[i]->joynum = i;
}
} }
//First plug in both, they'll change later as needed //First plug in both, they'll change later as needed
S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
} }
void S9xDeinitInputDevices () void S9xDeinitInputDevices()
{ {
for (int i = 0; gui_config->joystick[i] != NULL; i++) gui_config->joystick.clear();
{ SDL_Quit();
delete gui_config->joystick[i];
}
free (gui_config->joystick);
SDL_Quit ();
} }
JoyDevice::JoyDevice (unsigned int device_num) JoyDevice::JoyDevice()
{ {
enabled = false; enabled = false;
axis = NULL;
filedes = NULL; filedes = NULL;
mode = JOY_MODE_INDIVIDUAL; mode = JOY_MODE_INDIVIDUAL;
}
if ((int) device_num >= SDL_NumJoysticks ()) JoyDevice::~JoyDevice()
return; {
if (enabled)
{
SDL_JoystickClose(filedes);
}
}
filedes = SDL_JoystickOpen (device_num); bool JoyDevice::set_sdl_joystick_num(unsigned int device_num)
{
if ((int)device_num >= SDL_NumJoysticks())
{
enabled = false;
return false;
}
filedes = SDL_JoystickOpen(device_num);
if (!filedes) if (!filedes)
return; return false;
enabled = true; enabled = true;
num_axes = SDL_JoystickNumAxes (filedes); int num_axes = SDL_JoystickNumAxes(filedes);
num_hats = SDL_JoystickNumHats (filedes); int num_hats = SDL_JoystickNumHats(filedes);
axis = new int[num_axes]; axis.resize(num_axes);
hat = new int[num_hats]; hat.resize(num_hats);
calibration = new Calibration[num_axes]; calibration.resize(num_axes);
for (int i = 0; i < num_axes; i++) for (int i = 0; i < num_axes; i++)
{ {
@ -579,41 +534,31 @@ JoyDevice::JoyDevice (unsigned int device_num)
calibration[i].center = 0; calibration[i].center = 0;
} }
printf ("Joystick %d, %s:\n %d axes, %d buttons, %d hats\n", printf("Joystick %d, %s:\n %d axes, %d buttons, %d hats\n",
device_num + 1, device_num + 1,
SDL_JoystickName (filedes), SDL_JoystickName(filedes),
SDL_JoystickNumButtons (filedes), SDL_JoystickNumButtons(filedes),
num_axes, num_axes,
num_hats); num_hats);
memset (axis, 0, sizeof (int) * num_axes); for (auto &i : axis)
i = 0;
return true;
} }
JoyDevice::~JoyDevice () void JoyDevice::add_event(unsigned int parameter, unsigned int state)
{
if (enabled)
{
SDL_JoystickClose (filedes);
delete[] axis;
delete[] hat;
delete[] calibration;
}
enabled = false;
}
void JoyDevice::add_event (unsigned int parameter, unsigned int state)
{ {
JoyEvent event = { parameter, state }; JoyEvent event = { parameter, state };
queue.push (event); queue.push(event);
} }
void JoyDevice::register_centers () void JoyDevice::register_centers()
{ {
for (int i = 0; i < num_axes; i++) for (size_t i = 0; i < axis.size(); i++)
{ {
calibration[i].center = SDL_JoystickGetAxis (filedes, i); calibration[i].center = SDL_JoystickGetAxis(filedes, i);
/* Snap centers to specific target points */ /* Snap centers to specific target points */
if (calibration[i].center < -24576) if (calibration[i].center < -24576)
@ -629,7 +574,7 @@ void JoyDevice::register_centers ()
} }
} }
void JoyDevice::handle_event (SDL_Event *event) void JoyDevice::handle_event(SDL_Event *event)
{ {
if (event->type == SDL_JOYAXISMOTION) if (event->type == SDL_JOYAXISMOTION)
{ {
@ -644,20 +589,20 @@ void JoyDevice::handle_event (SDL_Event *event)
{ {
for (int i = 0; i < NUM_JOYPADS; i++) for (int i = 0; i < NUM_JOYPADS; i++)
{ {
Binding *pad = (Binding *) &(gui_config->pad[i]); Binding *pad = (Binding *)&(gui_config->pad[i]);
for (int j = 0; j < NUM_JOYPAD_LINKS; j++) for (int j = 0; j < NUM_JOYPAD_LINKS; j++)
{ {
if (pad[j].get_axis () == event->jaxis.axis && if (pad[j].get_axis() == event->jaxis.axis &&
pad[j].get_device () == (unsigned int) (joynum + 1)) pad[j].get_device() == (unsigned int)(joynum + 1))
{ {
t = pad[j].get_threshold (); t = pad[j].get_threshold();
if (pad[j].is_positive ()) if (pad[j].is_positive())
{ {
ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; ax_max = (cal_max - cal_cen) * t / 100 + cal_cen;
} }
else if (pad[j].is_negative ()) else if (pad[j].is_negative())
{ {
ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; ax_min = (cal_min - cal_cen) * t / 100 + cal_cen;
} }
@ -667,16 +612,16 @@ void JoyDevice::handle_event (SDL_Event *event)
for (int i = 0; i < NUM_EMU_LINKS; i++) for (int i = 0; i < NUM_EMU_LINKS; i++)
{ {
if (gui_config->shortcut[i].get_axis () == event->jaxis.axis && if (gui_config->shortcut[i].get_axis() == event->jaxis.axis &&
gui_config->shortcut[i].get_device () == gui_config->shortcut[i].get_device() ==
(unsigned int) (joynum + 1)) (unsigned int)(joynum + 1))
{ {
t = gui_config->shortcut[i].get_threshold (); t = gui_config->shortcut[i].get_threshold();
if (gui_config->shortcut[i].is_positive ()) if (gui_config->shortcut[i].is_positive())
{ {
ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; ax_max = (cal_max - cal_cen) * t / 100 + cal_cen;
} }
else if (gui_config->shortcut[i].is_negative ()) else if (gui_config->shortcut[i].is_negative())
{ {
ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; ax_min = (cal_min - cal_cen) * t / 100 + cal_cen;
} }
@ -698,38 +643,37 @@ void JoyDevice::handle_event (SDL_Event *event)
ax_max = cal_cen + 1; ax_max = cal_cen + 1;
if (event->jaxis.value <= ax_min && if (event->jaxis.value <= ax_min &&
axis[event->jaxis.axis] > ax_min) axis[event->jaxis.axis] > ax_min)
{ {
add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 1); add_event(JOY_AXIS(event->jaxis.axis, AXIS_NEG), 1);
} }
if (event->jaxis.value > ax_min && if (event->jaxis.value > ax_min &&
axis[event->jaxis.axis] <= ax_min) axis[event->jaxis.axis] <= ax_min)
{ {
add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 0); add_event(JOY_AXIS(event->jaxis.axis, AXIS_NEG), 0);
} }
if (event->jaxis.value >= ax_max && if (event->jaxis.value >= ax_max &&
axis[event->jaxis.axis] < ax_max) axis[event->jaxis.axis] < ax_max)
{ {
add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 1); add_event(JOY_AXIS(event->jaxis.axis, AXIS_POS), 1);
} }
if (event->jaxis.value < ax_max && if (event->jaxis.value < ax_max &&
axis[event->jaxis.axis] >= ax_max) axis[event->jaxis.axis] >= ax_max)
{ {
add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 0); add_event(JOY_AXIS(event->jaxis.axis, AXIS_POS), 0);
} }
axis[event->jaxis.axis] = event->jaxis.value; axis[event->jaxis.axis] = event->jaxis.value;
} }
else if (event->type == SDL_JOYBUTTONUP || else if (event->type == SDL_JOYBUTTONUP ||
event->type == SDL_JOYBUTTONDOWN) event->type == SDL_JOYBUTTONDOWN)
{ {
add_event (event->jbutton.button, add_event(event->jbutton.button,
event->jbutton.state == SDL_PRESSED ? 1 : 0); event->jbutton.state == SDL_PRESSED ? 1 : 0);
} }
else if (event->type == SDL_JOYHATMOTION) else if (event->type == SDL_JOYHATMOTION)
@ -737,83 +681,83 @@ void JoyDevice::handle_event (SDL_Event *event)
if ((event->jhat.value & SDL_HAT_UP) && if ((event->jhat.value & SDL_HAT_UP) &&
!(hat[event->jhat.hat] & SDL_HAT_UP)) !(hat[event->jhat.hat] & SDL_HAT_UP))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 1); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_POS), 1);
} }
if (!(event->jhat.value & SDL_HAT_UP) && if (!(event->jhat.value & SDL_HAT_UP) &&
(hat[event->jhat.hat] & SDL_HAT_UP)) (hat[event->jhat.hat] & SDL_HAT_UP))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 0); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_POS), 0);
} }
if ((event->jhat.value & SDL_HAT_DOWN) && if ((event->jhat.value & SDL_HAT_DOWN) &&
!(hat[event->jhat.hat] & SDL_HAT_DOWN)) !(hat[event->jhat.hat] & SDL_HAT_DOWN))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 1); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_NEG), 1);
} }
if (!(event->jhat.value & SDL_HAT_DOWN) && if (!(event->jhat.value & SDL_HAT_DOWN) &&
(hat[event->jhat.hat] & SDL_HAT_DOWN)) (hat[event->jhat.hat] & SDL_HAT_DOWN))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 0); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2), AXIS_NEG), 0);
} }
if ((event->jhat.value & SDL_HAT_LEFT) && if ((event->jhat.value & SDL_HAT_LEFT) &&
!(hat[event->jhat.hat] & SDL_HAT_LEFT)) !(hat[event->jhat.hat] & SDL_HAT_LEFT))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 1); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_NEG), 1);
} }
if (!(event->jhat.value & SDL_HAT_LEFT) && if (!(event->jhat.value & SDL_HAT_LEFT) &&
(hat[event->jhat.hat] & SDL_HAT_LEFT)) (hat[event->jhat.hat] & SDL_HAT_LEFT))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 0); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_NEG), 0);
} }
if ((event->jhat.value & SDL_HAT_RIGHT) && if ((event->jhat.value & SDL_HAT_RIGHT) &&
!(hat[event->jhat.hat] & SDL_HAT_RIGHT)) !(hat[event->jhat.hat] & SDL_HAT_RIGHT))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 1); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_POS), 1);
} }
if (!(event->jhat.value & SDL_HAT_RIGHT) && if (!(event->jhat.value & SDL_HAT_RIGHT) &&
(hat[event->jhat.hat] & SDL_HAT_RIGHT)) (hat[event->jhat.hat] & SDL_HAT_RIGHT))
{ {
add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 0); add_event(JOY_AXIS(axis.size() + (event->jhat.hat * 2) + 1, AXIS_POS), 0);
} }
hat[event->jhat.hat] = event->jhat.value; hat[event->jhat.hat] = event->jhat.value;
} }
} }
int JoyDevice::get_event (JoyEvent *event) int JoyDevice::get_event(JoyEvent *event)
{ {
poll_events (); poll_events();
if (queue.empty ()) if (queue.empty())
return 0; return 0;
event->parameter = queue.front ().parameter; event->parameter = queue.front().parameter;
event->state = queue.front ().state; event->state = queue.front().state;
queue.pop (); queue.pop();
return 1; return 1;
} }
void JoyDevice::poll_events () void JoyDevice::poll_events()
{ {
poll_joystick_events (); poll_joystick_events();
} }
void JoyDevice::flush () void JoyDevice::flush()
{ {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent (&event)) while (SDL_PollEvent(&event))
{ {
} }
while (!queue.empty ()) while (!queue.empty())
queue.pop (); queue.pop();
} }

View File

@ -18,21 +18,18 @@
const int NUM_JOYPADS = 10; const int NUM_JOYPADS = 10;
enum enum {
{
JOY_MODE_GLOBAL = 0, JOY_MODE_GLOBAL = 0,
JOY_MODE_INDIVIDUAL = 1, JOY_MODE_INDIVIDUAL = 1,
JOY_MODE_CALIBRATE = 2 JOY_MODE_CALIBRATE = 2
}; };
enum enum {
{
JOY_RELEASED = 0, JOY_RELEASED = 0,
JOY_PRESSED = 1 JOY_PRESSED = 1
}; };
enum enum {
{
PORT_COMMAND_FULLSCREEN = 1, PORT_COMMAND_FULLSCREEN = 1,
PORT_COMMAND_SAVE_SPC = 2, PORT_COMMAND_SAVE_SPC = 2,
PORT_OPEN_ROM = 3, PORT_OPEN_ROM = 3,
@ -70,15 +67,15 @@ typedef struct BindingLink
extern const BindingLink b_links[]; extern const BindingLink b_links[];
extern const int b_breaks[]; extern const int b_breaks[];
const int NUM_JOYPAD_LINKS = 24; const int NUM_JOYPAD_LINKS = 24;
const int NUM_EMU_LINKS = 62; const int NUM_EMU_LINKS = 62;
typedef struct JoypadBinding typedef struct JoypadBinding
{ {
std::array<Binding, NUM_JOYPAD_LINKS> data; std::array<Binding, NUM_JOYPAD_LINKS> data;
} JoypadBinding; } JoypadBinding;
bool S9xGrabJoysticks (); bool S9xGrabJoysticks();
void S9xReleaseJoysticks (); void S9xReleaseJoysticks();
typedef struct JoyEvent typedef struct JoyEvent
{ {
@ -97,31 +94,30 @@ typedef struct Calibration
class JoyDevice class JoyDevice
{ {
public: public:
JoyDevice (unsigned int device_num); JoyDevice();
~JoyDevice (); ~JoyDevice();
int get_event (JoyEvent *event); int get_event(JoyEvent *event);
void flush (); void flush();
void handle_event (SDL_Event *event); void handle_event(SDL_Event *event);
void register_centers (); void register_centers();
bool set_sdl_joystick_num(unsigned int device_num);
SDL_Joystick *filedes; SDL_Joystick *filedes;
Calibration *calibration;
std::queue<JoyEvent> queue; std::queue<JoyEvent> queue;
int mode; int mode;
int joynum; int joynum;
int num_axes; std::vector<Calibration> calibration;
int num_hats; std::vector<int> axis;
int *axis; std::vector<int> hat;
int *hat; bool enabled;
bool enabled;
private: private:
void poll_events (); void poll_events();
void add_event (unsigned int parameter, unsigned int state); void add_event(unsigned int parameter, unsigned int state);
}; };
void S9xDeinitInputDevices (); void S9xDeinitInputDevices();
Binding S9xGetBindingByName (const char *name); Binding S9xGetBindingByName(const char *name);
bool S9xIsMousePluggedIn (); bool S9xIsMousePluggedIn();
#endif /* __GTK_CONTROL_H*/ #endif /* __GTK_CONTROL_H*/

View File

@ -4,7 +4,7 @@
For further information, consult the LICENSE file in the root directory. For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include <sched.h> #include <sched.h>
#include "gtk_s9x.h" #include "gtk_s9x.h"
@ -12,6 +12,13 @@
#include "gtk_display_driver.h" #include "gtk_display_driver.h"
#include "gtk_display_driver_gtk.h" #include "gtk_display_driver_gtk.h"
#include "snes9x.h"
#include "memmap.h"
#include "cpuexec.h"
#include "ppu.h"
#include "gfx.h"
#include "netplay.h"
#if defined(USE_XV) && defined(GDK_WINDOWING_X11) #if defined(USE_XV) && defined(GDK_WINDOWING_X11)
#include "gtk_display_driver_xv.h" #include "gtk_display_driver_xv.h"
#endif #endif
@ -1284,12 +1291,12 @@ void S9xDisplayReconfigure()
void S9xQueryDrivers() void S9xQueryDrivers()
{ {
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (top_level->get_window())); GdkDisplay *gdk_display = top_level->window->get_display()->gobj();
gui_config->allow_xv = false; gui_config->allow_xv = false;
#if defined(USE_XV) && defined(GDK_WINDOWING_X11) #if defined(USE_XV) && defined(GDK_WINDOWING_X11)
if (GDK_IS_X11_DISPLAY (display)) if (GDK_IS_X11_DISPLAY(gdk_display))
gui_config->allow_xv = S9xXVDisplayDriver::query_availability (); gui_config->allow_xv = S9xXVDisplayDriver::query_availability();
#endif #endif
#ifdef USE_OPENGL #ifdef USE_OPENGL
@ -1300,10 +1307,10 @@ void S9xQueryDrivers()
gui_config->allow_xrandr = false; gui_config->allow_xrandr = false;
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_DISPLAY(display)) if (GDK_IS_X11_DISPLAY(gdk_display))
{ {
Display *dpy = gdk_x11_display_get_xdisplay(gtk_widget_get_display(GTK_WIDGET(top_level->get_window()))); Display *dpy = gdk_x11_display_get_xdisplay(gdk_display);
Window xid = gdk_x11_window_get_xid(gtk_widget_get_window(GTK_WIDGET(top_level->get_window()))); Window xid = gdk_x11_window_get_xid(top_level->window->get_window()->gobj());
gui_config->allow_xrandr = true; gui_config->allow_xrandr = true;
gui_config->xrr_screen_resources = XRRGetScreenResourcesCurrent(dpy, xid); gui_config->xrr_screen_resources = XRRGetScreenResourcesCurrent(dpy, xid);
@ -1397,31 +1404,29 @@ bool8 S9xDeinitUpdate(int width, int height)
static void S9xInitDriver() static void S9xInitDriver()
{ {
// Only OpenGL is supported on Wayland
#ifdef GDK_WINDOWING_WAYLAND #ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
{ {
gui_config->hw_accel = HWA_OPENGL; gui_config->hw_accel = HWA_OPENGL;
} }
#endif #endif
switch (gui_config->hw_accel) switch (gui_config->hw_accel)
{ {
#ifdef USE_OPENGL #ifdef USE_OPENGL
case HWA_OPENGL: case HWA_OPENGL:
driver = new S9xOpenGLDisplayDriver(top_level, gui_config);
driver = new S9xOpenGLDisplayDriver(top_level,
gui_config);
break; break;
#endif #endif
#if defined(USE_XV) && defined(GDK_WINDOWING_X11) #if defined(USE_XV) && defined(GDK_WINDOWING_X11)
case HWA_XV: case HWA_XV:
driver = new S9xXVDisplayDriver(top_level, gui_config); driver = new S9xXVDisplayDriver(top_level, gui_config);
break; break;
#endif #endif
default:
default:
driver = new S9xGTKDisplayDriver(top_level, gui_config); driver = new S9xGTKDisplayDriver(top_level, gui_config);
} }
@ -1430,7 +1435,6 @@ static void S9xInitDriver()
if (gui_config->hw_accel > 0) if (gui_config->hw_accel > 0)
{ {
delete driver; delete driver;
gui_config->hw_accel = HWA_NONE; gui_config->hw_accel = HWA_NONE;
S9xInitDriver(); S9xInitDriver();
@ -1452,7 +1456,8 @@ S9xDisplayDriver *S9xDisplayGetDriver()
void S9xDeinitDisplay() void S9xDeinitDisplay()
{ {
driver->deinit(); if (driver)
driver->deinit();
delete driver; delete driver;
if (pool) if (pool)

View File

@ -20,8 +20,7 @@
#include "filter_epx_unsafe.h" #include "filter_epx_unsafe.h"
#include "filter/snes_ntsc.h" #include "filter/snes_ntsc.h"
enum enum {
{
FILTER_NONE = 0, FILTER_NONE = 0,
FILTER_SUPEREAGLE = 1, FILTER_SUPEREAGLE = 1,
FILTER_2XSAI = 2, FILTER_2XSAI = 2,
@ -42,21 +41,18 @@ enum
NUM_FILTERS = 17 NUM_FILTERS = 17
}; };
enum enum {
{
NTSC_COMPOSITE = 0, NTSC_COMPOSITE = 0,
NTSC_SVIDEO = 1, NTSC_SVIDEO = 1,
NTSC_RGB = 2 NTSC_RGB = 2
}; };
enum enum {
{
ENDIAN_NORMAL = 0, ENDIAN_NORMAL = 0,
ENDIAN_SWAPPED = 1 ENDIAN_SWAPPED = 1
}; };
enum enum {
{
JOB_FILTER = 0, JOB_FILTER = 0,
JOB_CONVERT = 1, JOB_CONVERT = 1,
JOB_SCALE_AND_CONVERT = 2, JOB_SCALE_AND_CONVERT = 2,
@ -81,52 +77,53 @@ typedef struct thread_job_t
volatile bool complete; volatile bool complete;
} thread_job_t; } thread_job_t;
struct S9xRect { struct S9xRect
{
int x; int x;
int y; int y;
int w; int w;
int h; int h;
}; };
void S9xRegisterYUVTables (uint8 *y, uint8 *u, uint8 *v); void S9xRegisterYUVTables(uint8 *y, uint8 *u, uint8 *v);
void S9xSetEndianess (int type); void S9xSetEndianess(int type);
double S9xGetAspect (); double S9xGetAspect();
S9xRect S9xApplyAspect (int, int, int, int); S9xRect S9xApplyAspect(int, int, int, int);
void S9xConvertYUV (void *src_buffer, void S9xConvertYUV(void *src_buffer,
void *dst_buffer, void *dst_buffer,
int src_pitch,
int dst_pitch,
int width,
int height);
void S9xConvert(void *src,
void *dst,
int src_pitch,
int dst_pitch,
int width,
int height,
int bpp);
void S9xConvertMask(void *src,
void *dst,
int src_pitch, int src_pitch,
int dst_pitch, int dst_pitch,
int width, int width,
int height); int height,
void S9xConvert (void *src, int rshift,
void *dst, int gshift,
int src_pitch, int bshift,
int dst_pitch, int bpp);
int width, void S9xFilter(uint8 *src_buffer,
int height, int src_pitch,
int bpp); uint8 *dst_buffer,
void S9xConvertMask (void *src, int dst_pitch,
void *dst, int &width,
int src_pitch, int &height);
int dst_pitch, void get_filter_scale(int &width, int &height);
int width, void S9xDisplayRefresh(int width, int height);
int height, void S9xReinitDisplay();
int rshift, void S9xDisplayReconfigure();
int gshift, void S9xQueryDrivers();
int bshift, S9xDisplayDriver *S9xDisplayGetDriver();
int bpp); bool S9xDisplayDriverIsReady();
void S9xFilter (uint8 *src_buffer,
int src_pitch,
uint8 *dst_buffer,
int dst_pitch,
int& width,
int& height);
void get_filter_scale (int& width, int& height);
void S9xDisplayRefresh (int width, int height);
void S9xReinitDisplay ();
void S9xDisplayReconfigure ();
void S9xQueryDrivers ();
S9xDisplayDriver *S9xDisplayGetDriver ();
bool S9xDisplayDriverIsReady ();
#endif /* __GTK_DISPLAY_H */ #endif /* __GTK_DISPLAY_H */

View File

@ -26,7 +26,7 @@ class S9xDisplayDriver
protected: protected:
Snes9xWindow *window; Snes9xWindow *window;
Snes9xConfig *config; Snes9xConfig *config;
GtkWidget *drawing_area; Gtk::DrawingArea *drawing_area;
}; };
#endif /* __GTK_DISPLAY_DRIVER_H*/ #endif /* __GTK_DISPLAY_DRIVER_H*/

View File

@ -4,29 +4,25 @@
For further information, consult the LICENSE file in the root directory. For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include <cairo.h> #include <cairo.h>
#include "gtk_display.h" #include "gtk_display.h"
#include "gtk_display_driver_gtk.h" #include "gtk_display_driver_gtk.h"
#include "snes9x.h"
S9xGTKDisplayDriver::S9xGTKDisplayDriver(Snes9xWindow *window, S9xGTKDisplayDriver::S9xGTKDisplayDriver(Snes9xWindow *window,
Snes9xConfig *config) Snes9xConfig *config)
{ {
this->window = window; this->window = window;
this->config = config; this->config = config;
this->drawing_area = GTK_WIDGET(window->drawing_area); this->drawing_area = window->drawing_area;
} }
void S9xGTKDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) void S9xGTKDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{ {
GtkAllocation allocation;
if (width <= 0) if (width <= 0)
return; return;
S9xRect dst = S9xApplyAspect(width, height, drawing_area->get_width(), drawing_area->get_height());
gtk_widget_get_allocation(drawing_area, &allocation);
S9xRect dst = S9xApplyAspect(width, height, allocation.width, allocation.height);
output(buffer, stride_in_pixels * 2, dst.x, dst.y, width, height, dst.w, dst.h); output(buffer, stride_in_pixels * 2, dst.x, dst.y, width, height, dst.w, dst.h);
} }
@ -48,7 +44,6 @@ void S9xGTKDisplayDriver::output(void *src,
} }
cairo_t *cr = window->get_cairo(); cairo_t *cr = window->get_cairo();
cairo_surface_t *surface; cairo_surface_t *surface;
surface = cairo_image_surface_create_for_data((unsigned char *)src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch); surface = cairo_image_surface_create_for_data((unsigned char *)src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch);
@ -94,12 +89,8 @@ void S9xGTKDisplayDriver::deinit()
void S9xGTKDisplayDriver::clear() void S9xGTKDisplayDriver::clear()
{ {
int width, height; int width = drawing_area->get_width();
GtkAllocation allocation; int height = drawing_area->get_height();
gtk_widget_get_allocation(drawing_area, &allocation);
width = allocation.width;
height = allocation.height;
cairo_t *cr = window->get_cairo(); cairo_t *cr = window->get_cairo();

View File

@ -4,7 +4,7 @@
For further information, consult the LICENSE file in the root directory. For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include <dlfcn.h> #include <dlfcn.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -85,26 +85,23 @@ S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfi
{ {
this->window = window; this->window = window;
this->config = config; this->config = config;
this->drawing_area = GTK_WIDGET(window->drawing_area); this->drawing_area = window->drawing_area;
} }
void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{ {
GtkAllocation allocation; Gtk::Allocation allocation = drawing_area->get_allocation();
gtk_widget_get_allocation(drawing_area, &allocation);
if (output_window_width != allocation.width || if (output_window_width != allocation.get_width() ||
output_window_height != allocation.height) output_window_height != allocation.get_height())
{ {
resize(); resize();
} }
#if GTK_CHECK_VERSION(3, 10, 0) int scale_factor = drawing_area->get_scale_factor();
int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window);
allocation.width *= gdk_scale_factor; allocation.set_width(allocation.get_width() * scale_factor);
allocation.height *= gdk_scale_factor; allocation.set_height(allocation.get_height() * scale_factor);
#endif
if (!legacy) if (!legacy)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
@ -118,8 +115,8 @@ void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
S9xRect content = S9xApplyAspect(width, height, allocation.width, allocation.height); S9xRect content = S9xApplyAspect(width, height, allocation.get_width(), allocation.get_height());
glViewport(content.x, allocation.height - content.y - content.h, content.w, content.h); glViewport(content.x, allocation.get_height() - content.y - content.h, content.w, content.h);
window->set_mouseable_area(content.x, content.y, content.w, content.h); window->set_mouseable_area(content.x, content.y, content.w, content.h);
update_texture_size(width, height); update_texture_size(width, height);
@ -183,7 +180,7 @@ void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int
if (using_glsl_shaders) if (using_glsl_shaders)
{ {
glsl_shader->render(texmap, width, height, content.x, allocation.height - content.y - content.h, content.w, content.h, S9xViewportCallback); glsl_shader->render(texmap, width, height, content.x, allocation.get_height() - content.y - content.h, content.w, content.h, S9xViewportCallback);
swap_buffers(); swap_buffers();
return; return;
} }
@ -468,24 +465,26 @@ void S9xOpenGLDisplayDriver::resize()
bool S9xOpenGLDisplayDriver::create_context() bool S9xOpenGLDisplayDriver::create_context()
{ {
gdk_window = gtk_widget_get_window(drawing_area); gdk_window = drawing_area->get_window()->gobj();
GdkDisplay *gdk_display = drawing_area->get_display()->gobj();
#ifdef GDK_WINDOWING_WAYLAND #ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_WINDOW(gdk_window)) if (GDK_IS_WAYLAND_WINDOW(gdk_window))
{ {
if (!wl.attach(GTK_WIDGET(drawing_area->gobj())))
return false;
context = &wl; context = &wl;
} }
#endif #endif
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_WINDOW(gdk_window)) if (GDK_IS_X11_WINDOW(gdk_window))
{ {
if (!glx.attach(gdk_x11_display_get_xdisplay(gdk_display), gdk_x11_window_get_xid(gdk_window)))
return false;
context = &glx; context = &glx;
} }
#endif #endif
if (!context->attach(drawing_area))
return false;
if (!context->create_context()) if (!context->create_context())
return false; return false;

View File

@ -14,7 +14,7 @@
#include "gtk_opengl_context.h" #include "gtk_opengl_context.h"
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
#include "gtk_glx_context.h" #include "gtk_glx_context.h"
#endif #endif

View File

@ -4,7 +4,7 @@
For further information, consult the LICENSE file in the root directory. For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include <X11/extensions/XShm.h> #include <X11/extensions/XShm.h>
#include <X11/extensions/Xv.h> #include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h> #include <X11/extensions/Xvlib.h>
@ -31,15 +31,14 @@ static int get_inv_shift(uint32 mask, int bpp)
return (bpp - i); return (bpp - i);
} }
S9xXVDisplayDriver::S9xXVDisplayDriver(Snes9xWindow *window, S9xXVDisplayDriver::S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config)
Snes9xConfig *config)
{ {
this->window = window; this->window = window;
this->config = config; this->config = config;
this->drawing_area = GTK_WIDGET(window->drawing_area); this->drawing_area = window->drawing_area;
display = display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
gdk_x11_display_get_xdisplay(gtk_widget_get_display(drawing_area)); last_known_width = -1;
last_known_width = last_known_height = -1; last_known_height = -1;
} }
void S9xXVDisplayDriver::resize_window(int width, int height) void S9xXVDisplayDriver::resize_window(int width, int height)
@ -59,12 +58,13 @@ void S9xXVDisplayDriver::create_window(int width, int height)
window_attr.y = 0; window_attr.y = 0;
window_attr.wclass = GDK_INPUT_OUTPUT; window_attr.wclass = GDK_INPUT_OUTPUT;
window_attr.window_type = GDK_WINDOW_CHILD; window_attr.window_type = GDK_WINDOW_CHILD;
window_attr.visual = gdk_x11_screen_lookup_visual(gtk_widget_get_screen(drawing_area), vi->visualid); window_attr.visual = gdk_x11_screen_lookup_visual(drawing_area->get_screen()->gobj(), vi->visualid);
gdk_window = gdk_window_new(gtk_widget_get_window(drawing_area), gdk_window = gdk_window_new(drawing_area->get_window()->gobj(),
&window_attr, &window_attr,
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL); GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
gdk_window_set_user_data(gdk_window, (gpointer)drawing_area);
gdk_window_set_user_data(gdk_window, (gpointer)drawing_area->gobj());
gdk_window_show(gdk_window); gdk_window_show(gdk_window);
xwindow = gdk_x11_window_get_xid(gdk_window); xwindow = gdk_x11_window_get_xid(gdk_window);
@ -76,26 +76,22 @@ void S9xXVDisplayDriver::create_window(int width, int height)
void S9xXVDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels) void S9xXVDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{ {
int current_width, current_height; int current_width, current_height;
GtkAllocation allocation;
gtk_widget_get_allocation(drawing_area, &allocation); auto allocation = drawing_area->get_allocation();
if (output_window_width != allocation.width || if (output_window_width != allocation.get_width() ||
output_window_height != allocation.height) output_window_height != allocation.get_height())
{ {
resize_window(allocation.width, allocation.height); resize_window(allocation.get_width(), allocation.get_height());
} }
#if GTK_CHECK_VERSION(3, 10, 0) int scale_factor = drawing_area->get_scale_factor();
int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window);
allocation.width *= gdk_scale_factor; allocation.set_width(allocation.get_width() * scale_factor);
allocation.height *= gdk_scale_factor; allocation.set_height(allocation.get_height() * scale_factor);
#endif current_width = allocation.get_width();
current_height = allocation.get_height();
current_width = allocation.width;
current_height = allocation.height;
update_image_size(width, height); update_image_size(width, height);
@ -178,7 +174,7 @@ void S9xXVDisplayDriver::update_image_size(int width, int height)
{ {
/* Can't recover, send exit. */ /* Can't recover, send exit. */
fprintf(stderr, "Couldn't reallocate shared memory.\n"); fprintf(stderr, "Couldn't reallocate shared memory.\n");
S9xExit(); exit(1);
} }
else if (shm.shmaddr != (void *)-1) else if (shm.shmaddr != (void *)-1)
{ {
@ -209,10 +205,10 @@ int S9xXVDisplayDriver::init()
GdkWindow *root; GdkWindow *root;
/* Setup XV */ /* Setup XV */
gtk_widget_realize(drawing_area); gtk_widget_realize(GTK_WIDGET(drawing_area->gobj()));
display = gdk_x11_display_get_xdisplay(gtk_widget_get_display(drawing_area)); display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
screen = gtk_widget_get_screen(drawing_area); screen = drawing_area->get_screen()->gobj();
root = gdk_screen_get_root_window(screen); root = gdk_screen_get_root_window(screen);
xv_portid = -1; xv_portid = -1;
@ -391,7 +387,7 @@ int S9xXVDisplayDriver::init()
} }
xcolormap = XCreateColormap(display, xcolormap = XCreateColormap(display,
gdk_x11_window_get_xid(gtk_widget_get_window(drawing_area)), gdk_x11_window_get_xid(drawing_area->get_window()->gobj()),
vi->visual, vi->visual,
AllocNone); AllocNone);
@ -443,20 +439,10 @@ void S9xXVDisplayDriver::deinit()
void S9xXVDisplayDriver::clear() void S9xXVDisplayDriver::clear()
{ {
int width, height;
GtkAllocation allocation;
GC xgc = XDefaultGC(display, XDefaultScreen(display)); GC xgc = XDefaultGC(display, XDefaultScreen(display));
gtk_widget_get_allocation(drawing_area, &allocation); int width = drawing_area->get_width() * drawing_area->get_scale_factor();
#if GTK_CHECK_VERSION(3, 10, 0) int height = drawing_area->get_height() * drawing_area->get_scale_factor();
int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window);
allocation.width *= gdk_scale_factor;
allocation.height *= gdk_scale_factor;
#endif
width = allocation.width;
height = allocation.height;
if (window->last_width <= 0 || window->last_height <= 0) if (window->last_width <= 0 || window->last_height <= 0)
{ {

View File

@ -7,14 +7,14 @@
#ifndef __GTK_DISPLAY_DRIVER_XV_H #ifndef __GTK_DISPLAY_DRIVER_XV_H
#define __GTK_DISPLAY_DRIVER_XV_H #define __GTK_DISPLAY_DRIVER_XV_H
#include "gtk_s9x.h"
#include "gtk_display_driver.h"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/extensions/XShm.h> #include <X11/extensions/XShm.h>
#include <X11/extensions/Xvlib.h> #include <X11/extensions/Xvlib.h>
#include "gtk_s9x.h"
#include "gtk_display_driver.h"
const uint32 FOURCC_YUY2 = 0x32595559; const uint32 FOURCC_YUY2 = 0x32595559;
class S9xXVDisplayDriver : public S9xDisplayDriver class S9xXVDisplayDriver : public S9xDisplayDriver

View File

@ -7,27 +7,29 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "display.h"
#include "memmap.h"
#include "snapshot.h"
#include "cheats.h"
static char buf[PATH_MAX]; static char buf[PATH_MAX];
const char * const char *S9xChooseMovieFilename(bool8 read_only)
S9xChooseMovieFilename (bool8 read_only)
{ {
static char path[PATH_MAX]; static char path[PATH_MAX];
if (!gui_config->rom_loaded) if (!gui_config->rom_loaded)
return ""; return "";
const char *str = top_level->open_movie_dialog (read_only); auto filename = top_level->open_movie_dialog(read_only);
strcpy (path, str); strcpy(path, filename.c_str());
return path; return path;
} }
const char * const char *S9xChooseFilename(bool8 read_only)
S9xChooseFilename (bool8 read_only)
{ {
return ""; return "";
} }
@ -37,11 +39,10 @@ S9xChooseFilename (bool8 read_only)
#define SLASH_CHAR '/' #define SLASH_CHAR '/'
#endif #endif
void void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
_splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
{ {
char *slash = strrchr ((char *) path, SLASH_CHAR); char *slash = strrchr((char *)path, SLASH_CHAR);
char *dot = strrchr ((char *) path, '.'); char *dot = strrchr((char *)path, '.');
*drive = '\0'; *drive = '\0';
@ -53,12 +54,12 @@ _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
if (!slash) if (!slash)
{ {
*dir = '\0'; *dir = '\0';
strcpy (fname, path); strcpy(fname, path);
if (dot) if (dot)
{ {
fname[dot - path] = '\0'; fname[dot - path] = '\0';
strcpy (ext, dot + 1); strcpy(ext, dot + 1);
} }
else else
{ {
@ -67,14 +68,14 @@ _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
} }
else else
{ {
strcpy (dir, path); strcpy(dir, path);
dir[slash - path] = '\0'; dir[slash - path] = '\0';
strcpy (fname, slash + 1); strcpy(fname, slash + 1);
if (dot) if (dot)
{ {
fname[(dot - slash) - 1] = '\0'; fname[(dot - slash) - 1] = '\0';
strcpy (ext, dot + 1); strcpy(ext, dot + 1);
} }
else else
{ {
@ -83,57 +84,49 @@ _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
} }
} }
void void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
_makepath (char *path,
const char *drive,
const char *dir,
const char *fname,
const char *ext)
{ {
if (dir && *dir) if (dir && *dir)
{ {
strcpy (path, dir); strcpy(path, dir);
strcat (path, "/"); strcat(path, "/");
} }
else else
*path = '\0'; *path = '\0';
strcat (path, fname); strcat(path, fname);
if (ext && *ext) if (ext && *ext)
{ {
strcat (path, "."); strcat(path, ".");
strcat (path, ext); strcat(path, ext);
} }
} }
const char * const char *S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype)
S9xGetFilenameInc (const char *e, enum s9x_getdirtype dirtype)
{ {
static char filename[PATH_MAX + 1]; static char filename[PATH_MAX + 1];
char dir[_MAX_DIR + 1]; char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1]; char drive[_MAX_DRIVE + 1];
char fname[_MAX_FNAME + 1]; char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1]; char ext[_MAX_EXT + 1];
unsigned int i = 0; unsigned int i = 0;
struct stat buf; struct stat buf;
const char *d; const char *d;
_splitpath (Memory.ROMFilename, drive, dir, fname, ext); _splitpath(Memory.ROMFilename, drive, dir, fname, ext);
d = S9xGetDirectory (dirtype); d = S9xGetDirectory(dirtype);
do do
{ {
snprintf (filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e); snprintf(filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e);
i++; i++;
} } while (stat(filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */
while (stat (filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */
return (filename); return (filename);
} }
const char * const char *S9xGetDirectory(enum s9x_getdirtype dirtype)
S9xGetDirectory (enum s9x_getdirtype dirtype)
{ {
static char path[PATH_MAX + 1]; static char path[PATH_MAX + 1];
@ -187,15 +180,15 @@ S9xGetDirectory (enum s9x_getdirtype dirtype)
{ {
char *loc; char *loc;
strcpy (path, Memory.ROMFilename); strcpy(path, Memory.ROMFilename);
loc = strrchr (path, SLASH_CHAR); loc = strrchr(path, SLASH_CHAR);
if (loc == NULL) if (loc == NULL)
{ {
if (getcwd (path, PATH_MAX + 1) == NULL) if (getcwd(path, PATH_MAX + 1) == NULL)
{ {
strcpy (path, getenv ("HOME")); strcpy(path, getenv("HOME"));
} }
} }
else else
@ -207,279 +200,197 @@ S9xGetDirectory (enum s9x_getdirtype dirtype)
return path; return path;
} }
const char * const char *S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype)
S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype)
{ {
static char filename[PATH_MAX + 1]; static char filename[PATH_MAX + 1];
char dir[_MAX_DIR + 1]; char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1]; char drive[_MAX_DRIVE + 1];
char fname[_MAX_FNAME + 1]; char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1]; char ext[_MAX_EXT + 1];
_splitpath (Memory.ROMFilename, drive, dir, fname, ext); _splitpath(Memory.ROMFilename, drive, dir, fname, ext);
snprintf (filename, sizeof (filename), "%s" SLASH_STR "%s%s", snprintf(filename, sizeof(filename), "%s" SLASH_STR "%s%s",
S9xGetDirectory (dirtype), fname, ex); S9xGetDirectory(dirtype), fname, ex);
return (filename); return (filename);
} }
const char * const char *S9xBasename(const char *f)
S9xBasename (const char *f)
{ {
const char *p; const char *p;
if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL)
return (p + 1); return (p + 1);
return f; return f;
} }
const char * const char *S9xBasenameNoExt(const char *f)
S9xBasenameNoExt (const char *f)
{ {
static char filename[PATH_MAX]; static char filename[PATH_MAX];
const char *base, *ext; const char *base, *ext;
if (!(base = strrchr (f, SLASH_CHAR))) if (!(base = strrchr(f, SLASH_CHAR)))
base = f; base = f;
else else
base += 1; base += 1;
ext = strrchr (f, '.'); ext = strrchr(f, '.');
if (!ext) if (!ext)
snprintf (filename, PATH_MAX, "%s", base); snprintf(filename, PATH_MAX, "%s", base);
else else
{ {
int len = ext - base; int len = ext - base;
strncpy (filename, base, len); strncpy(filename, base, len);
filename[len] = '\0'; filename[len] = '\0';
} }
return filename; return filename;
} }
static int static int file_exists(const char *name)
file_exists (const char *name)
{ {
FILE *f = NULL; FILE *f = NULL;
f = fopen (name, "r"); f = fopen(name, "r");
if (!f) if (!f)
return 0; return 0;
else else
{ {
fclose (f); fclose(f);
return 1; return 1;
} }
} }
bool8 bool8 S9xOpenSnapshotFile(const char *fname, bool8 read_only, STREAM *file)
S9xOpenSnapshotFile (const char *fname, bool8 read_only, STREAM *file)
{ {
char filename [PATH_MAX + 1]; char filename[PATH_MAX + 1];
char drive [_MAX_DRIVE + 1]; char drive[_MAX_DRIVE + 1];
char dir [_MAX_DIR + 1]; char dir[_MAX_DIR + 1];
char ext [_MAX_EXT + 1]; char ext[_MAX_EXT + 1];
_splitpath (fname, drive, dir, filename, ext); _splitpath(fname, drive, dir, filename, ext);
if (*drive || *dir == '/' || (*dir == '.' && (*(dir + 1) == '/'))) if (*drive || *dir == '/' || (*dir == '.' && (*(dir + 1) == '/')))
{ {
snprintf (filename, PATH_MAX + 1, "%s", fname); snprintf(filename, PATH_MAX + 1, "%s", fname);
if (!file_exists (filename)) if (!file_exists(filename))
{ {
if (!*ext) if (!*ext)
strcat (filename, ".s9x"); strcat(filename, ".s9x");
} }
} }
else else
{ {
strcpy (filename, S9xGetDirectory (SNAPSHOT_DIR)); strcpy(filename, S9xGetDirectory(SNAPSHOT_DIR));
strcat (filename, SLASH_STR); strcat(filename, SLASH_STR);
strcat (filename, fname); strcat(filename, fname);
if (!file_exists (filename)) if (!file_exists(filename))
{ {
if (!*ext) if (!*ext)
strcat (filename, ".s9x"); strcat(filename, ".s9x");
} }
} }
#ifdef ZLIB #ifdef ZLIB
if (read_only) if (read_only)
{ {
if ((*file = OPEN_STREAM (filename, "rb"))) if ((*file = OPEN_STREAM(filename, "rb")))
return (true); return (true);
else else
fprintf (stderr, fprintf(stderr,
"Failed to open file stream for reading. (%s)\n", "Failed to open file stream for reading. (%s)\n",
zError (errno)); zError(errno));
} }
else else
{ {
if ((*file = OPEN_STREAM (filename, "wb"))) if ((*file = OPEN_STREAM(filename, "wb")))
{ {
return (true); return (true);
} }
else else
{ {
fprintf (stderr, fprintf(stderr,
"Couldn't open stream with zlib. (%s)\n", "Couldn't open stream with zlib. (%s)\n",
zError (errno)); zError(errno));
} }
} }
fprintf (stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename); fprintf(stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename);
#else #else
char command [PATH_MAX]; char command[PATH_MAX];
if (read_only) if (read_only)
{ {
sprintf (command, "gzip -d <\"%s\"", filename); sprintf(command, "gzip -d <\"%s\"", filename);
if (*file = popen (command, "r")) if (*file = popen(command, "r"))
return (true); return (true);
} }
else else
{ {
sprintf (command, "gzip --best >\"%s\"", filename); sprintf(command, "gzip --best >\"%s\"", filename);
if (*file = popen (command, "wb")) if (*file = popen(command, "wb"))
return (true); return (true);
} }
fprintf (stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename); fprintf(stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename);
#endif #endif
return (false); return (false);
} }
void S9xCloseSnapshotFile (STREAM file) void S9xCloseSnapshotFile(STREAM file)
{ {
#ifdef ZLIB #ifdef ZLIB
CLOSE_STREAM (file); CLOSE_STREAM(file);
#else #else
pclose (file); pclose(file);
#endif #endif
} }
void void S9xAutoSaveSRAM()
S9xAutoSaveSRAM ()
{ {
Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR));
S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
} }
void void S9xLoadState(const char *filename)
S9xLoadState (const char *filename)
{ {
S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame (filename)) if (S9xUnfreezeGame(filename))
{ {
sprintf (buf, "%s loaded", filename); sprintf(buf, "%s loaded", filename);
S9xSetInfoString (buf); S9xSetInfoString(buf);
} }
else else
{ {
fprintf (stderr, "Failed to load state file: %s\n", filename); fprintf(stderr, "Failed to load state file: %s\n", filename);
} }
} }
void void S9xSaveState(const char *filename)
S9xSaveState (const char *filename)
{ {
if (S9xFreezeGame (filename)) if (S9xFreezeGame(filename))
{ {
sprintf (buf, "%s saved", filename); sprintf(buf, "%s saved", filename);
S9xSetInfoString (buf); S9xSetInfoString(buf);
} }
else else
{ {
fprintf (stderr, "Couldn't save state file: %s\n", filename); fprintf(stderr, "Couldn't save state file: %s\n", filename);
} }
} }
char *
S9xOpenROMDialog ()
{
GtkWidget *dialog;
GtkFileFilter *filter;
char *filename = NULL;
gint result;
const char *extensions[] =
{
"*.smc", "*.SMC", "*.fig", "*.FIG", "*.sfc", "*.SFC",
"*.jma", "*.JMA", "*.zip", "*.ZIP", "*.gd3", "*.GD3",
"*.swc", "*.SWC", "*.gz" , "*.GZ", "*.bs", "*.BS",
NULL
};
top_level->pause_from_focus_change ();
dialog = gtk_file_chooser_dialog_new (_("Open SNES ROM Image"),
top_level->get_window (),
GTK_FILE_CHOOSER_ACTION_OPEN,
"gtk-cancel", GTK_RESPONSE_CANCEL,
"gtk-open", GTK_RESPONSE_ACCEPT,
NULL);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("SNES ROM Images"));
for (int i = 0; extensions[i]; i++)
{
gtk_file_filter_add_pattern (filter, extensions[i]);
}
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("All Files"));
gtk_file_filter_add_pattern (filter, "*.*");
gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
if (!gui_config->last_directory.empty ())
{
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
gui_config->last_directory.c_str ());
}
result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (dialog);
if (result == GTK_RESPONSE_ACCEPT)
{
char *directory;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
directory =
gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
if (directory)
{
gui_config->last_directory = directory;
g_free (directory);
}
}
else
{
filename = NULL;
}
gtk_widget_destroy (dialog);
top_level->unpause_from_focus_change ();
return filename;
}
/* QuickSave/Load from S9x base controls.cpp */ /* QuickSave/Load from S9x base controls.cpp */
void void S9xQuickSaveSlot(int slot)
S9xQuickSaveSlot (int slot)
{ {
char def[PATH_MAX]; char def[PATH_MAX];
char filename[PATH_MAX]; char filename[PATH_MAX];
@ -490,21 +401,21 @@ S9xQuickSaveSlot (int slot)
if (!gui_config->rom_loaded) if (!gui_config->rom_loaded)
return; return;
_splitpath (Memory.ROMFilename, drive, dir, def, ext); _splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf (filename, PATH_MAX, "%s%s%s.%03d", snprintf(filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def,
slot); slot);
if (S9xFreezeGame (filename)) if (S9xFreezeGame(filename))
{ {
snprintf (buf, PATH_MAX, "%s.%03d saved", def, slot); snprintf(buf, PATH_MAX, "%s.%03d saved", def, slot);
S9xSetInfoString (buf); S9xSetInfoString(buf);
} }
} }
void S9xQuickLoadSlot (int slot) void S9xQuickLoadSlot(int slot)
{ {
char def[PATH_MAX]; char def[PATH_MAX];
char filename[PATH_MAX]; char filename[PATH_MAX];
@ -515,44 +426,43 @@ void S9xQuickLoadSlot (int slot)
if (!gui_config->rom_loaded) if (!gui_config->rom_loaded)
return; return;
_splitpath (Memory.ROMFilename, drive, dir, def, ext); _splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf (filename, PATH_MAX, "%s%s%s.%03d", snprintf(filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def,
slot); slot);
if (file_exists (filename)) if (file_exists(filename))
S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame (filename)) if (S9xUnfreezeGame(filename))
{ {
snprintf (buf, PATH_MAX, "%s.%03d loaded", def, slot); snprintf(buf, PATH_MAX, "%s.%03d loaded", def, slot);
S9xSetInfoString (buf); S9xSetInfoString(buf);
return; return;
} }
static const char *digits = "t123456789"; static const char *digits = "t123456789";
_splitpath (Memory.ROMFilename, drive, dir, def, ext); _splitpath(Memory.ROMFilename, drive, dir, def, ext);
snprintf (filename, PATH_MAX, "%s%s%s.zs%c", snprintf(filename, PATH_MAX, "%s%s%s.zs%c",
S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR,
def, digits[slot]); def, digits[slot]);
if (file_exists (filename)) if (file_exists(filename))
S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR)); S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame (filename)) if (S9xUnfreezeGame(filename))
{ {
snprintf (buf, PATH_MAX, snprintf(buf, PATH_MAX,
"Loaded ZSNES freeze file %s.zs%c", "Loaded ZSNES freeze file %s.zs%c",
def, digits [slot]); def, digits[slot]);
S9xSetInfoString (buf); S9xSetInfoString(buf);
return; return;
} }
S9xMessage (S9X_ERROR, S9xMessage(S9X_ERROR,
S9X_FREEZE_FILE_NOT_FOUND, S9X_FREEZE_FILE_NOT_FOUND,
"Freeze file not found"); "Freeze file not found");
} }

View File

@ -7,13 +7,12 @@
#ifndef __GTK_FILE_H #ifndef __GTK_FILE_H
#define __GTK_FILE_H #define __GTK_FILE_H
char *S9xOpenROMDialog (); const char *S9xBasenameNoExt(const char *);
const char *S9xBasenameNoExt (const char *);
void S9xLoadState (const char *filename); void S9xLoadState(const char *filename);
void S9xSaveState (const char *filename); void S9xSaveState(const char *filename);
void S9xQuickSaveSlot (int slot); void S9xQuickSaveSlot(int slot);
void S9xQuickLoadSlot (int slot); void S9xQuickLoadSlot(int slot);
#endif /* __GTK_FILE_H */ #endif /* __GTK_FILE_H */

View File

@ -6,99 +6,61 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_glx_context.h" #include "gtk_glx_context.h"
#include "gtk_2_3_compat.h"
GTKGLXContext::GTKGLXContext () GTKGLXContext::GTKGLXContext()
{ {
gdk_display = NULL; display = NULL;
parent_gdk_window = NULL; context = NULL;
gdk_window = NULL;
display = NULL;
vi = NULL;
context = NULL;
version_major = -1; version_major = -1;
version_minor = -1; version_minor = -1;
use_oml_sync_control = false; use_oml_sync_control = false;
ust = msc = sbc = 0; ust = msc = sbc = 0;
} }
GTKGLXContext::~GTKGLXContext () GTKGLXContext::~GTKGLXContext()
{ {
if (context) if (context)
glXDestroyContext (display, context); glXDestroyContext(display, context);
if (gdk_window)
gdk_window_destroy (gdk_window);
if (vi)
XFree (vi);
} }
bool GTKGLXContext::attach (GtkWidget *widget) bool GTKGLXContext::attach(Display *dpy, Window xid)
{ {
GdkScreen *gdk_screen;
GdkWindow *window;
GLXFBConfig *fbconfigs; GLXFBConfig *fbconfigs;
int num_fbconfigs; int num_fbconfigs;
int attribs[] = { int attribs[] = {
GLX_DOUBLEBUFFER, True, GLX_DOUBLEBUFFER, True,
GLX_X_RENDERABLE, True, GLX_X_RENDERABLE, True,
GLX_RED_SIZE, 8, GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8, GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8, GLX_BLUE_SIZE, 8,
None None
}; };
window = gtk_widget_get_window (widget); this->xid = xid;
this->widget = widget; display = dpy;
if (!GDK_IS_X11_WINDOW (window)) glXQueryVersion(display, &version_major, &version_minor);
return false;
parent_gdk_window = window;
gdk_display = gdk_window_get_display (window);
gdk_screen = gdk_window_get_screen (window);
screen = gdk_x11_screen_get_screen_number (gdk_screen);
display = GDK_DISPLAY_XDISPLAY (gdk_display);
glXQueryVersion (display, &version_major, &version_minor);
if (version_major < 2 && version_minor < 3) if (version_major < 2 && version_minor < 3)
return false; return false;
fbconfigs = glXChooseFBConfig (display, screen, attribs, &num_fbconfigs); fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_fbconfigs);
if (!fbconfigs || num_fbconfigs < 1) if (!fbconfigs || num_fbconfigs < 1)
{ {
printf ("Couldn't match a GLX framebuffer config.\n"); printf("Couldn't match a GLX framebuffer config.\n");
return false; return false;
} }
fbconfig = fbconfigs[0]; fbconfig = fbconfigs[0];
XFree(fbconfigs);
vi = glXGetVisualFromFBConfig (display, fbconfig);
gdk_window_get_geometry (parent_gdk_window, &x, &y, &width, &height);
memset (&window_attr, 0, sizeof (GdkWindowAttr));
window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
window_attr.width = width;
window_attr.height = height;
window_attr.wclass = GDK_INPUT_OUTPUT;
window_attr.window_type = GDK_WINDOW_CHILD;
window_attr.visual = gdk_x11_screen_lookup_visual (gdk_screen, vi->visualid);
gdk_window = gdk_window_new (window, &window_attr, GDK_WA_VISUAL);
gdk_window_set_user_data (gdk_window, (gpointer) widget);
gdk_window_show (gdk_window);
xid = gdk_x11_window_get_xid (gdk_window);
return true; return true;
} }
bool GTKGLXContext::create_context () bool GTKGLXContext::create_context()
{ {
int context_attribs[] = { int context_attribs[] = {
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
@ -107,18 +69,21 @@ bool GTKGLXContext::create_context ()
None None
}; };
const char *extensions = glXQueryExtensionsString (display, screen); const char *extensions = glXQueryExtensionsString(display, screen);
gdk_x11_display_error_trap_push(gdk_display); XSetErrorHandler([](Display *dpy, XErrorEvent *event) -> int {
if (strstr (extensions, "GLX_ARB_create_context")) printf("XError: type: %d code: %d\n", event->type, event->error_code);
context = glXCreateContextAttribsARB (display, fbconfig, NULL, True, context_attribs); return X_OK;
});
if (strstr(extensions, "GLX_ARB_create_context"))
context = glXCreateContextAttribsARB(display, fbconfig, NULL, True, context_attribs);
if (!context) if (!context)
context = glXCreateNewContext (display, fbconfig, GLX_RGBA_TYPE, NULL, True); context = glXCreateNewContext(display, fbconfig, GLX_RGBA_TYPE, NULL, True);
gdk_x11_display_error_trap_pop_ignored(gdk_display); XSetErrorHandler(nullptr);
if (!context) if (!context)
{ {
printf ("Couldn't create GLX context.\n"); printf("Couldn't create GLX context.\n");
return false; return false;
} }
@ -128,31 +93,27 @@ bool GTKGLXContext::create_context ()
return true; return true;
} }
void GTKGLXContext::resize () void GTKGLXContext::resize()
{ {
gdk_window_get_geometry (parent_gdk_window, &x, &y, &width, &height); while (!ready())
usleep(100);
if (window_attr.width == width && window_attr.height == height) unsigned int width;
return; unsigned int height;
glXQueryDrawable(display, xid, GLX_WIDTH, &width);
glXQueryDrawable(display, xid, GLX_HEIGHT, &height);
window_attr.width = width; this->width = width;
window_attr.height = height; this->height = height;
make_current();
gdk_window_destroy (gdk_window);
gdk_window = gdk_window_new (parent_gdk_window, &window_attr, GDK_WA_VISUAL);
gdk_window_set_user_data (gdk_window, (gpointer) widget);
gdk_window_show (gdk_window);
xid = gdk_x11_window_get_xid (gdk_window);
make_current ();
} }
void GTKGLXContext::swap_buffers () void GTKGLXContext::swap_buffers()
{ {
if (use_oml_sync_control) if (use_oml_sync_control)
glXGetSyncValuesOML(display, xid, &ust, &msc, &sbc); glXGetSyncValuesOML(display, xid, &ust, &msc, &sbc);
glXSwapBuffers (display, xid); glXSwapBuffers(display, xid);
} }
bool GTKGLXContext::ready() bool GTKGLXContext::ready()
@ -170,21 +131,19 @@ bool GTKGLXContext::ready()
return true; return true;
} }
void GTKGLXContext::make_current () void GTKGLXContext::make_current()
{ {
glXMakeCurrent (display, xid, context); glXMakeCurrent(display, xid, context);
} }
void GTKGLXContext::swap_interval (int frames) void GTKGLXContext::swap_interval(int frames)
{ {
if (epoxy_has_glx_extension (display, screen, "GLX_EXT_swap_control")) if (epoxy_has_glx_extension(display, screen, "GLX_EXT_swap_control"))
glXSwapIntervalEXT (display, xid, frames); glXSwapIntervalEXT(display, xid, frames);
else if (epoxy_has_glx_extension (display, screen, "GLX_SGI_swap_control")) else if (epoxy_has_glx_extension(display, screen, "GLX_SGI_swap_control"))
glXSwapIntervalSGI (frames); glXSwapIntervalSGI(frames);
#ifdef GLX_MESA_swap_control #ifdef GLX_MESA_swap_control
else if (epoxy_has_glx_extension (display, screen, "GLX_MESA_swap_control")) else if (epoxy_has_glx_extension(display, screen, "GLX_MESA_swap_control"))
glXSwapIntervalMESA (frames); glXSwapIntervalMESA(frames);
#endif #endif
} }

View File

@ -7,36 +7,27 @@
#ifndef __GTK_GLX_CONTEXT_H #ifndef __GTK_GLX_CONTEXT_H
#define __GTK_GLX_CONTEXT_H #define __GTK_GLX_CONTEXT_H
#include "gtk_2_3_compat.h"
#include <epoxy/glx.h>
#include "gtk_opengl_context.h" #include "gtk_opengl_context.h"
#include <epoxy/glx.h>
class GTKGLXContext : public OpenGLContext class GTKGLXContext : public OpenGLContext
{ {
public: public:
GTKGLXContext (); GTKGLXContext();
~GTKGLXContext (); ~GTKGLXContext();
bool attach (GtkWidget *widget); bool attach(Display *dpy, Window xid);
bool create_context (); bool create_context();
void resize (); void resize();
void swap_buffers (); void swap_buffers();
void swap_interval (int frames); void swap_interval(int frames);
void make_current (); void make_current();
bool ready(); bool ready();
GtkWidget *widget;
GdkDisplay *gdk_display;
GdkWindow *parent_gdk_window;
GdkWindow *gdk_window;
GdkWindowAttr window_attr;
GLXContext context; GLXContext context;
GLXFBConfig fbconfig; GLXFBConfig fbconfig;
Display *display; Display *display;
int screen; int screen;
XVisualInfo *vi;
Window xid; Window xid;
int version_major; int version_major;

View File

@ -10,133 +10,132 @@
#include "gtk_netplay_dialog.h" #include "gtk_netplay_dialog.h"
#include "gtk_netplay.h" #include "gtk_netplay.h"
#include "gtk_sound.h" #include "gtk_sound.h"
#include "snes9x.h"
#include "memmap.h"
#include "netplay.h"
#include "cpuexec.h"
#include "display.h"
#include "ppu.h"
uint16 MovieGetJoypad (int i); uint16 MovieGetJoypad(int i);
void MovieSetJoypad (int i, uint16 buttons); void MovieSetJoypad(int i, uint16 buttons);
static uint32 local_joypads[8], joypads[8]; static uint32 local_joypads[8], joypads[8];
static GThread *npthread; static GThread *npthread;
extern SNPServer NPServer; extern SNPServer NPServer;
static void static void S9xNetplayPreconnect()
S9xNetplayPreconnect ()
{ {
S9xNetplayDisconnect (); S9xNetplayDisconnect();
if (gui_config->rom_loaded) if (gui_config->rom_loaded)
{ {
S9xAutoSaveSRAM (); S9xAutoSaveSRAM();
} }
NetPlay.MaxBehindFrameCount = gui_config->netplay_max_frame_loss; NetPlay.MaxBehindFrameCount = gui_config->netplay_max_frame_loss;
NetPlay.Waiting4EmulationThread = false; NetPlay.Waiting4EmulationThread = false;
} }
static void static void S9xNetplayConnect()
S9xNetplayConnect ()
{ {
GtkWidget *msg; GtkWidget *msg;
S9xNetplayPreconnect (); S9xNetplayPreconnect();
uint32 flags = CPU.Flags; uint32 flags = CPU.Flags;
if (!gui_config->netplay_last_rom.empty () && if (!gui_config->netplay_last_rom.empty() &&
!top_level->try_open_rom (gui_config->netplay_last_rom.c_str ())) !top_level->try_open_rom(gui_config->netplay_last_rom))
{ {
return; return;
} }
if (!S9xNPConnectToServer (gui_config->netplay_last_host.c_str (), if (!S9xNPConnectToServer(gui_config->netplay_last_host.c_str(),
gui_config->netplay_last_port, gui_config->netplay_last_port,
Memory.ROMName)) Memory.ROMName))
{ {
msg = gtk_message_dialog_new (NULL, msg = gtk_message_dialog_new(NULL,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE, GTK_BUTTONS_CLOSE,
"Couldn't connect to server: %s:%d", "Couldn't connect to server: %s:%d",
gui_config->netplay_last_host.c_str (), gui_config->netplay_last_host.c_str(),
gui_config->netplay_last_port); gui_config->netplay_last_port);
gtk_window_set_title (GTK_WINDOW (msg), _("Connection Error")); gtk_window_set_title(GTK_WINDOW(msg), _("Connection Error"));
gtk_dialog_run (GTK_DIALOG (msg)); gtk_dialog_run(GTK_DIALOG(msg));
gtk_widget_destroy (msg); gtk_widget_destroy(msg);
} }
gui_config->netplay_activated = true; gui_config->netplay_activated = true;
/* If no rom is specified, assume we'll get it from the server */ /* If no rom is specified, assume we'll get it from the server */
if (gui_config->netplay_last_rom.empty ()) if (gui_config->netplay_last_rom.empty())
{ {
Settings.StopEmulation = false; Settings.StopEmulation = false;
S9xROMLoaded (); S9xROMLoaded();
} }
S9xReset (); S9xReset();
CPU.Flags = flags; CPU.Flags = flags;
top_level->configure_widgets (); top_level->configure_widgets();
} }
void void S9xNetplaySyncClients()
S9xNetplaySyncClients ()
{ {
if (Settings.NetPlay && Settings.NetPlayServer) if (Settings.NetPlay && Settings.NetPlayServer)
S9xNPServerQueueSyncAll (); S9xNPServerQueueSyncAll();
} }
void void S9xNetplayStopServer()
S9xNetplayStopServer ()
{ {
S9xNPStopServer (); S9xNPStopServer();
g_thread_join (npthread); g_thread_join(npthread);
Settings.NetPlayServer = false; Settings.NetPlayServer = false;
gui_config->netplay_server_up = false; gui_config->netplay_server_up = false;
} }
void void S9xNetplayDisconnect()
S9xNetplayDisconnect ()
{ {
if (Settings.NetPlay) if (Settings.NetPlay)
{ {
if (NetPlay.Connected) if (NetPlay.Connected)
S9xNPDisconnect (); S9xNPDisconnect();
} }
if (gui_config->netplay_server_up) if (gui_config->netplay_server_up)
{ {
S9xNetplayStopServer (); S9xNetplayStopServer();
} }
gui_config->netplay_activated = false; gui_config->netplay_activated = false;
NetPlay.Paused = false; NetPlay.Paused = false;
top_level->configure_widgets (); top_level->configure_widgets();
} }
static gpointer static gpointer S9xNetplayServerThread(gpointer)
S9xNetplayServerThread (gpointer)
{ {
S9xNPStartServer (gui_config->netplay_default_port); S9xNPStartServer(gui_config->netplay_default_port);
return NULL; return NULL;
} }
void void S9xNetplayStartServer()
S9xNetplayStartServer ()
{ {
uint32 flags; uint32 flags;
S9xNetplayPreconnect (); S9xNetplayPreconnect();
flags = CPU.Flags; flags = CPU.Flags;
if (gui_config->netplay_last_rom.empty () || if (gui_config->netplay_last_rom.empty() ||
!top_level->try_open_rom (gui_config->netplay_last_rom.c_str ())) !top_level->try_open_rom(gui_config->netplay_last_rom))
{ {
return; return;
} }
@ -145,105 +144,103 @@ S9xNetplayStartServer ()
NPServer.SyncByReset = gui_config->netplay_sync_reset; NPServer.SyncByReset = gui_config->netplay_sync_reset;
NPServer.SendROMImageOnConnect = gui_config->netplay_send_rom; NPServer.SendROMImageOnConnect = gui_config->netplay_send_rom;
npthread = g_thread_new (NULL, S9xNetplayServerThread, NULL); npthread = g_thread_new(NULL, S9xNetplayServerThread, NULL);
/* Sleep to let the server create itself */ /* Sleep to let the server create itself */
usleep (10000); usleep(10000);
S9xNPConnectToServer ("127.0.0.1", S9xNPConnectToServer("127.0.0.1",
gui_config->netplay_default_port, gui_config->netplay_default_port,
Memory.ROMName); Memory.ROMName);
S9xReset (); S9xReset();
S9xROMLoaded (); S9xROMLoaded();
gui_config->netplay_activated = true; gui_config->netplay_activated = true;
gui_config->netplay_server_up = true; gui_config->netplay_server_up = true;
CPU.Flags = flags; CPU.Flags = flags;
top_level->configure_widgets (); top_level->configure_widgets();
} }
void void S9xNetplayDialogOpen()
S9xNetplayDialogOpen ()
{ {
Snes9xNetplayDialog *np_dialog; Snes9xNetplayDialog *np_dialog;
top_level->pause_from_focus_change (); top_level->pause_from_focus_change();
np_dialog = new Snes9xNetplayDialog (gui_config); np_dialog = new Snes9xNetplayDialog(gui_config);
gtk_window_set_transient_for (np_dialog->get_window (), gtk_window_set_transient_for(np_dialog->get_window(),
top_level->get_window ()); top_level->get_window());
if (np_dialog->show ()) if (np_dialog->show())
{ {
if (!gui_config->netplay_is_server) if (!gui_config->netplay_is_server)
{ {
S9xNetplayConnect (); S9xNetplayConnect();
} }
else else
{ {
S9xNetplayStartServer (); S9xNetplayStartServer();
} }
S9xSoundStart (); S9xSoundStart();
} }
delete np_dialog; delete np_dialog;
top_level->unpause_from_focus_change (); top_level->unpause_from_focus_change();
} }
int int S9xNetplaySyncSpeed()
S9xNetplaySyncSpeed ()
{ {
if (!Settings.NetPlay || !NetPlay.Connected) if (!Settings.NetPlay || !NetPlay.Connected)
return 0; return 0;
// Send 1st joypad's position update to server // Send 1st joypad's position update to server
S9xNPSendJoypadUpdate (local_joypads[0]); S9xNPSendJoypadUpdate(local_joypads[0]);
// set input from network // set input from network
for (int i = 0; i < NP_MAX_CLIENTS; i++) for (int i = 0; i < NP_MAX_CLIENTS; i++)
joypads[i] = S9xNPGetJoypad (i); joypads[i] = S9xNPGetJoypad(i);
if (!S9xNPCheckForHeartBeat ()) if (!S9xNPCheckForHeartBeat())
{ {
// No heartbeats already arrived, have to wait for one. // No heartbeats already arrived, have to wait for one.
NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (100); NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay(100);
IPPU.RenderThisFrame = true; IPPU.RenderThisFrame = true;
IPPU.SkippedFrames = 0; IPPU.SkippedFrames = 0;
} }
else else
{ {
int difference = (int) (NetPlay.MySequenceNum) - int difference = (int)(NetPlay.MySequenceNum) -
(int) (NetPlay.ServerSequenceNum); (int)(NetPlay.ServerSequenceNum);
if (difference < 0) if (difference < 0)
difference += 256; difference += 256;
if (NetPlay.Waiting4EmulationThread) if (NetPlay.Waiting4EmulationThread)
{ {
if ((unsigned int) difference <= (NetPlay.MaxBehindFrameCount / 2)) if ((unsigned int)difference <= (NetPlay.MaxBehindFrameCount / 2))
{ {
NetPlay.Waiting4EmulationThread = false; NetPlay.Waiting4EmulationThread = false;
S9xNPSendPause (false); S9xNPSendPause(false);
} }
} }
else else
{ {
if ((unsigned int) difference >= (NetPlay.MaxBehindFrameCount)) if ((unsigned int)difference >= (NetPlay.MaxBehindFrameCount))
{ {
NetPlay.Waiting4EmulationThread = true; NetPlay.Waiting4EmulationThread = true;
S9xNPSendPause (true); S9xNPSendPause(true);
} }
} }
NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (200); NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay(200);
if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip) if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip)
{ {
@ -260,27 +257,26 @@ S9xNetplaySyncSpeed ()
if (!NetPlay.PendingWait4Sync) if (!NetPlay.PendingWait4Sync)
{ {
NetPlay.FrameCount++; NetPlay.FrameCount++;
S9xNPStepJoypadHistory (); S9xNPStepJoypadHistory();
} }
return 1; return 1;
} }
int int S9xNetplayPush()
S9xNetplayPush ()
{ {
if (gui_config->netplay_activated && if (gui_config->netplay_activated &&
(!Settings.NetPlay || !NetPlay.Connected)) (!Settings.NetPlay || !NetPlay.Connected))
S9xNetplayDisconnect (); S9xNetplayDisconnect();
if (!Settings.NetPlay) if (!Settings.NetPlay)
return 0; return 0;
if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay (100)) if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay(100))
{ {
S9xProcessEvents (false); S9xProcessEvents(false);
S9xSoundStop (); S9xSoundStop();
NetPlay.Paused = true; NetPlay.Paused = true;
return 1; return 1;
@ -288,36 +284,31 @@ S9xNetplayPush ()
NetPlay.Paused = false; NetPlay.Paused = false;
S9xSoundStart (); S9xSoundStart();
/* Save the joypad input */ /* Save the joypad input */
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
local_joypads[i] = MovieGetJoypad (i); local_joypads[i] = MovieGetJoypad(i);
MovieSetJoypad (i, joypads[i]); MovieSetJoypad(i, joypads[i]);
} }
if (NetPlay.PendingWait4Sync) if (NetPlay.PendingWait4Sync)
{ {
NetPlay.PendingWait4Sync = false; NetPlay.PendingWait4Sync = false;
NetPlay.FrameCount++; NetPlay.FrameCount++;
S9xNPStepJoypadHistory (); S9xNPStepJoypadHistory();
} }
return 0; return 0;
} }
void void S9xNetplayPop()
S9xNetplayPop ()
{ {
if (!Settings.NetPlay) if (!Settings.NetPlay)
return; return;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
MovieSetJoypad (i, local_joypads[i]); MovieSetJoypad(i, local_joypads[i]);
} }

View File

@ -7,11 +7,11 @@
#ifndef __GTK_NETPLAY_H #ifndef __GTK_NETPLAY_H
#define __GTK_NETPLAY_H #define __GTK_NETPLAY_H
void S9xNetplayDialogOpen (); void S9xNetplayDialogOpen();
int S9xNetplayPush (); int S9xNetplayPush();
void S9xNetplayPop (); void S9xNetplayPop();
int S9xNetplaySyncSpeed (); int S9xNetplaySyncSpeed();
void S9xNetplaySyncClients (); void S9xNetplaySyncClients();
void S9xNetplayDisconnect (); void S9xNetplayDisconnect();
#endif /* __GTK_NETPLAY_H */ #endif /* __GTK_NETPLAY_H */

View File

@ -6,133 +6,91 @@
#include "gtk_netplay_dialog.h" #include "gtk_netplay_dialog.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_file.h"
static void Snes9xNetplayDialog::Snes9xNetplayDialog(Snes9xConfig *config)
event_browse_clicked (GtkButton *button, gpointer data) : GtkBuilderWindow("netplay_dialog")
{ {
char *filename; get_object<Gtk::RadioButton>("host_radio")->signal_toggled().connect([&] {
Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; update_state();
});
filename = S9xOpenROMDialog (); get_object<Gtk::Button>("clear_netplay")->signal_clicked().connect([&] {
get_object<Gtk::Entry>("rom_image")->set_text("");
});
if (filename) get_object<Gtk::Button>("browse_button")->signal_clicked().connect([&] {
{ auto filename = top_level->open_rom_dialog(false);
gtk_entry_set_text (GTK_ENTRY (np_dialog->get_widget ("rom_image")), if (!filename.empty())
filename); get_object<Gtk::Entry>("rom_image")->set_text(filename);
});
g_free (filename);
}
}
static void
event_clear_clicked (GtkButton *button, gpointer data)
{
Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data;
gtk_entry_set_text (GTK_ENTRY (np_dialog->get_widget ("rom_image")), "");
}
static void
event_server_toggled (GtkToggleButton *toggle, gpointer data)
{
Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data;
np_dialog->update_state ();
}
Snes9xNetplayDialog::Snes9xNetplayDialog (Snes9xConfig *config) :
GtkBuilderWindow ("netplay_dialog")
{
GtkBuilderWindowCallbacks callbacks[] =
{
{ "server_toggled", G_CALLBACK (event_server_toggled) },
{ "browse_clicked", G_CALLBACK (event_browse_clicked) },
{ "clear_clicked", G_CALLBACK (event_clear_clicked) },
{ NULL, NULL }
};
signal_connect (callbacks);
this->config = config; this->config = config;
} }
void Snes9xNetplayDialog::~Snes9xNetplayDialog()
Snes9xNetplayDialog::update_state ()
{ {
if (get_check ("host_radio")) }
void Snes9xNetplayDialog::update_state()
{
if (get_check("host_radio"))
{ {
enable_widget ("connect_box", false); enable_widget("connect_box", false);
enable_widget ("default_port_box", true); enable_widget("default_port_box", true);
enable_widget ("sync_reset", true); enable_widget("sync_reset", true);
enable_widget ("send_image", true); enable_widget("send_image", true);
} }
else else
{ {
enable_widget ("connect_box", true); enable_widget("connect_box", true);
enable_widget ("default_port_box", false); enable_widget("default_port_box", false);
enable_widget ("sync_reset", false); enable_widget("sync_reset", false);
enable_widget ("send_image", false); enable_widget("send_image", false);
} }
} }
void void Snes9xNetplayDialog::settings_to_dialog()
Snes9xNetplayDialog::settings_to_dialog ()
{ {
set_entry_text ("rom_image", config->netplay_last_rom.c_str ()); set_entry_text("rom_image", config->netplay_last_rom.c_str());
set_entry_text ("ip_entry", config->netplay_last_host.c_str ()); set_entry_text("ip_entry", config->netplay_last_host.c_str());
set_check ("sync_reset", config->netplay_sync_reset); set_check("sync_reset", config->netplay_sync_reset);
set_check ("send_image", config->netplay_send_rom); set_check("send_image", config->netplay_send_rom);
set_spin ("port", config->netplay_last_port); set_spin("port", config->netplay_last_port);
set_spin ("default_port", config->netplay_default_port); set_spin("default_port", config->netplay_default_port);
set_spin ("frames_behind", config->netplay_max_frame_loss); set_spin("frames_behind", config->netplay_max_frame_loss);
set_check ("connect_radio", !config->netplay_is_server); set_check("connect_radio", !config->netplay_is_server);
set_check ("host_radio", config->netplay_is_server); set_check("host_radio", config->netplay_is_server);
update_state (); update_state();
} }
void void Snes9xNetplayDialog::settings_from_dialog()
Snes9xNetplayDialog::settings_from_dialog ()
{ {
config->netplay_last_rom = get_entry_text ("rom_image"); config->netplay_last_rom = get_entry_text("rom_image");
config->netplay_last_host = get_entry_text ("ip_entry"); config->netplay_last_host = get_entry_text("ip_entry");
config->netplay_sync_reset = get_check ("sync_reset"); config->netplay_sync_reset = get_check("sync_reset");
config->netplay_send_rom = get_check ("send_image"); config->netplay_send_rom = get_check("send_image");
config->netplay_last_port = get_spin ("port"); config->netplay_last_port = get_spin("port");
config->netplay_default_port = get_spin ("default_port"); config->netplay_default_port = get_spin("default_port");
config->netplay_max_frame_loss = get_spin ("frames_behind"); config->netplay_max_frame_loss = get_spin("frames_behind");
config->netplay_is_server = get_check ("host_radio"); config->netplay_is_server = get_check("host_radio");
config->save_config_file (); config->save_config_file();
} }
bool Snes9xNetplayDialog::show() bool Snes9xNetplayDialog::show()
{ {
int result; settings_to_dialog();
settings_to_dialog (); auto result = Glib::RefPtr<Gtk::Dialog>::cast_static(window)->run();
window->hide();
result = gtk_dialog_run (GTK_DIALOG (window)); if (result == Gtk::RESPONSE_OK)
gtk_widget_hide (window);
if (result == GTK_RESPONSE_OK)
{ {
settings_from_dialog (); settings_from_dialog();
return true; return true;
} }
else return false;
{
return false;
}
}
Snes9xNetplayDialog::~Snes9xNetplayDialog ()
{
gtk_widget_destroy (window);
} }

View File

@ -12,17 +12,16 @@
class Snes9xNetplayDialog : public GtkBuilderWindow class Snes9xNetplayDialog : public GtkBuilderWindow
{ {
public: public:
Snes9xNetplayDialog (Snes9xConfig *config); Snes9xNetplayDialog(Snes9xConfig *config);
~Snes9xNetplayDialog (); ~Snes9xNetplayDialog();
bool show (); bool show();
void update_state (); void update_state();
private: private:
Snes9xConfig *config; Snes9xConfig *config;
void settings_to_dialog (); void settings_to_dialog();
void settings_from_dialog (); void settings_from_dialog();
}; };
#endif /* __GTK_NETPLAY_DIALOG_H */ #endif /* __GTK_NETPLAY_DIALOG_H */

View File

@ -7,19 +7,19 @@
#ifndef __GTK_OPENGL_CONTEXT_H #ifndef __GTK_OPENGL_CONTEXT_H
#define __GTK_OPENGL_CONTEXT_H #define __GTK_OPENGL_CONTEXT_H
#include "gtk_2_3_compat.h"
class OpenGLContext class OpenGLContext
{ {
public: public:
virtual ~OpenGLContext () {}; virtual ~OpenGLContext(){};
virtual bool attach (GtkWidget *widget) = 0; virtual bool create_context() = 0;
virtual bool create_context () = 0; virtual void resize() = 0;
virtual void resize () = 0; virtual void swap_buffers() = 0;
virtual void swap_buffers () = 0; virtual void swap_interval(int frames) = 0;
virtual void swap_interval (int frames) = 0; virtual void make_current() = 0;
virtual void make_current () = 0; virtual bool ready()
virtual bool ready() { return true; }; {
return true;
};
int x; int x;
int y; int y;

File diff suppressed because it is too large Load Diff

View File

@ -7,45 +7,47 @@
#ifndef __GTK_PREFERENCES_H #ifndef __GTK_PREFERENCES_H
#define __GTK_PREFERENCES_H #define __GTK_PREFERENCES_H
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_builder_window.h" #include "gtk_builder_window.h"
gboolean snes9x_preferences_open (GtkWidget *widget, void snes9x_preferences_open(Snes9xWindow *window, Snes9xConfig *config);
gpointer data);
class Snes9xPreferences : public GtkBuilderWindow class Snes9xPreferences : public GtkBuilderWindow
{ {
public: public:
Snes9xPreferences (Snes9xConfig *config); Snes9xPreferences(Snes9xConfig *config);
~Snes9xPreferences (); ~Snes9xPreferences();
void show (); void show();
void bindings_to_dialog (int joypad); void bindings_to_dialog(int joypad);
int get_focused_binding (); int get_focused_binding();
void store_binding (const char *string, Binding binding); void store_binding(const char *string, Binding binding);
void browse_folder_dialog (); int hw_accel_value(int combo_value);
int hw_accel_value (int combo_value); int combo_value(int hw_accel);
int combo_value (int hw_accel); void focus_next();
void focus_next (); void swap_with();
void swap_with (); void clear_binding(const char *name);
void clear_binding (const char *name); void reset_current_joypad();
void reset_current_joypad (); void load_ntsc_settings();
void load_ntsc_settings (); void store_ntsc_settings();
void store_ntsc_settings (); void calibration_dialog();
void calibration_dialog (); void connect_signals();
void input_rate_changed();
bool key_pressed(GdkEventKey *event);
void scale_method_changed();
void shader_select();
void game_data_browse(std::string folder);
void about_dialog();
Snes9xConfig *config; Snes9xConfig *config;
GtkToggleButton *last_toggled; bool awaiting_key;
bool awaiting_key; bool polling_joystick;
bool polling_joystick; std::array<JoypadBinding, NUM_JOYPADS> pad;
std::array<JoypadBinding, NUM_JOYPADS> pad; std::array<Binding, NUM_EMU_LINKS> shortcut;
std::array<Binding, NUM_EMU_LINKS> shortcut;
private: private:
void get_settings_from_dialog (); void get_settings_from_dialog();
void move_settings_to_dialog (); void move_settings_to_dialog();
unsigned int *mode_indices;
}; };
#endif /* __GTK_PREFERENCES_H */ #endif /* __GTK_PREFERENCES_H */

View File

@ -6,7 +6,9 @@
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
#include "gtk_2_3_compat.h" #include "giomm/application.h"
#include "glibmm/main.h"
#include "gtk_compat.h"
#include "gtk_config.h" #include "gtk_config.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_control.h" #include "gtk_control.h"
@ -15,84 +17,85 @@
#include "gtk_netplay.h" #include "gtk_netplay.h"
#include "statemanager.h" #include "statemanager.h"
#include "background_particles.h" #include "background_particles.h"
#include "snes9x.h"
#include "display.h"
#include "apu/apu.h"
#include "netplay.h"
#include "movie.h"
#include "controls.h"
#include "snapshot.h"
#include "gfx.h"
#include "memmap.h"
#include "ppu.h"
void S9xPostRomInit (); static void S9xThrottle(int);
static void S9xThrottle (int); static void S9xCheckPointerTimer();
static void S9xCheckPointerTimer (); static bool S9xIdleFunc();
static gboolean S9xIdleFunc (gpointer data); static bool S9xPauseFunc();
static gboolean S9xPauseFunc (gpointer data); static bool S9xScreenSaverCheckFunc();
static gboolean S9xScreenSaverCheckFunc (gpointer data);
Snes9xWindow *top_level; Snes9xWindow *top_level;
Snes9xConfig *gui_config; Snes9xConfig *gui_config;
StateManager state_manager; StateManager state_manager;
gint64 frame_clock = -1; gint64 frame_clock = -1;
gint64 pointer_timestamp = -1; gint64 pointer_timestamp = -1;
Background::Particles particles(Background::Particles::Mode::Snow); Background::Particles particles(Background::Particles::Snow);
void S9xTerm (int signal) static void S9xTerm(int signal)
{ {
S9xExit (); S9xExit();
} }
int main (int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct sigaction sig_callback; struct sigaction sig_callback;
auto app = Gtk::Application::create(argc, argv, "com.snes9x.gtk", Gio::APPLICATION_NON_UNIQUE);
gtk_init (&argc, &argv); setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, SNES9XLOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);
setlocale (LC_ALL, ""); memset(&Settings, 0, sizeof(Settings));
bindtextdomain (GETTEXT_PACKAGE, SNES9XLOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
memset (&Settings, 0, sizeof (Settings)); // Original config fills out values this port doesn't.
S9xLoadConfigFiles(argv, argc);
/* Allow original config file for backend settings */ gui_config = new Snes9xConfig();
S9xLoadConfigFiles (argv, argc);
/* Perform our config here */ S9xInitInputDevices();
gui_config = new Snes9xConfig ();
S9xInitInputDevices (); gui_config->load_config_file();
gui_config->load_config_file (); char *rom_filename = S9xParseArgs(argv, argc);
char *rom_filename = S9xParseArgs (argv, argc); auto settings = Gtk::Settings::get_default();
settings->set_property("gtk-menu-images", gui_config->enable_icons);
settings->set_property("gtk-button-images", gui_config->enable_icons);
#if GTK_MAJOR_VERSION >= 3 S9xReportControllers();
auto settings = gtk_settings_get_default();
g_object_set(settings,
"gtk-menu-images", gui_config->enable_icons,
"gtk_button_images", gui_config->enable_icons,
NULL);
#endif
S9xReportControllers (); if (!Memory.Init() || !S9xInitAPU())
exit(3);
if (!Memory.Init () || !S9xInitAPU ()) top_level = new Snes9xWindow(gui_config);
exit (3);
top_level = new Snes9xWindow (gui_config); // Setting fullscreen before showing the window avoids some flicker.
/* If we're going to fullscreen, do it before showing window to avoid flicker. */
if ((gui_config->full_screen_on_open && rom_filename) || (gui_config->fullscreen)) if ((gui_config->full_screen_on_open && rom_filename) || (gui_config->fullscreen))
gtk_window_fullscreen (top_level->get_window ()); top_level->window->fullscreen();
top_level->show (); top_level->show();
S9xInitDisplay (argc, argv); S9xInitDisplay(argc, argv);
Memory.PostRomInitFunc = S9xPostRomInit; S9xPortSoundInit();
S9xPortSoundInit ();
for (int port = 0; port < 2; port++) for (int port = 0; port < 2; port++)
{ {
enum controllers type; enum controllers type;
int8 id; int8 id;
S9xGetController (port, &type, &id, &id, &id, &id); S9xGetController(port, &type, &id, &id, &id, &id);
std::string device_type; std::string device_type;
switch (type) switch (type)
@ -113,96 +116,97 @@ int main (int argc, char *argv[])
device_type = "nothingpluggedin"; device_type = "nothingpluggedin";
} }
device_type += std::to_string (port + 1); device_type += std::to_string(port + 1);
top_level->set_menu_item_selected (device_type.c_str ()); top_level->set_menu_item_selected(device_type.c_str());
} }
gui_config->rebind_keys (); gui_config->rebind_keys();
top_level->update_accels (); top_level->update_accelerators();
Settings.Paused = true; Settings.Paused = true;
g_timeout_add (100, S9xPauseFunc, NULL);
g_timeout_add (10000, S9xScreenSaverCheckFunc, NULL);
S9xNoROMLoaded (); Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 100);
Glib::signal_timeout().connect(sigc::ptr_fun(S9xScreenSaverCheckFunc), 10000);
S9xNoROMLoaded();
if (rom_filename) if (rom_filename)
{ {
if (S9xOpenROM (rom_filename) && gui_config->full_screen_on_open) if (S9xOpenROM(rom_filename) && gui_config->full_screen_on_open)
gtk_window_unfullscreen (top_level->get_window()); top_level->window->unfullscreen();
} }
memset (&sig_callback, 0, sizeof (struct sigaction)); memset(&sig_callback, 0, sizeof(struct sigaction));
sig_callback.sa_handler = S9xTerm; sig_callback.sa_handler = S9xTerm;
sigaction (15 /* SIGTERM */, &sig_callback, NULL); sigaction(15, &sig_callback, NULL); // SIGTERM
sigaction (3 /* SIGQUIT */, &sig_callback, NULL); sigaction(3, &sig_callback, NULL); // SIGQUIT
sigaction (2 /* SIGINT */, &sig_callback, NULL); sigaction(2, &sig_callback, NULL); // SIGINT
// Perform the complete fullscreen process, including mode sets, which
// didn't happen in the earlier Gtk call.
if (gui_config->fullscreen) if (gui_config->fullscreen)
{ top_level->enter_fullscreen_mode();
top_level->enter_fullscreen_mode ();
}
gui_config->flush_joysticks (); gui_config->flush_joysticks();
if (rom_filename && *Settings.InitialSnapshotFilename) if (rom_filename && *Settings.InitialSnapshotFilename)
S9xUnfreezeGame(Settings.InitialSnapshotFilename); S9xUnfreezeGame(Settings.InitialSnapshotFilename);
gtk_main (); app->run(*top_level->window.get());
return 0; return 0;
} }
int S9xOpenROM (const char *rom_filename) int S9xOpenROM(const char *rom_filename)
{ {
uint32 flags; uint32 flags;
bool loaded; bool loaded;
if (gui_config->rom_loaded) if (gui_config->rom_loaded)
{ {
S9xAutoSaveSRAM (); S9xAutoSaveSRAM();
} }
S9xNetplayDisconnect (); S9xNetplayDisconnect();
flags = CPU.Flags; flags = CPU.Flags;
loaded = false; loaded = false;
if (Settings.Multi) if (Settings.Multi)
loaded = Memory.LoadMultiCart (Settings.CartAName, Settings.CartBName); loaded = Memory.LoadMultiCart(Settings.CartAName, Settings.CartBName);
else if (rom_filename) else if (rom_filename)
loaded = Memory.LoadROM (rom_filename); loaded = Memory.LoadROM(rom_filename);
Settings.StopEmulation = !loaded; Settings.StopEmulation = !loaded;
if (!loaded && rom_filename) if (!loaded && rom_filename)
{ {
char dir [_MAX_DIR + 1]; char dir[_MAX_DIR + 1];
char drive [_MAX_DRIVE + 1]; char drive[_MAX_DRIVE + 1];
char name [_MAX_FNAME + 1]; char name[_MAX_FNAME + 1];
char ext [_MAX_EXT + 1]; char ext[_MAX_EXT + 1];
char fname [_MAX_PATH + 1]; char fname[_MAX_PATH + 1];
_splitpath (rom_filename, drive, dir, name, ext); _splitpath(rom_filename, drive, dir, name, ext);
_makepath (fname, drive, dir, name, ext); _makepath(fname, drive, dir, name, ext);
strcpy (fname, S9xGetDirectory (ROM_DIR)); strcpy(fname, S9xGetDirectory(ROM_DIR));
strcat (fname, SLASH_STR); strcat(fname, SLASH_STR);
strcat (fname, name); strcat(fname, name);
if (ext [0]) if (ext[0])
{ {
strcat (fname, "."); strcat(fname, ".");
strcat (fname, ext); strcat(fname, ext);
} }
_splitpath (fname, drive, dir, name, ext); _splitpath(fname, drive, dir, name, ext);
_makepath (fname, drive, dir, name, ext); _makepath(fname, drive, dir, name, ext);
if ((Settings.StopEmulation = !Memory.LoadROM (fname))) if ((Settings.StopEmulation = !Memory.LoadROM(fname)))
{ {
fprintf (stderr, _("Error opening: %s\n"), rom_filename); fprintf(stderr, _("Error opening: %s\n"), rom_filename);
loaded = false; loaded = false;
} }
@ -212,79 +216,77 @@ int S9xOpenROM (const char *rom_filename)
if (loaded) if (loaded)
{ {
Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR));
} }
else else
{ {
CPU.Flags = flags; CPU.Flags = flags;
Settings.Paused = true; Settings.Paused = true;
S9xNoROMLoaded (); S9xNoROMLoaded();
top_level->refresh (); top_level->refresh();
return 1; return 1;
} }
CPU.Flags = flags; CPU.Flags = flags;
if (state_manager.init (gui_config->rewind_buffer_size * 1024 * 1024)) if (state_manager.init(gui_config->rewind_buffer_size * 1024 * 1024))
{ {
printf ("Using rewind buffer of %uMB\n", gui_config->rewind_buffer_size); printf("Using rewind buffer of %uMB\n", gui_config->rewind_buffer_size);
} }
S9xROMLoaded (); S9xROMLoaded();
return 0; return 0;
} }
void S9xROMLoaded () void S9xROMLoaded()
{ {
gui_config->rom_loaded = true; gui_config->rom_loaded = true;
top_level->configure_widgets (); top_level->configure_widgets();
if (gui_config->full_screen_on_open) if (gui_config->full_screen_on_open)
{ {
Settings.Paused = false; Settings.Paused = false;
top_level->enter_fullscreen_mode (); top_level->enter_fullscreen_mode();
} }
S9xSoundStart (); S9xSoundStart();
} }
void S9xNoROMLoaded () void S9xNoROMLoaded()
{ {
S9xSoundStop (); S9xSoundStop();
gui_config->rom_loaded = false; gui_config->rom_loaded = false;
S9xDisplayRefresh(-1, -1); S9xDisplayRefresh(-1, -1);
top_level->configure_widgets (); top_level->configure_widgets();
} }
static gboolean S9xPauseFunc (gpointer data) static bool S9xPauseFunc()
{ {
S9xProcessEvents (true); S9xProcessEvents(true);
if (!S9xNetplayPush ()) if (!S9xNetplayPush())
{ {
S9xNetplayPop (); S9xNetplayPop();
} }
if (!Settings.Paused) /* Coming out of pause */ if (!Settings.Paused) /* Coming out of pause */
{ {
/* Clear joystick queues */ /* Clear joystick queues */
gui_config->flush_joysticks (); gui_config->flush_joysticks();
S9xSoundStart (); S9xSoundStart();
if (Settings.NetPlay && NetPlay.Connected) if (Settings.NetPlay && NetPlay.Connected)
{ {
S9xNPSendPause (false); S9xNPSendPause(false);
} }
/* Resume high-performance callback */ /* Resume high-performance callback */
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, Glib::signal_idle().connect(sigc::ptr_fun(S9xIdleFunc));
S9xIdleFunc,
NULL,
NULL);
return false; return false;
} }
@ -304,44 +306,44 @@ static gboolean S9xPauseFunc (gpointer data)
} }
} }
g_timeout_add(8, S9xPauseFunc, NULL); Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 8);
return false; return false;
} }
gboolean S9xIdleFunc (gpointer data) static bool S9xIdleFunc()
{ {
if (Settings.Paused && gui_config->rom_loaded) if (Settings.Paused && gui_config->rom_loaded)
{ {
S9xSoundStop (); S9xSoundStop();
gui_config->flush_joysticks (); gui_config->flush_joysticks();
if (Settings.NetPlay && NetPlay.Connected) if (Settings.NetPlay && NetPlay.Connected)
{ {
S9xNPSendPause (true); S9xNPSendPause(true);
} }
/* Move to a timer-based function to use less CPU */ /* Move to a timer-based function to use less CPU */
g_timeout_add (8, S9xPauseFunc, NULL); Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 8);
return false; return false;
} }
S9xCheckPointerTimer (); S9xCheckPointerTimer();
S9xProcessEvents (true); S9xProcessEvents(true);
if (!S9xDisplayDriverIsReady ()) if (!S9xDisplayDriverIsReady())
{ {
usleep(100); usleep(100);
return true; return true;
} }
S9xThrottle (Settings.SkipFrames); S9xThrottle(Settings.SkipFrames);
if (!S9xNetplayPush ()) if (!S9xNetplayPush())
{ {
if(Settings.Rewinding) if (Settings.Rewinding)
{ {
uint16 joypads[8]; uint16 joypads[8];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
@ -350,115 +352,104 @@ gboolean S9xIdleFunc (gpointer data)
Settings.Rewinding = state_manager.pop(); Settings.Rewinding = state_manager.pop();
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
MovieSetJoypad (i, joypads[i]); MovieSetJoypad(i, joypads[i]);
} }
else if(IPPU.TotalEmulatedFrames % gui_config->rewind_granularity == 0) else if (IPPU.TotalEmulatedFrames % gui_config->rewind_granularity == 0)
state_manager.push(); state_manager.push();
static int muted_from_turbo = false; if ((Settings.TurboMode || Settings.Rewinding) && gui_config->mute_sound_turbo)
static int mute_saved_state = false; Settings.Mute |= 0x80;
else
Settings.Mute &= ~0x80;
if ((Settings.TurboMode || Settings.Rewinding) && !muted_from_turbo && gui_config->mute_sound_turbo) S9xMainLoop();
{
muted_from_turbo = true;
mute_saved_state = Settings.Mute;
S9xSetSoundMute (true);
}
if (!(Settings.TurboMode || Settings.Rewinding) && muted_from_turbo) S9xNetplayPop();
{
muted_from_turbo = false;
Settings.Mute = mute_saved_state;
}
S9xMainLoop ();
S9xNetplayPop ();
} }
return true; return true;
} }
gboolean S9xScreenSaverCheckFunc (gpointer data) static bool S9xScreenSaverCheckFunc()
{ {
if (!Settings.Paused && if (!Settings.Paused &&
(gui_config->screensaver_needs_reset || (gui_config->screensaver_needs_reset ||
gui_config->prevent_screensaver)) gui_config->prevent_screensaver))
top_level->reset_screensaver (); top_level->reset_screensaver();
return true; return true;
} }
/* Snes9x core hooks */ /* Snes9x core hooks */
void S9xMessage (int type, int number, const char *message) void S9xMessage(int type, int number, const char *message)
{ {
switch (number) switch (number)
{ {
case S9X_MOVIE_INFO: case S9X_MOVIE_INFO:
S9xSetInfoString (message); S9xSetInfoString(message);
break; break;
default: default:
break; break;
} }
} }
/* Varies from ParseArgs because this one is for the OS port to handle */ /* Varies from ParseArgs because this one is for the OS port to handle */
void S9xParseArg (char **argv, int &i, int argc) void S9xParseArg(char **argv, int &i, int argc)
{ {
if (!strcasecmp (argv[i], "-filter")) if (!strcasecmp(argv[i], "-filter"))
{ {
if ((++i) < argc) if ((++i) < argc)
{ {
if (!strcasecmp (argv[i], "none")) if (!strcasecmp(argv[i], "none"))
{ {
gui_config->scale_method = FILTER_NONE; gui_config->scale_method = FILTER_NONE;
} }
else if (!strcasecmp (argv[i], "supereagle")) else if (!strcasecmp(argv[i], "supereagle"))
{ {
gui_config->scale_method = FILTER_SUPEREAGLE; gui_config->scale_method = FILTER_SUPEREAGLE;
} }
else if (!strcasecmp (argv[i], "2xsai")) else if (!strcasecmp(argv[i], "2xsai"))
{ {
gui_config->scale_method = FILTER_2XSAI; gui_config->scale_method = FILTER_2XSAI;
} }
else if (!strcasecmp (argv[i], "super2xsai")) else if (!strcasecmp(argv[i], "super2xsai"))
{ {
gui_config->scale_method = FILTER_SUPER2XSAI; gui_config->scale_method = FILTER_SUPER2XSAI;
} }
#ifdef USE_HQ2X #ifdef USE_HQ2X
else if (!strcasecmp (argv[i], "hq2x")) else if (!strcasecmp(argv[i], "hq2x"))
{ {
gui_config->scale_method = FILTER_HQ2X; gui_config->scale_method = FILTER_HQ2X;
} }
else if (!strcasecmp (argv[i], "hq3x")) else if (!strcasecmp(argv[i], "hq3x"))
{ {
gui_config->scale_method = FILTER_HQ3X; gui_config->scale_method = FILTER_HQ3X;
} }
else if (!strcasecmp (argv[i], "hq4x")) else if (!strcasecmp(argv[i], "hq4x"))
{ {
gui_config->scale_method = FILTER_HQ4X; gui_config->scale_method = FILTER_HQ4X;
} }
#endif /* USE_HQ2X */ #endif /* USE_HQ2X */
#ifdef USE_XBRZ #ifdef USE_XBRZ
else if (!strcasecmp (argv[i], "2xbrz")) else if (!strcasecmp(argv[i], "2xbrz"))
{ {
gui_config->scale_method = FILTER_2XBRZ; gui_config->scale_method = FILTER_2XBRZ;
} }
else if (!strcasecmp (argv[i], "3xbrz")) else if (!strcasecmp(argv[i], "3xbrz"))
{ {
gui_config->scale_method = FILTER_3XBRZ; gui_config->scale_method = FILTER_3XBRZ;
} }
else if (!strcasecmp (argv[i], "4xbrz")) else if (!strcasecmp(argv[i], "4xbrz"))
{ {
gui_config->scale_method = FILTER_4XBRZ; gui_config->scale_method = FILTER_4XBRZ;
} }
#endif /* USE_XBRZ */ #endif /* USE_XBRZ */
else if (!strcasecmp (argv[i], "epx")) else if (!strcasecmp(argv[i], "epx"))
{ {
gui_config->scale_method = FILTER_EPX; gui_config->scale_method = FILTER_EPX;
} }
else if (!strcasecmp (argv[i], "ntsc")) else if (!strcasecmp(argv[i], "ntsc"))
{ {
gui_config->scale_method = FILTER_NTSC; gui_config->scale_method = FILTER_NTSC;
} }
@ -468,20 +459,20 @@ void S9xParseArg (char **argv, int &i, int argc)
} }
} }
} }
else if (!strcasecmp (argv[i], "-mutesound")) else if (!strcasecmp(argv[i], "-mutesound"))
{ {
gui_config->mute_sound = true; gui_config->mute_sound = true;
} }
} }
static void S9xThrottle (int method) static void S9xThrottle(int method)
{ {
gint64 now; gint64 now;
if (S9xNetplaySyncSpeed ()) if (S9xNetplaySyncSpeed())
return; return;
now = g_get_monotonic_time (); now = g_get_monotonic_time();
if (Settings.HighSpeedSeek > 0) if (Settings.HighSpeedSeek > 0)
{ {
@ -496,8 +487,7 @@ static void S9xThrottle (int method)
if (Settings.TurboMode) if (Settings.TurboMode)
{ {
IPPU.FrameSkip++; IPPU.FrameSkip++;
if ((IPPU.FrameSkip >= Settings.TurboSkipFrames) if ((IPPU.FrameSkip >= Settings.TurboSkipFrames) && !Settings.HighSpeedSeek)
&& !Settings.HighSpeedSeek)
{ {
IPPU.FrameSkip = 0; IPPU.FrameSkip = 0;
IPPU.SkippedFrames = 0; IPPU.SkippedFrames = 0;
@ -550,8 +540,8 @@ static void S9xThrottle (int method)
while (now - frame_clock < Settings.FrameTime) while (now - frame_clock < Settings.FrameTime)
{ {
usleep (100); usleep(100);
now = g_get_monotonic_time (); now = g_get_monotonic_time();
} }
frame_clock += Settings.FrameTime; frame_clock += Settings.FrameTime;
@ -560,129 +550,47 @@ static void S9xThrottle (int method)
} }
} }
void S9xSyncSpeed () void S9xSyncSpeed()
{ {
} }
static void S9xCheckPointerTimer () static void S9xCheckPointerTimer()
{ {
if (!gui_config->pointer_is_visible) if (!gui_config->pointer_is_visible)
return; return;
if (g_get_monotonic_time () - gui_config->pointer_timestamp > 1000000) if (g_get_monotonic_time() - gui_config->pointer_timestamp > 1000000)
{ {
top_level->hide_mouse_cursor (); top_level->hide_mouse_cursor();
gui_config->pointer_is_visible = false; gui_config->pointer_is_visible = false;
} }
} }
/* Final exit point, issues exit (0) */ /* Final exit point, issues exit (0) */
void S9xExit () void S9xExit()
{ {
gui_config->save_config_file (); gui_config->save_config_file();
top_level->leave_fullscreen_mode (); top_level->leave_fullscreen_mode();
S9xPortSoundDeinit (); S9xPortSoundDeinit();
Settings.StopEmulation = true; Settings.StopEmulation = true;
if (gui_config->rom_loaded) if (gui_config->rom_loaded)
{ {
S9xAutoSaveSRAM (); S9xAutoSaveSRAM();
} }
S9xDeinitAPU (); S9xDeinitAPU();
S9xDeinitInputDevices (); S9xDeinitInputDevices();
S9xDeinitDisplay (); S9xDeinitDisplay();
gtk_main_quit ();
delete top_level; delete top_level;
delete gui_config; delete gui_config;
exit (0); exit(0);
}
void
S9xPostRomInit ()
{
if (!strncmp ((const char *) Memory.NSRTHeader + 24, "NSRT", 4))
{
switch (Memory.NSRTHeader[29])
{
case 0: //Everything goes
break;
case 0x10: //Mouse in Port 0
S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0);
top_level->set_menu_item_selected ("mouse1");
break;
case 0x01: //Mouse in Port 1
S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0);
top_level->set_menu_item_selected ("mouse2");
break;
case 0x03: //Super Scope in Port 1
S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0);
top_level->set_menu_item_selected ("superscope1");
break;
case 0x06: //Multitap in Port 1
S9xSetController (1, CTL_MP5, 1, 2, 3, 4);
top_level->set_menu_item_selected ("multitap1");
break;
case 0x66: //Multitap in Ports 0 and 1
S9xSetController (0, CTL_MP5, 0, 1, 2, 3);
S9xSetController (1, CTL_MP5, 4, 5, 6, 7);
top_level->set_menu_item_selected ("multitap1");
top_level->set_menu_item_selected ("multitap2");
break;
case 0x08: //Multitap in Port 1, Mouse in new Port 1
S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0);
//There should be a toggle here for putting in Multitap instead
top_level->set_menu_item_selected ("mouse2");
break;
case 0x04: //Pad or Super Scope in Port 1
S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0);
top_level->set_menu_item_selected ("superscope2");
//There should be a toggle here for putting in a pad instead
break;
case 0x05: //Justifier - Must ask user...
S9xSetController (1, CTL_JUSTIFIER, 1, 0, 0, 0);
//There should be a toggle here for how many justifiers
break;
case 0x20: //Pad or Mouse in Port 0
S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0);
//There should be a toggle here for putting in a pad instead
break;
case 0x22: //Pad or Mouse in Port 0 & 1
S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0);
S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0);
//There should be a toggles here for putting in pads instead
break;
case 0x24: //Pad or Mouse in Port 0, Pad or Super Scope in Port 1
//There should be a toggles here for what to put in, I'm leaving it at gamepad for now
break;
case 0x27: //Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1
//There should be a toggles here for what to put in, I'm leaving it at gamepad for now
break;
//Not Supported yet
case 0x99: break; //Lasabirdie
case 0x0A: break; //Barcode Battler
}
}
} }
const char *S9xStringInput(const char *message) const char *S9xStringInput(const char *message)
@ -690,12 +598,12 @@ const char *S9xStringInput(const char *message)
return NULL; return NULL;
} }
void S9xExtraUsage () void S9xExtraUsage()
{ {
printf ("GTK port options:\n" printf("GTK port options:\n"
"-filter [option] Use a filter to scale the image.\n" "-filter [option] Use a filter to scale the image.\n"
" [option] is one of: none supereagle 2xsai\n" " [option] is one of: none supereagle 2xsai\n"
" super2xsai hq2x hq3x hq4x 2xbrz 3xbrz 4xbrz epx ntsc\n" " super2xsai hq2x hq3x hq4x 2xbrz 3xbrz 4xbrz epx ntsc\n"
"\n" "\n"
"-mutesound Disables sound output.\n"); "-mutesound Disables sound output.\n");
} }

View File

@ -8,19 +8,18 @@
#define __GTK_S9X_H #define __GTK_S9X_H
#include "gtk_config.h" #include "gtk_config.h"
#include "gtk_s9xcore.h"
#include "gtk_s9xwindow.h" #include "gtk_s9xwindow.h"
#include <glib/gi18n.h> #include <glib/gi18n.h>
#define SNES9X_GTK_AUTHORS "(c) 2007 - 2019 Brandon Wright (bearoso@gmail.com)" #define SNES9X_GTK_AUTHORS "(c) 2007 - 2020 Brandon Wright (bearoso@gmail.com)"
#define SNES9X_GTK_VERSION "87" #define SNES9X_GTK_VERSION "87"
extern Snes9xWindow *top_level; extern Snes9xWindow *top_level;
extern Snes9xConfig *gui_config; extern Snes9xConfig *gui_config;
int S9xOpenROM (const char *filename); int S9xOpenROM(const char *filename);
void S9xNoROMLoaded (); void S9xNoROMLoaded();
void S9xROMLoaded (); void S9xROMLoaded();
#endif /* __GTK_S9X_H */ #endif /* __GTK_S9X_H */

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
#ifndef __GTK_S9XWINDOW_H #ifndef __GTK_S9XWINDOW_H
#define __GTK_S9XWINDOW_H #define __GTK_S9XWINDOW_H
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include "port.h" #include "port.h"
#include "gtk_builder_window.h" #include "gtk_builder_window.h"
@ -15,90 +15,105 @@
class Snes9xWindow : public GtkBuilderWindow class Snes9xWindow : public GtkBuilderWindow
{ {
public: public:
Snes9xWindow (Snes9xConfig *config); Snes9xWindow(Snes9xConfig *config);
/* Pause related functions */ struct AcceleratorEntry
void pause_from_focus_change (); {
void unpause_from_focus_change (); std::string name;
void focus_notify (bool state); unsigned int key;
void pause_from_user (); Gdk::ModifierType modifiers;
void unpause_from_user (); };
bool is_paused ();
void propagate_pause_state ();
/* Fullscreen functions */ /* Pause related functions */
void enter_fullscreen_mode (); void pause_from_focus_change();
void leave_fullscreen_mode (); void unpause_from_focus_change();
void toggle_fullscreen_mode (); void focus_notify(bool state);
void finish_fullscreen (); void pause_from_user();
void unpause_from_user();
bool is_paused();
void propagate_pause_state();
/* Cursor modifying functions */ /* Fullscreen functions */
void show_mouse_cursor (); void enter_fullscreen_mode();
void hide_mouse_cursor (); void leave_fullscreen_mode();
void toggle_grab_mouse (); void toggle_fullscreen_mode();
void center_mouse (); void finish_fullscreen();
/* Rom-related functions */ /* Cursor modifying functions */
void open_rom_dialog (); void show_mouse_cursor();
void save_state_dialog (); void hide_mouse_cursor();
void load_state_dialog (); void toggle_grab_mouse();
void configure_widgets (); void center_mouse();
void save_spc_dialog ();
bool try_open_rom (const char *filename);
const char *open_movie_dialog (bool readonly);
void movie_seek_dialog ();
void open_multicart_dialog ();
void show_rom_info ();
/* GTK-base-related functions */ /* Rom-related functions */
void show (); std::string open_rom_dialog(bool run = true);
void set_menu_item_selected (const char *name); void save_state_dialog();
void set_mouseable_area (int x, int y, int width, int height); void load_state_dialog();
void set_menu_item_accel_to_binding (const char *name, void configure_widgets();
const char *binding); void save_spc_dialog();
void reset_screensaver (); bool try_open_rom(std::string filename);
void update_accels (); std::string open_movie_dialog(bool readonly);
void toggle_ui (); void movie_seek_dialog();
void resize_to_multiple (int factor); void open_multicart_dialog();
void resize_viewport (int width, int height); void show_rom_info();
void expose ();
void setup_splash();
double get_refresh_rate ();
int get_auto_input_rate ();
cairo_t *get_cairo (); /* GTK-base-related functions */
void release_cairo (); void show();
void set_menu_item_selected(const char *name);
void set_mouseable_area(int x, int y, int width, int height);
void set_accelerator_to_binding(const char *name,
const char *binding);
void reset_screensaver();
void update_accelerators();
void toggle_ui();
void resize_to_multiple(int factor);
void resize_viewport(int width, int height);
bool draw(const Cairo::RefPtr<Cairo::Context> &cr);
void setup_splash();
double get_refresh_rate();
int get_auto_input_rate();
void connect_signals();
bool event_key(GdkEventKey *event);
void port_activate(const char *name);
bool button_press(GdkEventButton *event);
bool button_release(GdkEventButton *event);
bool motion_notify(GdkEventMotion *event);
Snes9xConfig *config; cairo_t *get_cairo();
int user_pause, sys_pause; void release_cairo();
int last_width, last_height;
int mouse_region_x, mouse_region_y; Snes9xConfig *config;
int mouse_region_width, mouse_region_height; int user_pause, sys_pause;
int nfs_width, nfs_height, nfs_x, nfs_y; int last_width, last_height;
int fullscreen_state; int mouse_region_x, mouse_region_y;
int maximized_state; int mouse_region_width, mouse_region_height;
bool focused; int nfs_width, nfs_height, nfs_x, nfs_y;
bool paused_from_focus_loss; int fullscreen_state;
double snes_mouse_x, snes_mouse_y; int maximized_state;
double gdk_mouse_x, gdk_mouse_y; bool focused;
bool mouse_grabbed; bool paused_from_focus_loss;
GdkPixbuf *icon, *splash; double snes_mouse_x, snes_mouse_y;
GdkCursor *default_cursor, *empty_cursor; double gdk_mouse_x, gdk_mouse_y;
GtkDrawingArea *drawing_area; bool mouse_grabbed;
GtkWidget *recent_menu; GdkPixbuf *icon, *splash;
cairo_t *cr; Gtk::DrawingArea *drawing_area;
bool cairo_owned; Gtk::RecentChooserMenu *recent_menu;
#if GTK_MAJOR_VERSION >= 3 cairo_t *cr;
GdkDrawingContext *gdk_drawing_context; bool cairo_owned;
cairo_region_t *cairo_region; Glib::RefPtr<Gdk::DrawingContext> gdk_drawing_context;
#endif Glib::RefPtr<Gtk::AccelGroup> accel_group;
std::vector<AcceleratorEntry> accelerators;
unsigned int last_key_pressed_keyval;
GdkEventType last_key_pressed_type;
}; };
typedef struct gtk_splash_t { typedef struct gtk_splash_t
unsigned int width; {
unsigned int height; unsigned int width;
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ unsigned int height;
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
unsigned char pixel_data[256 * 224 * 3 + 1]; unsigned char pixel_data[256 * 224 * 3 + 1];
} gtk_splash_t; } gtk_splash_t;

View File

@ -4,7 +4,7 @@
For further information, consult the LICENSE file in the root directory. For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
#include <vector> #include <vector>
#include <math.h> #include <math.h>
@ -13,59 +13,27 @@
#include "gtk_shader_parameters.h" #include "gtk_shader_parameters.h"
#include "shaders/glsl.h" #include "shaders/glsl.h"
static GtkWidget *dialog = NULL; #include "gfx.h"
static std::vector<GLSLParam> *params = NULL;
static Gtk::Dialog *dialog = nullptr;
static std::vector<GLSLParam> *params = nullptr;
static std::vector<GLSLParam> saved_params; static std::vector<GLSLParam> saved_params;
static inline double snap_to_interval(double value, double interval) static inline double snap_to_interval(double value, double interval)
{ {
if (interval == 0.0)
return value;
return round(value / interval) * interval; return round(value / interval) * interval;
} }
static void value_changed(GtkRange *range, gpointer user_data) static void dialog_response(int response_id)
{ {
GLSLParam *p = (GLSLParam *)user_data; gui_config->shader_parameters_width = dialog->get_width();
GtkAdjustment *adj = gtk_range_get_adjustment(range); gui_config->shader_parameters_height = dialog->get_height();
double interval = gtk_adjustment_get_step_increment(adj);
double value = gtk_range_get_value(range);
value = snap_to_interval(value, interval);
gtk_range_set_value(range, value);
if (p->val != value)
{
p->val = value;
if (Settings.Paused)
S9xDeinitUpdate(top_level->last_width, top_level->last_height);
}
}
static void toggled(GtkToggleButton *togglebutton, gpointer user_data)
{
GLSLParam *p = (GLSLParam *)user_data;
double value = (double)gtk_toggle_button_get_active(togglebutton);
if (p->val != value)
{
p->val = value;
if (Settings.Paused)
S9xDeinitUpdate(top_level->last_width, top_level->last_height);
}
}
static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_data)
{
std::vector<GLSLParam> *params = (std::vector<GLSLParam> *)user_data;
int width, height;
gtk_window_get_size(GTK_WINDOW(pdialog), &width, &height);
gui_config->shader_parameters_width = width;
gui_config->shader_parameters_height = height;
switch (response_id) switch (response_id)
{ {
case GTK_RESPONSE_OK: case Gtk::RESPONSE_OK:
{ {
char path[PATH_MAX]; char path[PATH_MAX];
std::string config_file = get_config_dir(); std::string config_file = get_config_dir();
@ -78,17 +46,17 @@ static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_
gui_config->shader_filename = path; gui_config->shader_filename = path;
if (dialog) if (dialog)
gtk_widget_destroy(GTK_WIDGET(dialog)); delete dialog;
dialog = NULL; dialog = nullptr;
break; break;
} }
case GTK_RESPONSE_CANCEL: case Gtk::RESPONSE_CANCEL:
case GTK_RESPONSE_DELETE_EVENT: case Gtk::RESPONSE_DELETE_EVENT:
case GTK_RESPONSE_NONE: case Gtk::RESPONSE_NONE:
if (dialog) if (dialog)
gtk_widget_destroy(GTK_WIDGET(dialog)); delete dialog;
dialog = NULL; dialog = nullptr;
*params = saved_params; *params = saved_params;
if (Settings.Paused) if (Settings.Paused)
S9xDeinitUpdate(top_level->last_width, top_level->last_height); S9xDeinitUpdate(top_level->last_width, top_level->last_height);
@ -96,17 +64,14 @@ static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_
case 15: // Save As case 15: // Save As
{ {
auto dialog = gtk_file_chooser_dialog_new(_("Export Shader Preset to:"), Gtk::FileChooserDialog dialog(_("Export Shader Preset to:"), Gtk::FILE_CHOOSER_ACTION_SAVE);
top_level->get_window(), dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
GTK_FILE_CHOOSER_ACTION_SAVE, dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_ACCEPT);
"gtk-cancel", GTK_RESPONSE_CANCEL, dialog.set_current_folder(gui_config->last_shader_directory);
"gtk-save", GTK_RESPONSE_ACCEPT,
NULL); std::string name;
std::string extension;
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
gui_config->last_shader_directory.c_str());
const char *name;
const char *extension;
if (gui_config->shader_filename.find(".slang") != std::string::npos) if (gui_config->shader_filename.find(".slang") != std::string::npos)
{ {
name = "new.slangp"; name = "new.slangp";
@ -117,26 +82,23 @@ static void dialog_response(GtkDialog *pdialog, gint response_id, gpointer user_
name = "new.glslp"; name = "new.glslp";
extension = "*.glslp"; extension = "*.glslp";
} }
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), name);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), true);
auto filter = gtk_file_filter_new(); dialog.set_current_name(name);
gtk_file_filter_set_name(filter, _("Shader Preset")); dialog.set_do_overwrite_confirmation();
gtk_file_filter_add_pattern(filter, extension);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
auto result = gtk_dialog_run(GTK_DIALOG(dialog)); auto filter = Gtk::FileFilter::create();
filter->set_name(_("Shader Preset"));
filter->add_pattern(extension);
dialog.add_filter(filter);
auto result = dialog.run();
if (result == GTK_RESPONSE_ACCEPT) if (result == GTK_RESPONSE_ACCEPT)
{ S9xDisplayGetDriver()->save(dialog.get_filename().c_str());
auto filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
S9xDisplayGetDriver()->save(filename);
g_free(filename);
}
gtk_widget_destroy(dialog);
break; break;
} }
default: default:
break; break;
} }
@ -147,8 +109,8 @@ void gtk_shader_parameters_dialog_close()
if (dialog) if (dialog)
{ {
*params = saved_params; *params = saved_params;
gtk_widget_destroy(GTK_WIDGET(dialog)); delete dialog;
dialog = NULL; dialog = nullptr;
} }
} }
@ -156,7 +118,7 @@ bool gtk_shader_parameters_dialog(GtkWindow *parent)
{ {
if (dialog) if (dialog)
{ {
gtk_window_present(GTK_WINDOW(dialog)); dialog->present();
return false; return false;
} }
@ -166,145 +128,85 @@ bool gtk_shader_parameters_dialog(GtkWindow *parent)
if (!params || params->size() == 0) if (!params || params->size() == 0)
return false; return false;
dialog = gtk_dialog_new_with_buttons(_("Shader Parameters"), dialog = new Gtk::Dialog(_("Shader Parameters"), Gtk::DIALOG_DESTROY_WITH_PARENT);
parent, dialog->add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
GTK_DIALOG_DESTROY_WITH_PARENT, dialog->add_button(Gtk::StockID("gtk-save-as"), 15);
"gtk-cancel", dialog->add_button(Gtk::StockID("gtk-save"), GTK_RESPONSE_OK);
GTK_RESPONSE_CANCEL, dialog->signal_response().connect(sigc::ptr_fun(dialog_response));
"gtk-save-as",
15,
"gtk-save",
GTK_RESPONSE_OK,
NULL);
g_signal_connect_data(G_OBJECT(dialog), "response", G_CALLBACK(dialog_response), (gpointer)params, NULL, (GConnectFlags)0); dialog->set_size_request(640, 480);
GtkWidget *scrolled_window;
gtk_widget_set_size_request(dialog, 640, 480);
if (gui_config->shader_parameters_width > 0 && gui_config->shader_parameters_height > 0) if (gui_config->shader_parameters_width > 0 && gui_config->shader_parameters_height > 0)
{ dialog->resize(gui_config->shader_parameters_width, gui_config->shader_parameters_height);
gtk_window_resize(GTK_WINDOW(dialog),
gui_config->shader_parameters_width,
gui_config->shader_parameters_height);
}
scrolled_window = gtk_scrolled_window_new(NULL, NULL); auto scrolled_window = new Gtk::ScrolledWindow;
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), scrolled_window->set_hexpand();
scrolled_window); scrolled_window->set_vexpand();
scrolled_window->set_margin_start(5);
scrolled_window->set_margin_end(5);
scrolled_window->set_margin_top(5);
dialog->get_content_area()->add(*scrolled_window);
GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); auto grid = new Gtk::Grid;
grid->set_margin_end(5);
#if GTK_MAJOR_VERSION >= 3 grid->set_row_homogeneous();
grid->set_row_spacing(2);
gtk_widget_set_hexpand(scrolled_window, true); grid->set_column_spacing(12);
gtk_widget_set_vexpand(scrolled_window, true); auto vbox = new Gtk::VBox;
gtk_widget_set_margin_start(scrolled_window, 5); vbox->pack_start(*grid);
gtk_widget_set_margin_end(scrolled_window, 5); scrolled_window->add(*vbox);
gtk_widget_set_margin_top(scrolled_window, 5);
gtk_widget_set_margin_bottom(scrolled_window, 5);
GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *grid = gtk_grid_new();
gtk_widget_set_margin_end(grid, 5);
gtk_grid_set_row_homogeneous(GTK_GRID(grid), true);
gtk_grid_set_row_spacing(GTK_GRID(grid), 2);
gtk_grid_set_column_spacing(GTK_GRID(grid), 12);
gtk_container_add(GTK_CONTAINER(vbox), grid);
gtk_container_add(GTK_CONTAINER(scrolled_window), vbox);
auto sizegroup = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
for (unsigned int i = 0; i < params->size(); i++) for (unsigned int i = 0; i < params->size(); i++)
{ {
GLSLParam *p = &(*params)[i]; GLSLParam &p = (*params)[i];
GtkWidget *label = gtk_label_new(p->name); auto label = new Gtk::Label(p.name);
gtk_label_set_xalign(GTK_LABEL(label), 0.0f); label->set_xalign(0.0f);
gtk_widget_show(label); label->show();
grid->attach(*label, 0, i, 1, 1);
gtk_grid_attach(GTK_GRID(grid), label, 0, i, 1, 1); if (p.min == 0.0 && p.max == 1.0 && p.step == 1.0)
if (p->min == 0.0 && p->max == 1.0 && p->step == 1.0)
{ {
GtkWidget *check = gtk_check_button_new(); auto check = new Gtk::CheckButton;
gtk_grid_attach(GTK_GRID(grid), check, 1, i, 1, 1); grid->attach(*check, 1, i, 1, 1);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), (int)p->val); check->set_active(p.val);
g_signal_connect_data(G_OBJECT(check), "toggled", G_CALLBACK(toggled), (gpointer)p, NULL, (GConnectFlags)0); check->signal_toggled().connect([check, &param = p.val] {
double new_value = check->get_active();
if (param != new_value)
{
param = new_value;
if (Settings.Paused)
S9xDeinitUpdate(top_level->last_width, top_level->last_height);
}
});
} }
else else
{ {
GtkWidget *spin = gtk_spin_button_new_with_range(p->min, p->max, p->step); auto spin = new Gtk::SpinButton(0.0, p.digits);
gtk_entry_set_width_chars(GTK_ENTRY(spin), 5); spin->set_range(p.min, p.max);
gtk_grid_attach(GTK_GRID(grid), spin, 1, i, 1, 1); spin->get_adjustment()->set_step_increment(p.step);
gtk_size_group_add_widget(sizegroup, spin); spin->set_width_chars(6);
int digits = gtk_spin_button_get_digits(GTK_SPIN_BUTTON(spin)); grid->attach(*spin, 1, i, 1, 1);
if (digits == 2) sizegroup->add_widget(*spin);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 3);
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin)); auto scale = new Gtk::Scale(spin->get_adjustment());
scale->set_hexpand();
GtkWidget *scale = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, adjustment); grid->attach(*scale, 2, i, 1, 1);
gtk_widget_set_hexpand(scale, true); scale->set_draw_value(false);
gtk_grid_attach(GTK_GRID(grid), scale, 2, i, 1, 1); scale->set_value(p.val);
gtk_scale_set_draw_value(GTK_SCALE(scale), false); scale->signal_value_changed().connect([spin, &param = p.val] {
gtk_range_set_value(GTK_RANGE(scale), p->val); double new_value = snap_to_interval(spin->get_value(), spin->get_adjustment()->get_step_increment());
g_signal_connect_data(G_OBJECT(scale), spin->set_value(new_value);
"value-changed", if (param != new_value)
G_CALLBACK(value_changed), {
(gpointer)p, param = new_value;
NULL, if (Settings.Paused)
(GConnectFlags)0); S9xDeinitUpdate(top_level->last_width, top_level->last_height);
}
});
} }
} }
#else
GtkWidget *vbox = gtk_vbox_new(false, 5);
GtkWidget *table = gtk_table_new(params->size(), 3, false);
gtk_table_set_row_spacings(GTK_TABLE(table), 5);
gtk_table_set_col_spacings(GTK_TABLE(table), 12);
gtk_container_add(GTK_CONTAINER(vbox), table);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), vbox);
gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 5);
for (unsigned int i = 0; i < params->size(); i++) dialog->show_all();
{
GLSLParam *p = &(*params)[i];
GtkWidget *label = gtk_label_new(p->name);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_widget_show(label);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, i, i + 1, GTK_FILL, GTK_FILL, 0, 0);
if (p->min == 0.0 && p->max == 1.0 && p->step == 1.0)
{
GtkWidget *check = gtk_check_button_new();
gtk_table_attach(GTK_TABLE(table), check, 1, 2, i, i + 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), (int)p->val);
g_signal_connect_data(G_OBJECT(check), "toggled", G_CALLBACK(toggled), (gpointer)p, NULL, (GConnectFlags)0);
}
else
{
GtkWidget *spin = gtk_spin_button_new_with_range(p->min, p->max, p->step);
gtk_table_attach(GTK_TABLE(table), spin, 1, 2, i, i + 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_size_group_add_widget(sizegroup, spin);
int digits = gtk_spin_button_get_digits(GTK_SPIN_BUTTON(spin));
if (digits == 2)
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 3);
GtkAdjustment *adjustment = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(spin));
GtkWidget *scale = gtk_hscale_new(adjustment);
gtk_table_attach(GTK_TABLE(table), scale, 2, 3, i, i + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), GTK_FILL, 0, 0);
gtk_scale_set_draw_value(GTK_SCALE(scale), false);
gtk_range_set_value(GTK_RANGE(scale), p->val);
g_signal_connect_data(G_OBJECT(scale),
"value-changed",
G_CALLBACK(value_changed),
(gpointer)p,
NULL,
(GConnectFlags)0);
}
}
#endif
gtk_widget_show_all(dialog);
return true; return true;
} }

View File

@ -7,9 +7,9 @@
#ifndef __GTK_SHADER_PARAMETERS_H #ifndef __GTK_SHADER_PARAMETERS_H
#define __GTK_SHADER_PARAMETERS_H #define __GTK_SHADER_PARAMETERS_H
#include "gtk_2_3_compat.h" #include "gtk_compat.h"
bool gtk_shader_parameters_dialog (GtkWindow *parent); bool gtk_shader_parameters_dialog(GtkWindow *parent);
void gtk_shader_parameters_dialog_close (); void gtk_shader_parameters_dialog_close();
#endif // __GTK_SHADER_PARAMETERS_H #endif // __GTK_SHADER_PARAMETERS_H

View File

@ -10,6 +10,8 @@
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "gtk_sound.h" #include "gtk_sound.h"
#include "gtk_sound_driver.h" #include "gtk_sound_driver.h"
#include "snes9x.h"
#include "apu/apu.h"
#ifdef USE_PORTAUDIO #ifdef USE_PORTAUDIO
#include "gtk_sound_driver_portaudio.h" #include "gtk_sound_driver_portaudio.h"
@ -30,10 +32,9 @@ static int playback_rates[8] =
0, 8000, 11025, 16000, 22050, 32000, 44100, 48000 0, 8000, 11025, 16000, 22050, 32000, 44100, 48000
}; };
S9xSoundDriver *driver; static S9xSoundDriver *driver;
int int S9xSoundBase2log(int num)
S9xSoundBase2log (int num)
{ {
int power; int power;
@ -48,14 +49,12 @@ S9xSoundBase2log (int num)
return power; return power;
} }
int int S9xSoundPowerof2(int num)
S9xSoundPowerof2 (int num)
{ {
return (1 << num); return (1 << num);
} }
void void S9xPortSoundInit()
S9xPortSoundInit ()
{ {
int pao_driver = 0; int pao_driver = 0;
int sdl_driver = 0; int sdl_driver = 0;
@ -103,34 +102,34 @@ S9xPortSoundInit ()
#ifdef USE_PORTAUDIO #ifdef USE_PORTAUDIO
if (gui_config->sound_driver == pao_driver) if (gui_config->sound_driver == pao_driver)
driver = new S9xPortAudioSoundDriver (); driver = new S9xPortAudioSoundDriver();
#endif #endif
#ifdef USE_OSS #ifdef USE_OSS
if (gui_config->sound_driver == oss_driver) if (gui_config->sound_driver == oss_driver)
driver = new S9xOSSSoundDriver (); driver = new S9xOSSSoundDriver();
#endif #endif
if (gui_config->sound_driver == sdl_driver) if (gui_config->sound_driver == sdl_driver)
driver = new S9xSDLSoundDriver (); driver = new S9xSDLSoundDriver();
#ifdef USE_ALSA #ifdef USE_ALSA
if (gui_config->sound_driver == alsa_driver) if (gui_config->sound_driver == alsa_driver)
driver = new S9xAlsaSoundDriver (); driver = new S9xAlsaSoundDriver();
#endif #endif
#ifdef USE_PULSEAUDIO #ifdef USE_PULSEAUDIO
if (gui_config->sound_driver == pulse_driver) if (gui_config->sound_driver == pulse_driver)
driver = new S9xPulseSoundDriver (); driver = new S9xPulseSoundDriver();
#endif #endif
if (driver != NULL) if (driver != NULL)
{ {
driver->init (); driver->init();
if (gui_config->auto_input_rate) if (gui_config->auto_input_rate)
{ {
Settings.SoundInputRate = top_level->get_auto_input_rate (); Settings.SoundInputRate = top_level->get_auto_input_rate();
if (Settings.SoundInputRate == 0.0) if (Settings.SoundInputRate == 0.0)
{ {
Settings.SoundInputRate = 31950; Settings.SoundInputRate = 31950;
@ -139,68 +138,65 @@ S9xPortSoundInit ()
} }
else else
{ {
Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 31700, 32300); Settings.SoundInputRate = CLAMP(gui_config->sound_input_rate, 31700, 32300);
} }
Settings.SoundPlaybackRate = playback_rates[gui_config->sound_playback_rate]; Settings.SoundPlaybackRate = playback_rates[gui_config->sound_playback_rate];
S9xInitSound(0); S9xInitSound(0);
S9xSetSoundMute (false); S9xSetSoundMute(false);
} }
else else
{ {
S9xSetSoundMute (gui_config->mute_sound); S9xSetSoundMute(gui_config->mute_sound);
} }
} }
void void S9xPortSoundReinit()
S9xPortSoundReinit ()
{ {
S9xPortSoundDeinit (); S9xPortSoundDeinit();
/* Ensure the sound device is released before trying to reopen it. */ /* Ensure the sound device is released before trying to reopen it. */
sync (); sync();
S9xPortSoundInit (); S9xPortSoundInit();
} }
void void S9xPortSoundDeinit()
S9xPortSoundDeinit ()
{ {
S9xSoundStop (); S9xSoundStop();
driver->terminate (); if (driver)
driver->terminate();
delete driver; delete driver;
} }
void void S9xSoundStart()
S9xSoundStart ()
{ {
driver->start (); if (driver)
driver->start();
} }
void void S9xSoundStop()
S9xSoundStop ()
{ {
driver->stop (); if (driver)
driver->stop();
} }
bool8 bool8 S9xOpenSoundDevice()
S9xOpenSoundDevice ()
{ {
if (gui_config->mute_sound) if (gui_config->mute_sound)
return false; return false;
gui_config->sound_buffer_size = CLAMP (gui_config->sound_buffer_size, 2, 256); gui_config->sound_buffer_size = CLAMP(gui_config->sound_buffer_size, 2, 256);
return driver->open_device (); return driver->open_device();
} }
/* This really shouldn't be in the port layer */ /* This really shouldn't be in the port layer */
void void S9xToggleSoundChannel(int c)
S9xToggleSoundChannel (int c)
{ {
static int sound_switch = 255; static int sound_switch = 255;
@ -209,5 +205,5 @@ S9xToggleSoundChannel (int c)
else else
sound_switch ^= 1 << c; sound_switch ^= 1 << c;
S9xSetSoundControl (sound_switch); S9xSetSoundControl(sound_switch);
} }

View File

@ -6,6 +6,8 @@
#include "gtk_sound_driver_alsa.h" #include "gtk_sound_driver_alsa.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "snes9x.h"
#include "apu/apu.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>

View File

@ -6,6 +6,8 @@
#include "gtk_sound_driver_oss.h" #include "gtk_sound_driver_oss.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "snes9x.h"
#include "apu/apu.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>

View File

@ -6,6 +6,8 @@
#include "gtk_sound_driver_portaudio.h" #include "gtk_sound_driver_portaudio.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "apu/apu.h"
#include "snes9x.h"
static void port_audio_samples_available_callback(void *data) static void port_audio_samples_available_callback(void *data)
{ {

View File

@ -6,6 +6,8 @@
#include "gtk_sound_driver_pulse.h" #include "gtk_sound_driver_pulse.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "snes9x.h"
#include "apu/apu.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>

View File

@ -6,6 +6,8 @@
#include "gtk_sound_driver_sdl.h" #include "gtk_sound_driver_sdl.h"
#include "gtk_s9x.h" #include "gtk_s9x.h"
#include "apu/apu.h"
#include "snes9x.h"
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len) static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
{ {

View File

@ -7,11 +7,11 @@
#ifndef __GTK_WAYLAND_EGL_CONTEXT_H #ifndef __GTK_WAYLAND_EGL_CONTEXT_H
#define __GTK_WAYLAND_EGL_CONTEXT_H #define __GTK_WAYLAND_EGL_CONTEXT_H
#include <epoxy/egl.h>
#include <epoxy/egl_generated.h>
#include <wayland-egl.h>
#include "gtk_opengl_context.h" #include "gtk_opengl_context.h"
#include "gtk_compat.h"
#include <epoxy/egl.h>
#include <wayland-egl.h>
class WaylandEGLContext : public OpenGLContext class WaylandEGLContext : public OpenGLContext
{ {

View File

@ -285,7 +285,7 @@
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="layout_style">end</property> <property name="layout_style">end</property>
<child> <child>
<object class="GtkButton" id="button7"> <object class="GtkButton" id="cheats_close">
<property name="label">gtk-close</property> <property name="label">gtk-close</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
@ -351,7 +351,7 @@
<property name="border_width">5</property> <property name="border_width">5</property>
<property name="spacing">5</property> <property name="spacing">5</property>
<child> <child>
<object class="GtkButton" id="button4"> <object class="GtkButton" id="add_code">
<property name="label">gtk-add</property> <property name="label">gtk-add</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
@ -369,7 +369,7 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="button5"> <object class="GtkButton" id="remove_code">
<property name="label">gtk-remove</property> <property name="label">gtk-remove</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
@ -551,7 +551,7 @@
</object> </object>
</child> </child>
<action-widgets> <action-widgets>
<action-widget response="0">button7</action-widget> <action-widget response="0">cheats_close</action-widget>
</action-widgets> </action-widgets>
</object> </object>
<object class="GtkDialog" id="frame_advance_dialog"> <object class="GtkDialog" id="frame_advance_dialog">
@ -2274,7 +2274,7 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="button11"> <object class="GtkButton" id="clear_netplay">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
@ -2701,7 +2701,7 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="button8"> <object class="GtkButton" id="about_button">
<property name="label">gtk-about</property> <property name="label">gtk-about</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
@ -5446,7 +5446,7 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="button6"> <object class="GtkButton" id="reset_current_joypad">
<property name="label" translatable="yes">_Reset</property> <property name="label" translatable="yes">_Reset</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
@ -5502,7 +5502,7 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkButton" id="button12"> <object class="GtkButton" id="swap_with">
<property name="label" translatable="yes">_Swap</property> <property name="label" translatable="yes">_Swap</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
@ -9320,7 +9320,7 @@
<action-widget response="-6">cancel_button</action-widget> <action-widget response="-6">cancel_button</action-widget>
<action-widget response="-10">ok_button</action-widget> <action-widget response="-10">ok_button</action-widget>
<action-widget response="-5">button1</action-widget> <action-widget response="-5">button1</action-widget>
<action-widget response="0">button8</action-widget> <action-widget response="0">about_button</action-widget>
</action-widgets> </action-widgets>
</object> </object>
<object class="GtkTextBuffer" id="textbuffer1"> <object class="GtkTextBuffer" id="textbuffer1">

View File

@ -7,9 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
int int main(int argc, char *argv[])
main (int argc,
char *argv[])
{ {
FILE *infile, *outfile; FILE *infile, *outfile;
unsigned char inchar; unsigned char inchar;
@ -18,49 +16,46 @@ main (int argc,
if (argc != 4) if (argc != 4)
{ {
fprintf (stderr, "Usage: %s infile outfile identifier\n", argv[0]); fprintf(stderr, "Usage: %s infile outfile identifier\n", argv[0]);
return 1; return 1;
} }
stat (argv[1], &file_info); stat(argv[1], &file_info);
infile = fopen (argv[1], "r"); infile = fopen(argv[1], "r");
if (!infile) if (!infile)
{ {
fprintf (stderr, "Input file doesn't exist.\n"); fprintf(stderr, "Input file doesn't exist.\n");
return 2; return 2;
} }
outfile = fopen (argv[2], "w+"); outfile = fopen(argv[2], "w+");
fprintf (outfile, fprintf(outfile, "int %s_size = %d;\n\n", argv[3], (int)file_info.st_size);
"int %s_size = %d;\n\n", fprintf(outfile, "unsigned char %s [] = \n{\n ", argv[3]);
argv[3],
(int) file_info.st_size);
fprintf (outfile, "unsigned char %s [] = \n{\n ", argv[3]);
counter = 0; counter = 0;
while (fread (&inchar, 1, 1, infile)) while (fread(&inchar, 1, 1, infile))
{ {
if (counter >= 32) if (counter >= 32)
{ {
counter = 0; counter = 0;
fprintf (outfile, "\n "); fprintf(outfile, "\n ");
} }
fprintf (outfile, "%d,", inchar); fprintf(outfile, "%d,", inchar);
counter++; counter++;
} }
/* Erase extra "," */ /* Erase extra "," */
fseek (outfile, -1, SEEK_CUR); fseek(outfile, -1, SEEK_CUR);
fprintf (outfile, "\n};\n"); fprintf(outfile, "\n};\n");
fclose (infile); fclose(infile);
fclose (outfile); fclose(outfile);
return 0; return 0;
} }

View File

@ -345,6 +345,14 @@ void GLSLShader::read_shader_file_with_includes(std::string filename,
sscanf(line.c_str(), "#pragma parameter %s \"%[^\"]\" %f %f %f %f", sscanf(line.c_str(), "#pragma parameter %s \"%[^\"]\" %f %f %f %f",
par.id, par.name, &par.val, &par.min, &par.max, &par.step); par.id, par.name, &par.val, &par.min, &par.max, &par.step);
unsigned int last_decimal = line.rfind(".") + 1;
unsigned int index = last_decimal;
while (isdigit(line[index]) && index < line.length())
index++;
par.digits = index - last_decimal;
if (line[index - 1] == '0' && line[index - 2] == '.')
par.digits = 0;
if (par.step == 0.0f) if (par.step == 0.0f)
par.step = 1.0f; par.step = 1.0f;

View File

@ -151,6 +151,7 @@ typedef struct
float max; float max;
float val; float val;
float step; float step;
int digits;
GLint unif[glsl_max_passes]; GLint unif[glsl_max_passes];
} GLSLParam; } GLSLParam;