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

@ -54,9 +54,7 @@ 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);
@ -83,83 +81,70 @@ 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;
} }
@ -223,7 +208,6 @@ Binding::Binding (const char *raw_string)
{ {
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];

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
@ -58,7 +58,7 @@ class Binding
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;

View File

@ -11,240 +11,145 @@
extern const unsigned char snes9x_ui[]; extern const unsigned char snes9x_ui[];
extern const int snes9x_ui_size; extern const int snes9x_ui_size;
Glib::RefPtr<Gtk::Builder> global_builder;
bool global_builder_created = false;
GtkBuilderWindow::GtkBuilderWindow(const char *root) GtkBuilderWindow::GtkBuilderWindow(const char *root)
{ {
builder = gtk_builder_new (); if (!global_builder_created)
gtk_builder_add_from_string (builder, {
(const gchar *) snes9x_ui, global_builder = Gtk::Builder::create();
snes9x_ui_size, global_builder->add_from_string((const gchar *)snes9x_ui, snes9x_ui_size);
NULL); global_builder_created = true;
}
window = get_widget (root); window = get_object<Gtk::Window>(root);
} }
GtkBuilderWindow::~GtkBuilderWindow() GtkBuilderWindow::~GtkBuilderWindow()
{ {
gtk_widget_destroy (window);
g_object_unref (builder);
} }
GtkWidget * void GtkBuilderWindow::enable_widget(const char *name, bool state)
GtkBuilderWindow::get_widget (const char *name)
{ {
return GTK_WIDGET (gtk_builder_get_object (builder, name)); auto widget = get_object<Gtk::Widget>(name);
widget->set_sensitive(state);
} }
void void GtkBuilderWindow::show_widget(const char *name, bool state)
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; auto widget = get_object<Gtk::Widget>(name);
GtkBuilderWindow *window = (GtkBuilderWindow *) data; widget->set_visible(state);
GtkBuilderWindowCallbacks *callbacks = window->callbacks;
for (int i = 0; callbacks[i].signal; i++)
{
if (!strcmp (handler_name, callbacks[i].signal))
{
function = callbacks[i].function;
break;
}
} }
if (function) void GtkBuilderWindow::resize(int width, int height)
{ {
if (connect_object) window->resize(width, height);
{
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 void GtkBuilderWindow::refresh()
GtkBuilderWindow::signal_connect (GtkBuilderWindowCallbacks *callbacks)
{ {
if (!callbacks) window->queue_draw();
return;
this->callbacks = callbacks;
gtk_builder_connect_signals_full (builder,
signal_connection_func,
(gpointer) this);
this->callbacks = NULL;
} }
void int GtkBuilderWindow::get_width()
GtkBuilderWindow::enable_widget (const char *name, bool state)
{ {
gtk_widget_set_sensitive (get_widget (name), state); return window->get_width();
} }
void int GtkBuilderWindow::get_height()
GtkBuilderWindow::resize (int width, int height)
{ {
if (width > 0 && height > 0) return window->get_height();
gtk_window_resize (GTK_WINDOW (window), width, height);
} }
void void GtkBuilderWindow::set_button_label(const char *name, const char *label)
GtkBuilderWindow::refresh ()
{ {
gtk_widget_queue_draw (GTK_WIDGET (window)); get_object<Gtk::Button>(name)->set_label(label);
} }
int bool GtkBuilderWindow::get_check(const char *name)
GtkBuilderWindow::get_width ()
{ {
int width, height; return get_object<Gtk::ToggleButton>(name)->get_active();
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
return width;
}
int
GtkBuilderWindow::get_height ()
{
int width, height;
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
return height;
}
void
GtkBuilderWindow::set_button_label (const char *name, const char *label)
{
gtk_button_set_label (GTK_BUTTON (get_widget (name)), label);
}
unsigned char
GtkBuilderWindow::get_check (const char *name)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (get_widget (name))))
return 1;
return 0;
} }
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,35 +7,43 @@
#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);
template <typename T>
Glib::RefPtr<T> get_object(const char *name)
{
auto object = global_builder->get_object(name);
if (!object)
{
printf("No object named %s\n", name);
exit(1);
}
return Glib::RefPtr<T>::cast_static(object);
}
void resize(int width, int height); void resize(int width, int height);
GtkWindow *get_window(); GtkWindow *get_window();
void refresh(); void refresh();
int get_width(); int get_width();
int get_height(); int get_height();
void signal_connect (GtkBuilderWindowCallbacks *callbacks);
void enable_widget(const char *name, bool state); void enable_widget(const char *name, bool state);
void show_widget(const char *name, bool state);
void set_button_label(const char *name, const char *label); void set_button_label(const char *name, const char *label);
unsigned char get_check (const char *name); bool get_check(const char *name);
int get_entry_value(const char *name); int get_entry_value(const char *name);
const char *get_entry_text (const char *name); std::string get_entry_text(const char *name);
unsigned char get_combo (const char *name); int get_combo(const char *name);
void combo_box_append(const char *name, const char *value); void combo_box_append(const char *name, const char *value);
void combo_box_append (GtkComboBox *combo, const char *value); void combo_box_append(Gtk::ComboBox *combo, const char *value);
double get_spin(const char *name); double get_spin(const char *name);
float get_slider(const char *name); float get_slider(const char *name);
void set_check(const char *name, bool value); void set_check(const char *name, bool value);
@ -46,12 +54,7 @@ class GtkBuilderWindow
void set_slider(const char *name, float value); void set_slider(const char *name, float value);
bool has_focus(const char *widget); bool has_focus(const char *widget);
protected: Glib::RefPtr<Gtk::Window> window;
static void signal_connection_func (GtkBuilder *, GObject *, const gchar *, const char *, GObject *, GConnectFlags, gpointer);
GtkWidget *window;
GtkBuilder *builder;
GtkBuilderWindowCallbacks *callbacks;
}; };
#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,211 +18,114 @@ 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;
static void cheats_dialog->show();
event_update_code (GtkButton *button, gpointer data)
{
((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() Snes9xCheats::Snes9xCheats()
: GtkBuilderWindow("cheat_window") : 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();
gtk_dialog_run (GTK_DIALOG (window)); window->hide();
top_level->unpause_from_focus_change(); top_level->unpause_from_focus_change();
} }
@ -251,8 +153,7 @@ 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)
{ {
@ -264,158 +165,124 @@ Snes9xCheats::row_deleted (int src_row)
} }
} }
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 =
gtk_tree_view_get_selection (
GTK_TREE_VIEW (get_widget ("cheat_treeview")));
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;
} }
int int Snes9xCheats::get_index_from_path(Gtk::TreeModel::Path path)
Snes9xCheats::get_index_from_path (const gchar *path)
{ {
GtkTreePath *tree_path = gtk_tree_path_new_from_string (path); gint *indices = gtk_tree_path_get_indices(path.gobj());
gint *indices = gtk_tree_path_get_indices (tree_path);
int index = indices[0]; int index = indices[0];
gtk_tree_path_free (tree_path);
return index; return index;
} }
void int Snes9xCheats::get_index_from_path(const Glib::ustring &path)
Snes9xCheats::refresh_tree_view ()
{ {
GtkTreeIter iter; return get_index_from_path(Gtk::TreeModel::Path(path));
unsigned int list_size; }
void Snes9xCheats::refresh_tree_view()
{
enable_dnd(false); enable_dnd(false);
list_size = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL);
auto list_size = store->children().size();
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); Gtk::TreePath path;
path.push_back(index);
auto iter = store->get_iter(path);
store->erase(iter);
enable_dnd(true); enable_dnd(true);
S9xDeleteCheatGroup(index); 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;
@ -463,52 +330,40 @@ Snes9xCheats::search_database ()
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,
GTK_BUTTONS_CLOSE,
reason == -1 ? _("Couldn't Find Cheats Database") :
_("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.")); "translation or modified copy, you may be able to find and manually enter the codes."));
gtk_dialog_run (GTK_DIALOG (dialog)); dialog.run();
gtk_widget_destroy (GTK_WIDGET (dialog)); dialog.hide();
} }
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);
GtkTreePath *treepath = gtk_tree_path_new_from_string (path); bool enabled;
gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, treepath); iter->get_value(COLUMN_ENABLED, enabled);
gtk_list_store_set (store, &iter, COLUMN_ENABLED, enabled, -1); enabled = !enabled;
iter->set_value(COLUMN_ENABLED, enabled);
if (enabled) if (enabled)
S9xEnableCheatGroup(index); S9xEnableCheatGroup(index);
@ -516,39 +371,35 @@ Snes9xCheats::toggle_code (const gchar *path, int enabled)
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++)
{ {
@ -558,4 +409,3 @@ Snes9xCheats::disable_all ()
refresh_tree_view(); refresh_tree_view();
} }

View File

@ -9,8 +9,9 @@
#include "gtk_builder_window.h" #include "gtk_builder_window.h"
enum void open_snes9x_cheats_dialog();
{
enum {
TYPE_GAME_GENIE = 0, TYPE_GAME_GENIE = 0,
TYPE_ACTION_REPLAY = 1, TYPE_ACTION_REPLAY = 1,
TYPE_GOLDFINGER = 2 TYPE_GOLDFINGER = 2
@ -26,8 +27,8 @@ class Snes9xCheats : public GtkBuilderWindow
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);
@ -38,12 +39,13 @@ class Snes9xCheats : public GtkBuilderWindow
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,
@ -167,7 +167,7 @@ class Snes9xConfig
bool use_sync_control; bool use_sync_control;
#endif #endif
JoyDevice **joystick; std::vector<JoyDevice> joystick;
int joystick_threshold; int joystick_threshold;
}; };

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 */
@ -215,22 +220,18 @@ 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))
@ -238,65 +239,53 @@ void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2)
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();
@ -333,128 +322,102 @@ s9xcommand_t S9xGetPortCommandT (const char *name)
{ {
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);
@ -470,9 +433,9 @@ void S9xProcessEvents (bool8 block)
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);
@ -492,18 +455,16 @@ static void poll_joystick_events ()
{ {
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);
} }
} }
} }
@ -511,25 +472,12 @@ static void poll_joystick_events ()
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
@ -539,38 +487,45 @@ void S9xInitInputDevices ()
void S9xDeinitInputDevices() void S9xDeinitInputDevices()
{ {
for (int i = 0; gui_config->joystick[i] != NULL; i++) gui_config->joystick.clear();
{
delete gui_config->joystick[i];
}
free (gui_config->joystick);
SDL_Quit(); 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;
}
JoyDevice::~JoyDevice()
{
if (enabled)
{
SDL_JoystickClose(filedes);
}
}
bool JoyDevice::set_sdl_joystick_num(unsigned int device_num)
{
if ((int)device_num >= SDL_NumJoysticks()) if ((int)device_num >= SDL_NumJoysticks())
return; {
enabled = false;
return false;
}
filedes = SDL_JoystickOpen(device_num); 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++)
{ {
@ -586,20 +541,10 @@ JoyDevice::JoyDevice (unsigned int device_num)
num_axes, num_axes,
num_hats); num_hats);
memset (axis, 0, sizeof (int) * num_axes); for (auto &i : axis)
} i = 0;
JoyDevice::~JoyDevice () return true;
{
if (enabled)
{
SDL_JoystickClose (filedes);
delete[] axis;
delete[] hat;
delete[] calibration;
}
enabled = false;
} }
void JoyDevice::add_event(unsigned int parameter, unsigned int state) void JoyDevice::add_event(unsigned int parameter, unsigned int state)
@ -611,7 +556,7 @@ void JoyDevice::add_event (unsigned int parameter, unsigned int state)
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);
@ -722,7 +667,6 @@ void JoyDevice::handle_event (SDL_Event *event)
} }
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 ||
@ -737,49 +681,49 @@ 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;

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,
@ -97,22 +94,21 @@ 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:

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,11 +1291,11 @@ 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
@ -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,6 +1456,7 @@ S9xDisplayDriver *S9xDisplayGetDriver()
void S9xDeinitDisplay() void S9xDeinitDisplay()
{ {
if (driver)
driver->deinit(); driver->deinit();
delete driver; delete driver;

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,7 +77,8 @@ 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;

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,8 +39,7 @@ 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, '.');
@ -83,12 +84,7 @@ _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)
{ {
@ -107,8 +103,7 @@ _makepath (char *path,
} }
} }
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];
@ -126,14 +121,12 @@ S9xGetFilenameInc (const char *e, enum s9x_getdirtype dirtype)
{ {
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];
@ -207,8 +200,7 @@ 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];
@ -224,8 +216,7 @@ S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype)
return (filename); return (filename);
} }
const char * const char *S9xBasename(const char *f)
S9xBasename (const char *f)
{ {
const char *p; const char *p;
@ -235,8 +226,7 @@ S9xBasename (const char *f)
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;
@ -260,8 +250,7 @@ S9xBasenameNoExt (const char *f)
return filename; return filename;
} }
static int static int file_exists(const char *name)
file_exists (const char *name)
{ {
FILE *f = NULL; FILE *f = NULL;
@ -276,8 +265,7 @@ file_exists (const char *name)
} }
} }
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];
@ -367,15 +355,13 @@ void S9xCloseSnapshotFile (STREAM 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));
@ -390,8 +376,7 @@ S9xLoadState (const char *filename)
} }
} }
void void S9xSaveState(const char *filename)
S9xSaveState (const char *filename)
{ {
if (S9xFreezeGame(filename)) if (S9xFreezeGame(filename))
{ {
@ -404,82 +389,8 @@ S9xSaveState (const char *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];
@ -555,4 +466,3 @@ void S9xQuickLoadSlot (int slot)
S9X_FREEZE_FILE_NOT_FOUND, S9X_FREEZE_FILE_NOT_FOUND,
"Freeze file not found"); "Freeze file not found");
} }

View File

@ -7,7 +7,6 @@
#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);

View File

@ -6,18 +6,14 @@
#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;
parent_gdk_window = NULL;
gdk_window = NULL;
display = NULL; display = NULL;
vi = NULL;
context = NULL; context = NULL;
version_major = -1; version_major = -1;
@ -30,18 +26,10 @@ 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;
@ -54,17 +42,8 @@ bool GTKGLXContext::attach (GtkWidget *widget)
None None
}; };
window = gtk_widget_get_window (widget); this->xid = xid;
this->widget = widget; display = dpy;
if (!GDK_IS_X11_WINDOW (window))
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); glXQueryVersion(display, &version_major, &version_minor);
if (version_major < 2 && version_minor < 3) if (version_major < 2 && version_minor < 3)
@ -77,23 +56,6 @@ bool GTKGLXContext::attach (GtkWidget *widget)
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;
} }
@ -109,12 +71,15 @@ bool GTKGLXContext::create_context ()
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 {
printf("XError: type: %d code: %d\n", event->type, event->error_code);
return X_OK;
});
if (strstr(extensions, "GLX_ARB_create_context")) if (strstr(extensions, "GLX_ARB_create_context"))
context = glXCreateContextAttribsARB(display, fbconfig, NULL, True, context_attribs); 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)
{ {
@ -130,20 +95,16 @@ bool GTKGLXContext::create_context ()
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);
window_attr.width = width; glXQueryDrawable(display, xid, GLX_HEIGHT, &height);
window_attr.height = height;
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);
this->width = width;
this->height = height;
make_current(); make_current();
} }
@ -186,5 +147,3 @@ void GTKGLXContext::swap_interval (int frames)
glXSwapIntervalMESA(frames); glXSwapIntervalMESA(frames);
#endif #endif
} }

View File

@ -7,17 +7,16 @@
#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();
@ -25,18 +24,10 @@ class GTKGLXContext : public OpenGLContext
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,6 +10,12 @@
#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);
@ -19,8 +25,7 @@ static GThread *npthread;
extern SNPServer NPServer; extern SNPServer NPServer;
static void static void S9xNetplayPreconnect()
S9xNetplayPreconnect ()
{ {
S9xNetplayDisconnect(); S9xNetplayDisconnect();
@ -33,8 +38,7 @@ S9xNetplayPreconnect ()
NetPlay.Waiting4EmulationThread = false; NetPlay.Waiting4EmulationThread = false;
} }
static void static void S9xNetplayConnect()
S9xNetplayConnect ()
{ {
GtkWidget *msg; GtkWidget *msg;
@ -43,7 +47,7 @@ S9xNetplayConnect ()
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;
} }
@ -81,15 +85,13 @@ S9xNetplayConnect ()
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();
@ -98,8 +100,7 @@ S9xNetplayStopServer ()
gui_config->netplay_server_up = false; gui_config->netplay_server_up = false;
} }
void void S9xNetplayDisconnect()
S9xNetplayDisconnect ()
{ {
if (Settings.NetPlay) if (Settings.NetPlay)
{ {
@ -118,16 +119,14 @@ S9xNetplayDisconnect ()
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;
@ -136,7 +135,7 @@ S9xNetplayStartServer ()
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;
} }
@ -166,8 +165,7 @@ S9xNetplayStartServer ()
top_level->configure_widgets(); top_level->configure_widgets();
} }
void void S9xNetplayDialogOpen()
S9xNetplayDialogOpen ()
{ {
Snes9xNetplayDialog *np_dialog; Snes9xNetplayDialog *np_dialog;
@ -197,8 +195,7 @@ S9xNetplayDialogOpen ()
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;
@ -266,8 +263,7 @@ S9xNetplaySyncSpeed ()
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))
@ -308,8 +304,7 @@ S9xNetplayPush ()
return 0; return 0;
} }
void void S9xNetplayPop()
S9xNetplayPop ()
{ {
if (!Settings.NetPlay) if (!Settings.NetPlay)
return; return;
@ -317,7 +312,3 @@ S9xNetplayPop ()
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

@ -6,59 +6,32 @@
#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 () {
}
void Snes9xNetplayDialog::update_state()
{ {
if (get_check("host_radio")) if (get_check("host_radio"))
{ {
@ -77,8 +50,7 @@ Snes9xNetplayDialog::update_state ()
} }
} }
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());
@ -93,8 +65,7 @@ Snes9xNetplayDialog::settings_to_dialog ()
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");
@ -110,29 +81,16 @@ Snes9xNetplayDialog::settings_from_dialog ()
bool Snes9xNetplayDialog::show() bool Snes9xNetplayDialog::show()
{ {
int result;
settings_to_dialog(); settings_to_dialog();
result = gtk_dialog_run (GTK_DIALOG (window)); auto result = Glib::RefPtr<Gtk::Dialog>::cast_static(window)->run();
window->hide();
gtk_widget_hide (window); if (result == Gtk::RESPONSE_OK)
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

@ -24,5 +24,4 @@ class Snes9xNetplayDialog : public GtkBuilderWindow
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() { return true; }; virtual bool ready()
{
return true;
};
int x; int x;
int y; int y;

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,11 @@
#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
{ {
@ -23,7 +22,6 @@ class Snes9xPreferences : public GtkBuilderWindow
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();
@ -33,9 +31,15 @@ class Snes9xPreferences : public GtkBuilderWindow
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;
@ -44,8 +48,6 @@ class Snes9xPreferences : public GtkBuilderWindow
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,13 +17,22 @@
#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 gboolean S9xIdleFunc (gpointer data); static bool S9xIdleFunc();
static gboolean S9xPauseFunc (gpointer data); static bool S9xPauseFunc();
static gboolean S9xScreenSaverCheckFunc (gpointer data); static bool S9xScreenSaverCheckFunc();
Snes9xWindow *top_level; Snes9xWindow *top_level;
Snes9xConfig *gui_config; Snes9xConfig *gui_config;
@ -29,9 +40,9 @@ 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();
} }
@ -39,8 +50,7 @@ void S9xTerm (int signal)
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, ""); setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, SNES9XLOCALEDIR); bindtextdomain(GETTEXT_PACKAGE, SNES9XLOCALEDIR);
@ -49,10 +59,9 @@ int main (int argc, char *argv[])
memset(&Settings, 0, sizeof(Settings)); memset(&Settings, 0, sizeof(Settings));
/* Allow original config file for backend settings */ // Original config fills out values this port doesn't.
S9xLoadConfigFiles(argv, argc); S9xLoadConfigFiles(argv, argc);
/* Perform our config here */
gui_config = new Snes9xConfig(); gui_config = new Snes9xConfig();
S9xInitInputDevices(); S9xInitInputDevices();
@ -61,13 +70,9 @@ int main (int argc, char *argv[])
char *rom_filename = S9xParseArgs(argv, argc); char *rom_filename = S9xParseArgs(argv, argc);
#if GTK_MAJOR_VERSION >= 3 auto settings = Gtk::Settings::get_default();
auto settings = gtk_settings_get_default(); settings->set_property("gtk-menu-images", gui_config->enable_icons);
g_object_set(settings, settings->set_property("gtk-button-images", gui_config->enable_icons);
"gtk-menu-images", gui_config->enable_icons,
"gtk_button_images", gui_config->enable_icons,
NULL);
#endif
S9xReportControllers(); S9xReportControllers();
@ -76,16 +81,14 @@ int main (int argc, char *argv[])
top_level = new Snes9xWindow(gui_config); top_level = new Snes9xWindow(gui_config);
/* If we're going to fullscreen, do it before showing window to avoid flicker. */ // Setting fullscreen before showing the window avoids some 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++)
@ -118,38 +121,39 @@ int main (int argc, char *argv[])
} }
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); Glib::signal_timeout().connect(sigc::ptr_fun(S9xPauseFunc), 100);
Glib::signal_timeout().connect(sigc::ptr_fun(S9xScreenSaverCheckFunc), 10000);
S9xNoROMLoaded(); 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;
} }
@ -259,7 +263,7 @@ void S9xNoROMLoaded ()
top_level->configure_widgets(); top_level->configure_widgets();
} }
static gboolean S9xPauseFunc (gpointer data) static bool S9xPauseFunc()
{ {
S9xProcessEvents(true); S9xProcessEvents(true);
@ -281,10 +285,8 @@ static gboolean S9xPauseFunc (gpointer data)
} }
/* 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,12 +306,12 @@ 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)
{ {
@ -323,7 +325,7 @@ gboolean S9xIdleFunc (gpointer data)
} }
/* 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;
} }
@ -355,21 +357,10 @@ gboolean S9xIdleFunc (gpointer data)
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
if ((Settings.TurboMode || Settings.Rewinding) && !muted_from_turbo && gui_config->mute_sound_turbo) Settings.Mute &= ~0x80;
{
muted_from_turbo = true;
mute_saved_state = Settings.Mute;
S9xSetSoundMute (true);
}
if (!(Settings.TurboMode || Settings.Rewinding) && muted_from_turbo)
{
muted_from_turbo = false;
Settings.Mute = mute_saved_state;
}
S9xMainLoop(); S9xMainLoop();
@ -379,7 +370,7 @@ gboolean S9xIdleFunc (gpointer data)
return true; return true;
} }
gboolean S9xScreenSaverCheckFunc (gpointer data) static bool S9xScreenSaverCheckFunc()
{ {
if (!Settings.Paused && if (!Settings.Paused &&
@ -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;
@ -597,94 +587,12 @@ void S9xExit ()
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)
{ {
return NULL; return NULL;

View File

@ -8,12 +8,11 @@
#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;

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"
@ -18,6 +18,13 @@ class Snes9xWindow : public GtkBuilderWindow
public: public:
Snes9xWindow(Snes9xConfig *config); Snes9xWindow(Snes9xConfig *config);
struct AcceleratorEntry
{
std::string name;
unsigned int key;
Gdk::ModifierType modifiers;
};
/* Pause related functions */ /* Pause related functions */
void pause_from_focus_change(); void pause_from_focus_change();
void unpause_from_focus_change(); void unpause_from_focus_change();
@ -40,13 +47,13 @@ class Snes9xWindow : public GtkBuilderWindow
void center_mouse(); void center_mouse();
/* Rom-related functions */ /* Rom-related functions */
void open_rom_dialog (); std::string open_rom_dialog(bool run = true);
void save_state_dialog(); void save_state_dialog();
void load_state_dialog(); void load_state_dialog();
void configure_widgets(); void configure_widgets();
void save_spc_dialog(); void save_spc_dialog();
bool try_open_rom (const char *filename); bool try_open_rom(std::string filename);
const char *open_movie_dialog (bool readonly); std::string open_movie_dialog(bool readonly);
void movie_seek_dialog(); void movie_seek_dialog();
void open_multicart_dialog(); void open_multicart_dialog();
void show_rom_info(); void show_rom_info();
@ -55,17 +62,23 @@ class Snes9xWindow : public GtkBuilderWindow
void show(); void show();
void set_menu_item_selected(const char *name); void set_menu_item_selected(const char *name);
void set_mouseable_area(int x, int y, int width, int height); void set_mouseable_area(int x, int y, int width, int height);
void set_menu_item_accel_to_binding (const char *name, void set_accelerator_to_binding(const char *name,
const char *binding); const char *binding);
void reset_screensaver(); void reset_screensaver();
void update_accels (); void update_accelerators();
void toggle_ui(); void toggle_ui();
void resize_to_multiple(int factor); void resize_to_multiple(int factor);
void resize_viewport(int width, int height); void resize_viewport(int width, int height);
void expose (); bool draw(const Cairo::RefPtr<Cairo::Context> &cr);
void setup_splash(); void setup_splash();
double get_refresh_rate(); double get_refresh_rate();
int get_auto_input_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);
cairo_t *get_cairo(); cairo_t *get_cairo();
void release_cairo(); void release_cairo();
@ -84,18 +97,20 @@ class Snes9xWindow : public GtkBuilderWindow
double gdk_mouse_x, gdk_mouse_y; double gdk_mouse_x, gdk_mouse_y;
bool mouse_grabbed; bool mouse_grabbed;
GdkPixbuf *icon, *splash; GdkPixbuf *icon, *splash;
GdkCursor *default_cursor, *empty_cursor; Gtk::DrawingArea *drawing_area;
GtkDrawingArea *drawing_area; Gtk::RecentChooserMenu *recent_menu;
GtkWidget *recent_menu;
cairo_t *cr; cairo_t *cr;
bool cairo_owned; bool cairo_owned;
#if GTK_MAJOR_VERSION >= 3 Glib::RefPtr<Gdk::DrawingContext> gdk_drawing_context;
GdkDrawingContext *gdk_drawing_context; Glib::RefPtr<Gtk::AccelGroup> accel_group;
cairo_region_t *cairo_region; std::vector<AcceleratorEntry> accelerators;
#endif
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 width;
unsigned int height; unsigned int height;
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */

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,
NULL,
(GConnectFlags)0);
}
}
#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++)
{ {
GLSLParam *p = &(*params)[i]; param = new_value;
GtkWidget *label = gtk_label_new(p->name); if (Settings.Paused)
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); S9xDeinitUpdate(top_level->last_width, top_level->last_height);
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); dialog->show_all();
return true; return true;
} }

View File

@ -7,7 +7,7 @@
#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();

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;
@ -154,8 +153,7 @@ S9xPortSoundInit ()
} }
} }
void void S9xPortSoundReinit()
S9xPortSoundReinit ()
{ {
S9xPortSoundDeinit(); S9xPortSoundDeinit();
@ -165,30 +163,29 @@ S9xPortSoundReinit ()
S9xPortSoundInit(); S9xPortSoundInit();
} }
void void S9xPortSoundDeinit()
S9xPortSoundDeinit ()
{ {
S9xSoundStop(); S9xSoundStop();
if (driver)
driver->terminate(); driver->terminate();
delete driver; delete driver;
} }
void void S9xSoundStart()
S9xSoundStart ()
{ {
if (driver)
driver->start(); driver->start();
} }
void void S9xSoundStop()
S9xSoundStop ()
{ {
if (driver)
driver->stop(); driver->stop();
} }
bool8 bool8 S9xOpenSoundDevice()
S9xOpenSoundDevice ()
{ {
if (gui_config->mute_sound) if (gui_config->mute_sound)
return false; return false;
@ -199,8 +196,7 @@ S9xOpenSoundDevice ()
} }
/* 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;

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;
@ -34,10 +32,7 @@ main (int argc,
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",
argv[3],
(int) file_info.st_size);
fprintf(outfile, "unsigned char %s [] = \n{\n ", argv[3]); fprintf(outfile, "unsigned char %s [] = \n{\n ", argv[3]);
counter = 0; counter = 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;