fceux/src/drivers/sdl/gui.cpp

3779 lines
104 KiB
C++

#include "../../types.h"
#include "../../fceu.h"
#include "../../cheat.h"
#include "../../debug.h"
#include "../../driver.h"
#include "../../version.h"
#include "../../movie.h"
#include "../../palette.h"
#include "../../fds.h"
#include "../common/configSys.h"
#include "sdl.h"
#include "gui.h"
#include "dface.h"
#include "input.h"
#include "config.h"
#include "cheat.h"
#include "icon.xpm"
#include "memview.h"
#include "ramwatch.h"
#include "debugger.h"
#include "sdl-joystick.h"
#include "fceux_git_info.h"
#ifdef _S9XLUA_H
#include "../../fceulua.h"
#endif
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#ifdef _GTK3
#include <gdk/gdkkeysyms-compat.h>
#endif
#ifdef APPLEOPENGL
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <list>
#include "glxwin.h"
#include "sdl-video.h"
// Fix compliation errors for older version of GTK (Ubuntu 10.04 LTS)
#if GTK_MINOR_VERSION < 24 && GTK_MAJOR_VERSION == 2
#define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX
#define gtk_combo_box_text_new gtk_combo_box_new
#define gtk_combo_box_text_get_active_text gtk_combo_box_get_active_text
#define gtk_combo_box_text_append_text gtk_combo_box_append_text
#endif
// NES resolution = 256x240
const int NES_WIDTH = 256;
const int NES_HEIGHT = 240;
void toggleSound (GtkWidget * check, gpointer data);
void loadGame (void);
void closeGame (void);
extern Config *g_config;
extern bool gtk_gui_run;
GtkWidget *MainWindow = NULL;
GtkWidget *evbox = NULL;
static GtkWidget *Menubar = NULL;
static GtkRadioMenuItem *stateSlot[10] = { NULL };
bool gtkIsStarted = false;
bool menuTogglingEnabled = false;
enum videoDriver_t videoDriver = VIDEO_NONE;
unsigned int gtk_draw_area_width = NES_WIDTH;
unsigned int gtk_draw_area_height = NES_HEIGHT;
static GtkTreeStore *hotkey_store = NULL;
static cairo_surface_t *cairo_surface = NULL;
static cairo_pattern_t *cairo_pattern = NULL;
static int *cairo_pix_remapper = NULL;
static int numRendLines = 0;
static void cairo_recalc_mapper(void);
// check to see if a particular GTK version is available
// 2.24 is required for most of the dialogs -- ie: checkGTKVersion(2,24);
bool checkGTKVersion (int major_required, int minor_required)
{
int major = GTK_MAJOR_VERSION;
int minor = GTK_MINOR_VERSION;
if (major > major_required)
{
return true;
}
else if (major == major_required)
{
if (minor >= minor_required)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
void setCheckbox (GtkWidget * w, const char *configName)
{
int buf;
g_config->getOption (configName, &buf);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), buf);
}
// This function configures a single button on a gamepad
//int configGamepadButton (GtkButton * button, gpointer p)
//{
// gint x = ((gint) (glong) (p));
// //gint x = GPOINTER_TO_INT(p);
// int padNo =
// atoi (gtk_combo_box_text_get_active_text
// (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1;
//
// char buf[256];
// std::string prefix;
//
// // only configure when the "Change" button is pressed in, not when it is unpressed
// if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
// return 0;
//
// buttonConfigStatus = 2;
//
// ButtonConfigBegin ();
//
// snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo);
// prefix = buf;
// DWaitButton (NULL, &GamePad[padNo].bmap[x], &buttonConfigStatus );
//
//// g_config->setOption (prefix + GamePadNames[x],
//// GamePadConfig[padNo][x].ButtonNum[configNo]);
////
//// if (GamePadConfig[padNo][x].ButtType[0] == BUTTC_KEYBOARD)
//// {
//// g_config->setOption (prefix + "DeviceType", "Keyboard");
//// }
//// else if (GamePadConfig[padNo][x].ButtType[0] == BUTTC_JOYSTICK)
//// {
//// g_config->setOption (prefix + "DeviceType", "Joystick");
//// }
//// else
//// {
//// g_config->setOption (prefix + "DeviceType", "Unknown");
//// }
//// g_config->setOption (prefix + "DeviceNum",
//// GamePadConfig[padNo][x].DeviceNum[configNo]);
//
// snprintf (buf, sizeof (buf), "<tt>%s</tt>",
// ButtonName (&GamePad[padNo].bmap[x]));
//
// if ( buttonMappings[x] != NULL )
// {
// gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf);
// }
//
// ButtonConfigEnd ();
//
// buttonConfigStatus = 1;
//
// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
//
// return 0;
//}
void resetVideo (void)
{
//resizeGtkWindow ();
KillVideo ();
InitVideo (GameInfo);
}
void closeVideoWin (GtkWidget * w, gint response, gpointer p)
{
resetVideo ();
if (response != GTK_RESPONSE_APPLY)
{
gtk_widget_destroy (w);
}
}
void closeDialog (GtkWidget * w, GdkEvent * e, gpointer p)
{
gtk_widget_destroy (w);
}
void toggleLowPass (GtkWidget * w, gpointer p)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
{
g_config->setOption ("SDL.Sound.LowPass", 1);
FCEUI_SetLowPass (1);
}
else
{
g_config->setOption ("SDL.Sound.LowPass", 0);
FCEUI_SetLowPass (0);
}
g_config->save ();
}
void toggleSwapDuty (GtkWidget * w, gpointer p)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
{
g_config->setOption ("SDL.SwapDuty", 1);
swapDuty = 1;
}
else
{
g_config->setOption ("SDL.SwapDuty", 0);
swapDuty = 0;
}
g_config->save ();
}
// Wrapper for pushing GTK options into the config file
// p : pointer to the string that names the config option
// w : toggle widget
void toggleOption (GtkWidget * w, gpointer p)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
g_config->setOption ((char *) p, 1);
else
g_config->setOption ((char *) p, 0);
g_config->save ();
UpdateEMUCore (g_config);
}
int setTint (GtkWidget * w, gpointer p)
{
int v = gtk_range_get_value (GTK_RANGE (w));
g_config->setOption ("SDL.Tint", v);
g_config->save ();
int c, h;
g_config->getOption ("SDL.NTSCpalette", &c);
g_config->getOption ("SDL.Hue", &h);
FCEUI_SetNTSCTH (c, v, h);
return 0;
}
int setHue (GtkWidget * w, gpointer p)
{
int v = gtk_range_get_value (GTK_RANGE (w));
g_config->setOption ("SDL.Hue", v);
g_config->save ();
int c, t;
g_config->getOption ("SDL.Tint", &t);
g_config->getOption ("SDL.SDL.NTSCpalette", &c);
FCEUI_SetNTSCTH (c, t, v);
return 0;
}
void loadPalette (GtkWidget * w, gpointer p)
{
GtkWidget *fileChooser;
fileChooser =
gtk_file_chooser_dialog_new ("Open NES Palette",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fileChooser),
"/usr/share/fceux/palettes");
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
g_config->setOption ("SDL.Palette", filename);
g_config->setOption ("SDL.SDL.NTSCpalette", 0);
LoadCPalette (filename);
gtk_entry_set_text (GTK_ENTRY (p), filename);
}
gtk_widget_destroy (fileChooser);
}
void clearPalette (GtkWidget * w, gpointer p)
{
g_config->setOption ("SDL.Palette", 0);
gtk_entry_set_text (GTK_ENTRY (p), "");
}
void openPaletteConfig (void)
{
GtkWidget *win;
GtkWidget *vbox;
GtkWidget *paletteFrame;
GtkWidget *paletteHbox;
GtkWidget *paletteButton;
GtkWidget *paletteEntry;
GtkWidget *clearButton;
GtkWidget *ntscColorChk;
GtkWidget *slidersFrame;
GtkWidget *slidersVbox;
GtkWidget *tintFrame;
GtkWidget *tintHscale;
GtkWidget *hueFrame;
GtkWidget *hueHscale;
win = gtk_dialog_new_with_buttons ("Palette Options",
GTK_WINDOW (MainWindow),
(GtkDialogFlags)
(GTK_DIALOG_DESTROY_WITH_PARENT),
"_Close", GTK_RESPONSE_OK, NULL);
gtk_window_set_icon_name (GTK_WINDOW (win), "Color");
vbox = gtk_dialog_get_content_area (GTK_DIALOG (win));
paletteFrame = gtk_frame_new ("Custom palette: ");
paletteHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_container_set_border_width (GTK_CONTAINER (paletteHbox), 5);
gtk_container_add (GTK_CONTAINER (paletteFrame), paletteHbox);
paletteButton = gtk_button_new_with_label ("Open palette");
paletteEntry = gtk_entry_new ();
gtk_editable_set_editable (GTK_EDITABLE (paletteEntry), FALSE);
clearButton = gtk_button_new_with_label ("Clear");
gtk_box_pack_start (GTK_BOX (paletteHbox), paletteButton, FALSE, FALSE,
2);
gtk_box_pack_start (GTK_BOX (paletteHbox), paletteEntry, TRUE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (paletteHbox), clearButton, FALSE, FALSE,
0);
g_signal_connect (paletteButton, "clicked", G_CALLBACK (loadPalette),
paletteEntry);
g_signal_connect (clearButton, "clicked", G_CALLBACK (clearPalette),
paletteEntry);
// sync with config
std::string fn;
g_config->getOption ("SDL.Palette", &fn);
gtk_entry_set_text (GTK_ENTRY (paletteEntry), fn.c_str ());
// ntsc color check
ntscColorChk = gtk_check_button_new_with_label ("Use NTSC palette");
g_signal_connect (ntscColorChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.NTSCpalette");
setCheckbox (ntscColorChk, "SDL.NTSCpalette");
// color / tint / hue sliders
slidersFrame = gtk_frame_new ("NTSC palette controls");
slidersVbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
tintFrame = gtk_frame_new ("Tint");
tintHscale =
gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 128,
1);
gtk_container_add (GTK_CONTAINER (tintFrame), tintHscale);
hueFrame = gtk_frame_new ("Hue");
hueHscale =
gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 128,
1);
gtk_container_add (GTK_CONTAINER (hueFrame), hueHscale);
g_signal_connect (tintHscale, "button-release-event",
G_CALLBACK (setTint), NULL);
g_signal_connect (hueHscale, "button-release-event",
G_CALLBACK (setHue), NULL);
// sync with config
int h, t;
g_config->getOption ("SDL.Hue", &h);
g_config->getOption ("SDL.Tint", &t);
gtk_range_set_value (GTK_RANGE (hueHscale), h);
gtk_range_set_value (GTK_RANGE (tintHscale), t);
gtk_container_add (GTK_CONTAINER (slidersFrame), slidersVbox);
gtk_box_pack_start (GTK_BOX (slidersVbox), ntscColorChk, FALSE, FALSE,
5);
gtk_box_pack_start (GTK_BOX (slidersVbox), tintFrame, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (slidersVbox), hueFrame, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (vbox), paletteFrame, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (vbox), slidersFrame, FALSE, TRUE, 5);
g_signal_connect (win, "delete-event", G_CALLBACK (closeDialog), NULL);
g_signal_connect (win, "response", G_CALLBACK (closeDialog), NULL);
gtk_widget_show_all (win);
return;
}
GtkWidget *ipEntry;
GtkWidget *portSpin;
GtkWidget *pwEntry;
void launchNet (GtkWidget * w, gpointer p)
{
char *ip = (char *) gtk_entry_get_text (GTK_ENTRY (ipEntry));
char *pw = (char *) gtk_entry_get_text (GTK_ENTRY (pwEntry));
int port = (int) gtk_spin_button_get_value (GTK_SPIN_BUTTON (portSpin));
g_config->setOption ("SDL.NetworkIP", ip);
g_config->setOption ("SDL.NetworkPassword", pw);
g_config->setOption ("SDL.NetworkPort", port);
gtk_widget_destroy (GTK_WIDGET (w));
loadGame ();
}
void setUsername (GtkWidget * w, gpointer p)
{
char *s = (char *) gtk_entry_get_text (GTK_ENTRY (w));
g_config->setOption ("SDL.NetworkUsername", s);
}
void netResponse (GtkWidget * w, gint response_id, gpointer p)
{
if (response_id == GTK_RESPONSE_OK)
launchNet (w, p);
else
gtk_widget_destroy (w);
}
void openNetworkConfig (void)
{
GtkWidget *win;
GtkWidget *box;
GtkWidget *userBox;
GtkWidget *userEntry;
GtkWidget *userLbl;
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *ipBox;
GtkWidget *ipLbl;
GtkWidget *portBox;
GtkWidget *portLbl;
//GtkWidget* localPlayersCbo;
GtkWidget *pwBox;
GtkWidget *pwLbl;
win = gtk_dialog_new_with_buttons ("Network Options",
GTK_WINDOW (MainWindow),
(GtkDialogFlags)
(GTK_DIALOG_DESTROY_WITH_PARENT),
"_Close", GTK_RESPONSE_CLOSE,
"_Connect", GTK_RESPONSE_OK, NULL);
gtk_window_set_icon_name (GTK_WINDOW (win), "network-workgroup");
box = gtk_dialog_get_content_area (GTK_DIALOG (win));
userBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
userLbl = gtk_label_new ("Username:");
userEntry = gtk_entry_new ();
std::string s;
g_config->getOption ("SDL.NetworkUsername", &s);
gtk_entry_set_text (GTK_ENTRY (userEntry), s.c_str ());
g_signal_connect (userEntry, "changed", G_CALLBACK (setUsername), NULL);
frame = gtk_frame_new ("Network options");
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
ipBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
ipLbl = gtk_label_new ("Server IP:");
ipEntry = gtk_entry_new ();
portBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
portLbl = gtk_label_new ("Server port:");
portSpin = gtk_spin_button_new_with_range (0, 999999, 1);
//localPlayersCbo = gtk_combo_box_new_text();
pwBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
pwLbl = gtk_label_new ("Server password:");
pwEntry = gtk_entry_new ();
gtk_spin_button_set_value (GTK_SPIN_BUTTON (portSpin), 4046);
gtk_box_pack_start (GTK_BOX (userBox), userLbl, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (userBox), userEntry, TRUE, TRUE, 3);
gtk_box_pack_start (GTK_BOX (portBox), portLbl, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (portBox), portSpin, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (ipBox), ipLbl, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (ipBox), ipEntry, TRUE, TRUE, 3);
gtk_box_pack_start (GTK_BOX (pwBox), pwLbl, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (pwBox), pwEntry, TRUE, TRUE, 3);
gtk_box_pack_start (GTK_BOX (vbox), ipBox, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (vbox), portBox, FALSE, FALSE, 3);
//gtk_box_pack_start_defaults(GTK_BOX(vbox), localPlayersCbo);
gtk_box_pack_start (GTK_BOX (vbox), pwBox, FALSE, FALSE, 3);
gtk_container_add (GTK_CONTAINER (frame), vbox);
gtk_box_pack_start (GTK_BOX (box), userBox, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (box), frame, TRUE, TRUE, 0);
gtk_widget_show_all (win);
g_signal_connect (win, "delete-event", G_CALLBACK (closeDialog), NULL);
g_signal_connect (win, "response", G_CALLBACK (netResponse), NULL);
}
// handler prototype
void flushGtkEvents (void)
{
while (gtk_events_pending ())
gtk_main_iteration_do (FALSE);
return;
}
static void hotKeyWindowRefresh (void)
{
GtkTreeIter iter;
std::string prefix = "SDL.Hotkeys.";
if (hotkey_store == NULL) return;
gtk_tree_store_clear (hotkey_store);
gtk_tree_store_append (hotkey_store, &iter, NULL); // aquire iter
int keycode;
for (int i = 0; i < HK_MAX; i++)
{
std::string optionName = prefix + getHotkeyString(i);
g_config->getOption (optionName.c_str (), &keycode);
gtk_tree_store_set (hotkey_store, &iter,
0, optionName.c_str (), 1,
SDL_GetKeyName (keycode),
-1);
gtk_tree_store_append (hotkey_store, &iter, NULL); // acquire child iterator
}
}
static gint hotKeyPressCB (GtkTreeView * tree, GdkEventKey * event,
gpointer cb_data)
{
int numListRows;
GList *selListRows, *tmpList;
GtkTreeModel *model = NULL;
GtkTreeSelection *treeSel = gtk_tree_view_get_selection (tree);
printf ("Hot Key Press: %i \n", event->keyval);
numListRows = gtk_tree_selection_count_selected_rows (treeSel);
if (numListRows == 0)
{
return FALSE;
}
//printf("Number of Rows Selected: %i\n", numListRows );
selListRows = gtk_tree_selection_get_selected_rows (treeSel, &model);
tmpList = selListRows;
while (tmpList)
{
int depth;
int *indexArray;
GtkTreePath *path = (GtkTreePath *) tmpList->data;
depth = gtk_tree_path_get_depth (path);
indexArray = gtk_tree_path_get_indices (path);
if (depth > 0)
{
int sdlkey = 0;
std::string hotKeyName = "SDL.Hotkeys.";
hotKeyName.append ( getHotkeyString(indexArray[0]) );
// Convert this keypress from GDK to SDL.
sdlkey = GDKToSDLKeyval (event->keyval);
printf ("HotKey Index: %i '%s' %i %i \n",
indexArray[0], hotKeyName.c_str (),
event->keyval, sdlkey);
g_config->setOption (hotKeyName, sdlkey);
setHotKeys (); // Update Hot Keys in Input Model
hotKeyWindowRefresh ();
}
tmpList = tmpList->next;
}
g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free);
return TRUE;
}
// creates and opens hotkey config window
void openHotkeyConfig (void)
{
GtkWidget *win = gtk_dialog_new_with_buttons ("Hotkey Configuration",
GTK_WINDOW (MainWindow),
(GtkDialogFlags)
(GTK_DIALOG_DESTROY_WITH_PARENT),
"_Close",
GTK_RESPONSE_OK,
NULL);
gtk_window_set_default_size (GTK_WINDOW (win), 400, 800);
GtkWidget *tree;
GtkWidget *vbox;
GtkWidget *scroll;
vbox = gtk_dialog_get_content_area (GTK_DIALOG (win));
hotkey_store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
hotKeyWindowRefresh ();
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (hotkey_store));
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
g_signal_connect (G_OBJECT (tree), "key-press-event",
G_CALLBACK (hotKeyPressCB), NULL);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Command", renderer,
"text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
column = gtk_tree_view_column_new_with_attributes ("Key", renderer,
"text", 1, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scroll), tree);
gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 5);
gtk_widget_show_all (win);
g_signal_connect (win, "delete-event", G_CALLBACK (closeDialog), NULL);
g_signal_connect (win, "response", G_CALLBACK (closeDialog), NULL);
}
//static void selInputDevice (GtkWidget * w, gpointer p)
//{
// //std::string s = "SDL.Input.";
// int padNo = 0, devIdx = -1;
// const char *devTxt;
// jsDev_t *js;
//
// if ( (padNoCombo == NULL) )
// {
// return;
// }
// padNo =
// atoi (gtk_combo_box_text_get_active_text
// (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1;
//
// devTxt = gtk_combo_box_text_get_active_text ( GTK_COMBO_BOX_TEXT(w) );
//
// if ( isdigit( devTxt[0] ) )
// {
// devIdx = atoi( devTxt );
// }
// printf ("setInputDevice: %s %i", devTxt, devIdx );
//
//
// //g_config->setOption (s,
// // gtk_combo_box_text_get_active_text
// // (GTK_COMBO_BOX_TEXT (typeCombo)));
// //g_config->save ();
//
// return;
//}
//
//static void updateGamepadConfig (GtkWidget * w, gpointer p)
//{
// int i;
// char strBuf[128];
//
// if ( (padNoCombo == NULL) )
// {
// return;
// }
// int padNo =
// atoi (gtk_combo_box_text_get_active_text
// (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1;
//
// for (i = 0; i < 10; i++)
// {
// GtkWidget *mappedKey = buttonMappings[i];
// if (GamePad[padNo].bmap[i].ButtType == BUTTC_KEYBOARD)
// {
// snprintf (strBuf, sizeof (strBuf), "<tt>%s</tt>",
// SDL_GetKeyName (GamePad[padNo].bmap[i].
// ButtonNum));
// }
// else
// sprintf (strBuf, "<tt>%s</tt>", ButtonName( &GamePad[padNo].bmap[i] ) );
//
// if ( mappedKey != NULL )
// {
// gtk_label_set_text (GTK_LABEL (mappedKey), strBuf);
// gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE);
// }
// }
//}
//
//static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p)
//{
// gtk_widget_destroy (w);
//
// padNoCombo = NULL;
//
// for (int i = 0; i < 10; i++)
// {
// buttonMappings[i] = NULL;
// }
// buttonConfigStatus = 0;
//}
//
//// creates and opens the gamepad config window (requires GTK 2.24)
//void openGamepadConfig (void)
//{
// int portNum = 0;
// GtkWidget *win;
// GtkWidget *vbox;
// GtkWidget *hboxPadNo;
// GtkWidget *padNoLabel;
// GtkWidget* devSelLabel, *devSelHbox;
// GtkWidget *fourScoreChk;
// GtkWidget *oppositeDirChk;
// GtkWidget *buttonFrame;
// GtkWidget *buttonTable;
// char stmp[256];
//
// win = gtk_dialog_new_with_buttons ("Controller Configuration",
// GTK_WINDOW (MainWindow),
// (GtkDialogFlags)
// (GTK_DIALOG_DESTROY_WITH_PARENT),
// "_Close", GTK_RESPONSE_OK, NULL);
// gtk_window_set_title (GTK_WINDOW (win), "Controller Configuration");
// gtk_window_set_icon_name (GTK_WINDOW (win), "input-gaming");
// gtk_widget_set_size_request (win, 350, 500);
//
// vbox = gtk_dialog_get_content_area (GTK_DIALOG (win));
// gtk_box_set_homogeneous (GTK_BOX (vbox), FALSE);
//
// hboxPadNo = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
// padNoLabel = gtk_label_new ("Port:");
// //configNoLabel = gtk_label_new("Config Number:");
// fourScoreChk = gtk_check_button_new_with_label ("Enable Four Score");
// oppositeDirChk =
// gtk_check_button_new_with_label ("Allow Up+Down / Left+Right");
//
// //typeCombo = gtk_combo_box_text_new ();
// //gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// // "gamepad");
// //gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// // "zapper");
// //gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// // "powerpad.0");
// //gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// // "powerpad.1");
// //gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (typeCombo),
// // "arkanoid");
//
// //gtk_combo_box_set_active (GTK_COMBO_BOX (typeCombo), 0);
//
//
// padNoCombo = gtk_combo_box_text_new ();
// gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "1");
// gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "2");
// gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "3");
// gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (padNoCombo), "4");
// gtk_combo_box_set_active (GTK_COMBO_BOX (padNoCombo), 0);
// g_signal_connect (padNoCombo, "changed",
// G_CALLBACK (updateGamepadConfig), NULL);
//
// devSelHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
// devSelLabel = gtk_label_new ("Device:");
// devSelCombo = gtk_combo_box_text_new ();
// gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (devSelCombo), "Keyboard");
//
// gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0);
//
// for (int i=0; i<MAX_JOYSTICKS; i++)
// {
// jsDev_t *js = getJoystickDevice( i );
//
// if ( js != NULL )
// {
// if ( js->isConnected() )
// {
// sprintf( stmp, "%i: %s", i, js->getName() );
// gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT (devSelCombo), stmp );
// }
// }
// }
// gtk_combo_box_set_active (GTK_COMBO_BOX (devSelCombo), 0);
//
// {
// GtkTreeModel *treeModel = gtk_combo_box_get_model( GTK_COMBO_BOX (devSelCombo) );
// GtkTreeIter iter;
// gboolean iterValid;
//
// iterValid = gtk_tree_model_get_iter_first( treeModel, &iter );
//
// while ( iterValid )
// {
// GValue value;
//
// memset( &value, 0, sizeof(value));
//
// gtk_tree_model_get_value (treeModel, &iter, 0, &value );
//
// if ( G_IS_VALUE(&value) )
// {
// if ( G_VALUE_TYPE(&value) == G_TYPE_STRING )
// {
// int devIdx = -1;
// const char *s = (const char *)g_value_peek_pointer( &value );
//
// if ( isdigit( s[0] ) )
// {
// devIdx = atoi(s);
// }
// if ( (devIdx >= 0) && (devIdx == GamePad[portNum].getDeviceIndex() ) )
// {
// gtk_combo_box_set_active_iter (GTK_COMBO_BOX (devSelCombo), &iter);
// }
// }
// }
// g_value_unset(&value);
//
// iterValid = gtk_tree_model_iter_next( treeModel, &iter );
// }
// }
// g_signal_connect (devSelCombo, "changed", G_CALLBACK (selInputDevice), NULL );
//
// //g_signal_connect (typeCombo, "changed", G_CALLBACK (setInputDevice),
// // gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT
// // (typeCombo)));
//
// setCheckbox (fourScoreChk, "SDL.FourScore");
// g_signal_connect (fourScoreChk, "clicked", G_CALLBACK (toggleOption),
// (gpointer) "SDL.FourScore");
// setCheckbox (oppositeDirChk, "SDL.Input.EnableOppositeDirectionals");
// g_signal_connect (oppositeDirChk, "clicked", G_CALLBACK (toggleOption),
// (gpointer) "SDL.Input.EnableOppositeDirectionals");
//
//
// gtk_box_pack_start (GTK_BOX (hboxPadNo), padNoLabel, TRUE, TRUE, 5);
// gtk_box_pack_start (GTK_BOX (hboxPadNo), padNoCombo, TRUE, TRUE, 5);
// gtk_box_pack_start (GTK_BOX (vbox), hboxPadNo, FALSE, TRUE, 5);
// //gtk_box_pack_start_defaults(GTK_BOX(vbox), typeCombo);
//
// gtk_box_pack_start (GTK_BOX (devSelHbox), devSelLabel, TRUE, TRUE, 5);
// gtk_box_pack_start (GTK_BOX (devSelHbox), devSelCombo, TRUE, TRUE, 5);
// gtk_box_pack_start (GTK_BOX (vbox), devSelHbox, FALSE, TRUE, 5);
//
// gtk_box_pack_start (GTK_BOX (vbox), fourScoreChk, FALSE, TRUE, 5);
// gtk_box_pack_start (GTK_BOX (vbox), oppositeDirChk, FALSE, TRUE, 5);
//
//
// // create gamepad buttons
// buttonFrame = gtk_frame_new ("<b><i>Buttons</i></b>");
// gtk_label_set_use_markup (GTK_LABEL
// (gtk_frame_get_label_widget
// (GTK_FRAME (buttonFrame))), TRUE);
// buttonTable = gtk_grid_new ();
// gtk_container_add (GTK_CONTAINER (buttonFrame), buttonTable);
//
// for (int i = 0; i < 3; i++)
// {
// gtk_grid_insert_column (GTK_GRID (buttonTable), i);
// }
// gtk_grid_set_column_spacing (GTK_GRID (buttonTable), 5);
// gtk_grid_set_column_homogeneous (GTK_GRID (buttonTable), TRUE);
// gtk_grid_set_row_spacing (GTK_GRID (buttonTable), 3);
//
// for (int i = 0; i < 10; i++)
// {
// GtkWidget *buttonName = gtk_label_new (GamePadNames[i]);
// GtkWidget *mappedKey = gtk_label_new (NULL);
// GtkWidget *changeButton = gtk_toggle_button_new ();
// char strBuf[128];
//
// gtk_grid_insert_row (GTK_GRID (buttonTable), i);
//
// sprintf (strBuf, "%s:", GamePadNames[i]);
// gtk_label_set_text (GTK_LABEL (buttonName), strBuf);
//
// gtk_button_set_label (GTK_BUTTON (changeButton), "Change");
// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (changeButton),
// FALSE);
//
// gtk_grid_attach (GTK_GRID (buttonTable), buttonName, 0, i, 1,
// 1);
// gtk_grid_attach (GTK_GRID (buttonTable), mappedKey, 1, i, 1, 1);
// gtk_grid_attach (GTK_GRID (buttonTable), changeButton, 2, i, 1,
// 1);
//
// g_signal_connect (changeButton, "clicked",
// G_CALLBACK (configGamepadButton),
// GINT_TO_POINTER (i));
// buttonMappings[i] = mappedKey;
// }
//
// // display the button mappings for the currently selected configuration
// updateGamepadConfig (NULL, NULL);
//
// gtk_box_pack_start (GTK_BOX (vbox), buttonFrame, TRUE, TRUE, 5);
//
// g_signal_connect (win, "delete-event", G_CALLBACK (closeGamepadConfig), NULL);
// g_signal_connect (win, "response", G_CALLBACK (closeGamepadConfig), NULL);
//
// gtk_widget_show_all (win);
//
// g_signal_connect (G_OBJECT (win), "key-press-event",
// G_CALLBACK (convertKeypress), NULL);
// g_signal_connect (G_OBJECT (win), "key-release-event",
// G_CALLBACK (convertKeypress), NULL);
//
// buttonConfigStatus = 1;
//
// return;
//}
int setBufSize (GtkWidget * w, gpointer p)
{
int x = gtk_range_get_value (GTK_RANGE (w));
g_config->setOption ("SDL.Sound.BufSize", x);
// reset sound subsystem for changes to take effect
KillSound ();
InitSound ();
return false;
}
void setRate (GtkWidget * w, gpointer p)
{
char *str = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (w));
g_config->setOption ("SDL.Sound.Rate", atoi (str));
// reset sound subsystem for changes to take effect
KillSound ();
InitSound ();
g_config->save ();
return;
}
void setQuality (GtkWidget * w, gpointer p)
{
char *str = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (w));
if (!strcmp (str, "Very High"))
g_config->setOption ("SDL.Sound.Quality", 2);
if (!strcmp (str, "High"))
g_config->setOption ("SDL.Sound.Quality", 1);
if (!strcmp (str, "Low"))
g_config->setOption ("SDL.Sound.Quality", 0);
// reset sound subsystem for changes to take effect
KillSound ();
InitSound ();
g_config->save ();
return;
}
void resizeGtkWindow (void)
{
//if(GameInfo == 0)
//{
double xscale, yscale;
g_config->getOption ("SDL.XScale", &xscale);
g_config->getOption ("SDL.YScale", &yscale);
gtk_widget_set_size_request (evbox, NES_WIDTH * xscale,
NES_HEIGHT * yscale);
GtkRequisition req;
gtk_widget_get_preferred_size (GTK_WIDGET (MainWindow), NULL, &req);
//printf("GTK Resizing: w:%i h:%i \n", req.width, req.height );
gtk_window_resize (GTK_WINDOW (MainWindow), req.width, req.height);
gtk_widget_set_size_request (evbox, NES_WIDTH, NES_HEIGHT);
//}
return;
}
static void setVideoDriver (GtkWidget * w, gpointer p)
{
int vdSel = gtk_combo_box_get_active (GTK_COMBO_BOX (w));
init_gui_video( (videoDriver_t)vdSel );
g_config->setOption ("SDL.VideoDriver", videoDriver);
g_config->save ();
}
static void setRegion (GtkWidget * w, gpointer p)
{
int region = gtk_combo_box_get_active (GTK_COMBO_BOX (w));
g_config->setOption ("SDL.PAL", region);
FCEUI_SetRegion (region);
g_config->save ();
}
static int setXscale (GtkWidget * w, gpointer p)
{
double v = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w));
g_config->setOption ("SDL.XScale", v);
g_config->save ();
resizeGtkWindow ();
return 0;
}
static int setYscale (GtkWidget * w, gpointer p)
{
double v = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w));
g_config->setOption ("SDL.YScale", v);
g_config->save ();
resizeGtkWindow ();
return 0;
}
static void setDoubleBuffering (GtkWidget * w, gpointer p)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
g_config->setOption ("SDL.DoubleBuffering", 1);
else
g_config->setOption ("SDL.DoubleBuffering", 0);
g_config->save ();
}
void openVideoConfig (void)
{
GtkWidget *win;
GtkWidget *vbox;
GtkWidget *lbl;
GtkWidget *hbox1;
GtkWidget *scalerLbl;
GtkWidget *DriverCombo;
GtkWidget *linearChk;
GtkWidget *dbChk;
GtkWidget *palHbox;
GtkWidget *palLbl;
GtkWidget *palCombo;
GtkWidget *ppuChk;
GtkWidget *spriteLimitChk;
GtkWidget *frameskipChk;
GtkWidget *clipSidesChk;
GtkWidget *xscaleSpin;
GtkWidget *yscaleSpin;
GtkWidget *xscaleLbl;
GtkWidget *yscaleLbl;
GtkWidget *xscaleHbox;
GtkWidget *yscaleHbox;
GtkWidget *showFpsChk;
win = gtk_dialog_new_with_buttons ("Video Preferences",
GTK_WINDOW (MainWindow),
(GtkDialogFlags)
(GTK_DIALOG_DESTROY_WITH_PARENT),
"_Apply", GTK_RESPONSE_APPLY,
"_Close", GTK_RESPONSE_CLOSE, NULL);
gtk_window_set_icon_name (GTK_WINDOW (win), "video-display");
//gtk_widget_set_size_request(win, 250, 250);
vbox = gtk_dialog_get_content_area (GTK_DIALOG (win));
lbl = gtk_label_new
("Video options will not take\neffect until the emulator is restarted.");
// scalar widgets
hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
scalerLbl = gtk_label_new ("Video Driver: ");
DriverCombo = gtk_combo_box_text_new ();
// -Video Modes Tag-
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (DriverCombo), "OpenGL (GLX)");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (DriverCombo), "SDL");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (DriverCombo), "Cairo");
// sync with cfg
int buf;
g_config->getOption ("SDL.VideoDriver", &buf);
gtk_combo_box_set_active (GTK_COMBO_BOX (DriverCombo), buf);
g_signal_connect (DriverCombo, "changed", G_CALLBACK (setVideoDriver), NULL);
gtk_box_pack_start (GTK_BOX (hbox1), scalerLbl, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox1), DriverCombo, FALSE, FALSE, 5);
// openGL linear filter check
linearChk =
gtk_check_button_new_with_label ("Enable OpenGL linear filter");
g_signal_connect (linearChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.OpenGLip");
setCheckbox (linearChk, "SDL.OpenGLip");
// DoubleBuffering check
dbChk = gtk_check_button_new_with_label ("Enable double buffering");
g_signal_connect (dbChk, "clicked", G_CALLBACK (setDoubleBuffering),
NULL);
setCheckbox (dbChk, "SDL.DoubleBuffering");
// Region (NTSC/PAL/Dendy)
palHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
palLbl = gtk_label_new ("Region: ");
palCombo = gtk_combo_box_text_new ();
// -Video Modes Tag-
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (palCombo), "NTSC");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (palCombo), "PAL");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (palCombo), "Dendy");
// sync with cfg
g_config->getOption ("SDL.PAL", &buf);
gtk_combo_box_set_active (GTK_COMBO_BOX (palCombo), buf);
g_signal_connect (palCombo, "changed", G_CALLBACK (setRegion), NULL);
gtk_box_pack_start (GTK_BOX (palHbox), palLbl, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (palHbox), palCombo, FALSE, FALSE, 5);
// New PPU check
ppuChk = gtk_check_button_new_with_label ("Enable new PPU");
g_signal_connect (ppuChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.NewPPU");
setCheckbox (ppuChk, "SDL.NewPPU");
// "disable 8 sprite limit" check
spriteLimitChk =
gtk_check_button_new_with_label ("Disable sprite limit");
g_signal_connect (spriteLimitChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.DisableSpriteLimit");
setCheckbox (spriteLimitChk, "SDL.DisableSpriteLimit");
// frameskip check
frameskipChk = gtk_check_button_new_with_label ("Enable frameskip");
g_signal_connect (frameskipChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.Frameskip");
setCheckbox (frameskipChk, "SDL.Frameskip");
// clip sides check
clipSidesChk = gtk_check_button_new_with_label ("Clip sides");
g_signal_connect (clipSidesChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.ClipSides");
setCheckbox (clipSidesChk, "SDL.ClipSides");
// xscale / yscale
xscaleHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
xscaleLbl = gtk_label_new ("X scaling factor");
xscaleSpin = gtk_spin_button_new_with_range (1.0, 40.0, .1);
yscaleHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
yscaleLbl = gtk_label_new ("Y scaling factor");
yscaleSpin = gtk_spin_button_new_with_range (1.0, 40.0, .1);
gtk_box_pack_start (GTK_BOX (xscaleHbox), xscaleLbl, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (xscaleHbox), xscaleSpin, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (yscaleHbox), yscaleLbl, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (yscaleHbox), yscaleSpin, FALSE, FALSE, 2);
g_signal_connect (xscaleSpin, "value-changed", G_CALLBACK (setXscale),
NULL);
g_signal_connect (yscaleSpin, "value-changed", G_CALLBACK (setYscale),
NULL);
double f;
// sync with config
g_config->getOption ("SDL.XScale", &f);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (xscaleSpin), f);
g_config->getOption ("SDL.YScale", &f);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (yscaleSpin), f);
// show FPS check
showFpsChk = gtk_check_button_new_with_label ("Show FPS");
g_signal_connect (showFpsChk, "clicked", G_CALLBACK (toggleOption),
(gpointer) "SDL.ShowFPS");
setCheckbox (showFpsChk, "SDL.ShowFPS");
gtk_box_pack_start (GTK_BOX (vbox), lbl, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox1, FALSE, FALSE, 5);
//#ifdef OPENGL
gtk_box_pack_start (GTK_BOX (vbox), linearChk, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), dbChk, FALSE, FALSE, 5);
//#endif
gtk_box_pack_start (GTK_BOX (vbox), palHbox, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), ppuChk, FALSE, FALSE, 5);
#ifdef FRAMESKIP
gtk_box_pack_start (GTK_BOX (vbox), frameskipChk, FALSE, FALSE, 5);
#endif
gtk_box_pack_start (GTK_BOX (vbox), spriteLimitChk, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), clipSidesChk, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), xscaleHbox, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), yscaleHbox, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), showFpsChk, FALSE, FALSE, 5);
g_signal_connect (win, "delete-event", G_CALLBACK (closeVideoWin),
NULL);
g_signal_connect (win, "response", G_CALLBACK (closeVideoWin), NULL);
gtk_widget_show_all (win);
return;
}
const char *mixerStrings[6] =
{ "Volume", "Triangle", "Square1", "Square2", "Noise", "PCM" };
int mixerChanged (GtkWidget * w, gpointer p)
{
int v = gtk_range_get_value (GTK_RANGE (w));
GtkWidget *parent = gtk_widget_get_parent (w);
char *lbl = (char *) gtk_frame_get_label (GTK_FRAME (parent));
if (strcmp (lbl, "Volume") == 0)
{
g_config->setOption ("SDL.Sound.Volume", v);
FCEUI_SetSoundVolume (v);
}
if (strcmp (lbl, "Triangle") == 0)
{
g_config->setOption ("SDL.Sound.TriangleVolume", v);
FCEUI_SetTriangleVolume (v);
}
if (strcmp (lbl, "Square1") == 0)
{
g_config->setOption ("SDL.Sound.Square1Volume", v);
FCEUI_SetSquare1Volume (v);
}
if (strcmp (lbl, "Square2") == 0)
{
g_config->setOption ("SDL.Sound.Square2Volume", v);
FCEUI_SetSquare2Volume (v);
}
if (strcmp (lbl, "Noise") == 0)
{
g_config->setOption ("SDL.Sound.NoiseVolume", v);
FCEUI_SetNoiseVolume (v);
}
if (strcmp (lbl, "PCM") == 0)
{
g_config->setOption ("SDL.Sound.PCMVolume", v);
FCEUI_SetPCMVolume (v);
}
return 0;
}
void openSoundConfig (void)
{
GtkWidget *win;
GtkWidget *main_hbox;
GtkWidget *vbox;
GtkWidget *soundChk;
GtkWidget *lowpassChk;
GtkWidget *hbox1;
GtkWidget *qualityCombo;
GtkWidget *qualityLbl;
GtkWidget *hbox2;
GtkWidget *rateCombo;
GtkWidget *rateLbl;
GtkWidget *bufferLbl;
GtkWidget *bufferHscale;
GtkWidget *swapDutyChk;
GtkWidget *mixerFrame;
GtkWidget *mixerHbox;
GtkWidget *mixers[6];
GtkWidget *mixerFrames[6];
win = gtk_dialog_new_with_buttons ("Sound Preferences",
GTK_WINDOW (MainWindow),
(GtkDialogFlags)
(GTK_DIALOG_DESTROY_WITH_PARENT),
"_Close", GTK_RESPONSE_OK, NULL);
gtk_window_set_icon_name (GTK_WINDOW (win), "audio-x-generic");
main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 15);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
// sound enable check
soundChk = gtk_check_button_new_with_label ("Enable sound");
g_signal_connect (soundChk, "clicked", G_CALLBACK (toggleSound), NULL);
setCheckbox (soundChk, "SDL.Sound");
// low pass filter check
lowpassChk = gtk_check_button_new_with_label ("Enable low pass filter");
g_signal_connect (lowpassChk, "clicked", G_CALLBACK (toggleLowPass),
NULL);
setCheckbox (lowpassChk, "SDL.Sound.LowPass");
// sound quality combo box
hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
qualityCombo = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (qualityCombo),
"Low");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (qualityCombo),
"High");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (qualityCombo),
"Very High");
// sync widget with cfg
int buf;
g_config->getOption ("SDL.Sound.Quality", &buf);
gtk_combo_box_set_active (GTK_COMBO_BOX (qualityCombo), buf);
g_signal_connect (qualityCombo, "changed", G_CALLBACK (setQuality),
NULL);
qualityLbl = gtk_label_new ("Quality: ");
gtk_box_pack_start (GTK_BOX (hbox1), qualityLbl, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox1), qualityCombo, FALSE, FALSE, 5);
// sound rate widgets
hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
rateCombo = gtk_combo_box_text_new ();
const int rates[5] = { 11025, 22050, 44100, 48000, 96000 };
char choices[8];
for (int i = 0; i < 5; i++)
{
sprintf (choices, "%d", rates[i]);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (rateCombo),
choices);
}
// sync widget with cfg
g_config->getOption ("SDL.Sound.Rate", &buf);
for (int i = 0; i < 5; i++)
if (buf == rates[i])
gtk_combo_box_set_active (GTK_COMBO_BOX (rateCombo), i);
g_signal_connect (rateCombo, "changed", G_CALLBACK (setRate), NULL);
// sound rate widgets
rateLbl = gtk_label_new ("Rate (Hz): ");
gtk_box_pack_start (GTK_BOX (hbox2), rateLbl, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (hbox2), rateCombo, FALSE, FALSE, 5);
bufferHscale =
gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 15, 200,
2);
bufferLbl = gtk_label_new ("Buffer size (in ms)");
// sync widget with cfg
g_config->getOption ("SDL.Sound.BufSize", &buf);
gtk_range_set_value (GTK_RANGE (bufferHscale), buf);
g_signal_connect (bufferHscale, "button-release-event",
G_CALLBACK (setBufSize), NULL);
// Swap duty cycles
swapDutyChk = gtk_check_button_new_with_label ("Swap Duty Cycles");
g_signal_connect (swapDutyChk, "clicked", G_CALLBACK (toggleSwapDuty),
NULL);
setCheckbox (swapDutyChk, "SDL.SwapDuty");
// mixer
mixerFrame = gtk_frame_new ("Mixer:");
mixerHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
for (long int i = 0; i < 6; i++)
{
mixers[i] =
gtk_scale_new_with_range (GTK_ORIENTATION_VERTICAL, 0,
256, 1);
gtk_range_set_inverted (GTK_RANGE (mixers[i]), TRUE);
mixerFrames[i] = gtk_frame_new (mixerStrings[i]);
gtk_container_add (GTK_CONTAINER (mixerFrames[i]), mixers[i]);
gtk_box_pack_start (GTK_BOX (mixerHbox), mixerFrames[i], FALSE,
TRUE, 5);
g_signal_connect (mixers[i], "button-release-event",
G_CALLBACK (mixerChanged), (gpointer) i);
}
// sync with cfg
int v;
g_config->getOption ("SDL.Sound.Volume", &v);
gtk_range_set_value (GTK_RANGE (mixers[0]), v);
g_config->getOption ("SDL.Sound.TriangleVolume", &v);
gtk_range_set_value (GTK_RANGE (mixers[1]), v);
g_config->getOption ("SDL.Sound.Square1Volume", &v);
gtk_range_set_value (GTK_RANGE (mixers[2]), v);
g_config->getOption ("SDL.Sound.Square2Volume", &v);
gtk_range_set_value (GTK_RANGE (mixers[3]), v);
g_config->getOption ("SDL.Sound.NoiseVolume", &v);
gtk_range_set_value (GTK_RANGE (mixers[4]), v);
g_config->getOption ("SDL.Sound.PCMVolume", &v);
gtk_range_set_value (GTK_RANGE (mixers[5]), v);
// packing some boxes
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (vbox), soundChk, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), lowpassChk, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox1, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), bufferLbl, FALSE, FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), bufferHscale, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (vbox), swapDutyChk, FALSE, TRUE, 5);
gtk_box_pack_start (GTK_BOX (main_hbox), mixerFrame, TRUE, TRUE, 5);
gtk_container_add (GTK_CONTAINER (mixerFrame), mixerHbox);
gtk_box_pack_start (GTK_BOX
(gtk_dialog_get_content_area (GTK_DIALOG (win))),
main_hbox, TRUE, TRUE, 0);
g_signal_connect (win, "delete-event", G_CALLBACK (closeDialog), NULL);
g_signal_connect (win, "response", G_CALLBACK (closeDialog), NULL);
gtk_widget_show_all (win);
return;
}
static void mainMenuQuitCB(
GtkMenuItem *menuitem,
gpointer user_data)
{
printf("Main Menu Quit\n");
// Set gui run flag to false to allow main gui loop
// to exit normally.
gtk_gui_run = false;
// // manually flush GTK event queue
// while (gtk_events_pending ())
// gtk_main_iteration_do (FALSE);
//
// // this is not neccesary to be explicitly called
// // it raises a GTK-Critical when its called
// //gtk_main_quit();
// FCEUI_CloseGame ();
// FCEUI_Kill ();
// // LoadGame() checks for an IP and if it finds one begins a network session
// // clear the NetworkIP field so this doesn't happen unintentionally
// g_config->setOption ("SDL.NetworkIP", "");
// g_config->save ();
// SDL_Quit ();
// exit (0);
}
static gboolean deleteMainWindowCB(
GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
printf("Delete Main Window Requested...\n");
gtk_gui_run = false;
return(TRUE);
}
static gboolean destroyMainWindowCB(
GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
printf("Destroy Main Window\n");
gtk_gui_run = false;
return(FALSE);
}
const char *Authors[] = {
"Linux/SDL Developers:",
" mjbudd77",
" Lukas Sabota //punkrockguy318", " Soules", " Bryan Cain", " radsaq",
" Shinydoofy",
"FceuX 2.0 Developers:",
" SP", " zeromus", " adelikat", " caH4e3", " qfox",
" Luke Gustafson", " _mz", " UncombedCoconut", " DwEdit", " AnS",
"rainwarrior", "feos",
"Pre 2.0 Guys:",
" Bero", " Xodnizel", " Aaron Oneal", " Joe Nahmias",
" Paul Kuliniewicz", " Quietust", " Ben Parnell",
" Parasyte &amp; bbitmaster",
" blip &amp; nitsuja",
"Included components:",
" Mitsutaka Okazaki - YM2413 emulator",
" Andrea Mazzoleni - Scale2x/Scale3x scalers",
" Gilles Vollant - unzip.c PKZIP fileio",
NULL
};
void openAbout (void)
{
char versionString[512];
GdkPixbuf *logo = gdk_pixbuf_new_from_xpm_data (icon_xpm);
sprintf( versionString, "%s\ngit URL: %s\ngit Rev: %s",
FCEU_VERSION_STRING, fceu_get_git_url(), fceu_get_git_rev() );
gtk_show_about_dialog (GTK_WINDOW (MainWindow),
"program-name", "fceuX",
"version", versionString,
"copyright", "© 2016 FceuX development team",
"license", "GPL-2; See COPYING",
//"license-type", GTK_LICENSE_GPL_2_0,
"website", "http://fceux.com",
"authors", Authors, "logo", logo, NULL);
}
void toggleSound (GtkWidget * check, gpointer data)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)))
{
int last_soundopt;
g_config->getOption ("SDL.Sound", &last_soundopt);
g_config->setOption ("SDL.Sound", 1);
if (GameInfo && !last_soundopt)
InitSound ();
}
else
{
g_config->setOption ("SDL.Sound", 0);
KillSound ();
}
}
void emuReset ()
{
if (isloaded)
ResetNES ();
}
void hardReset ()
{
if (isloaded)
{
closeGame ();
const char *lastFile;
g_config->getOption ("SDL.LastOpenFile", &lastFile);
LoadGame (lastFile);
resizeGtkWindow ();
}
}
void enableFullscreen (void)
{
if (isloaded)
ToggleFS ();
}
void toggleMenuToggling (GtkCheckMenuItem * item, gpointer user_data)
{
bool toggleMenu = gtk_check_menu_item_get_active (item);
//printf("ToggleMenu: %i\n", (int)toggleMenu);
g_config->setOption ("SDL.ToggleMenu", (int) toggleMenu);
menuTogglingEnabled = toggleMenu;
}
void toggleAutoResume (GtkCheckMenuItem * item, gpointer user_data)
{
bool autoResume = gtk_check_menu_item_get_active (item);
//printf("AutoResume: %i\n", (int)autoResume);
g_config->setOption ("SDL.AutoResume", (int) autoResume);
AutoResumePlay = autoResume;
}
void recordMovie ()
{
if (isloaded)
{
std::string name = FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0);
FCEUI_printf ("Recording movie to %s\n", name.c_str ());
FCEUI_SaveMovie (name.c_str (), MOVIE_FLAG_NONE, L"");
}
return;
}
void recordMovieAs ()
{
if (!isloaded)
{
return;
}
GtkWidget *fileChooser;
GtkFileFilter *filterFm2;
GtkFileFilter *filterAll;
filterFm2 = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterFm2, "*.fm2");
gtk_file_filter_set_name (filterFm2, "FM2 Movies");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Save FM2 movie for recording",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fileChooser),
".fm2");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterFm2);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fileChooser),
getcwd (NULL, 0));
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
std::string fname;
fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
if (!fname.size ())
return; // no filename selected, quit the whole thing
std::string s = GetUserText ("Author name");
std::wstring author (s.begin (), s.end ());
FCEUI_SaveMovie (fname.c_str (), MOVIE_FLAG_NONE, author);
}
gtk_widget_destroy (fileChooser);
}
void loadMovie (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterMovies;
GtkFileFilter *filterFm2;
GtkFileFilter *filterAll;
filterMovies = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterMovies, "*.fm2");
gtk_file_filter_add_pattern (filterMovies, "*.FM2f");
gtk_file_filter_add_pattern (filterMovies, "*.fm3");
gtk_file_filter_set_name (filterMovies,
"FM2 Movies, TAS Editor Projects");
filterFm2 = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterFm2, "*.fm2");
gtk_file_filter_add_pattern (filterFm2, "*.FM2f");
gtk_file_filter_set_name (filterFm2, "FM2 Movies");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Open FM2 Movie",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser),
filterMovies);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterFm2);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fileChooser),
getcwd (NULL, 0));
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *fname;
fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
static int pauseframe;
g_config->getOption ("SDL.PauseFrame", &pauseframe);
g_config->setOption ("SDL.PauseFrame", 0);
FCEUI_printf ("Playing back movie located at %s\n", fname);
if (FCEUI_LoadMovie
(fname, false, pauseframe ? pauseframe : false) == FALSE)
{
GtkWidget *d;
d = gtk_message_dialog_new (GTK_WINDOW (MainWindow),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"Could not open the movie file.");
gtk_dialog_run (GTK_DIALOG (d));
gtk_widget_destroy (d);
}
}
gtk_widget_destroy (fileChooser);
}
#ifdef _S9XLUA_H
void loadLua (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterLua;
GtkFileFilter *filterAll;
filterLua = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterLua, "*.lua");
gtk_file_filter_add_pattern (filterLua, "*.LUA");
gtk_file_filter_set_name (filterLua, "Lua scripts");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Open LUA Script",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterLua);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
const char *last_file;
g_config->getOption ("SDL.LastLoadLua", &last_file);
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (fileChooser),
last_file);
if (strcmp (last_file, "") == 0)
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER
(fileChooser),
"/usr/share/fceux/luaScripts");
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
g_config->setOption ("SDL.LastLoadLua", filename);
gtk_widget_destroy (fileChooser);
if (FCEU_LoadLuaCode (filename) == 0)
{
// This is necessary because lua scripts do not use FCEUD_PrintError to print errors.
GtkWidget *d;
d = gtk_message_dialog_new (GTK_WINDOW (MainWindow),
GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"Could not open the selected lua script.");
gtk_dialog_run (GTK_DIALOG (d));
gtk_widget_destroy (d);
}
g_free (filename);
}
else
gtk_widget_destroy (fileChooser);
}
#endif
void loadFdsBios (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterDiskSys;
GtkFileFilter *filterRom;
GtkFileFilter *filterAll;
filterDiskSys = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterDiskSys, "disksys.rom");
gtk_file_filter_set_name (filterDiskSys, "disksys.rom");
filterRom = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterRom, "*.rom");
gtk_file_filter_set_name (filterRom, "*.rom");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Load FDS BIOS (disksys.rom)",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser),
filterDiskSys);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterRom);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fileChooser),
getcwd (NULL, 0));
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
// copy BIOS file to proper place (~/.fceux/disksys.rom)
std::ifstream fdsBios (filename, std::fstream::binary);
std::string output_filename =
FCEU_MakeFName (FCEUMKF_FDSROM, 0, "");
std::ofstream outFile (output_filename.c_str (),
std::fstream::trunc | std::fstream::
binary);
outFile << fdsBios.rdbuf ();
if (outFile.fail ())
{
FCEUD_PrintError ("Error copying the FDS BIOS file.");
}
else
{
GtkWidget *d;
d = gtk_message_dialog_new (GTK_WINDOW (MainWindow),
GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Famicom Disk System BIOS loaded. If you are you having issues, make sure your BIOS file is 8KB in size.");
gtk_dialog_run (GTK_DIALOG (d));
gtk_widget_destroy (d);
}
}
gtk_widget_destroy (fileChooser);
}
// TODO: is there somewhere else we can move this? works for now though
void enableGameGenie (int enabled)
{
g_config->setOption ("SDL.GameGenie", enabled);
g_config->save ();
FCEUI_SetGameGenie (enabled);
}
void toggleGameGenie (GtkCheckMenuItem * item, gpointer userData)
{
enableGameGenie (gtk_check_menu_item_get_active (item));
}
void togglePause (GtkMenuItem * item, gpointer userData)
{
SDL_Event sdlev;
int paused;
if (isloaded)
{
paused = FCEUI_EmulationPaused ();
sdlev.type = SDL_FCEU_HOTKEY_EVENT;
sdlev.user.code = HK_PAUSE;
if (SDL_PushEvent (&sdlev) < 0)
{
FCEU_printf ("Failed to push SDL event to %s game.\n",
paused ? "resume" : "pause");
return;
}
gtk_menu_item_set_label (item, paused ? "Pause" : "Resume");
//gtk_action_set_stock_id(action, paused ? GTK_STOCK_MEDIA_PAUSE : GTK_STOCK_MEDIA_PLAY);
}
}
void loadGameGenie ()
{
GtkWidget *fileChooser;
GtkFileFilter *filterGG;
GtkFileFilter *filterRom;
GtkFileFilter *filterNes;
GtkFileFilter *filterAll;
filterGG = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterGG, "gg.rom");
gtk_file_filter_set_name (filterGG, "gg.rom");
filterRom = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterRom, "*.rom");
gtk_file_filter_set_name (filterRom, "*.rom");
filterNes = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterNes, "*.nes");
gtk_file_filter_set_name (filterNes, "*.nes");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Load Game Genie ROM",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterGG);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterRom);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterNes);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fileChooser),
getcwd (NULL, 0));
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
// copy file to proper place (~/.fceux/gg.rom)
std::ifstream f1 (filename, std::fstream::binary);
std::string fn_out = FCEU_MakeFName (FCEUMKF_GGROM, 0, "");
std::ofstream f2 (fn_out.c_str (),
std::fstream::trunc | std::fstream::binary);
gtk_widget_destroy (fileChooser);
GtkWidget *d;
enableGameGenie (TRUE);
d = gtk_message_dialog_new (GTK_WINDOW (MainWindow),
GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Game Genie ROM copied to: '%s'.",
fn_out.c_str ());
gtk_dialog_run (GTK_DIALOG (d));
gtk_widget_destroy (d);
f2 << f1.rdbuf ();
g_free (filename);
}
else
gtk_widget_destroy (fileChooser);
}
void loadNSF (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterNSF;
GtkFileFilter *filterZip;
GtkFileFilter *filterAll;
filterNSF = gtk_file_filter_new ();
filterZip = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterNSF, "*.nsf");
gtk_file_filter_add_pattern (filterNSF, "*.NSF");
gtk_file_filter_add_pattern (filterZip, "*.zip");
gtk_file_filter_add_pattern (filterZip, "*.ZIP");
gtk_file_filter_set_name (filterNSF, "NSF sound files");
gtk_file_filter_set_name (filterZip, "Zip archives");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Open NSF File",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
const char *last_dir;
g_config->getOption ("SDL.LastOpenNSF", &last_dir);
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (fileChooser),
last_dir);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterNSF);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterZip);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
gtk_widget_destroy (fileChooser);
LoadGame (filename);
// no longer required with GTK FCEUD_PrintError implementation
/*if(LoadGame(filename) == 0)
{
GtkWidget* d;
d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"Could not open the selected NSF file.");
gtk_dialog_run(GTK_DIALOG(d));
gtk_widget_destroy(d);
} */
g_config->setOption ("SDL.LastOpenNSF", filename);
g_free (filename);
}
else
gtk_widget_destroy (fileChooser);
}
void closeGame (void)
{
//GdkColor bg = {0, 0, 0, 0};
//gtk_widget_modify_bg(evbox, GTK_STATE_NORMAL, &bg);
CloseGame ();
}
void loadGame (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterFCEU;
GtkFileFilter *filterNes;
GtkFileFilter *filterFds;
GtkFileFilter *filterNSF;
GtkFileFilter *filterZip;
GtkFileFilter *filterAll;
filterFCEU = gtk_file_filter_new ();
filterNes = gtk_file_filter_new ();
filterFds = gtk_file_filter_new ();
filterNSF = gtk_file_filter_new ();
filterZip = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterFCEU, "*.nes");
gtk_file_filter_add_pattern (filterFCEU, "*.NES");
gtk_file_filter_add_pattern (filterFCEU, "*.fds");
gtk_file_filter_add_pattern (filterFCEU, "*.FDS");
gtk_file_filter_add_pattern (filterFCEU, "*.zip");
gtk_file_filter_add_pattern (filterFCEU, "*.ZIP");
gtk_file_filter_add_pattern (filterFCEU, "*.Nes");
gtk_file_filter_add_pattern (filterFCEU, "*.Fds");
gtk_file_filter_add_pattern (filterFCEU, "*.Zip");
gtk_file_filter_add_pattern (filterFCEU, "*.nsf");
gtk_file_filter_add_pattern (filterFCEU, "*.NSF");
gtk_file_filter_add_pattern (filterNes, "*.nes");
gtk_file_filter_add_pattern (filterNes, "*.NES");
gtk_file_filter_add_pattern (filterFds, "*.fds");
gtk_file_filter_add_pattern (filterFds, "*.FDS");
gtk_file_filter_add_pattern (filterNSF, "*.nsf");
gtk_file_filter_add_pattern (filterNSF, "*.NSF");
gtk_file_filter_add_pattern (filterZip, "*.zip");
gtk_file_filter_add_pattern (filterZip, "*.zip");
gtk_file_filter_set_name (filterFCEU, "*.nes;*.fds;*.nsf;*.zip");
gtk_file_filter_set_name (filterNes, "NES ROM files");
gtk_file_filter_set_name (filterFds, "FDS ROM files");
gtk_file_filter_set_name (filterNSF, "NSF sound files");
gtk_file_filter_set_name (filterZip, "Zip archives");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Open ROM",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
const char *last_dir;
g_config->getOption ("SDL.LastOpenFile", &last_dir);
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (fileChooser),
last_dir);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser),
filterFCEU);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterNes);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterFds);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterNSF);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterZip);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
gtk_widget_destroy (fileChooser);
g_config->setOption ("SDL.LastOpenFile", filename);
closeGame ();
LoadGame (filename);
// Error dialog no longer required with GTK implementation of FCEUD_PrintError()
/*if(LoadGame(filename) == 0)
{
GtkWidget* d;
d = gtk_message_dialog_new(GTK_WINDOW(MainWindow), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"Could not open the selected ROM file.");
gtk_dialog_run(GTK_DIALOG(d));
gtk_widget_destroy(d);
} */
resizeGtkWindow ();
g_free (filename);
}
else
gtk_widget_destroy (fileChooser);
}
void saveStateAs (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterSav;
GtkFileFilter *filterAll;
filterSav = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterSav, "*.sav");
gtk_file_filter_add_pattern (filterSav, "*.SAV");
gtk_file_filter_set_name (filterSav, "SAV files");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
const char *last_dir;
g_config->getOption ("SDL.LastSaveStateAs", &last_dir);
fileChooser =
gtk_file_chooser_dialog_new ("Save State As",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Save", GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fileChooser),
last_dir);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fileChooser),
".sav");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterSav);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
FCEUI_SaveState (filename);
g_config->setOption ("SDL.LastSaveStateAs", filename);
g_free (filename);
}
gtk_widget_destroy (fileChooser);
}
void loadStateFrom (void)
{
GtkWidget *fileChooser;
GtkFileFilter *filterFcs;
GtkFileFilter *filterSav;
GtkFileFilter *filterAll;
filterSav = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterSav, "*.sav");
gtk_file_filter_add_pattern (filterSav, "*.SAV");
gtk_file_filter_set_name (filterSav, "SAV files");
filterFcs = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterFcs, "*.fc?");
gtk_file_filter_add_pattern (filterFcs, "*.FC?");
gtk_file_filter_set_name (filterFcs, "FCS files");
filterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (filterAll, "*");
gtk_file_filter_set_name (filterAll, "All Files");
fileChooser =
gtk_file_chooser_dialog_new ("Load State From",
GTK_WINDOW (MainWindow),
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
const char *last_dir;
g_config->getOption ("SDL.LastLoadStateFrom", &last_dir);
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (fileChooser),
last_dir);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterFcs);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterSav);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll);
if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT)
{
char *filename;
filename =
gtk_file_chooser_get_filename (GTK_FILE_CHOOSER
(fileChooser));
FCEUI_LoadState (filename);
g_config->setOption ("SDL.LastLoadStateFrom", filename);
g_free (filename);
}
gtk_widget_destroy (fileChooser);
}
void quickLoad (void)
{
FCEUI_LoadState (NULL);
}
void quickSave (void)
{
FCEUI_SaveState (NULL);
}
void setStateMenuItem( int i )
{
if ( (i >= 0) && (i < 10) )
{
gtk_menu_item_activate( GTK_MENU_ITEM(stateSlot[i]) );
}
}
static void changeState (GtkRadioMenuItem * radiomenuitem, gpointer user_data)
{
//printf("GTK Changing State: %li\n", (long)user_data);
FCEUI_SelectState ((long) user_data, 1);
}
// SDL 1.2/2.0 compatibility macros
#define SDLK_SCROLLOCK SDLK_SCROLLLOCK
#define SDLK_PRINT SDLK_PRINTSCREEN
#define SDLK_BREAK 0
#define SDLK_COMPOSE 0
#define SDLK_NUMLOCK SDLK_NUMLOCKCLEAR
#define SDLK_LMETA 0
#define SDLK_RMETA 0
// Adapted from Gens/GS. Converts a GDK key value into an SDL key value.
unsigned int GDKToSDLKeyval (int gdk_key)
{
if (!(gdk_key & 0xFF00))
{
// ASCII symbol.
// SDL and GDK use the same values for these keys.
// Make sure the key value is lowercase.
gdk_key = tolower (gdk_key);
// Return the key value.
return gdk_key;
}
if (gdk_key & 0xFFFF0000)
{
// Extended X11 key. Not supported by SDL.
#ifdef GDK_WINDOWING_X11
fprintf (stderr, "Unhandled extended X11 key: 0x%08X (%s)",
gdk_key, XKeysymToString (gdk_key));
#else
fprintf (stderr, "Unhandled extended key: 0x%08X\n", gdk_key);
#endif
return 0;
}
// Non-ASCII symbol.
static const int gdk_to_sdl_table[0x100] = {
// 0x00 - 0x0F
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
SDLK_BACKSPACE, SDLK_TAB, SDLK_RETURN, SDLK_CLEAR,
0x0000, SDLK_RETURN, 0x0000, 0x0000,
// 0x10 - 0x1F
0x0000, 0x0000, 0x0000, SDLK_PAUSE,
SDLK_SCROLLOCK, SDLK_SYSREQ, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, SDLK_ESCAPE,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x20 - 0x2F
SDLK_COMPOSE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x30 - 0x3F [Japanese keys]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x40 - 0x4F [unused]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x50 - 0x5F
SDLK_HOME, SDLK_LEFT, SDLK_UP, SDLK_RIGHT,
SDLK_DOWN, SDLK_PAGEUP, SDLK_PAGEDOWN, SDLK_END,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x60 - 0x6F
0x0000, SDLK_PRINT, 0x0000, SDLK_INSERT,
SDLK_UNDO, 0x0000, 0x0000, SDLK_MENU,
0x0000, SDLK_HELP, SDLK_BREAK, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0x70 - 0x7F [mostly unused, except for Alt Gr and Num Lock]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, SDLK_MODE, SDLK_NUMLOCK,
// 0x80 - 0x8F [mostly unused, except for some numeric keypad keys]
SDLK_KP_5, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, SDLK_KP_ENTER, 0x0000, 0x0000,
// 0x90 - 0x9F
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, SDLK_KP_7, SDLK_KP_4, SDLK_KP_8,
SDLK_KP_6, SDLK_KP_2, SDLK_KP_9, SDLK_KP_3,
SDLK_KP_1, SDLK_KP_5, SDLK_KP_0, SDLK_KP_PERIOD,
// 0xA0 - 0xAF
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, SDLK_KP_MULTIPLY, SDLK_KP_PLUS,
0x0000, SDLK_KP_MINUS, SDLK_KP_PERIOD, SDLK_KP_DIVIDE,
// 0xB0 - 0xBF
SDLK_KP_0, SDLK_KP_1, SDLK_KP_2, SDLK_KP_3,
SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_7,
SDLK_KP_8, SDLK_KP_9, 0x0000, 0x0000,
0x0000, SDLK_KP_EQUALS, SDLK_F1, SDLK_F2,
// 0xC0 - 0xCF
SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6,
SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10,
SDLK_F11, SDLK_F12, SDLK_F13, SDLK_F14,
SDLK_F15, 0x0000, 0x0000, 0x0000,
// 0xD0 - 0xDF [L* and R* function keys]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
// 0xE0 - 0xEF
0x0000, SDLK_LSHIFT, SDLK_RSHIFT, SDLK_LCTRL,
SDLK_RCTRL, SDLK_CAPSLOCK, 0x0000, SDLK_LMETA,
SDLK_RMETA, SDLK_LALT, SDLK_RALT, SDLK_LGUI,
SDLK_RGUI, 0x0000, 0x0000, 0x0000,
// 0xF0 - 0xFF [mostly unused, except for Delete]
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, SDLK_DELETE,
};
unsigned int sdl_key = gdk_to_sdl_table[gdk_key & 0xFF];
if (sdl_key == 0)
{
// Unhandled GDK key.
fprintf (stderr, "Unhandled GDK key: 0x%04X (%s)", gdk_key,
gdk_keyval_name (gdk_key));
return 0;
}
// ignore pause and screenshot hotkeys since they is handled by GTK+ as accelerators
if ( (sdl_key == Hotkeys[HK_PAUSE]) || (sdl_key == Hotkeys[HK_SCREENSHOT]) ||
(sdl_key == Hotkeys[HK_SAVE_STATE]) || (sdl_key == Hotkeys[HK_LOAD_STATE]) )
{
return 0;
}
return sdl_key;
}
// Function adapted from Gens/GS (source/gens/input/input_sdl.c)
gboolean convertKeypress (GtkWidget * grab, GdkEventKey * event,
gpointer user_data)
{
SDL_Event sdlev;
SDL_Keycode sdlkey;
switch (event->type)
{
case GDK_KEY_PRESS:
sdlev.type = SDL_KEYDOWN;
sdlev.key.state = SDL_PRESSED;
break;
case GDK_KEY_RELEASE:
sdlev.type = SDL_KEYUP;
sdlev.key.state = SDL_RELEASED;
break;
default:
fprintf (stderr, "Unhandled GDK event type: %d",
event->type);
return FALSE;
}
// Convert this keypress from GDK to SDL.
sdlkey = GDKToSDLKeyval (event->keyval);
// Create an SDL event from the keypress.
sdlev.key.keysym.scancode = SDL_GetScancodeFromKey(sdlkey);
sdlev.key.keysym.sym = sdlkey;
sdlev.key.keysym.mod = 0;
if ( event->state & GDK_SHIFT_MASK )
{
sdlev.key.keysym.mod |= KMOD_SHIFT;
}
if ( event->state & GDK_CONTROL_MASK )
{
sdlev.key.keysym.mod |= KMOD_CTRL;
}
if ( event->state & GDK_MOD1_MASK )
{
sdlev.key.keysym.mod |= KMOD_ALT;
}
sdlev.key.repeat = 0;
if ( (event->state & GDK_MOD1_MASK) ||
getKeyState( SDL_SCANCODE_LALT ) || getKeyState( SDL_SCANCODE_RALT ) )
{
// Don't pass ALT + Enter to game, as this toggles fullscreen in GTK
if ( sdlkey == SDLK_RETURN )
{
return FALSE;
}
}
if (sdlkey != 0)
{
SDL_PushEvent (&sdlev);
}
// Allow GTK+ to process this key.
return FALSE;
}
static GtkWidget *CreateMenubar (GtkWidget * window)
{
GtkWidget *menubar, *menu, *submenu, *item;
GSList *radioGroup;
GtkAccelGroup *accel_group;
// Create Menu Bar
menubar = gtk_menu_bar_new ();
// Create a GtkAccelGroup and add it to the window.
accel_group = gtk_accel_group_new ();
gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
//---------------------------------------
// Create File Menu
item = gtk_menu_item_new_with_label ("File");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
// Load File Menu Items
//-File --> Open ROM ---------------------
item = gtk_menu_item_new_with_label ("Open ROM");
g_signal_connect (item, "activate", G_CALLBACK (loadGame), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_o, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Close ROM ------------------
item = gtk_menu_item_new_with_label ("Close ROM");
g_signal_connect (item, "activate", G_CALLBACK (closeGame), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_c, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Play NSF ------------------
item = gtk_menu_item_new_with_label ("Play NSF");
g_signal_connect (item, "activate", G_CALLBACK (loadNSF), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_n, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Load State From ------------------
item = gtk_menu_item_new_with_label ("Load State From");
g_signal_connect (item, "activate", G_CALLBACK (loadStateFrom), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Save State As ------------------
item = gtk_menu_item_new_with_label ("Save State As");
g_signal_connect (item, "activate", G_CALLBACK (saveStateAs), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Quick Load ------------------
item = gtk_menu_item_new_with_label ("Quick Load");
g_signal_connect (item, "activate", G_CALLBACK (quickLoad), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F7, (GdkModifierType) 0,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Quick Save ------------------
item = gtk_menu_item_new_with_label ("Quick Save");
g_signal_connect (item, "activate", G_CALLBACK (quickSave), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F5, (GdkModifierType) 0,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Change State ------------------
item = gtk_menu_item_new_with_label ("Change State");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
submenu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
//-File --> Change State --> State 0:9 ------------------
radioGroup = NULL;
for (long int i = 0; i < 10; i++)
{
char stmp[32];
sprintf (stmp, "%li", i);
item = gtk_radio_menu_item_new_with_label (radioGroup, stmp);
stateSlot[i] = GTK_RADIO_MENU_ITEM(item);
radioGroup =
gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM
(item));
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
g_signal_connect (item, "activate", G_CALLBACK (changeState),
(gpointer) i);
}
#ifdef _S9XLUA_H
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> Load Lua Script ------------------
item = gtk_menu_item_new_with_label ("Load Lua Script");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
g_signal_connect (item, "activate", G_CALLBACK (loadLua), NULL);
#endif
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-File --> ScreenShot ------------------
item = gtk_menu_item_new_with_label ("Screenshot");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
g_signal_connect (item, "activate", G_CALLBACK (FCEUI_SaveSnapshot),
NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F12, (GdkModifierType) 0,
GTK_ACCEL_VISIBLE);
//-File --> Quit ------------------
item = gtk_menu_item_new_with_label ("Quit");
g_signal_connect (item, "activate", G_CALLBACK (mainMenuQuitCB), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_q, GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//---------------------------------------
// Create Options Menu
item = gtk_menu_item_new_with_label ("Options");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
// Load Options Menu Items
//-Options --> Gamepad Config ---------------------
item = gtk_menu_item_new_with_label ("Gamepad Config");
g_signal_connect (item, "activate", G_CALLBACK (openGamepadConfig),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Hotkey Config ---------------------
item = gtk_menu_item_new_with_label ("Hotkey Config");
g_signal_connect (item, "activate", G_CALLBACK (openHotkeyConfig),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Sound Config ---------------------
item = gtk_menu_item_new_with_label ("Sound Config");
g_signal_connect (item, "activate", G_CALLBACK (openSoundConfig), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Video Config ---------------------
item = gtk_menu_item_new_with_label ("Video Config");
g_signal_connect (item, "activate", G_CALLBACK (openVideoConfig), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Palette Config ---------------------
item = gtk_menu_item_new_with_label ("Palette Config");
g_signal_connect (item, "activate", G_CALLBACK (openPaletteConfig),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Network Config ---------------------
item = gtk_menu_item_new_with_label ("Network Config");
g_signal_connect (item, "activate", G_CALLBACK (openNetworkConfig),
NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Auto-Resume Play ---------------------
item = gtk_check_menu_item_new_with_label ("Auto-Resume Play");
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
AutoResumePlay);
g_signal_connect (item, "toggled", G_CALLBACK (toggleAutoResume), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Toggle Menubar ---------------------
item = gtk_check_menu_item_new_with_label ("Toggle Menubar (Alt+M)");
//gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), FALSE);
g_signal_connect (item, "toggled", G_CALLBACK (toggleMenuToggling),
NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Options --> Fullscreen ---------------------
item = gtk_menu_item_new_with_label ("Fullscreen");
g_signal_connect (item, "activate", G_CALLBACK (enableFullscreen),
NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_Return, GDK_MOD1_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//---------------------------------------
// Create Emulation Menu
item = gtk_menu_item_new_with_label ("Emulation");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
// Load Emulation Menu Items
//-Emulation --> Power ---------------------
item = gtk_menu_item_new_with_label ("Power");
g_signal_connect (item, "activate", G_CALLBACK (FCEUI_PowerNES), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulation --> Reset ---------------------
item = gtk_menu_item_new_with_label ("Reset");
g_signal_connect (item, "activate", G_CALLBACK (hardReset), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulation --> Soft Reset ---------------------
item = gtk_menu_item_new_with_label ("Soft Reset");
g_signal_connect (item, "activate", G_CALLBACK (emuReset), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulation --> Pause ---------------------
item = gtk_menu_item_new_with_label ("Pause");
g_signal_connect (item, "activate", G_CALLBACK (togglePause), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_Pause, (GdkModifierType) 0,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulator --> Enable Game Genie ---------------------
item = gtk_check_menu_item_new_with_label ("Enable Game Genie");
int gameGenieEnabled = 0;
g_config->getOption ("SDL.GameGenie", &gameGenieEnabled);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
gameGenieEnabled);
g_signal_connect (item, "toggled", G_CALLBACK (toggleGameGenie), NULL);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulation --> Load Game Genie ROM ---------------------
item = gtk_menu_item_new_with_label ("Load Game Genie ROM");
g_signal_connect (item, "activate", G_CALLBACK (loadGameGenie), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulation --> Insert Coin ---------------------
item = gtk_menu_item_new_with_label ("Insert Coin");
g_signal_connect (item, "activate", G_CALLBACK (FCEUI_VSUniCoin), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Emulation --> FDS ------------------
item = gtk_menu_item_new_with_label ("FDS");
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
submenu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
//-Emulation --> FDS --> Switch Disk ---------------------
item = gtk_menu_item_new_with_label ("Switch Disk");
g_signal_connect (item, "activate", G_CALLBACK (FCEU_FDSSelect), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
//-Emulation --> FDS --> Eject Disk ---------------------
item = gtk_menu_item_new_with_label ("Eject Disk");
g_signal_connect (item, "activate", G_CALLBACK (FCEU_FDSInsert), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
//-Emulation --> FDS --> Load BIOS File ---------------------
item = gtk_menu_item_new_with_label ("Load BIOS File");
g_signal_connect (item, "activate", G_CALLBACK (loadFdsBios), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
//---------------------------------------
// Create Tools Menu
item = gtk_menu_item_new_with_label ("Tools");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
// Load Tools Menu Items
//-Tools --> Cheats ---------------------
item = gtk_menu_item_new_with_label ("Cheats...");
g_signal_connect (item, "activate", G_CALLBACK (openCheatsWindow),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Tools --> Ram Watch ---------------------
item = gtk_menu_item_new_with_label ("Ram Watch...");
g_signal_connect (item, "activate", G_CALLBACK (openMemoryWatchWindow),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Tools --> Memory Viewer ---------------------
item = gtk_menu_item_new_with_label ("Memory Viewer");
g_signal_connect (item, "activate", G_CALLBACK (openMemoryViewWindow),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//---------------------------------------
// Create Debug Menu
item = gtk_menu_item_new_with_label ("Debug");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
//-Debugger --> Debugger ---------------------
item = gtk_menu_item_new_with_label ("Debugger");
g_signal_connect (item, "activate", G_CALLBACK (openDebuggerWindow),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Debug --> Hex Editor ---------------------
item = gtk_menu_item_new_with_label ("Hex Editor");
g_signal_connect (item, "activate", G_CALLBACK (openMemoryViewWindow),
NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//---------------------------------------
// Create Movie Menu
item = gtk_menu_item_new_with_label ("Movie");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
// Load Movie Menu Items
//-Movie --> Open ---------------------
item = gtk_menu_item_new_with_label ("Open");
g_signal_connect (item, "activate", G_CALLBACK (loadMovie), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F7, GDK_SHIFT_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Movie --> Stop ---------------------
item = gtk_menu_item_new_with_label ("Stop");
g_signal_connect (item, "activate", G_CALLBACK (FCEUI_StopMovie), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_F7, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Add Separator
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Movie --> Record ---------------------
item = gtk_menu_item_new_with_label ("Record");
g_signal_connect (item, "activate", G_CALLBACK (recordMovie), NULL);
gtk_widget_add_accelerator (item, "activate", accel_group,
GDK_KEY_F5, GDK_SHIFT_MASK,
GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//-Movie --> Record As ---------------------
item = gtk_menu_item_new_with_label ("Record As");
g_signal_connect (item, "activate", G_CALLBACK (recordMovieAs), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_F5, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
//---------------------------------------
// Create Help Menu
item = gtk_menu_item_new_with_label ("Help");
gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
// Load Help Menu Items
//-Help --> About ---------------------
item = gtk_menu_item_new_with_label ("About");
g_signal_connect (item, "activate", G_CALLBACK (openAbout), NULL);
//gtk_widget_add_accelerator( item, "activate", accel_group,
// GDK_KEY_F7, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
// Finally, return the actual menu bar created
return menubar;
}
void pushOutputToGTK (const char *str)
{
// we don't really do anything with the output right now
return;
}
void showGui (bool b)
{
if (b)
{
//gtk_window_unmaximize( GTK_WINDOW(MainWindow) );
gtk_window_unfullscreen( GTK_WINDOW(MainWindow) );
gtk_widget_show_all (MainWindow);
//gtk_window_unfullscreen( GTK_WINDOW(MainWindow) );
}
else
{
//gtk_widget_hide (MainWindow);
//gtk_widget_hide (Menubar);
//gtk_window_maximize( GTK_WINDOW(MainWindow) );
gtk_window_fullscreen( GTK_WINDOW(MainWindow) );
}
}
void toggleMenuVis(void)
{
if (menuTogglingEnabled)
{
if ( gtk_widget_get_visible(Menubar) )
{
gtk_widget_hide (Menubar);
}
else
{
gtk_widget_show (Menubar);
}
}
};
int GtkMouseData[3] = { 0, 0, 0 };
gint handleMouseClick (GtkWidget * widget, GdkEvent * event,
gpointer callback_data)
{
GtkMouseData[0] = ((GdkEventButton *) event)->x;
GtkMouseData[1] = ((GdkEventButton *) event)->y;
int button = ((GdkEventButton *) event)->button;
if (!(((GdkEventButton *) event)->type == GDK_BUTTON_PRESS))
GtkMouseData[2] = 0;
else
{
if (button == 1)
GtkMouseData[2] |= 0x1;
if (button == 3)
GtkMouseData[2] |= 0x3;
}
// this doesn't work because we poll the mouse position rather
// than use events
/*
SDL_Event sdlev;
sdlev.type = SDL_MOUSEBUTTONDOWN;
if(((GdkEventButton*)event)->type == GDK_BUTTON_PRESS)
sdlev.button.type = SDL_MOUSEBUTTONDOWN;
else
sdlev.button.type = SDL_MOUSEBUTTONUP;
sdlev.button.button = ((GdkEventButton*)event)->button;
sdlev.button.state = ((GdkEventButton*)event)->state;
sdlev.button.x = ((GdkEventButton*)event)->x;
sdlev.button.y = ((GdkEventButton*)event)->y;
SDL_PushEvent(&sdlev);
*/
return 0;
}
union cairo_pixel_t
{
uint32_t u32;
uint8_t u8[4];
};
static void transferPix2CairoSurface(void)
{
union cairo_pixel_t *p;
union cairo_pixel_t *g;
int x, y, i,j, w, h;
if ( cairo_surface == NULL )
{
return;
}
//printf("Cairo Pixel ReMap\n");
cairo_surface_flush( cairo_surface );
if ( numRendLines != glx_shm->nrow )
{
cairo_recalc_mapper();
}
w = cairo_image_surface_get_width (cairo_surface);
h = cairo_image_surface_get_height (cairo_surface);
p = (cairo_pixel_t*)cairo_image_surface_get_data (cairo_surface);
g = (cairo_pixel_t*)glx_shm->pixbuf;
i=0;
for (y=0; y<h; y++)
{
for (x=0; x<w; x++)
{
j = cairo_pix_remapper[i];
if ( j < 0 )
{
p[i].u32 = 0xff000000;
}
else
{
// RGBA to ARGB
//#ifdef LSB_FIRST
p[i].u32 = g[j].u32 | 0xff000000;
//p[i].u8[0] = g[j].u8[0];
//p[i].u8[1] = g[j].u8[1];
//p[i].u8[2] = g[j].u8[2];
//p[i].u8[3] = 0xff; // Force Alpha to full
//#else
//// Big-Endian is untested.
//p[i].u8[2] = g[j].u8[0];
//p[i].u8[1] = g[j].u8[1];
//p[i].u8[0] = g[j].u8[2];
//p[i].u8[3] = 0xff; // Force Alpha to full
//#endif
//p[i].u32 = 0xffffffff;
}
i++;
}
}
cairo_surface_mark_dirty( cairo_surface );
gtk_widget_queue_draw( evbox );
}
uint32_t *getGuiPixelBuffer( int *w, int *h, int *s )
{
if ( w ) *w = GLX_NES_WIDTH;
if ( h ) *h = GLX_NES_HEIGHT;
if ( s ) *s = GLX_NES_WIDTH*4;
//return NULL;
return glx_shm->pixbuf;
//if ( cairo_surface == NULL )
//{
// if ( w ) *w = 0;
// if ( h ) *h = 0;
// if ( s ) *s = 0;
// return NULL;
//}
//cairo_surface_flush( cairo_surface );
//if ( w )
//{
// *w = cairo_image_surface_get_width (cairo_surface);
//}
//if ( h )
//{
// *h = cairo_image_surface_get_height (cairo_surface);
//}
//if ( s )
//{
// *s = cairo_image_surface_get_stride(cairo_surface);
//}
////return NULL;
//return (uint32_t*)cairo_image_surface_get_data (cairo_surface);
}
int guiPixelBufferReDraw(void)
{
glx_shm->blit_count++;
switch ( videoDriver )
{
case VIDEO_CAIRO:
transferPix2CairoSurface();
break;
case VIDEO_OPENGL_GLX:
gtk3_glx_render();
break;
case VIDEO_SDL:
gtk3_sdl_render();
break;
default:
case VIDEO_NONE:
// Nothing to do
break;
}
return 0;
}
int guiClearSurface(void)
{
uint32_t *p;
int w, h, z, i;
if ( cairo_surface != NULL )
{
cairo_surface_flush( cairo_surface );
p = (uint32_t*)cairo_image_surface_get_data (cairo_surface);
w = cairo_image_surface_get_width (cairo_surface);
h = cairo_image_surface_get_height (cairo_surface);
z = w * h;
for (i=0; i<z; i++)
{
p[i] = 0x00000000;
}
cairo_surface_mark_dirty( cairo_surface );
}
return 0;
}
//static void loadPixelTestPattern(void)
//{
// uint32_t *p;
// int i,x,y,width,height,w2,h2;
//
// width = 256;
// height = 256;
// p = (uint32_t*)glx_shm->pixbuf;
//
// w2 = width / 2;
// h2 = height / 2;
//
// //printf("W:%i H:%i W/2:%i H/2:%i\n", width, height, w2, h2 );
//
// i=0;
// for (y=0; y<height; y++)
// {
// for (x=0; x<width; x++)
// {
// if ( x < w2 )
// {
// if ( y < h2 )
// {
// p[i] = 0xff0000ff;
// }
// else
// {
// p[i] = 0xffffffff;
// }
// }
// else
// {
// if ( y < h2 )
// {
// p[i] = 0xffff0000;
// }
// else
// {
// p[i] = 0xff00ff00;
// }
// }
// i++;
// }
// }
//
//}
static void cairo_recalc_mapper(void)
{
int w, h, s;
int i, j, x, y;
int sw, sh, rx, ry, gw, gh;
int llx, lly, urx, ury;
float sx, sy, nw, nh;
w = cairo_image_surface_get_width (cairo_surface);
h = cairo_image_surface_get_height (cairo_surface);
s = w * h * 4;
gw = glx_shm->ncol;
gh = glx_shm->nrow;
if ( cairo_pix_remapper != NULL )
{
::free( cairo_pix_remapper ); cairo_pix_remapper = NULL;
}
cairo_pix_remapper = (int*)malloc(s);
if ( cairo_pix_remapper == NULL )
{
printf("Error: Failed to allocate memory for Pixel Surface Remapper\n");
return;
}
memset( cairo_pix_remapper, 0, s );
sx = (float)w / (float)gw;
sy = (float)h / (float)gh;
if (sx < sy )
{
sy = sx;
}
else
{
sx = sy;
}
sw = (int) ( (float)gw * sx );
sh = (int) ( (float)gh * sy );
llx = (w - sw) / 2;
lly = (h - sh) / 2;
urx = llx + sw;
ury = lly + sh;
i=0;
for (y=0; y<h; y++)
{
if ( (y < lly) || (y > ury) )
{
for (x=0; x<w; x++)
{
cairo_pix_remapper[i] = -1; i++;
}
}
else
{
for (x=0; x<w; x++)
{
if ( (x < llx) || (x > urx) )
{
cairo_pix_remapper[i] = -1; i++;
}
else
{
nw = (float)(x - llx) / (float)sw;
nh = (float)(y - lly) / (float)sh;
rx = (int)((float)gw * nw);
ry = (int)((float)gh * nh);
if ( rx < 0 )
{
rx = 0;
}
else if ( rx >= GLX_NES_WIDTH )
{
rx = GLX_NES_WIDTH-1;
}
if ( ry < 0 )
{
ry = 0;
}
else if ( ry >= GLX_NES_HEIGHT )
{
ry = GLX_NES_HEIGHT-1;
}
j = (ry * GLX_NES_WIDTH) + rx;
cairo_pix_remapper[i] = j; i++;
//printf("Remap: (%i,%i)=%i (%i,%i)=%i \n", x,y,i, rx,ry,j );
}
}
}
}
numRendLines = gh;
}
static void cairo_handle_resize(void)
{
int w, h;
//cairo_format_t cairo_format;
if (cairo_surface)
{
cairo_surface_destroy (cairo_surface); cairo_surface = NULL;
}
w = gtk_widget_get_allocated_width( evbox );
h = gtk_widget_get_allocated_height( evbox );
cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h );
//cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, w, h );
//printf("Cairo Surface: %p \n", cairo_surface );
//cairo_format = cairo_image_surface_get_format( cairo_surface );
if (cairo_pattern)
{
cairo_pattern_destroy (cairo_pattern); cairo_pattern = NULL;
}
cairo_pattern = cairo_pattern_create_for_surface( cairo_surface );
//printf("Cairo Format: %i \n", cairo_format );
cairo_recalc_mapper();
guiClearSurface();
transferPix2CairoSurface();
//cairo_surface_mark_dirty( cairo_surface );
}
int destroy_gui_video( void )
{
printf("Destroy GUI Video\n");
destroy_cairo_screen();
destroy_gtk3_GLXContext();
destroy_gtk3_sdl_video();
videoDriver = VIDEO_NONE;
return 0;
}
int init_gui_video( videoDriver_t videoDriverSelect )
{
if ( videoDriver == videoDriverSelect )
{
return 0;
}
destroy_gui_video();
videoDriver = videoDriverSelect;
switch ( videoDriver )
{
case VIDEO_OPENGL_GLX:
{
int flags=0;
int linear_interpolation_ena=0;
int double_buffer_ena=0;
g_config->getOption("SDL.OpenGLip" , &linear_interpolation_ena );
g_config->getOption("SDL.DoubleBuffering", &double_buffer_ena );
if ( linear_interpolation_ena ) flags |= GLXWIN_PIXEL_LINEAR_FILTER;
if ( double_buffer_ena ) flags |= GLXWIN_DOUBLE_BUFFER;
init_gtk3_GLXContext( flags );
}
break;
case VIDEO_CAIRO:
{
init_cairo_screen();
}
break;
case VIDEO_SDL:
{
init_gtk3_sdl_video();
}
break;
default:
case VIDEO_NONE:
// Nothing to do
break;
}
return 0;
}
void init_cairo_screen(void)
{
cairo_handle_resize();
}
void destroy_cairo_screen(void)
{
if (cairo_pattern)
{
printf("Destroying Cairo Pattern\n");
cairo_pattern_destroy (cairo_pattern); cairo_pattern = NULL;
}
if (cairo_surface)
{
printf("Destroying Cairo Surface\n");
cairo_surface_destroy (cairo_surface); cairo_surface = NULL;
}
if ( cairo_pix_remapper != NULL )
{
printf("Destroying Cairo Pixel Remapper\n");
::free( cairo_pix_remapper ); cairo_pix_remapper = NULL;
}
}
gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data)
{
// This should handle resizing so the emulation takes up as much
// of the GTK window as possible
// get new window width/height
int width, height, winsize_changed = 0;
width = event->configure.width;
height = event->configure.height;
//printf ("DEBUG: Configure new window size: %dx%d\n", width, height);
winsize_changed = 0;
// get width/height multipliers
double xscale = width / (double) NES_WIDTH;
double yscale = height / (double) NES_HEIGHT;
printf("DRAW: %ix%i \n", width, height );
if ( (width != gtk_draw_area_width) || (height != gtk_draw_area_height) )
{
winsize_changed = 1;
}
gtk_draw_area_width = width;
gtk_draw_area_height = height;
if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH;
if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT;
// TODO check KeepRatio (where is this)
// do this to keep aspect ratio
if (xscale > yscale)
xscale = yscale;
if (yscale > xscale)
yscale = xscale;
if ( winsize_changed )
{
switch ( videoDriver )
{
case VIDEO_CAIRO:
cairo_handle_resize();
break;
case VIDEO_SDL:
gtk3_sdl_resize();
break;
default:
case VIDEO_OPENGL_GLX:
// Nothing to do
break;
}
}
//TODO if openGL make these integers
g_config->setOption ("SDL.XScale", xscale);
g_config->setOption ("SDL.YScale", yscale);
//gtk_widget_realize(evbox);
//flushGtkEvents ();
//if ( winsize_changed && (GameInfo != 0) )
//{
// KillVideo ();
// InitVideo (GameInfo);
//}
gtk_widget_queue_draw( evbox );
//gtk_widget_set_size_request(evbox, (int)(NES_WIDTH*xscale), (int)(NES_HEIGHT*yscale));
//printf ("DEBUG: new xscale: %f yscale: %f\n", xscale, yscale);
return FALSE;
}
// Clear Drawing Area to Black
//static gboolean cairo_clear_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
//{
// GdkRGBA color;
// GtkStyleContext *context;
//
// context = gtk_widget_get_style_context (widget);
//
// color.red = 0, color.blue = 0; color.green = 0; color.alpha = 1.0;
//
// gtk_render_background( context, cr, 0, 0, gtk_draw_area_width, gtk_draw_area_height );
// gdk_cairo_set_source_rgba (cr, &color);
//
// cairo_fill (cr);
// cairo_paint (cr);
//
// return FALSE;
//}
/* Redraw the screen from the surface. Note that the ::draw
* signal receives a ready-to-be-used cairo_t that is already
* clipped to only draw the exposed areas of the widget
*/
static gboolean cairo_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
{
//printf("Cairo Draw\n");
//cairo_clear_cb( widget, cr, data );
//cairo_surface_mark_dirty( cairo_surface );
//cairo_set_source_surface (cr, cairo_surface, 0, 0);
cairo_set_source (cr, cairo_pattern);
cairo_paint (cr);
return FALSE;
}
static gboolean draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data)
{
gtk_draw_area_width = gtk_widget_get_allocated_width (widget);
gtk_draw_area_height = gtk_widget_get_allocated_height (widget);
if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH;
if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT;
switch ( videoDriver )
{
case VIDEO_CAIRO:
cairo_draw_cb( widget, cr, data );
break;
case VIDEO_OPENGL_GLX:
gtk3_glx_render();
break;
case VIDEO_SDL:
gtk3_sdl_render();
break;
default:
case VIDEO_NONE:
// Nothing to do
break;
}
return FALSE;
}
static void
drawAreaRealizeCB (GtkWidget *widget,
gpointer user_data)
{
int vdSel = VIDEO_OPENGL_GLX;
g_config->getOption("SDL.VideoDriver", &vdSel);
printf("Draw Area Realize: Video Driver Select: %i\n", vdSel);
init_gui_video( (videoDriver_t)vdSel );
}
int InitGTKSubsystem (int argc, char **argv)
{
GtkWidget *vbox;
MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_events (GTK_WIDGET (MainWindow), GDK_KEY_RELEASE_MASK);
// gtk_window_set_policy (GTK_WINDOW (MainWindow), FALSE, FALSE, TRUE);
gtk_window_set_resizable (GTK_WINDOW (MainWindow), TRUE);
gtk_window_set_title (GTK_WINDOW (MainWindow), FCEU_NAME_AND_VERSION);
gtk_window_set_default_size (GTK_WINDOW (MainWindow), NES_WIDTH,
NES_HEIGHT);
GdkPixbuf *icon = gdk_pixbuf_new_from_xpm_data (icon_xpm);
gtk_window_set_default_icon (icon);
gtk_window_set_icon (GTK_WINDOW (MainWindow), icon);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (MainWindow), vbox);
Menubar = CreateMenubar (MainWindow);
gtk_box_pack_start (GTK_BOX (vbox), Menubar, FALSE, TRUE, 0);
// PRG: this code here is the the windowID "hack" to render SDL
// in a GTK window. however, I can't get it to work right now
// so i'm commenting it out and haivng a seperate GTK2 window with
// controls
// 12/21/09
// ---
// uncommented and fixed by Bryan Cain
// 1/24/11
//
// prg - Bryan Cain, you are the man!
evbox = gtk_drawing_area_new ();
gtk_box_pack_start (GTK_BOX (vbox), evbox, TRUE, TRUE, 0);
double xscale, yscale;
g_config->getOption ("SDL.XScale", &xscale);
g_config->getOption ("SDL.YScale", &yscale);
// set up keypress "snooper" to convert GDK keypress events into SDL keypresses
//gtk_key_snooper_install(convertKeypress, NULL);
g_signal_connect (G_OBJECT (MainWindow), "key-press-event",
G_CALLBACK (convertKeypress), NULL);
g_signal_connect (G_OBJECT (MainWindow), "key-release-event",
G_CALLBACK (convertKeypress), NULL);
// pass along mouse data from GTK to SDL
g_signal_connect (G_OBJECT (evbox), "button-press-event",
G_CALLBACK (handleMouseClick), NULL);
g_signal_connect (G_OBJECT (evbox), "button-release-event",
G_CALLBACK (handleMouseClick), NULL);
// signal handlers
g_signal_connect (MainWindow, "delete-event", G_CALLBACK(deleteMainWindowCB), NULL);
g_signal_connect (MainWindow, "destroy-event", G_CALLBACK(destroyMainWindowCB), NULL);
g_signal_connect (evbox, "configure-event",
G_CALLBACK (handle_resize), NULL);
g_signal_connect (evbox, "realize", G_CALLBACK (drawAreaRealizeCB), NULL);
g_signal_connect (evbox, "draw", G_CALLBACK (draw_cb), NULL);
gtk_widget_set_size_request (evbox, NES_WIDTH * xscale,
NES_HEIGHT * yscale);
gtk_widget_realize (evbox);
gtk_widget_show (evbox);
gtk_widget_show_all (vbox);
gtk_widget_show_all (MainWindow);
GtkRequisition req;
gtk_widget_get_preferred_size (GTK_WIDGET (MainWindow), NULL, &req);
//printf("Init Resize: w:%i h:%i \n", req.width, req.height );
gtk_window_resize (GTK_WINDOW (MainWindow), req.width, req.height);
// Once the window has been resized, return draw area size request to minimum values
gtk_widget_set_size_request (evbox, NES_WIDTH, NES_HEIGHT);
gtkIsStarted = true;
return 0;
}