diff --git a/SConstruct b/SConstruct index a400ebb7..97b30bce 100644 --- a/SConstruct +++ b/SConstruct @@ -19,8 +19,8 @@ opts.AddVariables( BoolVariable('FRAMESKIP', 'Enable frameskipping', 1), BoolVariable('OPENGL', 'Enable OpenGL support', 1), BoolVariable('LUA', 'Enable Lua support', 1), - BoolVariable('GTK', 'Enable GTK2 GUI (SDL only)', 1), - BoolVariable('GTK3', 'Enable GTK3 GUI (SDL only)', 0), + BoolVariable('GTK', 'Enable GTK2 GUI (SDL only)', 0), + BoolVariable('GTK3', 'Enable GTK3 GUI (SDL only)', 1), BoolVariable('NEWPPU', 'Enable new PPU core', 1), BoolVariable('CREATE_AVI', 'Enable avi creation support (SDL only)', 1), BoolVariable('LOGO', 'Enable a logoscreen when creating avis (SDL only)', 1), @@ -28,7 +28,7 @@ opts.AddVariables( BoolVariable('SYSTEM_MINIZIP', 'Use system minizip instead of static minizip provided with fceux', 0), BoolVariable('LSB_FIRST', 'Least signficant byte first (non-PPC)', 1), BoolVariable('CLANG', 'Compile with llvm-clang instead of gcc', 0), - BoolVariable('SDL2', 'Compile using SDL2 instead of SDL 1.2 (experimental/non-functional)', 0) + BoolVariable('SDL2', 'Compile using SDL2 instead of SDL 1.2 (experimental/non-functional)', 1) ) AddOption('--prefix', dest='prefix', type='string', nargs=1, action='store', metavar='DIR', help='installation prefix') @@ -44,7 +44,7 @@ if platform.system == "ppc": env['LSB_FIRST'] = 0 # Default compiler flags: -env.Append(CCFLAGS = ['-Wall', '-Wno-write-strings', '-Wno-sign-compare']) +env.Append(CCFLAGS = ['-Wall', '-Wno-write-strings', '-Wno-sign-compare', '-Wno-parentheses', '-Wno-unused-local-typedefs']) env.Append(CXXFLAGS = ['-std=c++0x']) if 'PLATFORM' in os.environ: @@ -97,7 +97,7 @@ else: if conf.CheckFunc('asprintf'): conf.env.Append(CCFLAGS = "-DHAVE_ASPRINTF") if env['SYSTEM_MINIZIP']: - assert conf.CheckLibWithHeader('minizip', 'minizip/unzip.h', 'C', 'unzOpen;', 1), "please install: libminizip" + assert env.ParseConfig('pkg-config minizip --cflags --libs'), "please install: libminizip" assert conf.CheckLibWithHeader('z', 'zlib.h', 'c', 'inflate;', 1), "please install: zlib" env.Append(CPPDEFINES=["_SYSTEM_MINIZIP"]) else: @@ -153,6 +153,9 @@ else: elif conf.CheckLib('lua5.1'): lua_link_flags = "-llua5.1" lua_include_dir = "/usr/include/lua5.1" + elif conf.CheckLib('lua-5.1'): + lua_link_flags = "-llua-5.1" + lua_include_dir = "/usr/include/lua-5.1" elif conf.CheckLib('lua'): lua_link_flags = "-llua" lua_include_dir = "/usr/include/lua" @@ -183,7 +186,7 @@ else: if env['OPENGL'] and conf.CheckLibWithHeader('GL', 'GL/gl.h', 'c', autoadd=1): conf.env.Append(CCFLAGS = "-DOPENGL") - conf.env.Append(CPPDEFINES = ['PSS_STYLE=1']) + conf.env.Append(CPPDEFINES = ['PSS_STYLE=1',"FCEUDEF_DEBUGGER"]) env = conf.Finish() diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..ff7c0140 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,8 @@ +version: 1.0.{build} +image: +- Visual Studio 2019 +- Ubuntu2004 + #- Ubuntu1804 +build_script: +- cmd: msbuild "./vc/vc14_fceux.sln" +- sh: ./pipelines/linux_build.sh diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..8365c84a --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,16 @@ +# C/C++ with GCC +# Build your C/C++ project with GCC using make. +# Add steps that publish test results, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/c-cpp/gcc + +trigger: +- master +- development + +pool: + vmImage: 'ubuntu-latest' + +steps: +- script: | + ./pipelines/linux_build.sh + displayName: 'make' diff --git a/pipelines/debpkg.pl b/pipelines/debpkg.pl new file mode 100755 index 00000000..64c04735 --- /dev/null +++ b/pipelines/debpkg.pl @@ -0,0 +1,119 @@ +#!/usr/bin/perl + +use strict; + +my $VERSION="2.2.4"; +my $INSTALL_PREFIX="/tmp/fceux"; +my $CTL_FILENAME="$INSTALL_PREFIX/DEBIAN/control"; +my $ARCH="amd64"; +my $PKG_OUTPUT_FILE="fceux-$VERSION-$ARCH.deb"; + +# Start by auto figuring out dependencies of the executable. +# the rest of the package creation is trival. +my $SO_LIST=`objdump -x $INSTALL_PREFIX/usr/bin/fceux`; + +#print "$SO_LIST"; + +my $i; my $j; my $k; my $pkg; +my @fd = split /\n/, $SO_LIST; +my @libls; + +$#libls=0; + +for ($i=0; $i<=$#fd; $i++) +{ + #$fd[$i] =~ s/^\s+//; + #print "$fd[$i]\n"; + + if ( $fd[$i] =~ m/NEEDED\s+(.*)/ ) + { + #print "$1 \n"; + $libls[$#libls] = $1; $#libls++; + } + +} + +my %pkghash; my $pkgsearch; +my @pkglist; my @pkgdeps; +my $pkg; my $filepath; + +$#pkgdeps=0; + +for ($i=0; $i<$#libls; $i++) +{ + $pkgsearch=`dpkg-query -S $libls[$i]`; + + @pkglist = split /\n/, $pkgsearch; + + for ($j=0; $j<=$#pkglist; $j++) + { + #$pkghash{$pkg} = 1; + #print " $libls[$i] '$pkglist[$j]' \n"; + + if ( $pkglist[$j] =~ m/(.*):$ARCH:\s+(.*)/ ) + { + $pkg = $1; + $filepath = $2; + + $filepath =~ s/^.*\///; + + if ( $libls[$i] eq $filepath ) + { + #print "PKG: '$pkg' '$libls[$i]' == '$filepath' \n"; + # Don't put duplicate entries into the pkg depend list. + if ( !defined( $pkghash{$pkg} ) ) + { + $pkgdeps[ $#pkgdeps ] = $pkg; $#pkgdeps++; + $pkghash{$pkg} = 1; + } + } + } + } +} +# +# +system("mkdir -p $INSTALL_PREFIX/DEBIAN"); + +open CTL, ">$CTL_FILENAME" or die "Error: Could not open file '$CTL_FILENAME'\n"; +# +print CTL "Package: fceux\n"; +print CTL "Version: $VERSION\n"; +print CTL "Section: games\n"; +print CTL "Priority: extra\n"; +print CTL "Architecture: $ARCH\n"; +print CTL "Homepage: http://fceux.com/\n"; +print CTL "Essential: no\n"; +#print CTL "Installed-Size: 1024\n"; +print CTL "Maintainer: mjbudd77\n"; +print CTL "Description: fceux is an emulator of the original (8-bit) Nintendo Entertainment System (NES)\n"; +print CTL "Depends: $pkgdeps[0]"; + +for ($i=1; $i<$#pkgdeps; $i++) +{ + print CTL ", $pkgdeps[$i]"; +} +print CTL "\n"; + +close CTL; + +#system("cat $CTL_FILENAME"); +# +chdir "/tmp"; +system("dpkg-deb --build fceux "); +if ( !(-e "/tmp/fceux.deb") ) +{ + die "Error: Failed to create package $PKG_OUTPUT_FILE\n"; +} +system("mv fceux.deb $PKG_OUTPUT_FILE"); +system("dpkg-deb -I $PKG_OUTPUT_FILE"); +# +if ( -e "/tmp/$PKG_OUTPUT_FILE" ) +{ + print "**********************************************\n"; + print "Created deb package: /tmp/$PKG_OUTPUT_FILE\n"; + print "**********************************************\n"; +} +else +{ + die "Error: Failed to create package $PKG_OUTPUT_FILE\n"; +} diff --git a/pipelines/linux_build.sh b/pipelines/linux_build.sh new file mode 100755 index 00000000..118422fa --- /dev/null +++ b/pipelines/linux_build.sh @@ -0,0 +1,115 @@ +#!/bin/bash + +id +pwd +cat /etc/os-release + +SCRIPT_DIR=$( cd $(dirname $BASH_SOURCE[0]); pwd ); + +#echo $SCRIPT_DIR; + +gcc --version +python2 --version +python3 --version + +INSTALL_PREFIX=/tmp/fceux + +echo '****************************************' +echo "APPVEYOR_SSH_KEY=$APPVEYOR_SSH_KEY"; +echo "APPVEYOR_SSH_BLOCK=$APPVEYOR_SSH_BLOCK"; +echo '****************************************' + +echo '****************************************' +echo '****************************************' +echo '*** Installing Package Dependencies ***' +echo '****************************************' +echo '****************************************' +# Install Lua-5.1 development package +echo '****************************************' +echo 'Install Dependency lua5.1-dev' +echo '****************************************' +sudo apt-get --assume-yes install lua5.1-dev +pkg-config --cflags --libs lua5.1 + +# Install libSDL-1.2 and libSDL-2 +# libSDL-1.2 no long needed +#echo '****************************************' +#echo 'Install Dependency libsdl1.2-dev' +#echo '****************************************' +#sudo apt-get --assume-yes install libsdl1.2-dev +#sdl-config --cflags --libs +echo '****************************************' +echo 'Install Dependency libsdl2-dev' +echo '****************************************' +sudo apt-get --assume-yes install libsdl2-dev +sdl2-config --cflags --libs + +# Install libminizip-dev +echo '****************************************' +echo 'Install Dependency libminizip-dev' +echo '****************************************' +sudo apt-get --assume-yes install libminizip-dev +pkg-config --cflags --libs minizip + +# GTK+-2 is no longer needed +#sudo apt-get install libgtk2.0-dev + +# Install GTK+-3 +echo '****************************************' +echo 'Install Dependency libgtk-3-dev' +echo '****************************************' +sudo apt-get --assume-yes install libgtk-3-dev +pkg-config --cflags --libs gtk+-3.0 + +# Install GTK+-3 Sourceview +sudo apt-get --assume-yes install libgtksourceview-3.0-dev +pkg-config --cflags --libs gtksourceview-3.0 + +# Install scons +echo '****************************************' +echo 'Install Build Dependency scons' +echo '****************************************' +sudo apt-get --assume-yes install scons + +# Install cppcheck +echo '****************************************' +echo 'Install Check Dependency cppcheck' +echo '****************************************' +sudo apt-get --assume-yes install cppcheck + +echo '**************************' +echo '*** Building Project ***' +echo '**************************' +mkdir -p $INSTALL_PREFIX/usr; +scons --clean +scons GTK3=1 SYSTEM_LUA=1 SYSTEM_MINIZIP=1 CREATE_AVI=1 install --prefix=$INSTALL_PREFIX/usr + +# Debug via ssh if necessary +if [ ! -z $APPVEYOR_SSH_BLOCK ]; then + curl -sflL 'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-ssh.sh' | bash -e - +fi + +if [ -e $INSTALL_PREFIX/usr/bin/fceux ]; then + echo '**************************************************************' + echo 'Printing Shared Object Dependencies for ./bin/fceux Executable' + echo '**************************************************************' + ldd $INSTALL_PREFIX/usr/bin/fceux +else + echo "Error: Executable Failed to build: $INSTALL_PREFIX/usr/bin/fceux"; + exit 1; +fi + +echo '**************************************************************' +echo 'Printing To Be Packaged Files ' +echo '**************************************************************' +find $INSTALL_PREFIX + +echo '**************************************************************' +echo 'Creating Debian Package' +echo '**************************************************************' +$SCRIPT_DIR/debpkg.pl; + +echo '**************************************************************' +echo 'Testing Install of Package' +echo '**************************************************************' +sudo dpkg -i /tmp/fceux-*.deb diff --git a/src/cart.h b/src/cart.h index e94ee17b..e78c87ea 100644 --- a/src/cart.h +++ b/src/cart.h @@ -104,4 +104,4 @@ bool FCEU_OpenGenie(void); void FCEU_CloseGenie(void); void FCEU_KillGenie(void); -#endif#endif \ No newline at end of file +#endif diff --git a/src/debug.cpp b/src/debug.cpp index 04a7cf73..c88e581a 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -565,9 +565,9 @@ void BreakHit(int bp_num) { FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused() -#ifdef WIN32 +//#ifdef WIN32 FCEUD_DebugBreakpoint(bp_num); -#endif +//#endif } int StackAddrBackup; diff --git a/src/drivers/common/vidblit.cpp b/src/drivers/common/vidblit.cpp index 7a3eb0f9..d93c520a 100644 --- a/src/drivers/common/vidblit.cpp +++ b/src/drivers/common/vidblit.cpp @@ -218,6 +218,11 @@ int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int return(0); //allocate adequate room for 32bpp palette + if ( palettetranslate ) + { + free(palettetranslate); + palettetranslate=NULL; + } palettetranslate=(uint32*)FCEU_dmalloc(256*4 + 512*4); if(!palettetranslate) diff --git a/src/drivers/sdl/SConscript b/src/drivers/sdl/SConscript index 23e11b95..22fbb644 100644 --- a/src/drivers/sdl/SConscript +++ b/src/drivers/sdl/SConscript @@ -8,7 +8,12 @@ Export('env') source_list = Split( """ input.cpp + cheat.cpp config.cpp + memview.cpp + ramwatch.cpp + debugger.cpp + glxwin.cpp sdl.cpp sdl-joystick.cpp sdl-sound.cpp @@ -18,8 +23,6 @@ source_list = Split( """) Import('env') -if 'GL' in env['LIBS']: - source_list.append('sdl-opengl.cpp') if env['GTK'] or env['GTK3']: source_list.append('gui.cpp') diff --git a/src/drivers/sdl/cheat.cpp b/src/drivers/sdl/cheat.cpp new file mode 100644 index 00000000..2cf3f91e --- /dev/null +++ b/src/drivers/sdl/cheat.cpp @@ -0,0 +1,1323 @@ +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#ifdef _GTK3 +#include +#endif + +#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" + +extern Config *g_config; + +static void updateAllActvCheatLists (bool redraw); + +//----------------------------------------- +class cheat_win_t +{ + public: + + GtkTreeStore * actv_cheats_store; + GtkTreeStore *ram_match_store; + GtkTreeIter actv_cheats_iter; + GtkTreeIter ram_match_iter; + int cheat_search_known_value; + int cheat_search_neq_value; + int cheat_search_gt_value; + int cheat_search_lt_value; + int new_cheat_addr; + int new_cheat_val; + int new_cheat_cmp; + std::string new_cheat_name; + bool wasPausedByCheats; + bool pauseWhileCheatsActv; + bool actv_cheat_redraw; + + GtkWidget *win; + GtkWidget *actv_cheat_tree; + GtkWidget *search_cheat_tree; + GtkWidget *neq_chkbox; + GtkWidget *lt_chkbox; + GtkWidget *gt_chkbox; + GtkWidget *cheat_name_entry; + GtkWidget *cheat_addr_entry; + GtkWidget *cheat_val_entry; + GtkWidget *cheat_cmp_entry; + GtkWidget *cheat_del_button; + GtkWidget *cheat_edit_button; + GtkWidget *cheat_search_known_btn; + GtkWidget *cheat_search_eq_btn; + GtkWidget *cheat_search_neq_btn; + GtkWidget *cheat_search_gr_btn; + GtkWidget *cheat_search_lt_btn; + + cheat_win_t (void) + { + win = NULL; + actv_cheats_store = NULL; + ram_match_store = NULL; + cheat_search_known_value = 0; + cheat_search_neq_value = 0; + cheat_search_gt_value = 0; + cheat_search_lt_value = 0; + new_cheat_addr = -1; + new_cheat_val = -1; + new_cheat_cmp = -1; + wasPausedByCheats = false; + pauseWhileCheatsActv = false; + actv_cheat_redraw = true; + actv_cheat_tree = NULL; + search_cheat_tree = NULL; + neq_chkbox = NULL; + lt_chkbox = NULL; + gt_chkbox = NULL; + cheat_name_entry = NULL; + cheat_addr_entry = NULL; + cheat_val_entry = NULL; + cheat_cmp_entry = NULL; + cheat_del_button = NULL; + cheat_edit_button = NULL; + cheat_search_known_btn = NULL; + cheat_search_eq_btn = NULL; + cheat_search_neq_btn = NULL; + cheat_search_gr_btn = NULL; + cheat_search_lt_btn = NULL; + } + + void showActiveCheatList (bool reset); + void showCheatSearchResults (void); + int getSelCheatRow(void); +}; + +static cheat_win_t *curr_cw = NULL; +static std::list < cheat_win_t * >cheatWinList; + +//******************************************************************************************************* +// Cheat Window +//******************************************************************************************************* + +static int ShowCheatSearchResultsCallB (uint32 a, uint8 last, uint8 current) +{ + char addrStr[32], lastStr[32], curStr[32]; + + sprintf (addrStr, "0x%04X ", a); + sprintf (lastStr, " 0x%02X ", last); + sprintf (curStr, " 0x%02X ", current); + + gtk_tree_store_append (curr_cw->ram_match_store, &curr_cw->ram_match_iter, NULL); // aquire iter + + gtk_tree_store_set (curr_cw->ram_match_store, &curr_cw->ram_match_iter, + 0, addrStr, 1, lastStr, 2, curStr, -1); + + return 1; +} + +void cheat_win_t::showCheatSearchResults (void) +{ + int total_matches = 0; + + curr_cw = this; + + gtk_tree_store_clear (ram_match_store); + + total_matches = FCEUI_CheatSearchGetCount (); + + //printf("Cheat Search Matches: %i \n", total_matches ); + + FCEUI_CheatSearchGetRange (0, total_matches, + ShowCheatSearchResultsCallB); +} + +static void cheatSearchReset (GtkButton * button, cheat_win_t * cw) +{ + //printf("Cheat Search Reset!\n"); + + //cheat_search_known_value = 0; + //cheat_search_neq_value = 0; + //cheat_search_gt_value = 0; + //cheat_search_lt_value = 0; + + gtk_widget_set_sensitive( cw->cheat_search_known_btn , TRUE ); + gtk_widget_set_sensitive( cw->cheat_search_eq_btn , TRUE ); + gtk_widget_set_sensitive( cw->cheat_search_neq_btn , TRUE ); + gtk_widget_set_sensitive( cw->cheat_search_gr_btn , TRUE ); + gtk_widget_set_sensitive( cw->cheat_search_lt_btn , TRUE ); + + FCEUI_CheatSearchBegin (); + cw->showCheatSearchResults (); + // Enable Cheat Search Buttons - Change Sensitivity +} + +static void cheatSearchKnown (GtkButton * button, cheat_win_t * cw) +{ + //printf("Cheat Search Known!\n"); + + FCEUI_CheatSearchEnd (FCEU_SEARCH_NEWVAL_KNOWN, + cw->cheat_search_known_value, 0); + cw->showCheatSearchResults (); +} + +static void cheatSearchEqual (GtkButton * button, cheat_win_t * cw) +{ + + //printf("Cheat Search Equal !\n"); + + FCEUI_CheatSearchEnd (FCEU_SEARCH_PUERLY_RELATIVE_CHANGE, 0, 0); + cw->showCheatSearchResults (); +} + +static void cheatSearchNotEqual (GtkButton * button, cheat_win_t * cw) +{ + int checked = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON + (cw->neq_chkbox)); + + //printf("Cheat Search NotEqual %i!\n", checked); + + if (checked) + { + FCEUI_CheatSearchEnd (FCEU_SEARCH_PUERLY_RELATIVE_CHANGE, 0, + cw->cheat_search_neq_value); + } + else + { + FCEUI_CheatSearchEnd (FCEU_SEARCH_ANY_CHANGE, 0, 0); + } + cw->showCheatSearchResults (); +} + +static void cheatSearchGreaterThan (GtkButton * button, cheat_win_t * cw) +{ + int checked = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON + (cw->gt_chkbox)); + + //printf("Cheat Search GreaterThan %i!\n", checked); + + if (checked) + { + FCEUI_CheatSearchEnd (FCEU_SEARCH_NEWVAL_GT_KNOWN, 0, + cw->cheat_search_gt_value); + } + else + { + FCEUI_CheatSearchEnd (FCEU_SEARCH_NEWVAL_GT, 0, 0); + } + cw->showCheatSearchResults (); +} + +static void cheatSearchLessThan (GtkButton * button, cheat_win_t * cw) +{ + int checked = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON + (cw->lt_chkbox)); + + //printf("Cheat Search LessThan %i!\n", checked); + + if (checked) + { + FCEUI_CheatSearchEnd (FCEU_SEARCH_NEWVAL_LT_KNOWN, 0, + cw->cheat_search_lt_value); + } + else + { + FCEUI_CheatSearchEnd (FCEU_SEARCH_NEWVAL_LT, 0, 0); + } + cw->showCheatSearchResults (); +} + +static void pauseDuringCheatWinActvCB (GtkToggleButton * button, + cheat_win_t * cw) +{ + cw->pauseWhileCheatsActv = gtk_toggle_button_get_active (button); + + if (cw->pauseWhileCheatsActv) + { + if (EmulationPaused == 0) + { + EmulationPaused = 1; + cw->wasPausedByCheats = true; + } + } + else + { + if (EmulationPaused && cw->wasPausedByCheats) + { + EmulationPaused = 0; + } + cw->wasPausedByCheats = false; + } + FCEU_printf ("Emulation paused: %d\n", EmulationPaused); +} + +static void cheatSearchValueEntryCB1 (GtkWidget * widget, cheat_win_t * cw) +{ + long value; + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + value = strtol (entry_text, NULL, 16); + + cw->cheat_search_known_value = value; + + //printf("Cheat Value Entry contents: '%s' Value: 0x%02lx\n", entry_text, value); +} + +static void cheatSearchValueEntryCB2 (GtkWidget * widget, cheat_win_t * cw) +{ + long value; + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + value = strtol (entry_text, NULL, 16); + + cw->cheat_search_neq_value = value; + + //printf("Cheat Value Entry contents: '%s' Value: 0x%02lx\n", entry_text, value); +} + +static void cheatSearchValueEntryCB3 (GtkWidget * widget, cheat_win_t * cw) +{ + long value; + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + value = strtol (entry_text, NULL, 16); + + cw->cheat_search_gt_value = value; + + //printf("Cheat Value Entry contents: '%s' Value: 0x%02lx\n", entry_text, value); +} + +static void cheatSearchValueEntryCB4 (GtkWidget * widget, cheat_win_t * cw) +{ + long value; + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + value = strtol (entry_text, NULL, 16); + + cw->cheat_search_lt_value = value; + + //printf("Cheat Value Entry contents: '%s' Value: 0x%02lx\n", entry_text, value); +} + +static int activeCheatListCB (char *name, uint32 a, uint8 v, int c, int s, + int type, void *data) +{ + char addrStr[32], valStr[16], cmpStr[16]; + //printf("Cheat Name:'%s' Addr:0x%04x Val:0x%02x \n", name, a, v ); + // + cheat_win_t *cw = (cheat_win_t *) data; + + if (cw->actv_cheat_redraw) + { + gtk_tree_store_append (cw->actv_cheats_store, &cw->actv_cheats_iter, NULL); // aquire iter + } + + sprintf (addrStr, "0x%04X ", a); + sprintf (valStr, " 0x%02X ", v); + + if (c >= 0) + { + sprintf (cmpStr, " 0x%02X ", c); + } + else + { + strcpy (cmpStr, " 0xFF "); + } + + gtk_tree_store_set (cw->actv_cheats_store, &cw->actv_cheats_iter, + 0, s, 1, addrStr, 2, valStr, 3, cmpStr, 4, name, + -1); + + if (!cw->actv_cheat_redraw) + { + if (!gtk_tree_model_iter_next + (GTK_TREE_MODEL (cw->actv_cheats_store), + &cw->actv_cheats_iter)) + { + gtk_tree_store_append (cw->actv_cheats_store, &cw->actv_cheats_iter, NULL); // aquire iter + } + } + + return 1; +} + +void cheat_win_t::showActiveCheatList (bool reset) +{ + actv_cheat_redraw = reset; + + if (actv_cheat_redraw) + { + gtk_tree_store_clear (actv_cheats_store); + } + else + { + if (!gtk_tree_model_get_iter_first + (GTK_TREE_MODEL (actv_cheats_store), &actv_cheats_iter)) + { + //printf("No Tree Entries Loaded.\n"); + actv_cheat_redraw = 1; + } + } + + FCEUI_ListCheats (activeCheatListCB, (void *) this); + + actv_cheat_redraw = false; +} + +int cheat_win_t::getSelCheatRow(void) +{ + int numListRows, retval = -1; + GList *selListRows, *tmpList; + GtkTreeModel *model = NULL; + GtkTreeSelection *treeSel; + + treeSel = + gtk_tree_view_get_selection (GTK_TREE_VIEW + (actv_cheat_tree)); + + numListRows = gtk_tree_selection_count_selected_rows (treeSel); + + if (numListRows == 0) + { + return -1; + } + //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) + { + retval = indexArray[0]; + } + + tmpList = tmpList->next; + } + + g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free); + + return retval; +} + +static void cheatListEnableToggle (GtkCellRendererToggle * renderer, + gchar * pathStr, cheat_win_t * cw) +{ + GtkTreePath *path; + int depth; + int *indexArray; + + path = gtk_tree_path_new_from_string (pathStr); + + if (path == NULL) + { + printf ("Error: gtk_tree_path_new_from_string failed\n"); + return; + } + + depth = gtk_tree_path_get_depth (path); + indexArray = gtk_tree_path_get_indices (path); + + if (depth > 0) + { + //printf("Toggle: %i\n", indexArray[0] ); + FCEUI_ToggleCheat (indexArray[0]); + } + + gtk_tree_path_free (path); + + updateAllActvCheatLists (0); + +} + +static void +cheat_select_rowCB (GtkTreeView *treeview, + cheat_win_t * cw ) +{ + int row, row_is_selected; + + row = cw->getSelCheatRow(); + + row_is_selected = (row >= 0); + + //printf("Selected row = %i\n", row); + // + gtk_widget_set_sensitive( cw->cheat_del_button , row_is_selected ); + gtk_widget_set_sensitive( cw->cheat_edit_button, row_is_selected ); + + if ( !row_is_selected ) + { + return; + } + uint32 a; + uint8 v; + int c, s, type; + char *name = NULL; + + if (FCEUI_GetCheat (row, &name, &a, &v, &c, &s, &type)) + { + char txt[64]; + + if ( name ) + { + gtk_entry_set_text( GTK_ENTRY(cw->cheat_name_entry), name ); + } + + sprintf( txt, "%04X", a ); + gtk_entry_set_text( GTK_ENTRY(cw->cheat_addr_entry), txt ); + + sprintf( txt, "%02X", v ); + gtk_entry_set_text( GTK_ENTRY(cw->cheat_val_entry), txt ); + + if ( c >= 0 ) + { + sprintf( txt, "%02X", c ); + } + else + { + txt[0] = 0; + } + gtk_entry_set_text( GTK_ENTRY(cw->cheat_cmp_entry), txt ); + } + + //gtk_widget_set_sensitive( dw->del_bp_button , row_is_selected ); + //gtk_widget_set_sensitive( dw->edit_bp_button, row_is_selected ); +} +static void refreshCheatListCB(GtkWidget * widget, cheat_win_t * cw) +{ + updateAllActvCheatLists (1); +} + +static void openCheatFile (GtkWidget * widget, cheat_win_t * cw) +{ + GtkWidget *fileChooser; + GtkFileFilter *filterCht; + GtkFileFilter *filterAll; + + filterCht = gtk_file_filter_new (); + filterAll = gtk_file_filter_new (); + + gtk_file_filter_add_pattern (filterCht, "*.cht"); + gtk_file_filter_add_pattern (filterAll, "*"); + + gtk_file_filter_set_name (filterCht, "*.cht"); + gtk_file_filter_set_name (filterAll, "All Files"); + + fileChooser = + gtk_file_chooser_dialog_new ("Open Cheat", + GTK_WINDOW (cw->win), + 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), filterCht); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterAll); + + if (gtk_dialog_run (GTK_DIALOG (fileChooser)) == GTK_RESPONSE_ACCEPT) + { + FILE *fp; + char *filename; + + filename = + gtk_file_chooser_get_filename (GTK_FILE_CHOOSER + (fileChooser)); + gtk_widget_destroy (fileChooser); + + fp = fopen (filename, "r"); + + if (fp != NULL) + { + FCEU_LoadGameCheats (fp, 0); + fclose (fp); + } + //g_config->setOption("SDL.LastOpenFile", filename); + // Error dialog no longer required with GTK implementation of FCEUD_PrintError() + + resizeGtkWindow (); + g_free (filename); + } + else + { + gtk_widget_destroy (fileChooser); + } + + updateAllActvCheatLists (1); +} + +static void newCheatEntryCB1 (GtkWidget * widget, cheat_win_t * cw) +{ + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + if (entry_text[0] == 0) + { + cw->new_cheat_addr = -1; + } + else + { + cw->new_cheat_addr = strtol (entry_text, NULL, 16); + } +} + +static void newCheatEntryCB2 (GtkWidget * widget, cheat_win_t * cw) +{ + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + if (entry_text[0] == 0) + { + cw->new_cheat_val = -1; + } + else + { + cw->new_cheat_val = strtol (entry_text, NULL, 16); + } +} + +static void newCheatEntryCB3 (GtkWidget * widget, cheat_win_t * cw) +{ + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + if (entry_text[0] == 0) + { + cw->new_cheat_cmp = -1; + } + else + { + cw->new_cheat_cmp = strtol (entry_text, NULL, 16); + } +} + +static void newCheatEntryCB4 (GtkWidget * widget, cheat_win_t * cw) +{ + const gchar *entry_text; + entry_text = gtk_entry_get_text (GTK_ENTRY (widget)); + + cw->new_cheat_name.assign (entry_text); +} + +static void addCheat2Active (GtkWidget * widget, cheat_win_t * cw) +{ + + if ((cw->new_cheat_addr >= 0) && (cw->new_cheat_val >= 0)) + { + if (FCEUI_AddCheat + (cw->new_cheat_name.c_str (), cw->new_cheat_addr, + cw->new_cheat_val, cw->new_cheat_cmp, 1)) + { + updateAllActvCheatLists (1); + } + } +} + +static void removeCheatFromActive (GtkWidget * widget, cheat_win_t * cw) +{ + int numListRows; + GList *selListRows, *tmpList; + GtkTreeModel *model = NULL; + GtkTreeSelection *treeSel; + + treeSel = + gtk_tree_view_get_selection (GTK_TREE_VIEW + (cw->actv_cheat_tree)); + + numListRows = gtk_tree_selection_count_selected_rows (treeSel); + + if (numListRows == 0) + { + return; + } + //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) + { + //GtkTreeIter iter; + FCEUI_DelCheat (indexArray[0]); + + //if ( gtk_tree_model_get_iter ( model, &iter, path ) ) + //{ + // gtk_tree_store_remove( actv_cheats_store, &iter ); + //} + } + + tmpList = tmpList->next; + } + + g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free); + + updateAllActvCheatLists (1); +} + +static void updateCheatList (GtkWidget * widget, cheat_win_t * cw) +{ + int numListRows; + GList *selListRows, *tmpList; + GtkTreeModel *model = NULL; + GtkTreeSelection *treeSel; + + treeSel = + gtk_tree_view_get_selection (GTK_TREE_VIEW + (cw->actv_cheat_tree)); + + numListRows = gtk_tree_selection_count_selected_rows (treeSel); + + if (numListRows == 0) + { + return; + } + //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) + { + uint32 a; + uint8 v; + int c, s, type; + const char *name = NULL; + if (FCEUI_GetCheat + (indexArray[0], NULL, &a, &v, &c, &s, &type)) + { + if (cw->new_cheat_addr >= 0) + { + a = cw->new_cheat_addr; + } + if (cw->new_cheat_val >= 0) + { + v = cw->new_cheat_val; + } + if (cw->new_cheat_cmp >= 0) + { + c = cw->new_cheat_cmp; + } + if (cw->new_cheat_name.size ()) + { + name = cw->new_cheat_name.c_str (); + } + FCEUI_SetCheat (indexArray[0], name, a, v, c, s, + type); + } + } + //printf("Depth: %i \n", depth ); + + //for (int i=0; inext; + } + + g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free); + + updateAllActvCheatLists (0); +} + +static void cheat_cell_edited_cb1 (GtkCellRendererText * cell, + gchar * path_string, + gchar * new_text, cheat_win_t * cw) +{ + long int row_idx = -1; + + //printf("'%s'\n", path_string ); + //printf("'%s'\n", new_text ); + //printf("%p\n", user_data ); + + if (isdigit (path_string[0])) + { + row_idx = atoi (path_string); + } + + if (row_idx >= 0) + { + uint32 a; + uint8 v; + int c, s, type; + const char *name = NULL; + if (FCEUI_GetCheat (row_idx, NULL, &a, &v, &c, &s, &type)) + { + a = strtol (new_text, NULL, 0); + FCEUI_SetCheat (row_idx, name, a, v, c, s, type); + updateAllActvCheatLists (0); + } + } +} + +static void cheat_cell_edited_cb2 (GtkCellRendererText * cell, + gchar * path_string, + gchar * new_text, cheat_win_t * cw) +{ + long int row_idx = -1; + + //printf("'%s'\n", path_string ); + //printf("'%s'\n", new_text ); + //printf("%p\n", user_data ); + + if (isdigit (path_string[0])) + { + row_idx = atoi (path_string); + } + + if (row_idx >= 0) + { + uint32 a; + uint8 v; + int c, s, type; + const char *name = NULL; + if (FCEUI_GetCheat (row_idx, NULL, &a, &v, &c, &s, &type)) + { + v = strtol (new_text, NULL, 0); + FCEUI_SetCheat (row_idx, name, a, v, c, s, type); + updateAllActvCheatLists (0); + } + } +} + +static void cheat_cell_edited_cb3 (GtkCellRendererText * cell, + gchar * path_string, + gchar * new_text, cheat_win_t * cw) +{ + long int row_idx = -1; + + //printf("'%s'\n", path_string ); + //printf("'%s'\n", new_text ); + //printf("%p\n", user_data ); + + if (isdigit (path_string[0])) + { + row_idx = atoi (path_string); + } + + if (row_idx >= 0) + { + uint32 a; + uint8 v; + int c, s, type; + const char *name = NULL; + if (FCEUI_GetCheat (row_idx, NULL, &a, &v, &c, &s, &type)) + { + c = strtol (new_text, NULL, 0); + FCEUI_SetCheat (row_idx, name, a, v, c, s, type); + updateAllActvCheatLists (0); + } + } +} + +static void cheat_cell_edited_cb4 (GtkCellRendererText * cell, + gchar * path_string, + gchar * new_text, cheat_win_t * cw) +{ + long int row_idx = -1; + + //printf("'%s'\n", path_string ); + //printf("'%s'\n", new_text ); + //printf("%p\n", user_data ); + + if (isdigit (path_string[0])) + { + row_idx = atoi (path_string); + } + + if (row_idx >= 0) + { + uint32 a; + uint8 v; + int c, s, type; + const char *name = NULL; + if (FCEUI_GetCheat (row_idx, NULL, &a, &v, &c, &s, &type)) + { + name = new_text; + FCEUI_SetCheat (row_idx, name, a, v, c, s, type); + updateAllActvCheatLists (0); + } + } +} + +static void updateAllActvCheatLists (bool redraw) +{ + std::list < cheat_win_t * >::iterator it; + + for (it = cheatWinList.begin (); it != cheatWinList.end (); it++) + { + (*it)->showActiveCheatList (redraw); + } +} + +static void closeCheatDialog (GtkWidget * w, GdkEvent * e, gpointer p) +{ + std::list < cheat_win_t * >::iterator it; + cheat_win_t *cw = (cheat_win_t *) p; + + if (EmulationPaused && cw->wasPausedByCheats) + { + EmulationPaused = 0; + } + + for (it = cheatWinList.begin (); it != cheatWinList.end (); it++) + { + if (cw == *it) + { + //printf("Removing Cheat Window %p from List\n", cw); + cheatWinList.erase (it); + break; + } + } + //printf("Number of Cheat Windows Still Open: %zi\n", cheatWinList.size() ); + + delete cw; + + gtk_widget_destroy (w); +} + +// creates and opens cheats window +void openCheatsWindow (void) +{ + GtkWidget *win; + GtkWidget *main_hbox; + GtkWidget *hbox; + GtkWidget *vbox, *prev_cmp_vbox; + GtkWidget *frame; + GtkWidget *label, *txt_entry; + GtkWidget *button; + GtkWidget *scroll; + + cheat_win_t *cw = new cheat_win_t; + + cheatWinList.push_back (cw); + + win = gtk_dialog_new_with_buttons ("Cheats", + GTK_WINDOW (MainWindow), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Close", GTK_RESPONSE_OK, NULL); + gtk_window_set_default_size (GTK_WINDOW (win), 600, 600); + + cw->win = win; + + main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + frame = gtk_frame_new ("Active Cheats"); + + cw->actv_cheats_store = gtk_tree_store_new (5, G_TYPE_BOOLEAN, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + cw->actv_cheat_tree = + gtk_tree_view_new_with_model (GTK_TREE_MODEL + (cw->actv_cheats_store)); + + GtkCellRenderer *renderer; + GtkCellRenderer *chkbox_renderer; + GtkTreeViewColumn *column; + + g_signal_connect (cw->actv_cheat_tree, "cursor-changed", + G_CALLBACK (cheat_select_rowCB), (gpointer) cw); + + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (cw->actv_cheat_tree), + GTK_TREE_VIEW_GRID_LINES_VERTICAL); + + chkbox_renderer = gtk_cell_renderer_toggle_new (); + gtk_cell_renderer_toggle_set_activatable ((GtkCellRendererToggle *) + chkbox_renderer, TRUE); + column = gtk_tree_view_column_new_with_attributes ("Ena", + chkbox_renderer, + "active", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->actv_cheat_tree), + column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", (GCallback) cheat_cell_edited_cb1, + (gpointer) cw); + column = gtk_tree_view_column_new_with_attributes ("Addr", renderer, + "text", 1, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->actv_cheat_tree), + column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", (GCallback) cheat_cell_edited_cb2, + (gpointer) cw); + column = gtk_tree_view_column_new_with_attributes ("Val", renderer, + "text", 2, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->actv_cheat_tree), + column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", (GCallback) cheat_cell_edited_cb3, + (gpointer) cw); + column = gtk_tree_view_column_new_with_attributes ("Cmp", renderer, + "text", 3, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->actv_cheat_tree), + column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", (GCallback) cheat_cell_edited_cb4, + (gpointer) cw); + column = gtk_tree_view_column_new_with_attributes ("Desc", renderer, + "text", 4, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->actv_cheat_tree), + column); + + g_signal_connect (chkbox_renderer, "toggled", + G_CALLBACK (cheatListEnableToggle), (void *) cw); + + updateAllActvCheatLists (1); + + 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), cw->actv_cheat_tree); + gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + label = gtk_label_new ("Name:"); + cw->cheat_name_entry = gtk_entry_new (); + + g_signal_connect (cw->cheat_name_entry, "activate", + G_CALLBACK (newCheatEntryCB4), (void *) cw); + g_signal_connect (cw->cheat_name_entry, "changed", + G_CALLBACK (newCheatEntryCB4), (void *) cw); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + gtk_box_pack_start (GTK_BOX (hbox), cw->cheat_name_entry, TRUE, TRUE, 1); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + label = gtk_label_new ("Addr:"); + cw->cheat_addr_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (cw->cheat_addr_entry), 4); + gtk_entry_set_width_chars (GTK_ENTRY (cw->cheat_addr_entry), 4); + + g_signal_connect (cw->cheat_addr_entry, "activate", + G_CALLBACK (newCheatEntryCB1), (void *) cw); + g_signal_connect (cw->cheat_addr_entry, "changed", + G_CALLBACK (newCheatEntryCB1), (void *) cw); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + gtk_box_pack_start (GTK_BOX (hbox), cw->cheat_addr_entry, TRUE, TRUE, 1); + + label = gtk_label_new ("Val:"); + cw->cheat_val_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (cw->cheat_val_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (cw->cheat_val_entry), 2); + + g_signal_connect (cw->cheat_val_entry, "activate", + G_CALLBACK (newCheatEntryCB2), (void *) cw); + g_signal_connect (cw->cheat_val_entry, "changed", + G_CALLBACK (newCheatEntryCB2), (void *) cw); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + gtk_box_pack_start (GTK_BOX (hbox), cw->cheat_val_entry, TRUE, TRUE, 1); + + label = gtk_label_new ("Cmp:"); + cw->cheat_cmp_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (cw->cheat_cmp_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (cw->cheat_cmp_entry), 2); + + g_signal_connect (cw->cheat_cmp_entry, "activate", + G_CALLBACK (newCheatEntryCB3), (void *) cw); + g_signal_connect (cw->cheat_cmp_entry, "changed", + G_CALLBACK (newCheatEntryCB3), (void *) cw); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + gtk_box_pack_start (GTK_BOX (hbox), cw->cheat_cmp_entry, TRUE, TRUE, 1); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + button = gtk_button_new_with_label ("Add"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 1); + + g_signal_connect (button, "clicked", + G_CALLBACK (addCheat2Active), (gpointer) cw); + + cw->cheat_del_button = gtk_button_new_with_label ("Delete"); + gtk_box_pack_start (GTK_BOX (hbox), cw->cheat_del_button, TRUE, FALSE, 1); + + gtk_widget_set_sensitive( cw->cheat_del_button, FALSE ); + + g_signal_connect (cw->cheat_del_button, "clicked", + G_CALLBACK (removeCheatFromActive), (gpointer) cw); + + cw->cheat_edit_button = gtk_button_new_with_label ("Update"); + gtk_box_pack_start (GTK_BOX (hbox), cw->cheat_edit_button, TRUE, FALSE, 1); + + gtk_widget_set_sensitive( cw->cheat_edit_button, FALSE ); + + g_signal_connect (cw->cheat_edit_button, "clicked", + G_CALLBACK (updateCheatList), (gpointer) cw); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + button = gtk_button_new_with_label ("Refresh List"); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 1); + g_signal_connect (button, "clicked", + G_CALLBACK (refreshCheatListCB), (gpointer) cw); + + button = gtk_button_new_with_label ("Add from CHT file..."); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, FALSE, 1); + g_signal_connect (button, "clicked", + G_CALLBACK (openCheatFile), (gpointer) cw); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1); + + gtk_container_add (GTK_CONTAINER (frame), vbox); + // + gtk_box_pack_start (GTK_BOX (main_hbox), frame, TRUE, TRUE, 1); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + button = gtk_button_new_with_label ("Reset"); + g_signal_connect (button, "clicked", + G_CALLBACK (cheatSearchReset), (gpointer) cw); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 5); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + button = gtk_button_new_with_label ("Known Value:"); + cw->cheat_search_known_btn = button; + g_signal_connect (button, "clicked", + G_CALLBACK (cheatSearchKnown), (gpointer) cw); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 5); + label = gtk_label_new ("0x"); + txt_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (txt_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (txt_entry), 2); + + g_signal_connect (txt_entry, "activate", + G_CALLBACK (cheatSearchValueEntryCB1), (void *) cw); + g_signal_connect (txt_entry, "changed", + G_CALLBACK (cheatSearchValueEntryCB1), (void *) cw); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox), txt_entry, FALSE, FALSE, 5); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5); + + frame = gtk_frame_new ("Previous Compare"); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 5); + button = gtk_check_button_new_with_label + ("Pause emulation when this window is active"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 5); + g_signal_connect (button, "clicked", + G_CALLBACK (pauseDuringCheatWinActvCB), + (gpointer) cw); + + prev_cmp_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); + gtk_container_add (GTK_CONTAINER (frame), prev_cmp_vbox); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + button = gtk_button_new_with_label ("Equal"); + cw->cheat_search_eq_btn = button; + //gtk_widget_set_halign( button, GTK_ALIGN_BASELINE); + + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); + gtk_box_pack_start (GTK_BOX (prev_cmp_vbox), hbox, FALSE, FALSE, 5); + g_signal_connect (button, "clicked", + G_CALLBACK (cheatSearchEqual), (gpointer) cw); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + button = gtk_button_new_with_label ("Not Equal"); + cw->cheat_search_neq_btn = button; + //gtk_widget_set_halign( button, GTK_ALIGN_BASELINE); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); + cw->neq_chkbox = gtk_check_button_new (); + gtk_box_pack_start (GTK_BOX (hbox), cw->neq_chkbox, FALSE, FALSE, 5); + g_signal_connect (button, "clicked", + G_CALLBACK (cheatSearchNotEqual), (gpointer) cw); + label = gtk_label_new ("By: 0x"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 5); + txt_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (txt_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (txt_entry), 2); + g_signal_connect (txt_entry, "activate", + G_CALLBACK (cheatSearchValueEntryCB2), (void *) cw); + g_signal_connect (txt_entry, "changed", + G_CALLBACK (cheatSearchValueEntryCB2), (void *) cw); + gtk_box_pack_start (GTK_BOX (hbox), txt_entry, FALSE, FALSE, 5); + + gtk_box_pack_start (GTK_BOX (prev_cmp_vbox), hbox, FALSE, FALSE, 5); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + button = gtk_button_new_with_label ("Greater Than"); + cw->cheat_search_gr_btn = button; + //gtk_widget_set_halign( button, GTK_ALIGN_BASELINE); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); + cw->gt_chkbox = gtk_check_button_new (); + g_signal_connect (button, "clicked", + G_CALLBACK (cheatSearchGreaterThan), (gpointer) cw); + gtk_box_pack_start (GTK_BOX (hbox), cw->gt_chkbox, FALSE, FALSE, 5); + label = gtk_label_new ("By: 0x"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 5); + txt_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (txt_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (txt_entry), 2); + g_signal_connect (txt_entry, "activate", + G_CALLBACK (cheatSearchValueEntryCB3), (void *) cw); + g_signal_connect (txt_entry, "changed", + G_CALLBACK (cheatSearchValueEntryCB3), (void *) cw); + gtk_box_pack_start (GTK_BOX (hbox), txt_entry, FALSE, FALSE, 5); + + gtk_box_pack_start (GTK_BOX (prev_cmp_vbox), hbox, FALSE, FALSE, 5); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + button = gtk_button_new_with_label ("Less Than"); + cw->cheat_search_lt_btn = button; + //gtk_widget_set_halign( button, GTK_ALIGN_BASELINE); + gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5); + cw->lt_chkbox = gtk_check_button_new (); + g_signal_connect (button, "clicked", + G_CALLBACK (cheatSearchLessThan), (gpointer) cw); + gtk_box_pack_start (GTK_BOX (hbox), cw->lt_chkbox, FALSE, FALSE, 5); + label = gtk_label_new ("By: 0x"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 5); + txt_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (txt_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (txt_entry), 2); + g_signal_connect (txt_entry, "activate", + G_CALLBACK (cheatSearchValueEntryCB4), (void *) cw); + g_signal_connect (txt_entry, "changed", + G_CALLBACK (cheatSearchValueEntryCB4), (void *) cw); + gtk_box_pack_start (GTK_BOX (hbox), txt_entry, FALSE, FALSE, 5); + + gtk_box_pack_start (GTK_BOX (prev_cmp_vbox), hbox, FALSE, FALSE, 1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 1); + + gtk_widget_set_sensitive( cw->cheat_search_known_btn , FALSE ); + gtk_widget_set_sensitive( cw->cheat_search_eq_btn , FALSE ); + gtk_widget_set_sensitive( cw->cheat_search_neq_btn , FALSE ); + gtk_widget_set_sensitive( cw->cheat_search_gr_btn , FALSE ); + gtk_widget_set_sensitive( cw->cheat_search_lt_btn , FALSE ); + + frame = gtk_frame_new ("Cheat Search"); + gtk_container_add (GTK_CONTAINER (frame), hbox); + gtk_box_pack_start (GTK_BOX (main_hbox), frame, TRUE, TRUE, 5); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + //hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1); + + cw->ram_match_store = + gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING); + + cw->search_cheat_tree = + gtk_tree_view_new_with_model (GTK_TREE_MODEL + (cw->ram_match_store)); + + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (cw->search_cheat_tree), + GTK_TREE_VIEW_GRID_LINES_VERTICAL); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + column = gtk_tree_view_column_new_with_attributes ("Addr", renderer, + "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->search_cheat_tree), + column); + column = gtk_tree_view_column_new_with_attributes ("Last", renderer, + "text", 1, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->search_cheat_tree), + column); + column = gtk_tree_view_column_new_with_attributes ("Curr", renderer, + "text", 2, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (cw->search_cheat_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), cw->search_cheat_tree); + gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 5); + + frame = gtk_frame_new (""); + gtk_container_add (GTK_CONTAINER (frame), vbox); + + gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 5); + + 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 (closeCheatDialog), + cw); + g_signal_connect (win, "response", G_CALLBACK (closeCheatDialog), cw); + + gtk_widget_show_all (win); + + //printf("Added Cheat Window %p. Number of Cheat Windows Open: %zi\n", cw, cheatWinList.size() ); +} diff --git a/src/drivers/sdl/cheat.h b/src/drivers/sdl/cheat.h new file mode 100644 index 00000000..bd3837ba --- /dev/null +++ b/src/drivers/sdl/cheat.h @@ -0,0 +1,3 @@ +// cheat.h + +void openCheatsWindow(void); diff --git a/src/drivers/sdl/config.cpp b/src/drivers/sdl/config.cpp index 3c5b04df..9774e0d0 100644 --- a/src/drivers/sdl/config.cpp +++ b/src/drivers/sdl/config.cpp @@ -26,6 +26,46 @@ #include #include +static const char* HotkeyStrings[HK_MAX] = { + "CheatMenu", + "BindState", + "LoadLua", + "ToggleBG", + "SaveState", + "FDSSelect", + "LoadState", + "FDSEject", + "VSInsertCoin", + "VSToggleDip", + "MovieToggleFrameDisplay", + "SubtitleDisplay", + "Reset", + "Screenshot", + "Pause", + "DecreaseSpeed", + "IncreaseSpeed", + "FrameAdvance", + "Turbo", + "ToggleInputDisplay", + "ToggleMovieRW", + "MuteCapture", + "Quit", + "FrameAdvanceLagSkip", + "LagCounterDisplay", + "SelectState0", "SelectState1", "SelectState2", "SelectState3", + "SelectState4", "SelectState5", "SelectState6", "SelectState7", + "SelectState8", "SelectState9", "SelectStateNext", "SelectStatePrev", + "VolumeDown", "VolumeUp" }; + +const char *getHotkeyString( int i ) +{ + if ( (i>=0) && (iaddOption("SDL.LastXRes", 0); config->addOption("SDL.LastYRes", 0); config->addOption('b', "bpp", "SDL.BitsPerPixel", 32); - config->addOption("doublebuf", "SDL.DoubleBuffering", 0); + config->addOption("doublebuf", "SDL.DoubleBuffering", 1); config->addOption("autoscale", "SDL.AutoScale", 1); config->addOption("keepratio", "SDL.KeepRatio", 1); config->addOption("xscale", "SDL.XScale", 1.0); @@ -179,8 +219,8 @@ InitConfig() config->addOption("togglemenu", "SDL.ToggleMenu", 0); // OpenGL options - config->addOption("opengl", "SDL.OpenGL", 0); - config->addOption("openglip", "SDL.OpenGLip", 0); + config->addOption("opengl", "SDL.OpenGL", 1); + config->addOption("openglip", "SDL.OpenGLip", 1); config->addOption("SDL.SpecialFilter", 0); config->addOption("SDL.SpecialFX", 0); config->addOption("SDL.Vsync", 1); @@ -269,9 +309,10 @@ InitConfig() config->addOption("4buttonexit", "SDL.ABStartSelectExit", 0); // GamePad 0 - 3 - for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) { + for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) + { char buf[64]; - snprintf(buf, 20, "SDL.Input.GamePad.%d.", i); + snprintf(buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i); prefix = buf; config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]); @@ -284,7 +325,7 @@ InitConfig() // PowerPad 0 - 1 for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { char buf[64]; - snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i); + snprintf(buf, sizeof(buf)-1, "SDL.Input.PowerPad.%u.", i); prefix = buf; config->addOption(prefix + "DeviceType", DefaultPowerPadDevice[i]); diff --git a/src/drivers/sdl/config.h b/src/drivers/sdl/config.h index 17001111..dbf6a0b6 100644 --- a/src/drivers/sdl/config.h +++ b/src/drivers/sdl/config.h @@ -22,36 +22,7 @@ enum HOTKEY { HK_CHEAT_MENU=0, HK_BIND_STATE, HK_LOAD_LUA, HK_TOGGLE_BG, HK_SELECT_STATE_NEXT, HK_SELECT_STATE_PREV, HK_VOLUME_DOWN, HK_VOLUME_UP, HK_MAX}; +const char *getHotkeyString( int i ); -static const char* HotkeyStrings[HK_MAX] = { - "CheatMenu", - "BindState", - "LoadLua", - "ToggleBG", - "SaveState", - "FDSSelect", - "LoadState", - "FDSEject", - "VSInsertCoin", - "VSToggleDip", - "MovieToggleFrameDisplay", - "SubtitleDisplay", - "Reset", - "Screenshot", - "Pause", - "DecreaseSpeed", - "IncreaseSpeed", - "FrameAdvance", - "Turbo", - "ToggleInputDisplay", - "ToggleMovieRW", - "MuteCapture", - "Quit", - "FrameAdvanceLagSkip", - "LagCounterDisplay", - "SelectState0", "SelectState1", "SelectState2", "SelectState3", - "SelectState4", "SelectState5", "SelectState6", "SelectState7", - "SelectState8", "SelectState9", "SelectStateNext", "SelectStatePrev", - "VolumeDown", "VolumeUp" }; #endif diff --git a/src/drivers/sdl/debugger.cpp b/src/drivers/sdl/debugger.cpp new file mode 100644 index 00000000..c5982e24 --- /dev/null +++ b/src/drivers/sdl/debugger.cpp @@ -0,0 +1,2290 @@ +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#ifdef _GTK3 +#include +#endif + +#include "../../types.h" +#include "../../fceu.h" +#include "../../cheat.h" +#include "../../debug.h" +#include "../../driver.h" +#include "../../version.h" +#include "../../video.h" +#include "../../movie.h" +#include "../../palette.h" +#include "../../fds.h" +#include "../../cart.h" +#include "../../ines.h" +#include "../../asm.h" +#include "../../ppu.h" +#include "../../x6502.h" +#include "../common/configSys.h" + +#include "sdl.h" +#include "gui.h" +#include "dface.h" +#include "input.h" +#include "config.h" +#include "debugger.h" + +extern Config *g_config; +extern int vblankScanLines; +extern int vblankPixel; + +static int breakpoint_hit = 0; +static void updateAllDebugWindows(void); +//******************************************************************************************************* +// Debugger Window +//******************************************************************************************************* +// + +struct dbg_asm_entry_t +{ + int addr; + int bank; + int rom; + int size; + int line; + uint8 opcode[3]; + std::string text; + + + dbg_asm_entry_t(void) + { + addr = 0; bank = 0; rom = -1; + size = 0; line = 0; + + for (int i=0; i<3; i++) + { + opcode[i] = 0; + } + } +}; + +struct debuggerWin_t +{ + GtkWidget *win; + GtkTextView *textview; + GtkTextBuffer *textbuf; + GtkTextView *stackview; + GtkTextBuffer *stackTextBuf; + GtkTreeStore *bp_store; + GtkTreeStore *bkm_store; + GtkWidget *bp_tree; + GtkWidget *bkm_tree; + GtkWidget *pc_entry; + GtkWidget *A_entry; + GtkWidget *X_entry; + GtkWidget *Y_entry; + GtkWidget *P_N_chkbox; + GtkWidget *P_V_chkbox; + GtkWidget *P_U_chkbox; + GtkWidget *P_B_chkbox; + GtkWidget *P_D_chkbox; + GtkWidget *P_I_chkbox; + GtkWidget *P_Z_chkbox; + GtkWidget *P_C_chkbox; + GtkWidget *add_bp_button; + GtkWidget *edit_bp_button; + GtkWidget *del_bp_button; + GtkWidget *stack_frame; + GtkWidget *ppu_label; + GtkWidget *sprite_label; + GtkWidget *scanline_label; + GtkWidget *pixel_label; + GtkWidget *cpu_label1; + GtkWidget *cpu_label2; + GtkWidget *instr_label1; + GtkWidget *instr_label2; + GtkWidget *bp_start_entry; + GtkWidget *bp_end_entry; + GtkWidget *bp_read_chkbox; + GtkWidget *bp_write_chkbox; + GtkWidget *bp_execute_chkbox; + GtkWidget *bp_enable_chkbox; + GtkWidget *bp_forbid_chkbox; + GtkWidget *bp_cond_entry; + GtkWidget *bp_name_entry; + GtkWidget *cpu_radio_btn; + GtkWidget *ppu_radio_btn; + GtkWidget *sprite_radio_btn; + GtkWidget *badop_chkbox; + GtkWidget *brkcycles_chkbox; + GtkWidget *brkinstrs_chkbox; + GtkWidget *brk_cycles_lim_entry; + GtkWidget *brk_instrs_lim_entry; + GtkWidget *seektoEntry; + + int dialog_op; + int bpEditIdx; + int ctx_menu_addr; + char displayROMoffsets; + + dbg_asm_entry_t *asmPC; + std::vector asmEntry; + + debuggerWin_t(void) + { + win = NULL; + textview = NULL; + textbuf = NULL; + bp_store = NULL; + bp_tree = NULL; + bkm_store = NULL; + bkm_tree = NULL; + pc_entry = NULL; + A_entry = NULL; + X_entry = NULL; + Y_entry = NULL; + stackview = NULL; + stackTextBuf = NULL; + ppu_label = NULL; + sprite_label = NULL; + scanline_label = NULL; + pixel_label = NULL; + cpu_label1 = NULL; + cpu_label2 = NULL; + instr_label1 = NULL; + instr_label2 = NULL; + bp_start_entry = NULL; + bp_end_entry = NULL; + bp_cond_entry = NULL; + bp_name_entry = NULL; + bp_read_chkbox = NULL; + bp_write_chkbox = NULL; + bp_execute_chkbox = NULL; + bp_enable_chkbox = NULL; + bp_forbid_chkbox = NULL; + add_bp_button = NULL; + edit_bp_button = NULL; + del_bp_button = NULL; + cpu_radio_btn = NULL; + ppu_radio_btn = NULL; + sprite_radio_btn = NULL; + stack_frame = NULL; + P_N_chkbox = NULL; + P_V_chkbox = NULL; + P_U_chkbox = NULL; + P_B_chkbox = NULL; + P_D_chkbox = NULL; + P_I_chkbox = NULL; + P_Z_chkbox = NULL; + P_C_chkbox = NULL; + badop_chkbox = NULL; + brkcycles_chkbox = NULL; + brkinstrs_chkbox = NULL; + brk_cycles_lim_entry = NULL; + brk_instrs_lim_entry = NULL; + seektoEntry = NULL; + dialog_op = 0; + bpEditIdx = -1; + ctx_menu_addr = 0; + displayROMoffsets = 0; + asmPC = NULL; + } + + ~debuggerWin_t(void) + { + asmClear(); + } + + void asmClear(void); + void bpListUpdate(void); + void updateViewPort(void); + void updateRegisterView(void); + void updateAssemblyView(void); + int get_bpList_selrow(void); + int getAsmLineFromAddr(int addr); + int scrollAsmLine(int line); + int seekAsmPC(void); + int seekAsmAddr(int addr); + void setRegsFromEntry(void); +}; + +static std::list debuggerWinList; + +void debuggerWin_t::setRegsFromEntry(void) +{ + X.PC = strtol( gtk_entry_get_text( GTK_ENTRY( pc_entry ) ), NULL, 16 ); + X.A = strtol( gtk_entry_get_text( GTK_ENTRY( A_entry ) ), NULL, 16 ); + X.X = strtol( gtk_entry_get_text( GTK_ENTRY( X_entry ) ), NULL, 16 ); + X.Y = strtol( gtk_entry_get_text( GTK_ENTRY( Y_entry ) ), NULL, 16 ); +} + +void debuggerWin_t::asmClear(void) +{ + for (size_t i=0; iaddr ) + { + return 0; + } + else if ( addr > asmEntry[ asmEntry.size() - 1 ]->addr ) + { + return asmEntry.size() - 1; + } + + if ( incr < 1 ) incr = 1; + + nextLine = line = incr; + + // algorithm to efficiently find line from address. Starts in middle of list and + // keeps dividing the list in 2 until it arrives at an answer. + while ( run ) + { + //printf("incr:%i line:%i addr:%04X delta:%i\n", incr, line, asmEntry[line]->addr, addr - asmEntry[line]->addr); + + if ( incr == 1 ) + { + if ( asmEntry[line]->addr < addr ) + { + nextLine = line + 1; + if ( asmEntry[line]->addr > nextLine ) + { + break; + } + line = nextLine; + } + else if ( asmEntry[line]->addr > addr ) + { + nextLine = line - 1; + if ( asmEntry[line]->addr < nextLine ) + { + break; + } + line = nextLine; + } + else + { + run = 0; break; + } + } + else + { + incr = incr / 2; + if ( incr < 1 ) incr = 1; + + if ( asmEntry[line]->addr < addr ) + { + nextLine = line + incr; + } + else if ( asmEntry[line]->addr > addr ) + { + nextLine = line - incr; + } + else + { + run = 0; break; + } + line = nextLine; + } + } + + //for (size_t i=0; iaddr >= addr ) + // { + // line = i; break; + // } + //} + + return line; +} + +int debuggerWin_t::scrollAsmLine(int line) +{ + GtkTextIter iter; + + if ( line < 0 ) + { + return -1; + } + gtk_text_buffer_get_iter_at_line( textbuf, &iter, line ); + gtk_text_view_scroll_to_iter ( textview, &iter, 0.0, 1, 0.0, 0.50 ); + gtk_text_buffer_place_cursor( textbuf, &iter ); + + return 0; +} + +int debuggerWin_t::seekAsmPC(void) +{ + int line; + + if ( asmPC == NULL ) + { + line = getAsmLineFromAddr( X.PC ); + } + else + { + line = asmPC->line; + } + + scrollAsmLine( line ); + + return 0; +} + +int debuggerWin_t::seekAsmAddr( int addr ) +{ + int line; + + line = getAsmLineFromAddr( addr ); + + scrollAsmLine( line ); + + return 0; +} + +int debuggerWin_t::get_bpList_selrow(void) +{ + int retval = -1, numListRows; + GList *selListRows, *tmpList; + GtkTreeModel *model = NULL; + GtkTreeSelection *treeSel; + + treeSel = + gtk_tree_view_get_selection (GTK_TREE_VIEW(bp_tree) ); + + numListRows = gtk_tree_selection_count_selected_rows (treeSel); + + if (numListRows == 0) + { + return retval; + } + //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) + { + retval = indexArray[0]; + break; + } + tmpList = tmpList->next; + } + + g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free); + + return retval; +} + +void debuggerWin_t::bpListUpdate(void) +{ + GtkTreeIter iter; + char line[256], addrStr[32], flags[16], enable; + + gtk_tree_store_clear( bp_store ); + + for (int i=0; i 0 ) + { + sprintf( addrStr, "$%04X-%04X:", watchpoint[i].address, watchpoint[i].endaddress ); + } + else + { + sprintf( addrStr, "$%04X:", watchpoint[i].address ); + } + + flags[0] = (watchpoint[i].flags & WP_E) ? 'E' : '-'; + + if ( watchpoint[i].flags & BT_P ) + { + flags[1] = 'P'; + } + else if ( watchpoint[i].flags & BT_S ) + { + flags[1] = 'S'; + } + else + { + flags[1] = 'C'; + } + + flags[2] = (watchpoint[i].flags & WP_R) ? 'R' : '-'; + flags[3] = (watchpoint[i].flags & WP_W) ? 'W' : '-'; + flags[4] = (watchpoint[i].flags & WP_X) ? 'X' : '-'; + flags[5] = (watchpoint[i].flags & WP_F) ? 'F' : '-'; + flags[6] = 0; + + enable = (watchpoint[i].flags & WP_E) ? 1 : 0; + + strcpy( line, addrStr ); + strcat( line, flags ); + + if (watchpoint[i].desc ) + { + strcat( line, " "); + strcat( line, watchpoint[i].desc); + strcat( line, " "); + } + + if (watchpoint[i].condText ) + { + strcat( line, " Condition:"); + strcat( line, watchpoint[i].condText); + strcat( line, " "); + } + gtk_tree_store_set( bp_store, &iter, 0, enable, 1, line, -1 ); + } + +} + +void debuggerWin_t::updateRegisterView(void) +{ + int stackPtr; + char stmp[64]; + char str[32], str2[32]; + std::string stackLine; + + sprintf( stmp, "%04X", X.PC ); + + gtk_entry_set_text( GTK_ENTRY(pc_entry), stmp ); + + sprintf( stmp, "%02X", X.A ); + + gtk_entry_set_text( GTK_ENTRY(A_entry), stmp ); + + sprintf( stmp, "%02X", X.X ); + + gtk_entry_set_text( GTK_ENTRY(X_entry), stmp ); + + sprintf( stmp, "%02X", X.Y ); + + gtk_entry_set_text( GTK_ENTRY(Y_entry), stmp ); + + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_N_chkbox ), (X.P & N_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_V_chkbox ), (X.P & V_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_U_chkbox ), (X.P & U_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_B_chkbox ), (X.P & B_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_D_chkbox ), (X.P & D_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_I_chkbox ), (X.P & I_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_Z_chkbox ), (X.P & Z_FLAG) ? TRUE : FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( P_C_chkbox ), (X.P & C_FLAG) ? TRUE : FALSE ); + + stackPtr = X.S | 0x0100; + + sprintf( stmp, "Stack: %04X", stackPtr ); + gtk_frame_set_label( GTK_FRAME(stack_frame), stmp ); + + stackPtr++; + + if ( stackPtr <= 0x01FF ) + { + sprintf( stmp, "%02X", GetMem(stackPtr) ); + + stackLine.assign( stmp ); + + for (int i = 1; i < 128; i++) + { + //tmp = ((tmp+1)|0x0100)&0x01FF; //increment and fix pointer to $0100-$01FF range + stackPtr++; + if (stackPtr > 0x1FF) + break; + if ((i & 7) == 0) + sprintf( stmp, ",\r\n%02X", GetMem(stackPtr) ); + else + sprintf( stmp, ",%02X", GetMem(stackPtr) ); + + stackLine.append( stmp ); + } + } + + gtk_text_buffer_set_text( stackTextBuf, stackLine.c_str(), -1 ) ; + + // update counters + int64 counter_value = timestampbase + (uint64)timestamp - total_cycles_base; + if (counter_value < 0) // sanity check + { + ResetDebugStatisticsCounters(); + counter_value = 0; + } + sprintf( stmp, "CPU Cycles: %llu", counter_value); + + gtk_label_set_text( GTK_LABEL(cpu_label1), stmp ); + + //SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_CYCLES_COUNT, str); + counter_value = timestampbase + (uint64)timestamp - delta_cycles_base; + if (counter_value < 0) // sanity check + { + ResetDebugStatisticsCounters(); + counter_value = 0; + } + sprintf(stmp, "(+%llu)", counter_value); + + gtk_label_set_text( GTK_LABEL(cpu_label2), stmp ); + + sprintf(stmp, "Instructions: %llu", total_instructions); + gtk_label_set_text( GTK_LABEL(instr_label1), stmp ); + + sprintf(stmp, "(+%llu)", delta_instructions); + gtk_label_set_text( GTK_LABEL(instr_label2), stmp ); + + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(badop_chkbox ), FCEUI_Debugger().badopbreak ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(brkcycles_chkbox), break_on_cycles ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(brkinstrs_chkbox), break_on_instructions ); + + sprintf(stmp, "%llu", break_cycles_limit); + gtk_entry_set_text( GTK_ENTRY(brk_cycles_lim_entry), stmp ); + + sprintf(stmp, "%llu", break_instructions_limit); + gtk_entry_set_text( GTK_ENTRY(brk_instrs_lim_entry), stmp ); + + sprintf(stmp, "PPU: 0x%04X", (int)FCEUPPU_PeekAddress()); + gtk_label_set_text( GTK_LABEL(ppu_label), stmp ); + + sprintf(stmp, "Sprite: 0x%02X", PPU[3] ); + gtk_label_set_text( GTK_LABEL(sprite_label), stmp ); + + extern int linestartts; + #define GETLASTPIXEL (PAL?((timestamp*48-linestartts)/15) : ((timestamp*48-linestartts)/16) ) + + int ppupixel = GETLASTPIXEL; + + if (ppupixel>341) //maximum number of pixels per scanline + ppupixel = 0; //Currently pixel display is borked until Run 128 lines is clicked, this keeps garbage from displaying + + // If not in the 0-239 pixel range, make special cases for display + if (scanline == 240 && vblankScanLines < (PAL?72:22)) + { + if (!vblankScanLines) + { + // Idle scanline (240) + sprintf(str, "%d", scanline); // was "Idle %d" + } else if (scanline + vblankScanLines == (PAL?311:261)) + { + // Pre-render + sprintf(str, "-1"); // was "Prerender -1" + } else + { + // Vblank lines (241-260/310) + sprintf(str, "%d", scanline + vblankScanLines); // was "Vblank %d" + } + sprintf(str2, "%d", vblankPixel); + } else + { + // Scanlines 0 - 239 + sprintf(str, "%d", scanline); + sprintf(str2, "%d", ppupixel); + } + + if(newppu) + { + sprintf(str ,"%d",newppu_get_scanline()); + sprintf(str2,"%d",newppu_get_dot()); + } + + sprintf( stmp, "Scanline: %s", str ); + gtk_label_set_text( GTK_LABEL(scanline_label), stmp ); + + sprintf( stmp, "Pixel: %s", str2 ); + gtk_label_set_text( GTK_LABEL(pixel_label), stmp ); + +} + +// This function is for "smart" scrolling... +// it attempts to scroll up one line by a whole instruction +static int InstructionUp(int from) +{ + int i = std::min(16, from), j; + + while (i > 0) + { + j = i; + while (j > 0) + { + if (GetMem(from - j) == 0x00) + break; // BRK usually signifies data + if (opsize[GetMem(from - j)] == 0) + break; // invalid instruction! + if (opsize[GetMem(from - j)] > j) + break; // instruction is too long! + if (opsize[GetMem(from - j)] == j) + return (from - j); // instruction is just right! :D + j -= opsize[GetMem(from - j)]; + } + i--; + } + + // if we get here, no suitable instruction was found + if ((from >= 2) && (GetMem(from - 2) == 0x00)) + return (from - 2); // if a BRK instruction is possible, use that + if (from) + return (from - 1); // else, scroll up one byte + return 0; // of course, if we can't scroll up, just return 0! +} +//static int InstructionDown(int from) +//{ +// int tmp = opsize[GetMem(from)]; +// if ((tmp)) +// return from + tmp; +// else +// return from + 1; // this is data or undefined instruction +//} + +void debuggerWin_t::updateAssemblyView(void) +{ + int starting_address, start_address_lp, addr, size; + int instruction_addr, textview_lines_allocated; + std::string line; + char chr[64]; + uint8 opcode[3]; + const char *disassemblyText = NULL; + dbg_asm_entry_t *a; + GtkTextIter iter, next_iter; + char pc_found = 0; + + start_address_lp = starting_address = X.PC; + + for (int i=0; i < 0xFFFF; i++) + { + //printf("%i: Start Address: 0x%04X \n", i, start_address_lp ); + + starting_address = InstructionUp( start_address_lp ); + + if ( starting_address == start_address_lp ) + { + break; + } + if ( starting_address < 0x8000 ) + { + starting_address = start_address_lp; + break; + } + start_address_lp = starting_address; + } + + asmClear(); + + addr = starting_address; + asmPC = NULL; + + gtk_text_buffer_get_start_iter( textbuf, &iter ); + + textview_lines_allocated = gtk_text_buffer_get_line_count( textbuf ) - 1; + + //printf("Num Lines: %i\n", textview_lines_allocated ); + + for (int i=0; i < 0xFFFF; i++) + { + line.clear(); + + // PC pointer + if (addr > 0xFFFF) break; + + a = new dbg_asm_entry_t; + + instruction_addr = addr; + + if ( !pc_found ) + { + if (addr > X.PC) + { + asmPC = a; + line.assign(">"); + pc_found = 1; + } + else if (addr == X.PC) + { + asmPC = a; + line.assign(">"); + pc_found = 1; + } + else + { + line.assign(" "); + } + } + else + { + line.assign(" "); + } + a->addr = addr; + + if (addr >= 0x8000) + { + a->bank = getBank(addr); + a->rom = GetNesFileAddress(addr); + + if (displayROMoffsets && (a->rom != -1) ) + { + sprintf(chr, " %06X: ", a->rom); + } + else + { + sprintf(chr, "%02X:%04X: ", a->bank, addr); + } + } + else + { + sprintf(chr, " :%04X: ", addr); + } + line.append(chr); + + size = opsize[GetMem(addr)]; + if (size == 0) + { + sprintf(chr, "%02X UNDEFINED", GetMem(addr++)); + line.append(chr); + } else + { + if ((addr + size) > 0xFFFF) + { + while (addr < 0xFFFF) + { + sprintf(chr, "%02X OVERFLOW\n", GetMem(addr++)); + line.append(chr); + } + break; + } + for (int j = 0; j < size; j++) + { + sprintf(chr, "%02X ", opcode[j] = GetMem(addr++)); + line.append(chr); + } + while (size < 3) + { + line.append(" "); //pad output to align ASM + size++; + } + + disassemblyText = Disassemble(addr, opcode); + + if ( disassemblyText ) + { + line.append( disassemblyText ); + } + } + for (int j=0; jopcode[j] = opcode[j]; + } + a->size = size; + + // special case: an RTS opcode + if (GetMem(instruction_addr) == 0x60) + { + line.append("-------------------------"); + } + + a->text.assign( line ); + + a->line = asmEntry.size(); + + if ( i < textview_lines_allocated ) + { + char *txt; + + //gtk_text_buffer_get_iter_at_line( textbuf, &iter, i ); + + next_iter = iter; + + gtk_text_iter_forward_to_line_end( &next_iter ); + + //gtk_text_iter_backward_chars( &next_iter, -1 ); + txt = gtk_text_buffer_get_text( textbuf, &iter, &next_iter, FALSE); + + if ( strcmp( txt, line.c_str() ) != 0 ) + { + //printf("Text is the diff\n%s\n", txt); + + gtk_text_buffer_delete( textbuf, &iter, &next_iter ); + + gtk_text_buffer_insert( textbuf, &iter, line.c_str(), -1 ); + } + else + { + iter = next_iter; + } + gtk_text_iter_forward_chars( &iter, 1 ); + + g_free(txt); + } + else + { + line.append("\n"); + + gtk_text_buffer_insert( textbuf, &iter, line.c_str(), -1 ); + //gtk_text_buffer_get_end_iter( textbuf, &iter ); + } + + asmEntry.push_back(a); + } + +} + +void debuggerWin_t::updateViewPort(void) +{ + updateRegisterView(); + updateAssemblyView(); + bpListUpdate(); +} + +static void handleDialogResponse (GtkWidget * w, gint response_id, debuggerWin_t * dw) +{ + //printf("Response %i\n", response_id ); + + if ( response_id == GTK_RESPONSE_OK ) + { + const char *txt; + + ////printf("Reponse OK\n"); + switch ( dw->dialog_op ) + { + case 1: // Breakpoint Add + case 2: // Breakpoint Edit + { + int start_addr = -1, end_addr = -1, type = 0, enable = 1, slot; + const char *name; + const char *cond; + + slot = (dw->dialog_op == 1) ? numWPs : dw->bpEditIdx; + + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->cpu_radio_btn ) ) ) + { + type |= BT_C; + } + else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->ppu_radio_btn ) ) ) + { + type |= BT_P; + } + else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->sprite_radio_btn ) ) ) + { + type |= BT_S; + } + + txt = gtk_entry_get_text( GTK_ENTRY( dw->bp_start_entry ) ); + + if ( txt[0] != 0 ) + { + start_addr = offsetStringToInt( type, txt ); + } + + txt = gtk_entry_get_text( GTK_ENTRY( dw->bp_end_entry ) ); + + if ( txt[0] != 0 ) + { + end_addr = offsetStringToInt( type, txt ); + } + + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->bp_read_chkbox ) ) ) + { + type |= WP_R; + } + + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->bp_write_chkbox ) ) ) + { + type |= WP_W; + } + + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->bp_execute_chkbox ) ) ) + { + type |= WP_X; + } + + //this overrides all + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->bp_forbid_chkbox ) ) ) + { + type = WP_F; + } + + enable = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( dw->bp_enable_chkbox ) ); + + name = gtk_entry_get_text( GTK_ENTRY( dw->bp_name_entry ) ); + cond = gtk_entry_get_text( GTK_ENTRY( dw->bp_cond_entry ) ); + + if ( (start_addr >= 0) && (numWPs < 64) ) + { + unsigned int retval; + + retval = NewBreak( name, start_addr, end_addr, type, cond, slot, enable); + + if ( (retval == 1) || (retval == 2) ) + { + printf("Breakpoint Add Failed\n"); + } + else + { + if (dw->dialog_op == 1) + { + numWPs++; + } + + dw->bpListUpdate(); + } + } + } + break; + default: + // Do Nothing + break; + } + } + //else if ( response_id == GTK_RESPONSE_CANCEL ) + //{ + // printf("Reponse Cancel\n"); + //} + gtk_widget_destroy (w); + +} + +static void +tree_select_rowCB (GtkTreeView *treeview, + debuggerWin_t * dw ) +{ + int row, row_is_selected; + + row = dw->get_bpList_selrow(); + + row_is_selected = (row >= 0); + + //printf("Selected row = %i\n", row); + + gtk_widget_set_sensitive( dw->del_bp_button , row_is_selected ); + gtk_widget_set_sensitive( dw->edit_bp_button, row_is_selected ); +} + +static void closeDialogWindow (GtkWidget * w, GdkEvent * e, debuggerWin_t * dw) +{ + gtk_widget_destroy (w); +} + +static void create_breakpoint_dialog( int index, watchpointinfo *wp, debuggerWin_t * dw ) +{ + GtkWidget *win; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *vbox1; + GtkWidget *label; + GtkWidget *frame; + GtkWidget *grid; + char stmp[64]; + + if ( index < 0 ) + { + dw->dialog_op = 1; + + win = gtk_dialog_new_with_buttons ("Add Breakpoint", + GTK_WINDOW (dw->win), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Cancel", GTK_RESPONSE_CANCEL, + "_Add", GTK_RESPONSE_OK, NULL); + } + else + { + dw->dialog_op = 2; + + win = gtk_dialog_new_with_buttons ("Edit Breakpoint", + GTK_WINDOW (dw->win), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Cancel", GTK_RESPONSE_CANCEL, + "_Edit", GTK_RESPONSE_OK, NULL); + + dw->bpEditIdx = index; + } + + gtk_dialog_set_default_response( GTK_DIALOG(win), GTK_RESPONSE_OK ); + + vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + + // Adress entry fields + label = gtk_label_new("Address:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); + + dw->bp_start_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->bp_start_entry), 4); + gtk_entry_set_width_chars (GTK_ENTRY (dw->bp_start_entry), 4); + + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_start_entry, TRUE, TRUE, 2); + + label = gtk_label_new("-"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); + + dw->bp_end_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->bp_end_entry), 4); + gtk_entry_set_width_chars (GTK_ENTRY (dw->bp_end_entry), 4); + + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_end_entry, TRUE, TRUE, 2); + + dw->bp_forbid_chkbox = gtk_check_button_new_with_label("Forbid"); + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_forbid_chkbox, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX (vbox1), hbox, FALSE, FALSE, 2); + + // flags frame + frame = gtk_frame_new (""); + gtk_box_pack_start (GTK_BOX (vbox1), frame, FALSE, FALSE, 2); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + + dw->bp_read_chkbox = gtk_check_button_new_with_label("Read"); + dw->bp_write_chkbox = gtk_check_button_new_with_label("Write"); + dw->bp_execute_chkbox = gtk_check_button_new_with_label("Execute"); + dw->bp_enable_chkbox = gtk_check_button_new_with_label("Enable"); + + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_read_chkbox , FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_write_chkbox , FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_execute_chkbox, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), dw->bp_enable_chkbox , FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX (vbox), hbox , FALSE, FALSE, 2); + + gtk_container_add (GTK_CONTAINER (frame), vbox); + + frame = gtk_frame_new ("Memory"); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 2); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + + dw->cpu_radio_btn = gtk_radio_button_new_with_label (NULL, "CPU"); + dw->ppu_radio_btn = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(dw->cpu_radio_btn), "PPU"); + dw->sprite_radio_btn = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON(dw->cpu_radio_btn), "Sprite"); + + gtk_box_pack_start (GTK_BOX (hbox), dw->cpu_radio_btn , TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (hbox), dw->ppu_radio_btn , TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (hbox), dw->sprite_radio_btn, TRUE, TRUE, 2); + + gtk_container_add (GTK_CONTAINER (frame), hbox); + + grid = gtk_grid_new(); + + gtk_grid_set_row_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_column_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_row_spacing( GTK_GRID(grid), 5 ); + gtk_grid_set_column_spacing( GTK_GRID(grid), 10 ); + + label = gtk_label_new("Condition:"); + gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1 ); + + label = gtk_label_new("Name:"); + gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1 ); + + dw->bp_cond_entry = gtk_entry_new (); + dw->bp_name_entry = gtk_entry_new (); + + gtk_grid_attach (GTK_GRID (grid), dw->bp_cond_entry, 1, 0, 3, 1 ); + gtk_grid_attach (GTK_GRID (grid), dw->bp_name_entry, 1, 1, 3, 1 ); + + gtk_box_pack_start (GTK_BOX (vbox1), grid, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (win))), vbox1, TRUE, TRUE, 1); + + gtk_widget_show_all (win); + + g_signal_connect (win, "delete-event", + G_CALLBACK (closeDialogWindow), dw); + g_signal_connect (win, "response", + G_CALLBACK (handleDialogResponse), dw); + + if ( wp != NULL ) + { // Sync entries to passed in breakpoint + if ( wp->flags & BT_P ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->ppu_radio_btn ), TRUE ); + } + else if ( wp->flags & BT_S ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->sprite_radio_btn ), TRUE ); + } + else + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->cpu_radio_btn ), TRUE ); + } + + sprintf( stmp, "%04X", wp->address ); + + gtk_entry_set_text (GTK_ENTRY (dw->bp_start_entry), stmp ); + + if ( wp->endaddress > 0 ) + { + sprintf( stmp, "%04X", wp->endaddress ); + + gtk_entry_set_text (GTK_ENTRY (dw->bp_end_entry), stmp ); + } + + if ( wp->flags & WP_R ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_read_chkbox ), TRUE ); + } + if ( wp->flags & WP_W ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_write_chkbox ), TRUE ); + } + if ( wp->flags & WP_X ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_execute_chkbox ), TRUE ); + } + if ( wp->flags & WP_F ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_forbid_chkbox ), TRUE ); + } + if ( wp->flags & WP_E ) + { + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_enable_chkbox ), TRUE ); + } + + if ( wp->condText ) + { + gtk_entry_set_text (GTK_ENTRY (dw->bp_cond_entry), wp->condText ); + } + + if ( wp->desc ) + { + gtk_entry_set_text (GTK_ENTRY (dw->bp_name_entry), wp->desc ); + } + } + else + { // New entry, fill in current PC + sprintf( stmp, "%04X", X.PC ); + + gtk_entry_set_text (GTK_ENTRY (dw->bp_start_entry), stmp ); + + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_enable_chkbox ), TRUE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( dw->bp_execute_chkbox ), TRUE ); + } +} + +static void addBreakpointCB (GtkButton * button, debuggerWin_t * dw) +{ + create_breakpoint_dialog( -1, NULL, dw ); +} + +static void editBreakpointCB (GtkButton * button, debuggerWin_t * dw) +{ + int selRow; + + selRow = dw->get_bpList_selrow(); + + if ( selRow >= 0 ) + { + create_breakpoint_dialog( selRow, &watchpoint[selRow], dw ); + } +} + +static void enableBreakpointCB (GtkCellRendererToggle * renderer, + gchar * pathStr, debuggerWin_t * dw) +{ + GtkTreePath *path; + int depth; + int *indexArray; + + path = gtk_tree_path_new_from_string (pathStr); + + if (path == NULL) + { + printf ("Error: gtk_tree_path_new_from_string failed\n"); + return; + } + + depth = gtk_tree_path_get_depth (path); + indexArray = gtk_tree_path_get_indices (path); + + if (depth > 0) + { + if ( !gtk_cell_renderer_toggle_get_active(renderer) ) + { + //printf("Toggle: %i On\n", indexArray[0] ); + watchpoint[indexArray[0]].flags |= WP_E; + } + else + { + //printf("Toggle: %i Off\n", indexArray[0] ); + watchpoint[indexArray[0]].flags &= ~WP_E; + } + } + + gtk_tree_path_free (path); + + dw->bpListUpdate(); +} + +static void DeleteBreak(int sel) +{ + if(sel<0) return; + if(sel>=numWPs) return; + if (watchpoint[sel].cond) + { + freeTree(watchpoint[sel].cond); + } + if (watchpoint[sel].condText) + { + free(watchpoint[sel].condText); + } + if (watchpoint[sel].desc) + { + free(watchpoint[sel].desc); + } + // move all BP items up in the list + for (int i = sel; i < numWPs; i++) + { + watchpoint[i].address = watchpoint[i+1].address; + watchpoint[i].endaddress = watchpoint[i+1].endaddress; + watchpoint[i].flags = watchpoint[i+1].flags; +// ################################## Start of SP CODE ########################### + watchpoint[i].cond = watchpoint[i+1].cond; + watchpoint[i].condText = watchpoint[i+1].condText; + watchpoint[i].desc = watchpoint[i+1].desc; +// ################################## End of SP CODE ########################### + } + // erase last BP item + watchpoint[numWPs].address = 0; + watchpoint[numWPs].endaddress = 0; + watchpoint[numWPs].flags = 0; + watchpoint[numWPs].cond = 0; + watchpoint[numWPs].condText = 0; + watchpoint[numWPs].desc = 0; + numWPs--; +} + +static void deleteBreakpointCB (GtkButton * button, debuggerWin_t * dw) +{ + int selRow; + + selRow = dw->get_bpList_selrow(); + + if ( (selRow >= 0) && (selRow < numWPs) ) + { + DeleteBreak( selRow ); + dw->bpListUpdate(); + } +} + +static void debugRunCB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + FCEUI_ToggleEmulationPause(); + //DebuggerWasUpdated = false done in above function; + } +} + +static void debugStepIntoCB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + } + FCEUI_Debugger().step = true; + FCEUI_SetEmulationPaused(0); +} + +static void debugStepOutCB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused() > 0) + { + DebuggerState &dbgstate = FCEUI_Debugger(); + dw->setRegsFromEntry(); + if (dbgstate.stepout) + { + printf("Step Out is currently in process.\n"); + return; + } + if (GetMem(X.PC) == 0x20) + { + dbgstate.jsrcount = 1; + } + else + { + dbgstate.jsrcount = 0; + } + dbgstate.stepout = 1; + FCEUI_SetEmulationPaused(0); + } +} + +static void debugStepOverCB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + int tmp=X.PC; + uint8 opcode = GetMem(X.PC); + bool jsr = opcode==0x20; + bool call = jsr; + #ifdef BRK_3BYTE_HACK + //with this hack, treat BRK similar to JSR + if(opcode == 0x00) + { + call = true; + } + #endif + if (call) + { + if (watchpoint[64].flags) + { + printf("Step Over is currently in process.\n"); + return; + } + watchpoint[64].address = (tmp+3); + watchpoint[64].flags = WP_E|WP_X; + } + else + { + FCEUI_Debugger().step = true; + } + FCEUI_SetEmulationPaused(0); + } +} +static void debugRunLineCB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + } + uint64 ts=timestampbase; + ts+=timestamp; + ts+=341/3; + //if (scanline == 240) vblankScanLines++; + //else vblankScanLines = 0; + FCEUI_Debugger().runline = true; + FCEUI_Debugger().runline_end_time=ts; + FCEUI_SetEmulationPaused(0); +} + +static void debugRunLine128CB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + } + FCEUI_Debugger().runline = true; + { + uint64 ts=timestampbase; + ts+=timestamp; + ts+=128*341/3; + FCEUI_Debugger().runline_end_time=ts; + //if (scanline+128 >= 240 && scanline+128 <= 257) vblankScanLines = (scanline+128)-240; + //else vblankScanLines = 0; + } + FCEUI_SetEmulationPaused(0); +} + +static void seekPCCB (GtkButton * button, debuggerWin_t * dw) +{ + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + updateAllDebugWindows(); + } + dw->seekAsmPC(); +} + +static void seekToCB (GtkButton * button, debuggerWin_t * dw) +{ + int addr; + const char *txt; + + if (FCEUI_EmulationPaused()) + { + dw->setRegsFromEntry(); + } + txt = gtk_entry_get_text( GTK_ENTRY(dw->seektoEntry) ); + + addr = offsetStringToInt( BT_C, txt ); + + dw->seekAsmAddr(addr); +} + +static void Flag_N_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= N_FLAG; +} +static void Flag_V_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= V_FLAG; +} +static void Flag_U_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= U_FLAG; +} +static void Flag_B_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= B_FLAG; +} +static void Flag_D_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= D_FLAG; +} +static void Flag_I_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= I_FLAG; +} +static void Flag_Z_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= Z_FLAG; +} +static void Flag_C_CB (GtkToggleButton * button, debuggerWin_t * dw) +{ + X.P ^= C_FLAG; +} + +static void +addBreakpointMenuCB (GtkMenuItem *menuitem, + debuggerWin_t * dw) +{ + watchpointinfo wp; + + wp.address = dw->ctx_menu_addr; + wp.endaddress = 0; + wp.flags = WP_X | WP_E; + wp.condText = 0; + wp.desc = NULL; + + create_breakpoint_dialog( -1, &wp, dw ); + +} + +static gboolean +populate_context_menu (GtkWidget *popup, + debuggerWin_t * dw ) +{ + GtkWidget *menu = NULL; + GtkWidget *item; + GtkTextIter iter; + char stmp[256]; + gint cpos, lineNum; + int addr; + + g_object_get( dw->textbuf, "cursor-position", &cpos, NULL ); + + gtk_text_buffer_get_iter_at_offset( dw->textbuf, &iter, cpos ); + + lineNum = gtk_text_iter_get_line( &iter ); + + if ( (lineNum < 0) || (lineNum >= (int)dw->asmEntry.size() ) ) + { + return TRUE; + } + dw->ctx_menu_addr = addr = dw->asmEntry[lineNum]->addr; + + //printf("Context Menu: CP:%i Line:%i Addr:0x%04X\n", cpos, lineNum, addr ); + + menu = gtk_menu_new (); + + sprintf( stmp, "Add Breakpoint at 0x%04X", addr ); + + item = gtk_menu_item_new_with_label( stmp ); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (addBreakpointMenuCB), dw); + + gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL ); + //gtk_widget_show_all (popup); + gtk_widget_show_all (menu); + + return TRUE; +} + +static gboolean textview_keypress_cb (GtkWidget * grab, GdkEventKey * event, debuggerWin_t * dw) +{ + gboolean stopKeyPropagate; + + stopKeyPropagate = (event->keyval != GDK_KEY_Up ) && + (event->keyval != GDK_KEY_Down ) && + (event->keyval != GDK_KEY_Left ) && + (event->keyval != GDK_KEY_Right ) && + (event->keyval != GDK_KEY_Page_Up ) && + (event->keyval != GDK_KEY_Page_Down); + + return stopKeyPropagate; +} + +static gboolean +textview_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + debuggerWin_t * dw ) +{ + gboolean ret = FALSE; + //printf("Press Button %i %u\n", event->type, event->button ); + + if ( event->button == 3 ) + { + ret = populate_context_menu( widget, dw ); + } + + return ret; +} + +static void resetCountersCB( GtkWidget *button, debuggerWin_t * dw) +{ + ResetDebugStatisticsCounters(); + + updateAllDebugWindows(); +} + +static void breakOnBadOpcodeCB( GtkToggleButton *togglebutton, debuggerWin_t * dw) +{ + FCEUI_Debugger().badopbreak = !FCEUI_Debugger().badopbreak; + + updateAllDebugWindows(); +} + +static void breakOnCyclesCB( GtkToggleButton *togglebutton, debuggerWin_t * dw) +{ + const char *txt; + + break_on_cycles = !break_on_cycles; + + txt = gtk_entry_get_text( GTK_ENTRY(dw->brk_cycles_lim_entry) ); + + //printf("'%s'\n", txt ); + + if ( isdigit(txt[0]) ) + { + break_cycles_limit = strtoul( txt, NULL, 0 ); + } + + updateAllDebugWindows(); +} + +static void +breakOnCyclesLimitCB (GtkEntry *entry, +// gchar *string, + gpointer user_data) +{ + const char *txt; + + txt = gtk_entry_get_text( entry ); + + //printf("'%s'\n", txt ); + + if ( isdigit(txt[0]) ) + { + break_cycles_limit = strtoul( txt, NULL, 0 ); + } + updateAllDebugWindows(); +} + +static void breakOnInstructionsCB( GtkToggleButton *togglebutton, debuggerWin_t * dw) +{ + const char *txt; + + break_on_instructions = !break_on_instructions; + + txt = gtk_entry_get_text( GTK_ENTRY(dw->brk_instrs_lim_entry) ); + + //printf("'%s'\n", txt ); + + if ( isdigit(txt[0]) ) + { + break_instructions_limit = strtoul( txt, NULL, 0 ); + } + + updateAllDebugWindows(); +} + +static void +breakOnInstructionsLimitCB (GtkEntry *entry, +// gchar *string, + gpointer user_data) +{ + const char *txt; + + txt = gtk_entry_get_text( entry ); + + //printf("'%s'\n", txt ); + + if ( isdigit(txt[0]) ) + { + break_instructions_limit = strtoul( txt, NULL, 0 ); + } + updateAllDebugWindows(); +} + +static void romOffsetToggleCB( GtkToggleButton *togglebutton, debuggerWin_t * dw) +{ + dw->displayROMoffsets = gtk_toggle_button_get_active( togglebutton ); + + dw->updateViewPort(); + + //printf("Toggle ROM Offset: %i \n", dw->displayROMoffsets ); +} + +static void updateAllDebugWindows(void) +{ + std::list < debuggerWin_t * >::iterator it; + + for (it = debuggerWinList.begin (); it != debuggerWinList.end (); it++) + { + (*it)->updateViewPort(); + } +} + +static void seekPC_AllDebugWindows(void) +{ + std::list < debuggerWin_t * >::iterator it; + + for (it = debuggerWinList.begin (); it != debuggerWinList.end (); it++) + { + (*it)->seekAsmPC(); + } +} + +static void winDebuggerLoopStep(void) +{ + FCEUD_UpdateInput(); + + while(gtk_events_pending()) + { + gtk_main_iteration_do(FALSE); + } + + if ( XBackBuf ) + { + BlitScreen(XBackBuf); + } + + if ( breakpoint_hit ) + { + seekPC_AllDebugWindows(); + breakpoint_hit = 0; + } +} + +//this code enters the debugger when a breakpoint was hit +void FCEUD_DebugBreakpoint(int bp_num) +{ + //printf("Breakpoint Hit: %i \n", bp_num); + + breakpoint_hit = 1; + + updateAllDebugWindows(); + + winDebuggerLoopStep(); + + while(FCEUI_EmulationPaused() && !FCEUI_EmulationFrameStepped()) + { + usleep(50000); + winDebuggerLoopStep(); + } +} + +static void closeDebuggerWindow (GtkWidget * w, GdkEvent * e, debuggerWin_t * dw) +{ + std::list < debuggerWin_t * >::iterator it; + + for (it = debuggerWinList.begin (); it != debuggerWinList.end (); it++) + { + if (dw == *it) + { + debuggerWinList.erase (it); + break; + } + } + + delete dw; + + gtk_widget_destroy (w); +} + +void openDebuggerWindow (void) +{ + GtkWidget *main_hbox; + GtkWidget *vbox1, *vbox2, *vbox3; + GtkWidget *hbox1, *hbox2; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *button; + GtkWidget *scroll; + GtkWidget *frame; + GtkWidget *entry; + GtkWidget *grid; + GtkCellRenderer *renderer; + GtkCellRenderer *chkbox_renderer; + GtkTreeViewColumn *column; + debuggerWin_t *dw; + + dw = new debuggerWin_t; + + debuggerWinList.push_back (dw); + + dw->win = gtk_dialog_new_with_buttons ("6502 Debugger", + GTK_WINDOW (MainWindow), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Close", GTK_RESPONSE_OK, + NULL); + + gtk_window_set_default_size (GTK_WINDOW (dw->win), 800, 800); + + main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + dw->textview = (GtkTextView*) gtk_text_view_new(); + + gtk_text_view_set_monospace( dw->textview, TRUE ); + gtk_text_view_set_overwrite( dw->textview, TRUE ); + gtk_text_view_set_editable( dw->textview, TRUE ); + gtk_text_view_set_wrap_mode( dw->textview, GTK_WRAP_NONE ); + gtk_text_view_set_cursor_visible( dw->textview, TRUE ); + //gtk_widget_set_size_request( GTK_WIDGET(dw->textview), 400, 400 ); + + g_signal_connect (dw->textview, "key-press-event", + G_CALLBACK (textview_keypress_cb), dw); + g_signal_connect (dw->textview, "button-press-event", + G_CALLBACK (textview_button_press_cb), dw); + + dw->textbuf = gtk_text_view_get_buffer( dw->textview ); + + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + //GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS); + GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET(dw->textview) ); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); + gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 2); + + vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); + hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 2); + + /* + * Vertical box 2 contains: + * 1. "Run" and "Step Into" Buttons + * 2. "Step Out" and "Step Over" Buttons + * 3. "Run Line" and "128 Lines" Buttons + * 4. "Seek To:" button and Address Entry Field + * 5. PC Entry Field and "Seek PC" Button + * 6. A, X, Y Register Entry Fields + */ + vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + + gtk_box_pack_start (GTK_BOX (hbox1), vbox2, TRUE, TRUE, 2); + + grid = gtk_grid_new(); + + gtk_grid_set_row_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_column_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_row_spacing( GTK_GRID(grid), 5 ); + gtk_grid_set_column_spacing( GTK_GRID(grid), 10 ); + + gtk_grid_insert_column( GTK_GRID(grid), 0 ); + gtk_grid_insert_column( GTK_GRID(grid), 0 ); + + for (int i=0; i<5;i++) + { + gtk_grid_insert_row( GTK_GRID(grid), 0 ); + } + gtk_box_pack_start (GTK_BOX (hbox ), grid, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 2); + + // Row 1 + button = gtk_button_new_with_label ("Run"); + + g_signal_connect (button, "clicked", + G_CALLBACK (debugRunCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 0, 0, 1, 1 ); + + button = gtk_button_new_with_label ("Step Into"); + + g_signal_connect (button, "clicked", + G_CALLBACK (debugStepIntoCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 1, 0, 1, 1 ); + + // Row 2 + button = gtk_button_new_with_label ("Step Out"); + + g_signal_connect (button, "clicked", + G_CALLBACK (debugStepOutCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 0, 1, 1, 1 ); + + button = gtk_button_new_with_label ("Step Over"); + + g_signal_connect (button, "clicked", + G_CALLBACK (debugStepOverCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 1, 1, 1, 1 ); + + // Row 3 + button = gtk_button_new_with_label ("Run Line"); + + g_signal_connect (button, "clicked", + G_CALLBACK (debugRunLineCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 0, 2, 1, 1 ); + + button = gtk_button_new_with_label ("128 Lines"); + + g_signal_connect (button, "clicked", + G_CALLBACK (debugRunLine128CB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 1, 2, 1, 1 ); + + // Row 4 + button = gtk_button_new_with_label ("Seek To:"); + + g_signal_connect (button, "clicked", + G_CALLBACK (seekToCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 0, 3, 1, 1 ); + + dw->seektoEntry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->seektoEntry), 4); + gtk_entry_set_width_chars (GTK_ENTRY (dw->seektoEntry), 4); + + gtk_grid_attach( GTK_GRID(grid), dw->seektoEntry, 1, 3, 1, 1 ); + + // Row 5 + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + label = gtk_label_new("PC:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); + + dw->pc_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->pc_entry), 4); + gtk_entry_set_width_chars (GTK_ENTRY (dw->pc_entry), 4); + + gtk_box_pack_start (GTK_BOX (hbox), dw->pc_entry, TRUE, TRUE, 2); + + gtk_grid_attach( GTK_GRID(grid), hbox, 0, 4, 1, 1 ); + + button = gtk_button_new_with_label ("Seek PC"); + + g_signal_connect (button, "clicked", + G_CALLBACK (seekPCCB), (gpointer) dw); + + gtk_grid_attach( GTK_GRID(grid), button, 1, 4, 1, 1 ); + + // Row 6 + grid = gtk_grid_new(); + + gtk_grid_set_row_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_column_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_row_spacing( GTK_GRID(grid), 5 ); + gtk_grid_set_column_spacing( GTK_GRID(grid), 10 ); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + label = gtk_label_new("A:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); + + dw->A_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->A_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (dw->A_entry), 2); + + gtk_box_pack_start (GTK_BOX (hbox), dw->A_entry, FALSE, FALSE, 2); + + gtk_grid_attach( GTK_GRID(grid), hbox, 0, 0, 1, 1 ); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + label = gtk_label_new("X:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); + + dw->X_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->X_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (dw->X_entry), 2); + + gtk_box_pack_start (GTK_BOX (hbox), dw->X_entry, FALSE, FALSE, 2); + + gtk_grid_attach( GTK_GRID(grid), hbox, 1, 0, 1, 1 ); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + label = gtk_label_new("Y:"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2); + + dw->Y_entry = gtk_entry_new (); + gtk_entry_set_max_length (GTK_ENTRY (dw->Y_entry), 2); + gtk_entry_set_width_chars (GTK_ENTRY (dw->Y_entry), 2); + + gtk_box_pack_start (GTK_BOX (hbox), dw->Y_entry, FALSE, FALSE, 2); + + gtk_grid_attach( GTK_GRID(grid), hbox, 2, 0, 1, 1 ); + + gtk_box_pack_start (GTK_BOX (vbox2), grid, FALSE, FALSE, 2); + + // Stack Frame + dw->stack_frame = gtk_frame_new ("Stack"); + + dw->stackview = (GtkTextView*) gtk_text_view_new(); + + gtk_text_view_set_monospace( dw->stackview, TRUE ); + gtk_text_view_set_overwrite( dw->stackview, TRUE ); + gtk_text_view_set_editable( dw->stackview, FALSE ); + gtk_text_view_set_wrap_mode( dw->stackview, GTK_WRAP_NONE ); + gtk_text_view_set_cursor_visible( dw->stackview, TRUE ); + + dw->stackTextBuf = gtk_text_view_get_buffer( dw->stackview ); + + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS); + gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET(dw->stackview) ); + + gtk_container_add (GTK_CONTAINER (dw->stack_frame), scroll); + + gtk_box_pack_start (GTK_BOX (vbox2), dw->stack_frame, TRUE, TRUE, 2); + /* + * Vertical box 3 contains: + * 1. Breakpoints Frame + * 2. Status Flags Frame + */ + vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + + gtk_box_pack_start (GTK_BOX (hbox1), vbox3, TRUE, TRUE, 2); + + /* + * Breakpoints Frame contains: + * 1. Breakpoints tree view + * 2. Add, delete, edit breakpoint button row. + * 3. Break on bad opcodes checkbox/label + */ + frame = gtk_frame_new ("Breakpoints"); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); + + gtk_container_add (GTK_CONTAINER (frame), vbox); + + gtk_box_pack_start (GTK_BOX (vbox3), frame, TRUE, TRUE, 2); + + dw->bp_store = + gtk_tree_store_new (2, G_TYPE_BOOLEAN, G_TYPE_STRING ); + + dw->bp_tree = + gtk_tree_view_new_with_model (GTK_TREE_MODEL + (dw->bp_store)); + + g_signal_connect (dw->bp_tree, "cursor-changed", + G_CALLBACK (tree_select_rowCB), (gpointer) dw); + + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (dw->bp_tree), + GTK_TREE_VIEW_GRID_LINES_VERTICAL); + + chkbox_renderer = gtk_cell_renderer_toggle_new (); + gtk_cell_renderer_toggle_set_activatable ((GtkCellRendererToggle *) + chkbox_renderer, TRUE); + column = gtk_tree_view_column_new_with_attributes ("Ena", + chkbox_renderer, + "active", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (dw->bp_tree), column); + + g_signal_connect (chkbox_renderer, "toggled", + G_CALLBACK (enableBreakpointCB), (void *) dw); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + column = gtk_tree_view_column_new_with_attributes ("Addr/Flags", renderer, + "text", 1, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (dw->bp_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), dw->bp_tree); + gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 1); + + dw->add_bp_button = gtk_button_new_with_label ("Add"); + + g_signal_connect (dw->add_bp_button, "clicked", + G_CALLBACK (addBreakpointCB), (gpointer) dw); + + gtk_box_pack_start (GTK_BOX (hbox), dw->add_bp_button, TRUE, TRUE, 2); + + dw->del_bp_button = gtk_button_new_with_label ("Delete"); + + gtk_widget_set_sensitive( dw->del_bp_button, FALSE ); + + g_signal_connect (dw->del_bp_button, "clicked", + G_CALLBACK (deleteBreakpointCB), (gpointer) dw); + + gtk_box_pack_start (GTK_BOX (hbox), dw->del_bp_button, TRUE, TRUE, 2); + + dw->edit_bp_button = gtk_button_new_with_label ("Edit"); + + gtk_widget_set_sensitive( dw->edit_bp_button, FALSE ); + + g_signal_connect (dw->edit_bp_button, "clicked", + G_CALLBACK (editBreakpointCB), (gpointer) dw); + + gtk_box_pack_start (GTK_BOX (hbox), dw->edit_bp_button, TRUE, TRUE, 2); + + dw->badop_chkbox = gtk_check_button_new_with_label("Break on Bad Opcodes"); + g_signal_connect (dw->badop_chkbox, "toggled", + G_CALLBACK (breakOnBadOpcodeCB), dw); + gtk_box_pack_start (GTK_BOX (vbox), dw->badop_chkbox, FALSE, FALSE, 1); + + // Status Flags Frame + frame = gtk_frame_new ("Status Flags"); + + grid = gtk_grid_new(); + + gtk_grid_set_row_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_column_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_row_spacing( GTK_GRID(grid), 5 ); + gtk_grid_set_column_spacing( GTK_GRID(grid), 10 ); + + dw->P_N_chkbox = gtk_check_button_new_with_label("N"); + g_signal_connect (dw->P_N_chkbox, "toggled", + G_CALLBACK (Flag_N_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_N_chkbox, 0, 0, 1, 1 ); + + dw->P_V_chkbox = gtk_check_button_new_with_label("V"); + g_signal_connect (dw->P_V_chkbox, "toggled", + G_CALLBACK (Flag_V_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_V_chkbox, 1, 0, 1, 1 ); + + dw->P_U_chkbox = gtk_check_button_new_with_label("U"); + g_signal_connect (dw->P_U_chkbox, "toggled", + G_CALLBACK (Flag_U_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_U_chkbox, 2, 0, 1, 1 ); + + dw->P_B_chkbox = gtk_check_button_new_with_label("B"); + g_signal_connect (dw->P_B_chkbox, "toggled", + G_CALLBACK (Flag_B_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_B_chkbox, 3, 0, 1, 1 ); + + dw->P_D_chkbox = gtk_check_button_new_with_label("D"); + g_signal_connect (dw->P_D_chkbox, "toggled", + G_CALLBACK (Flag_D_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_D_chkbox, 0, 1, 1, 1 ); + + dw->P_I_chkbox = gtk_check_button_new_with_label("I"); + g_signal_connect (dw->P_I_chkbox, "toggled", + G_CALLBACK (Flag_I_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_I_chkbox, 1, 1, 1, 1 ); + + dw->P_Z_chkbox = gtk_check_button_new_with_label("Z"); + g_signal_connect (dw->P_Z_chkbox, "toggled", + G_CALLBACK (Flag_Z_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_Z_chkbox, 2, 1, 1, 1 ); + + dw->P_C_chkbox = gtk_check_button_new_with_label("C"); + g_signal_connect (dw->P_C_chkbox, "toggled", + G_CALLBACK (Flag_C_CB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->P_C_chkbox, 3, 1, 1, 1 ); + + gtk_container_add (GTK_CONTAINER (frame), grid); + + gtk_box_pack_start (GTK_BOX (vbox3), frame, FALSE, FALSE, 2); + + /* + * End Vertical Box 3 + */ + + /* + * Start PPU Frame + */ + grid = gtk_grid_new(); + + gtk_grid_set_row_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_column_homogeneous( GTK_GRID(grid), TRUE ); + gtk_grid_set_row_spacing( GTK_GRID(grid), 5 ); + gtk_grid_set_column_spacing( GTK_GRID(grid), 10 ); + + frame = gtk_frame_new (""); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); + + dw->ppu_label = gtk_label_new("PPU:"); + dw->sprite_label = gtk_label_new("Sprite:"); + dw->scanline_label = gtk_label_new("Scanline:"); + dw->pixel_label = gtk_label_new("Pixel:"); + + gtk_box_pack_start (GTK_BOX (vbox), dw->ppu_label , FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), dw->sprite_label , FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), dw->scanline_label, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), dw->pixel_label , FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 2); + gtk_container_add (GTK_CONTAINER (frame), hbox); + + gtk_grid_attach( GTK_GRID(grid), frame, 0, 0, 1, 4 ); + /* + * End PPU Frame + */ + + /* + * Start Cycle Break Block + */ + dw->cpu_label1 = gtk_label_new("CPU Cycles:"); + dw->cpu_label2 = gtk_label_new("+(0)"); + + dw->instr_label1 = gtk_label_new("Instructions:"); + dw->instr_label2 = gtk_label_new("+(0)"); + + gtk_grid_attach( GTK_GRID(grid), dw->cpu_label1, 1, 0, 1, 1 ); + gtk_grid_attach( GTK_GRID(grid), dw->cpu_label2, 2, 0, 1, 1 ); + gtk_grid_attach( GTK_GRID(grid), dw->instr_label1, 1, 2, 1, 1 ); + gtk_grid_attach( GTK_GRID(grid), dw->instr_label2, 2, 2, 1, 1 ); + + dw->brkcycles_chkbox = gtk_check_button_new_with_label("Break when exceed"); + g_signal_connect (dw->brkcycles_chkbox, "toggled", + G_CALLBACK (breakOnCyclesCB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->brkcycles_chkbox, 1, 1, 1, 1 ); + dw->brk_cycles_lim_entry = gtk_entry_new (); + //g_signal_connect (dw->brk_cycles_lim_entry, "preedit-changed", + g_signal_connect (dw->brk_cycles_lim_entry, "activate", + G_CALLBACK (breakOnCyclesLimitCB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->brk_cycles_lim_entry, 2, 1, 1, 1 ); + + dw->brkinstrs_chkbox = gtk_check_button_new_with_label("Break when exceed"); + g_signal_connect (dw->brkinstrs_chkbox, "toggled", + G_CALLBACK (breakOnInstructionsCB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->brkinstrs_chkbox, 1, 3, 1, 1 ); + dw->brk_instrs_lim_entry = gtk_entry_new (); + g_signal_connect (dw->brk_instrs_lim_entry, "activate", + G_CALLBACK (breakOnInstructionsLimitCB), dw); + gtk_grid_attach( GTK_GRID(grid), dw->brk_instrs_lim_entry, 2, 3, 1, 1 ); + + gtk_box_pack_start (GTK_BOX (vbox1), grid, FALSE, FALSE, 2); + /* + * End Cycle Break Block + */ + + /* + * Start Address Bookmarks + */ + hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + frame = gtk_frame_new ("Address Bookmarks"); + + vbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 1); + + gtk_container_add (GTK_CONTAINER (frame), vbox); + + dw->bkm_store = + gtk_tree_store_new (1, G_TYPE_STRING ); + + dw->bkm_tree = + gtk_tree_view_new_with_model (GTK_TREE_MODEL + (dw->bkm_store)); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + column = gtk_tree_view_column_new_with_attributes ("Bookmarks", renderer, + "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (dw->bkm_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), dw->bkm_tree); + gtk_box_pack_start (GTK_BOX (hbox), scroll, TRUE, TRUE, 1); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 1); + entry = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 2); + button = gtk_button_new_with_label ("Add"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_button_new_with_label ("Delete"); + gtk_widget_set_sensitive( button , FALSE ); // TODO Insensitive until functionality implemented + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_button_new_with_label ("Name"); + gtk_widget_set_sensitive( button , FALSE ); // TODO Insensitive until functionality implemented + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX (hbox2), frame, TRUE, TRUE, 2); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); + gtk_box_pack_start (GTK_BOX (hbox2), vbox, FALSE, FALSE, 2); + + button = gtk_button_new_with_label ("Reset Counters"); + g_signal_connect (button, "clicked", + G_CALLBACK (resetCountersCB), dw); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label("ROM Offsets"); + g_signal_connect (button, "toggled", + G_CALLBACK (romOffsetToggleCB), dw); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label("Symbolic Debug"); + gtk_widget_set_sensitive( button , FALSE ); // TODO Insensitive until functionality implemented + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_check_button_new_with_label("Register Names"); + gtk_widget_set_sensitive( button , FALSE ); // TODO Insensitive until functionality implemented + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_button_new_with_label ("Reload Symbols"); + gtk_widget_set_sensitive( button , FALSE ); // TODO Insensitive until functionality implemented + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + button = gtk_button_new_with_label ("ROM Patcher"); + gtk_widget_set_sensitive( button , FALSE ); // TODO Insensitive until functionality implemented + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 2); + + gtk_box_pack_start (GTK_BOX (vbox1), hbox2, TRUE, TRUE, 2); + /* + * End Address Bookmarks + */ + gtk_box_pack_start (GTK_BOX (main_hbox), vbox1, TRUE, TRUE, 2); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (dw->win))), main_hbox, TRUE, TRUE, + 0); + + g_signal_connect (dw->win, "delete-event", + G_CALLBACK (closeDebuggerWindow), dw); + g_signal_connect (dw->win, "response", + G_CALLBACK (closeDebuggerWindow), dw); + + gtk_widget_show_all (dw->win); + + dw->updateViewPort(); + + return; +} diff --git a/src/drivers/sdl/debugger.h b/src/drivers/sdl/debugger.h new file mode 100644 index 00000000..de1eb3bb --- /dev/null +++ b/src/drivers/sdl/debugger.h @@ -0,0 +1,3 @@ +// debugger.h +// +void openDebuggerWindow (void); diff --git a/src/drivers/sdl/glxwin.cpp b/src/drivers/sdl/glxwin.cpp new file mode 100644 index 00000000..547df24f --- /dev/null +++ b/src/drivers/sdl/glxwin.cpp @@ -0,0 +1,508 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "glxwin.h" + +static Display *dpy = NULL; +static Window root; +static XVisualInfo *vi = NULL; +static Colormap cmap; +static XSetWindowAttributes swa; +static Window win; +static GLXContext glc = NULL; +static XWindowAttributes gwa; +static XEvent xev; +static GLint double_buffer_ena = 1; + +static GLuint gltexture = 0; +static int spawn_new_window = 0; + +glxwin_shm_t *glx_shm = NULL; + +static int screen_width = 512; +static int screen_height = 512; + +extern GtkWidget *evbox; +extern unsigned int gtk_draw_area_width; +extern unsigned int gtk_draw_area_height; +//************************************************************************ +static glxwin_shm_t *open_shm(void) +{ + int shmId; + glxwin_shm_t *vaddr; + struct shmid_ds ds; + + shmId = shmget( IPC_PRIVATE, sizeof(struct glxwin_shm_t), IPC_CREAT | S_IRWXU | S_IRWXG ); + + if ( shmId == -1 ) + { + perror("Error: GLX shmget Failed:"); + return NULL; + } + printf("Created ShmID: %i \n", shmId ); + + vaddr = (glxwin_shm_t*)shmat( shmId, NULL, 0); + + if ( vaddr == (glxwin_shm_t*)-1 ) + { + perror("Error: GLX shmat Failed:"); + return NULL; + } + memset( vaddr, 0, sizeof(struct glxwin_shm_t)); + + if ( shmctl( shmId, IPC_RMID, &ds ) != 0 ) + { + perror("Error: GLX shmctl IPC_RMID Failed:"); + } + + sem_init( &vaddr->sem, 1, 1 ); + + vaddr->ncol = 256; + vaddr->nrow = 256; + vaddr->pitch = 256 * 4; + + return vaddr; +} +//************************************************************************ +static void getAttrbList( GLint *buf ) +{ + int i=0; + + buf[i] = GLX_RGBA; i++; + buf[i] = GLX_DEPTH_SIZE; i++; + buf[i] = 24; i++; + + if ( double_buffer_ena ) + { + buf[i] = GLX_DOUBLEBUFFER ; i++; + } + buf[i] = None; + +} +//************************************************************************ +static void genTextures( int ipolate ) +{ + glEnable(GL_TEXTURE_2D); + + if ( gltexture ) + { + printf("GL Texture already exists\n"); + } + else + { + glGenTextures(1, &gltexture); + } + printf("Linear Interpolation on GL Texture: %s \n", ipolate ? "Enabled" : "Disabled"); + + glBindTexture(GL_TEXTURE_2D, gltexture); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); + +} +//************************************************************************ +static int open_window(void) +{ + GLint att[32]; + + getAttrbList( att ); + + dpy = XOpenDisplay(NULL); + + if (dpy == NULL) { + printf("\n\tcannot connect to X server\n\n"); + exit(0); + } + root = DefaultRootWindow(dpy); + + vi = glXChooseVisual(dpy, 0, att); + + if (vi == NULL) + { + printf("\n\tno appropriate visual found\n\n"); + exit(0); + } + else { + printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ + } + + cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); + + swa.colormap = cmap; + swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask; + + win = XCreateWindow(dpy, root, 0, 0, screen_width, screen_height, 0, + vi->depth, InputOutput, vi->visual, + CWColormap | CWEventMask, &swa); + + XMapWindow(dpy, win); + + XStoreName(dpy, win, "FCEUX VIEWPORT"); + + if ( glc == NULL ) + { + glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); + + if ( glc == NULL ) + { + printf("Error: glXCreateContext Failed\n"); + } + } + else + { + printf("GLX Context Already Exists\n"); + } + XFree(vi); vi = NULL; + + glXMakeCurrent(dpy, win, glc); + + genTextures(1); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // In a double buffered setup with page flipping, be sure to clear both buffers. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + return 0; +} +//************************************************************************ +//static void print_pixbuf(void) +//{ +// for (int x=0; x<256; x++) +// { +// for (int y=0; y<256; y++) +// { +// printf("(%i,%i) = %08X \n", x, y, glx_shm->pixbuf[y*256+x] ); +// } +// } +//} +//************************************************************************ +static void render_image(void) +{ + static int null_glc_error = 0; + int l=0, r=glx_shm->ncol; + int t=0, b=glx_shm->nrow; + + float xscale = (float)screen_width / (float)glx_shm->ncol; + float yscale = (float)screen_height / (float)glx_shm->nrow; + + if (xscale < yscale ) + { + yscale = xscale; + } + else + { + xscale = yscale; + } + int rw=(int)((r-l)*xscale); + int rh=(int)((b-t)*yscale); + int sx=(screen_width-rw)/2; + int sy=(screen_height-rh)/2; + + if ( glc == NULL ) + { + if ( !null_glc_error ) + { + printf("Error: GLX Render has NULL Context\n"); + null_glc_error = 1; + } + return; + } + null_glc_error = 0; + + glXMakeCurrent(dpy, win, glc); + //printf("Viewport: (%i,%i) %i %i %i %i \n", + // screen_width, screen_height, sx, sy, rw, rh ); + glViewport(sx, sy, rw, rh); + //glViewport( 0, 0, screen_width, screen_height); + + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + + glDisable(GL_DEPTH_TEST); + glClearColor( 0.0, 0.0f, 0.0f, 0.0f); // Background color to black. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_TEXTURE_2D); + //glBindTexture(GL_TEXTURE_2D, gltexture); + glBindTexture(GL_TEXTURE_2D, gltexture); + + //print_pixbuf(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, + GL_RGBA, GL_UNSIGNED_BYTE, glx_shm->pixbuf ); + + glBegin(GL_QUADS); + glTexCoord2f(1.0f*l/256, 1.0f*b/256); // Bottom left of picture. + glVertex2f(-1.0f, -1.0f); // Bottom left of target. + + glTexCoord2f(1.0f*r/256, 1.0f*b/256);// Bottom right of picture. + glVertex2f( 1.0f, -1.0f); // Bottom right of target. + + glTexCoord2f(1.0f*r/256, 1.0f*t/256); // Top right of our picture. + glVertex2f( 1.0f, 1.0f); // Top right of target. + + glTexCoord2f(1.0f*l/256, 1.0f*t/256); // Top left of our picture. + glVertex2f(-1.0f, 1.0f); // Top left of target. + glEnd(); + + glDisable(GL_TEXTURE_2D); + + //glColor4f( 1.0, 1.0, 1.0, 1.0 ); + //glLineWidth(5.0); + //glBegin(GL_LINES); + //glVertex2f(-1.0f, -1.0f); // Bottom left of target. + //glVertex2f( 1.0f, 1.0f); // Top right of target. + //glEnd(); + + if ( double_buffer_ena ) + { + glXSwapBuffers( dpy, win ); + } + else + { + glFlush(); + } +} +//************************************************************************ +static int mainWindowLoop(void) +{ + + while( glx_shm->run ) + { + while ( XPending( dpy ) ) + { + XNextEvent(dpy, &xev); + + if (xev.type == Expose) + { + XGetWindowAttributes(dpy, win, &gwa); + //glViewport(0, 0, gwa.width, gwa.height); + //DrawAQuad(); + glXSwapBuffers(dpy, win); + //printf("Expose\n"); + } + else if (xev.type == ConfigureNotify) + { + screen_width = xev.xconfigure.width; + screen_height = xev.xconfigure.height; + + render_image(); + } + else if (xev.type == KeyPress) + { + printf("Key press: %i %08X \n", xev.xkey.keycode, xev.xkey.state ); + + } + else if (xev.type == DestroyNotify) + { + printf("DestroyNotify\n"); + glx_shm->run = 0; + //glXMakeCurrent(dpy, None, NULL); + //glXDestroyContext(dpy, glc); + //XDestroyWindow(dpy, win); + //XCloseDisplay(dpy); + //exit(0); + } + } + + if ( glx_shm->blit_count != glx_shm->render_count ) + { + render_image(); + glx_shm->render_count++; + } + + usleep(10000); + } + + glXMakeCurrent(dpy, None, NULL); + glXDestroyContext(dpy, glc); + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + exit(0); + return 0; +} +//************************************************************************ +int spawn_glxwin( int flags ) +{ + int pid; + + glx_shm = open_shm(); + + if ( !spawn_new_window ) + { + return 0; + } + pid = fork(); + + if ( pid == 0 ) + { + // Child Process + glx_shm->run = 1; + glx_shm->pid = getpid(); + + printf("Child Process Running: %i\n", glx_shm->pid ); + + open_window(); + + mainWindowLoop(); + + exit(0); + } + else if ( pid > 0 ) + { // Parent Process + + } + else + { + // Error + printf("Error: Failed to Fork GLX Window Process\n"); + } + + return pid; +} +//************************************************************************ +int init_gtk3_GLXContext( int flags ) +{ + GLint att[32]; + + XWindowAttributes xattrb; + + double_buffer_ena = (flags & GLXWIN_DOUBLE_BUFFER) ? 1 : 0; + + getAttrbList( att ); + + printf("Init GLX Context\n"); + printf("Double Buffering: %s\n", double_buffer_ena ? "Enabled" : "Disabled"); + + GdkWindow *gdkWin = gtk_widget_get_window(evbox); + + if ( gdkWin == NULL ) + { + printf("Error: Failed to obtain gdkWindow Handle for evbox widget\n"); + return -1; + } + win = GDK_WINDOW_XID( gdkWin ); + + root = GDK_ROOT_WINDOW(); + + dpy = gdk_x11_get_default_xdisplay(); + + if ( dpy == NULL ) + { + printf("Error: Failed to obtain X Display Handle for evbox widget\n"); + return -1; + } + + if ( XGetWindowAttributes( dpy, win, &xattrb ) == 0 ) + { + printf("Error: XGetWindowAttributes failed\n"); + return -1; + } + //printf("XWinLocation: (%i,%i) \n", xattrb.x, xattrb.y ); + //printf("XWinSize: (%i x %i) \n", xattrb.width, xattrb.height ); + //printf("XWinDepth: %i \n", xattrb.depth ); + //printf("XWinVisual: %p \n", xattrb.visual ); + + vi = glXChooseVisual(dpy, 0, att); + + if (vi == NULL) + { + printf("\n\tno appropriate visual found\n\n"); + exit(0); + } + else { + printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ + } + + if ( glc == NULL ) + { + glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); + + if ( glc == NULL ) + { + printf("Error: glXCreateContext Failed\n"); + } + } + XFree(vi); vi = NULL; + + glXMakeCurrent(dpy, win, glc); + + genTextures( flags & GLXWIN_PIXEL_LINEAR_FILTER ? 1 : 0 ); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // In a double buffered setup with page flipping, be sure to clear both buffers. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + return 0; +} +//************************************************************************ +int destroy_gtk3_GLXContext(void) +{ + if ( dpy != NULL ) + { + glXMakeCurrent(dpy, None, NULL); + } + + if (gltexture) + { + printf("Destroying GLX Texture\n"); + glDeleteTextures(1, &gltexture); + gltexture=0; + } + if ( glc != NULL ) + { + printf("Destroying GLX Context\n"); + glXDestroyContext(dpy, glc); glc = NULL; + } + if ( dpy != NULL ) + { + XSync( dpy, False ); + } + + return 0; +} +//************************************************************************ +int gtk3_glx_render(void) +{ + screen_width = gtk_draw_area_width; + screen_height = gtk_draw_area_height; + + render_image(); + + return 0; +} +//************************************************************************ diff --git a/src/drivers/sdl/glxwin.h b/src/drivers/sdl/glxwin.h new file mode 100644 index 00000000..ba2d8224 --- /dev/null +++ b/src/drivers/sdl/glxwin.h @@ -0,0 +1,77 @@ +// glxwin.cpp +// + +#ifndef __GLXWIN_H__ +#define __GLXWIN_H__ + +#include + +#include + +int spawn_glxwin( int flags ); + +#define GLXWIN_PIXEL_LINEAR_FILTER 0x0001 +#define GLXWIN_DOUBLE_BUFFER 0x0002 + +int init_gtk3_GLXContext( int flags ); + +int destroy_gtk3_GLXContext( void ); + +int gtk3_glx_render(void); + +#define GLX_NES_WIDTH 256 +#define GLX_NES_HEIGHT 256 + +struct glxwin_shm_t +{ + int pid; + int run; + uint32_t render_count; + uint32_t blit_count; + sem_t sem; + + int ncol; + int nrow; + int pitch; + + // Pass Key Events back to GTK Gui + struct + { + int head; + int tail; + + struct { + int type; + int keycode; + int state; + } data[64]; + + } keyEventBuf; + + // Gui Command Event Queue + struct + { + int head; + int tail; + + struct { + int id; + + union { + int i32[4]; + float f32[4]; + } param; + } cmd[64]; + } guiEvent; + + uint32_t pixbuf[65536]; // 256 x 256 + + void clear_pixbuf(void) + { + memset( pixbuf, 0, sizeof(pixbuf) ); + } +}; + +extern glxwin_shm_t *glx_shm; + +#endif diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 837eb6d1..fe82a062 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -1,5 +1,7 @@ #include "../../types.h" #include "../../fceu.h" +#include "../../cheat.h" +#include "../../debug.h" #include "../../driver.h" #include "../../version.h" #include "../../movie.h" @@ -12,7 +14,11 @@ #include "dface.h" #include "input.h" #include "config.h" +#include "cheat.h" #include "icon.xpm" +#include "memview.h" +#include "ramwatch.h" +#include "debugger.h" #ifdef _S9XLUA_H #include "../../fceulua.h" @@ -28,46 +34,78 @@ #include #endif +#ifdef APPLEOPENGL +#include +#include +#include +#else +#include +#include +#include +#endif + #include #include #include +#include + +#include "glxwin.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 +#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 -void toggleSound(GtkWidget* check, gpointer data); -void loadGame (); -void closeGame(); +// 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; -GtkWidget* MainWindow = NULL; -GtkWidget* evbox = NULL; -GtkWidget* padNoCombo = NULL; -GtkWidget* configNoCombo = NULL; -GtkWidget* buttonMappings[10]; -GtkWidget* Menubar; -GtkRadioAction* stateSlot = NULL; +GtkWidget *MainWindow = NULL; +GtkWidget *evbox = NULL; +GtkWidget *padNoCombo = NULL; +GtkWidget *configNoCombo = NULL; +GtkWidget *buttonMappings[10] = { NULL }; +static GtkWidget *Menubar = NULL; +static GtkRadioMenuItem *stateSlot[10] = { NULL }; bool gtkIsStarted = false; -bool menuTogglingEnabled; +bool menuTogglingEnabled = false; +static int buttonConfigStatus = 0; + +static char useCairoDraw = 0; +static int drawAreaGL = 0; +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); + +static gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data); // 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) +bool checkGTKVersion (int major_required, int minor_required) { int major = GTK_MAJOR_VERSION; int minor = GTK_MINOR_VERSION; - if(major > major_required) + if (major > major_required) { return true; - } else if (major == major_required) + } + else if (major == major_required) { - if(minor >= minor_required) + if (minor >= minor_required) { return true; } @@ -75,416 +113,429 @@ bool checkGTKVersion(int major_required, int minor_required) { return false; } - } else + } + else { return false; } } -void setCheckbox(GtkWidget* w, const char* configName) +void setCheckbox (GtkWidget * w, const char *configName) { int buf; - g_config->getOption(configName, &buf); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), buf); + g_config->getOption (configName, &buf); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), buf); } -// This function configures a single hotkey -int configHotkey(char* hotkeyString) -{ - // This is broken right now - //SDL_Surface *screen; -// SDL_Event event; -// KillVideo(); -#if SDL_VERSION_ATLEAST(2, 0, 0) - return 0; // TODO - SDL 2.0 -#else - //screen = SDL_SetVideoMode(420, 200, 8, 0); - //SDL_WM_SetCaption("Press a key to bind...", 0); -/* - int newkey = 0; - while(1) - { - SDL_WaitEvent(&event); - - switch (event.type) - { - case SDL_KEYDOWN: - newkey = event.key.keysym.sym; - g_config->setOption(hotkeyString, newkey); - extern FCEUGI *GameInfo; - InitVideo(GameInfo); - return 0; - } - } - - return 0;*/ -#endif -} // This function configures a single button on a gamepad -int configGamepadButton(GtkButton* button, gpointer p) +int configGamepadButton (GtkButton * button, gpointer p) { - gint x = ((gint)(glong)(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; - int configNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(configNoCombo))) - 1; - + int padNo = + atoi (gtk_combo_box_text_get_active_text + (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1; + int configNo = + atoi (gtk_combo_box_text_get_active_text + (GTK_COMBO_BOX_TEXT (configNoCombo))) - 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))) + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return 0; - - ButtonConfigBegin(); - - snprintf(buf, sizeof(buf), "SDL.Input.GamePad.%d", padNo); + + buttonConfigStatus = 2; + + ButtonConfigBegin (); + + snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); prefix = buf; - DWaitButton(NULL, &GamePadConfig[padNo][x], configNo); + DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus ); - g_config->setOption(prefix + GamePadNames[x], GamePadConfig[padNo][x].ButtonNum[configNo]); + g_config->setOption (prefix + GamePadNames[x], + GamePadConfig[padNo][x].ButtonNum[configNo]); - if(GamePadConfig[padNo][x].ButtType[0] == BUTTC_KEYBOARD) + 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 + "DeviceType", "Keyboard"); } - g_config->setOption(prefix + "DeviceNum", GamePadConfig[padNo][x].DeviceNum[configNo]); - - snprintf(buf, sizeof(buf), "%s", ButtonName(&GamePadConfig[padNo][x], configNo)); - gtk_label_set_markup(GTK_LABEL(buttonMappings[x]), buf); - - ButtonConfigEnd(); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); - - return 0; -} - -void resetVideo() -{ - KillVideo(); - InitVideo(GameInfo); -} - -void closeVideoWin(GtkWidget* w, gint response, gpointer p) -{ - resetVideo(); - if(response != GTK_RESPONSE_APPLY) + else if (GamePadConfig[padNo][x].ButtType[0] == BUTTC_JOYSTICK) { - 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); + g_config->setOption (prefix + "DeviceType", "Joystick"); } else { - g_config->setOption("SDL.Sound.LowPass", 0); - FCEUI_SetLowPass(0); + g_config->setOption (prefix + "DeviceType", "Unknown"); } - g_config->save(); + g_config->setOption (prefix + "DeviceNum", + GamePadConfig[padNo][x].DeviceNum[configNo]); + + snprintf (buf, sizeof (buf), "%s", + ButtonName (&GamePadConfig[padNo][x], configNo)); + + 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 toggleSwapDuty(GtkWidget* w, gpointer p) +void resetVideo (void) { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) + //resizeGtkWindow (); + KillVideo (); + InitVideo (GameInfo); +} + +void closeVideoWin (GtkWidget * w, gint response, gpointer p) +{ + resetVideo (); + if (response != GTK_RESPONSE_APPLY) { - g_config->setOption("SDL.SwapDuty", 1); + 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); + g_config->setOption ("SDL.SwapDuty", 0); swapDuty = 0; } - g_config->save(); + 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) +void toggleOption (GtkWidget * w, gpointer p) { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) - g_config->setOption((char*)p, 1); + 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); + g_config->setOption ((char *) p, 0); + + g_config->save (); + UpdateEMUCore (g_config); } -int setTint(GtkWidget* w, gpointer p) +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 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fileChooser), "/usr/share/fceux/palettes"); + g_config->getOption ("SDL.NTSCpalette", &c); + g_config->getOption ("SDL.Hue", &h); + FCEUI_SetNTSCTH (c, v, h); - if (gtk_dialog_run (GTK_DIALOG (fileChooser)) ==GTK_RESPONSE_ACCEPT) + 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); - + 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) +void clearPalette (GtkWidget * w, gpointer p) { - g_config->setOption("SDL.Palette", 0); - gtk_entry_set_text(GTK_ENTRY(p), ""); + g_config->setOption ("SDL.Palette", 0); + gtk_entry_set_text (GTK_ENTRY (p), ""); } -void openPaletteConfig() +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), - GTK_STOCK_CLOSE, - GTK_RESPONSE_OK, - NULL); - gtk_window_set_icon_name(GTK_WINDOW(win), GTK_STOCK_SELECT_COLOR); - vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); - - paletteFrame = gtk_frame_new("Custom palette: "); - paletteHbox = gtk_hbox_new(FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(paletteHbox), 5); - gtk_container_add(GTK_CONTAINER(paletteFrame), paletteHbox); - paletteButton = gtk_button_new_from_stock(GTK_STOCK_OPEN); - gtk_button_set_label(GTK_BUTTON(paletteButton), "Open palette"); - paletteEntry = gtk_entry_new(); - gtk_editable_set_editable(GTK_EDITABLE(paletteEntry), FALSE); - - clearButton = gtk_button_new_from_stock(GTK_STOCK_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); - + 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()); - + 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"); - + 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_vbox_new(FALSE, 2); - tintFrame = gtk_frame_new("Tint"); - tintHscale = gtk_hscale_new_with_range(0, 128, 1); - gtk_container_add(GTK_CONTAINER(tintFrame), tintHscale); - hueFrame = gtk_frame_new("Hue"); - hueHscale = gtk_hscale_new_with_range(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); - + 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); + 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); - 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; +GtkWidget *ipEntry; +GtkWidget *portSpin; +GtkWidget *pwEntry; -void launchNet(GtkWidget* w, gpointer p) +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(); + 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) +void setUsername (GtkWidget * w, gpointer p) { - char* s = (char*)gtk_entry_get_text(GTK_ENTRY(w)); - g_config->setOption("SDL.NetworkUsername", s); + 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) +void netResponse (GtkWidget * w, gint response_id, gpointer p) { - if(response_id == GTK_RESPONSE_OK) - launchNet(w, p); + if (response_id == GTK_RESPONSE_OK) + launchNet (w, p); else - gtk_widget_destroy(w); + gtk_widget_destroy (w); } -void openNetworkConfig() +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),GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_CONNECT, GTK_RESPONSE_OK, NULL); - gtk_window_set_icon_name(GTK_WINDOW(win), GTK_STOCK_NETWORK); - box = gtk_dialog_get_content_area(GTK_DIALOG(win)); - - userBox = gtk_hbox_new(FALSE, 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); + GtkWidget *win; + GtkWidget *box; + GtkWidget *userBox; + GtkWidget *userEntry; + GtkWidget *userLbl; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *ipBox; + GtkWidget *ipLbl; - frame = gtk_frame_new("Network options"); - vbox = gtk_vbox_new(FALSE, 5); - ipBox = gtk_hbox_new(FALSE, 5); - ipLbl = gtk_label_new("Server IP:"); - ipEntry = gtk_entry_new(); - portBox = gtk_hbox_new(FALSE, 5); - portLbl = gtk_label_new("Server port:"); - portSpin = gtk_spin_button_new_with_range(0, 999999, 1); + 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_hbox_new(FALSE, 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); + 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); + 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 -static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data); -void flushGtkEvents() +void flushGtkEvents (void) { while (gtk_events_pending ()) gtk_main_iteration_do (FALSE); @@ -492,1051 +543,1211 @@ void flushGtkEvents() return; } -GtkWidget* HotkeyWin; + +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 openHotkeyConfig (void) { - enum - { - COMMAND_COLUMN, - KEY_COLUMN, - N_COLUMNS - }; - GtkWidget* win = gtk_dialog_new_with_buttons("Hotkey Configuration", - GTK_WINDOW(MainWindow), (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), - GTK_STOCK_CLOSE, - GTK_RESPONSE_OK, - NULL); - gtk_window_set_default_size(GTK_WINDOW(win), 400, 800); - HotkeyWin = win; + 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); - vbox = gtk_dialog_get_content_area(GTK_DIALOG(win)); - - GtkTreeStore *hotkey_store = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); + hotKeyWindowRefresh (); - std::string prefix = "SDL.Hotkeys."; - GtkTreeIter iter; - - gtk_tree_store_append(hotkey_store, &iter, NULL); // aquire iter - - int keycode; - for(int i=0; igetOption(optionName.c_str(), &keycode); - gtk_tree_store_set(hotkey_store, &iter, - COMMAND_COLUMN, optionName.c_str(), - KEY_COLUMN, -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_GetKeyName(keycode), -#else - SDL_GetKeyName((SDLKey)keycode), -#endif - -1); - gtk_tree_store_append(hotkey_store, &iter, NULL); // acquire child iterator - } - - tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(hotkey_store)); + tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (hotkey_store)); GtkCellRenderer *renderer; - GtkTreeViewColumn* column; + GtkTreeViewColumn *column; - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes("Command", renderer, "text", COMMAND_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column); - column = gtk_tree_view_column_new_with_attributes("Key", renderer, "text", KEY_COLUMN, 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 (G_OBJECT (tree), "key-press-event", + G_CALLBACK (hotKeyPressCB), NULL); - g_signal_connect(win, "delete-event", G_CALLBACK(closeDialog), NULL); - g_signal_connect(win, "response", G_CALLBACK(closeDialog), 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); - GtkTreeSelection *select; + g_signal_connect (win, "delete-event", G_CALLBACK (closeDialog), NULL); + g_signal_connect (win, "response", G_CALLBACK (closeDialog), NULL); - select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)); - gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); - g_signal_connect ( G_OBJECT (select), "changed", G_CALLBACK (tree_selection_changed_cb), - NULL); - gtk_tree_selection_unselect_all (select); } -static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data) -{ - GtkTreeIter iter; - GtkTreeModel *model; - char* hotkey; - - if (gtk_tree_selection_get_selected (selection, &model, &iter)) - { - gtk_tree_model_get (model, &iter, 0, &hotkey, -1); - - gtk_widget_hide(HotkeyWin); - - flushGtkEvents(); - - configHotkey(hotkey); - - g_signal_emit_by_name(HotkeyWin, "destroy-event"); - - openHotkeyConfig(); - - g_free (hotkey); - - } -} - -GtkWidget* typeCombo; +//GtkWidget *typeCombo; // TODO: finish this -int setInputDevice(GtkWidget* w, gpointer p) -{ - std::string s = "SDL.Input."; - s = s + (char*)p; - printf("%s", s.c_str()); - g_config->setOption(s, gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(typeCombo))); - g_config->save(); - - return 1; -} +//int setInputDevice (GtkWidget * w, gpointer p) +//{ +// std::string s = "SDL.Input."; +// s = s + (char *) p; +// printf ("setInputDevice: %s", s.c_str ()); +// g_config->setOption (s, +// gtk_combo_box_text_get_active_text +// (GTK_COMBO_BOX_TEXT (typeCombo))); +// g_config->save (); +// +// return 1; +//} -void updateGamepadConfig(GtkWidget* w, gpointer p) +void updateGamepadConfig (GtkWidget * w, gpointer p) { int i; char strBuf[128]; - int padNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(padNoCombo))) - 1; - int configNo = atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(configNoCombo))) - 1; - - for(i=0; i<10; i++) + + if ( (padNoCombo == NULL) || (configNoCombo == NULL) ) { - GtkWidget* mappedKey = buttonMappings[i]; - if(GamePadConfig[padNo][i].ButtType[configNo] == BUTTC_KEYBOARD) - { -#if SDL_VERSION_ATLEAST(2, 0, 0) - snprintf(strBuf, sizeof(strBuf), "%s", - SDL_GetKeyName(GamePadConfig[padNo][i].ButtonNum[configNo])); -#else - snprintf(strBuf, sizeof(strBuf), "%s", - SDL_GetKeyName((SDLKey)GamePadConfig[padNo][i].ButtonNum[configNo])); -#endif - } - else // FIXME: display joystick button/hat/axis names properly - strncpy(strBuf, "Joystick", sizeof(strBuf)); - - gtk_label_set_text(GTK_LABEL(mappedKey), strBuf); - gtk_label_set_use_markup(GTK_LABEL(mappedKey), TRUE); + return; } + int padNo = + atoi (gtk_combo_box_text_get_active_text + (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1; + int configNo = + atoi (gtk_combo_box_text_get_active_text + (GTK_COMBO_BOX_TEXT (configNoCombo))) - 1; + + for (i = 0; i < 10; i++) + { + GtkWidget *mappedKey = buttonMappings[i]; + if (GamePadConfig[padNo][i].ButtType[configNo] == BUTTC_KEYBOARD) + { + snprintf (strBuf, sizeof (strBuf), "%s", + SDL_GetKeyName (GamePadConfig[padNo][i]. + ButtonNum[configNo])); + } + else + sprintf (strBuf, "%s", ButtonName( &GamePadConfig[padNo][i], configNo ) ); + + 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; + configNoCombo = 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 openGamepadConfig (void) { - // GTK 2.24 required for this dialog - if (checkGTKVersion(2, 24) == false) - { - // TODO: present this in a GTK MessageBox? - printf(" Warning: GTK >= 2.24 required for this dialog.\nTo configure the gamepads, use \"--inputcfg\" from the command line (ie: \"fceux --inputcfg gamepad1\").\n"); - return; - } - - GtkWidget* win; - GtkWidget* vbox; - GtkWidget* hboxPadNo; - GtkWidget* padNoLabel; + GtkWidget *win; + GtkWidget *vbox; + GtkWidget *hboxPadNo; + GtkWidget *padNoLabel; //GtkWidget* configNoLabel; - GtkWidget* fourScoreChk; - GtkWidget* oppositeDirChk; - GtkWidget* buttonFrame; - GtkWidget* buttonTable; - - win = gtk_dialog_new_with_buttons("Controller Configuration", - GTK_WINDOW(MainWindow), - (GtkDialogFlags)(GTK_DIALOG_DESTROY_WITH_PARENT), - GTK_STOCK_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_hbox_new(FALSE, 0); - padNoLabel = gtk_label_new("Port:"); + GtkWidget *fourScoreChk; + GtkWidget *oppositeDirChk; + GtkWidget *buttonFrame; + GtkWidget *buttonTable; + + 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); - - configNoCombo = gtk_combo_box_text_new(); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "1"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "2"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "3"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(configNoCombo), "4"); - gtk_combo_box_set_active(GTK_COMBO_BOX(configNoCombo), 0); - g_signal_connect(padNoCombo, "changed", G_CALLBACK(updateGamepadConfig), 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); + 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); + + configNoCombo = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (configNoCombo), + "1"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (configNoCombo), + "2"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (configNoCombo), + "3"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (configNoCombo), + "4"); + gtk_combo_box_set_active (GTK_COMBO_BOX (configNoCombo), 0); + g_signal_connect (padNoCombo, "changed", + G_CALLBACK (updateGamepadConfig), 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(hboxPadNo), configNoLabel, TRUE, TRUE, 5); //gtk_box_pack_start(GTK_BOX(hboxPadNo), configNoCombo, TRUE, TRUE, 5); - gtk_box_pack_start(GTK_BOX(vbox), hboxPadNo, FALSE, 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(vbox), fourScoreChk, FALSE, TRUE, 5); - gtk_box_pack_start(GTK_BOX(vbox), oppositeDirChk, 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("Buttons"); - gtk_label_set_use_markup(GTK_LABEL(gtk_frame_get_label_widget(GTK_FRAME(buttonFrame))), TRUE); - buttonTable = gtk_table_new(10, 3, FALSE); - gtk_table_set_col_spacings(GTK_TABLE(buttonTable), 5); - gtk_container_add(GTK_CONTAINER(buttonFrame), buttonTable); - for(int i=0; i<10; i++) + buttonFrame = gtk_frame_new ("Buttons"); + 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++) { - GtkWidget* buttonName = gtk_label_new(GamePadNames[i]); - GtkWidget* mappedKey = gtk_label_new(NULL); - GtkWidget* changeButton = gtk_toggle_button_new(); + 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]; - - sprintf(strBuf, "%s:", GamePadNames[i]); - gtk_label_set_text(GTK_LABEL(buttonName), strBuf); - gtk_misc_set_alignment(GTK_MISC(buttonName), 1.0, 0.5); - - gtk_misc_set_alignment(GTK_MISC(mappedKey), 0.0, 0.5); - - gtk_button_set_label(GTK_BUTTON(changeButton), "Change"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(changeButton), FALSE); - - gtk_table_attach(GTK_TABLE(buttonTable), buttonName, 0, 1, i, i+1, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach(GTK_TABLE(buttonTable), mappedKey, 1, 2, i, i+1, - (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), 0, 0); - gtk_table_attach(GTK_TABLE(buttonTable), changeButton, 2, 3, i, i+1, - (GtkAttachOptions)0, (GtkAttachOptions)0, 0, 0); - - g_signal_connect(changeButton, "clicked", G_CALLBACK(configGamepadButton), GINT_TO_POINTER(i)); + + 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(closeDialog), NULL); - g_signal_connect(win, "response", G_CALLBACK(closeDialog), NULL); - - gtk_widget_show_all(win); - + 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 setBufSize (GtkWidget * w, gpointer p) { - int x = gtk_range_get_value(GTK_RANGE(w)); - g_config->setOption("SDL.Sound.BufSize", x); + 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(); + KillSound (); + InitSound (); return false; } -void setRate(GtkWidget* w, gpointer p) +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)); + 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(); + KillSound (); + InitSound (); + g_config->save (); return; } -void setQuality(GtkWidget* w, gpointer p) +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); + 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(); + KillSound (); + InitSound (); + g_config->save (); return; } -void resizeGtkWindow() +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, 256*xscale, 224*yscale); - GtkRequisition req; - gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); - gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); - } + //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; } -void setScaler(GtkWidget* w, gpointer p) +void setScaler (GtkWidget * w, gpointer p) { - int scaler = gtk_combo_box_get_active(GTK_COMBO_BOX(w)); + int scaler = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); int opengl; - g_config->getOption("SDL.OpenGL", &opengl); - if(opengl && scaler) + g_config->getOption ("SDL.OpenGL", &opengl); + if (opengl && scaler) { - FCEUD_PrintError("Scalers not supported in OpenGL mode."); - gtk_combo_box_set_active(GTK_COMBO_BOX(w), 0); + FCEUD_PrintError ("Scalers not supported in OpenGL mode."); + gtk_combo_box_set_active (GTK_COMBO_BOX (w), 0); return; } - g_config->setOption("SDL.SpecialFilter", scaler); - + g_config->setOption ("SDL.SpecialFilter", scaler); + // 1=hq2x 2=Scale2x 3=NTSC2x 4=hq3x 5=Scale3x 6=Prescale2x 7=Prescale3x 8=Prescale4x 9=pal - switch(scaler) + switch (scaler) { case 4: // hq3x case 5: // scale3x case 7: // prescale3x - g_config->setOption("SDL.XScale", 3.0); - g_config->setOption("SDL.YScale", 3.0); - resizeGtkWindow(); + g_config->setOption ("SDL.XScale", 3.0); + g_config->setOption ("SDL.YScale", 3.0); + resizeGtkWindow (); break; - case 8: // prescale4x - g_config->setOption("SDL.XScale", 4.0); - g_config->setOption("SDL.YScale", 4.0); + case 8: // prescale4x + g_config->setOption ("SDL.XScale", 4.0); + g_config->setOption ("SDL.YScale", 4.0); break; default: - g_config->setOption("SDL.XScale", 2.0); - g_config->setOption("SDL.YScale", 2.0); - resizeGtkWindow(); + g_config->setOption ("SDL.XScale", 2.0); + g_config->setOption ("SDL.YScale", 2.0); + resizeGtkWindow (); break; } - g_config->save(); + g_config->save (); } -void setRegion(GtkWidget* w, gpointer p) +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(); - + int region = gtk_combo_box_get_active (GTK_COMBO_BOX (w)); + g_config->setOption ("SDL.PAL", region); + FCEUI_SetRegion (region); + + g_config->save (); + } -int setXscale(GtkWidget* w, gpointer p) +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(); + double v = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w)); + g_config->setOption ("SDL.XScale", v); + g_config->save (); + resizeGtkWindow (); return 0; } -int setYscale(GtkWidget* w, gpointer p) +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(); + double v = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w)); + g_config->setOption ("SDL.YScale", v); + g_config->save (); + resizeGtkWindow (); return 0; } #ifdef OPENGL -void setGl(GtkWidget* w, gpointer p) +void setGl (GtkWidget * w, gpointer p) { int scaler; - int opengl = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); - g_config->getOption("SDL.SpecialFilter", &scaler); - if(scaler && opengl) + int opengl = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)); + g_config->getOption ("SDL.SpecialFilter", &scaler); + if (scaler && opengl) { - FCEUD_PrintError("Scalers not supported in OpenGL mode."); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), 0); + FCEUD_PrintError ("Scalers not supported in OpenGL mode."); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), 0); return; } - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) - g_config->setOption("SDL.OpenGL", 1); + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w))) + g_config->setOption ("SDL.OpenGL", 1); else - g_config->setOption("SDL.OpenGL", 0); - g_config->save(); + g_config->setOption ("SDL.OpenGL", 0); + g_config->save (); } -void setDoubleBuffering(GtkWidget* w, gpointer p) +void setDoubleBuffering (GtkWidget * w, gpointer p) { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) - g_config->setOption("SDL.DoubleBuffering", 1); + 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(); + g_config->setOption ("SDL.DoubleBuffering", 0); + g_config->save (); } #endif -void openVideoConfig() +void openVideoConfig (void) { - GtkWidget* win; - GtkWidget* vbox; - GtkWidget* lbl; - GtkWidget* hbox1; - GtkWidget* scalerLbl; - GtkWidget* scalerCombo; - GtkWidget* glChk; - 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), - GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, - GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); - gtk_window_set_icon_name(GTK_WINDOW(win), "video-display"); + GtkWidget *win; + GtkWidget *vbox; + GtkWidget *lbl; + GtkWidget *hbox1; + GtkWidget *scalerLbl; + GtkWidget *scalerCombo; + GtkWidget *glChk; + 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."); - + + 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_hbox_new(FALSE, 3); - scalerLbl = gtk_label_new("Special Scaler: "); - scalerCombo = gtk_combo_box_text_new(); + hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + scalerLbl = gtk_label_new ("Special Scaler: "); + scalerCombo = gtk_combo_box_text_new (); // -Video Modes Tag- - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "none"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "hq2x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "scale2x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "NTSC 2x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "hq3x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "scale3x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "prescale2x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "prescale3x"); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "prescale4x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "none"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "hq2x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "scale2x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "NTSC 2x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "hq3x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "scale3x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "prescale2x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "prescale3x"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (scalerCombo), + "prescale4x"); //gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(scalerCombo), "pal"); - + // sync with cfg int buf; - g_config->getOption("SDL.SpecialFilter", &buf); - gtk_combo_box_set_active(GTK_COMBO_BOX(scalerCombo), buf); - - g_signal_connect(scalerCombo, "changed", G_CALLBACK(setScaler), NULL); - gtk_box_pack_start(GTK_BOX(hbox1), scalerLbl, FALSE, FALSE, 5); - gtk_box_pack_start(GTK_BOX(hbox1), scalerCombo, FALSE, FALSE, 5); -#ifdef OPENGL + g_config->getOption ("SDL.SpecialFilter", &buf); + gtk_combo_box_set_active (GTK_COMBO_BOX (scalerCombo), buf); + + g_signal_connect (scalerCombo, "changed", G_CALLBACK (setScaler), NULL); + gtk_box_pack_start (GTK_BOX (hbox1), scalerLbl, FALSE, FALSE, 5); + gtk_box_pack_start (GTK_BOX (hbox1), scalerCombo, FALSE, FALSE, 5); +#ifdef OPENGL // openGL check - glChk = gtk_check_button_new_with_label("Enable OpenGL"); - g_signal_connect(glChk, "clicked", G_CALLBACK(setGl), NULL); - setCheckbox(glChk, "SDL.OpenGL"); - + glChk = gtk_check_button_new_with_label ("Enable OpenGL"); + g_signal_connect (glChk, "clicked", G_CALLBACK (setGl), NULL); + setCheckbox (glChk, "SDL.OpenGL"); + // 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"); - + 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"); + dbChk = gtk_check_button_new_with_label ("Enable double buffering"); + g_signal_connect (dbChk, "clicked", G_CALLBACK (setDoubleBuffering), + NULL); + setCheckbox (dbChk, "SDL.DoubleBuffering"); #endif - + // Region (NTSC/PAL/Dendy) - palHbox = gtk_hbox_new(FALSE, 3); - palLbl = gtk_label_new("Region: "); - palCombo = gtk_combo_box_text_new(); + 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"); + 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); + 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"); + 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"); - + 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"); + 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"); - + 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_hbox_new(FALSE, 5); - xscaleLbl = gtk_label_new("X scaling factor"); - xscaleSpin = gtk_spin_button_new_with_range(1.0, 40.0, .1); - yscaleHbox = gtk_hbox_new(FALSE, 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); - + 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); + 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"); + 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); + 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), glChk, FALSE, FALSE, 5); - gtk_box_pack_start(GTK_BOX(vbox), linearChk, FALSE, FALSE, 5); - gtk_box_pack_start(GTK_BOX(vbox), dbChk, FALSE, FALSE, 5); + gtk_box_pack_start (GTK_BOX (vbox), glChk, FALSE, FALSE, 5); + 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); + 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); - + 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"}; +const char *mixerStrings[6] = + { "Volume", "Triangle", "Square1", "Square2", "Noise", "PCM" }; -int mixerChanged(GtkWidget* w, gpointer p) +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) + 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); + g_config->setOption ("SDL.Sound.Volume", v); + FCEUI_SetSoundVolume (v); } - if(strcmp(lbl, "Triangle") == 0) + if (strcmp (lbl, "Triangle") == 0) { - g_config->setOption("SDL.Sound.TriangleVolume", v); - FCEUI_SetTriangleVolume(v); + g_config->setOption ("SDL.Sound.TriangleVolume", v); + FCEUI_SetTriangleVolume (v); } - if(strcmp(lbl, "Square1") == 0) + if (strcmp (lbl, "Square1") == 0) { - g_config->setOption("SDL.Sound.Square1Volume", v); - FCEUI_SetSquare1Volume(v); + g_config->setOption ("SDL.Sound.Square1Volume", v); + FCEUI_SetSquare1Volume (v); } - if(strcmp(lbl, "Square2") == 0) + if (strcmp (lbl, "Square2") == 0) { - g_config->setOption("SDL.Sound.Square2Volume", v); - FCEUI_SetSquare2Volume(v); + g_config->setOption ("SDL.Sound.Square2Volume", v); + FCEUI_SetSquare2Volume (v); } - if(strcmp(lbl, "Noise") == 0) + if (strcmp (lbl, "Noise") == 0) { - g_config->setOption("SDL.Sound.NoiseVolume", v); - FCEUI_SetNoiseVolume(v); + g_config->setOption ("SDL.Sound.NoiseVolume", v); + FCEUI_SetNoiseVolume (v); } - if(strcmp(lbl, "PCM") == 0) + if (strcmp (lbl, "PCM") == 0) { - g_config->setOption("SDL.Sound.PCMVolume", v); - FCEUI_SetPCMVolume(v); + g_config->setOption ("SDL.Sound.PCMVolume", v); + FCEUI_SetPCMVolume (v); } - + return 0; } -void openSoundConfig() +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]; + 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), - GTK_STOCK_CLOSE, - GTK_RESPONSE_OK, - NULL); - gtk_window_set_icon_name(GTK_WINDOW(win), "audio-x-generic"); - main_hbox = gtk_hbox_new(FALSE, 15); - vbox = gtk_vbox_new(FALSE, 5); + 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"); + 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"); - + 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_hbox_new(FALSE, 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"); + 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); - + 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_hbox_new(FALSE, 3); - rateCombo = gtk_combo_box_text_new(); - - const int rates[5] = {11025, 22050, 44100, 48000, 96000}; - + 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++) + for (int i = 0; i < 5; i++) { - sprintf(choices, "%d", rates[i]); - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(rateCombo), choices); + 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_hscale_new_with_range(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); + 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"); + 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_hbox_new(TRUE, 5); - for(int i=0; i<6; i++) + mixerFrame = gtk_frame_new ("Mixer:"); + mixerHbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + for (long int i = 0; i < 6; i++) { - mixers[i] = gtk_vscale_new_with_range(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); + 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); + 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); - + + 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; } -void quit () +void quit (void) { // manually flush GTK event queue - while(gtk_events_pending()) - gtk_main_iteration_do(FALSE); + 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(); + 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); + g_config->setOption ("SDL.NetworkIP", ""); + g_config->save (); + SDL_Quit (); + exit (0); } -const char* Authors[]= { + +const char *Authors[] = { "Linux/SDL Developers:", - " Lukas Sabota //punkrockguy318", " Soules", " Bryan Cain", " radsaq", " Shinydoofy", + " 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", + " Luke Gustafson", " _mz", " UncombedCoconut", " DwEdit", " AnS", + "rainwarrior", "feos", "Pre 2.0 Guys:", " Bero", " Xodnizel", " Aaron Oneal", " Joe Nahmias", - " Paul Kuliniewicz", " Quietust", " Ben Parnell", " Parasyte & bbitmaster", - " blip & nitsuja", + " Paul Kuliniewicz", " Quietust", " Ben Parnell", + " Parasyte & bbitmaster", + " blip & nitsuja", "Included components:", - " Mitsutaka Okazaki - YM2413 emulator", " Andrea Mazzoleni - Scale2x/Scale3x scalers", " Gilles Vollant - unzip.c PKZIP fileio", - NULL}; + " Mitsutaka Okazaki - YM2413 emulator", + " Andrea Mazzoleni - Scale2x/Scale3x scalers", + " Gilles Vollant - unzip.c PKZIP fileio", + NULL +}; -void openAbout () +void openAbout (void) { - GdkPixbuf* logo = gdk_pixbuf_new_from_xpm_data(icon_xpm); - - gtk_show_about_dialog(GTK_WINDOW(MainWindow), - "program-name", "fceuX", - "version", FCEU_VERSION_STRING, - "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); + GdkPixbuf *logo = gdk_pixbuf_new_from_xpm_data (icon_xpm); + + gtk_show_about_dialog (GTK_WINDOW (MainWindow), + "program-name", "fceuX", + "version", FCEU_VERSION_STRING, + "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) +void toggleSound (GtkWidget * check, gpointer data) { - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) + 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(); + 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(); + g_config->setOption ("SDL.Sound", 0); + KillSound (); } } void emuReset () { - if(isloaded) - ResetNES(); + if (isloaded) + ResetNES (); } void hardReset () { - if(isloaded) + if (isloaded) { - closeGame(); - const char* lastFile; - g_config->getOption("SDL.LastOpenFile", &lastFile); - LoadGame(lastFile); - resizeGtkWindow(); + closeGame (); + const char *lastFile; + g_config->getOption ("SDL.LastOpenFile", &lastFile); + LoadGame (lastFile); + resizeGtkWindow (); } } -void enableFullscreen () +void enableFullscreen (void) { - if(isloaded) - ToggleFS(); + if (isloaded) + ToggleFS (); } -void toggleMenuToggling (GtkToggleAction *action) +void toggleMenuToggling (GtkCheckMenuItem * item, gpointer user_data) { - bool toggleMenu = gtk_toggle_action_get_active(action); + bool toggleMenu = gtk_check_menu_item_get_active (item); - g_config->setOption("SDL.ToggleMenu", (int)toggleMenu); + //printf("ToggleMenu: %i\n", (int)toggleMenu); + g_config->setOption ("SDL.ToggleMenu", (int) toggleMenu); menuTogglingEnabled = toggleMenu; } -void toggleAutoResume (GtkToggleAction *action) +void toggleAutoResume (GtkCheckMenuItem * item, gpointer user_data) { - bool autoResume = gtk_toggle_action_get_active(action); + bool autoResume = gtk_check_menu_item_get_active (item); - g_config->setOption("SDL.AutoResume", (int)autoResume); + //printf("AutoResume: %i\n", (int)autoResume); + g_config->setOption ("SDL.AutoResume", (int) autoResume); AutoResumePlay = autoResume; } -void recordMovie() +void recordMovie () { - if(isloaded) + 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""); + 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) + 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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) + 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); + 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 loadMovie (void) { - GtkWidget* fileChooser; - - GtkFileFilter* filterMovies; - GtkFileFilter* filterFm2; - GtkFileFilter* filterAll; + GtkWidget *fileChooser; - 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"); + GtkFileFilter *filterMovies; + GtkFileFilter *filterFm2; + GtkFileFilter *filterAll; - 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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) + 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)); + 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) + 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); + 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 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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) + 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) + 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); + 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); + g_free (filename); } else gtk_widget_destroy (fileChooser); @@ -1544,968 +1755,1891 @@ void loadLua () #endif -void loadFdsBios () +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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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) + 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)); + 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<setOption("SDL.GameGenie", enabled); - g_config->save(); - FCEUI_SetGameGenie(enabled); + g_config->setOption ("SDL.GameGenie", enabled); + g_config->save (); + FCEUI_SetGameGenie (enabled); } -void toggleGameGenie(GtkToggleAction *action) +void toggleGameGenie (GtkCheckMenuItem * item, gpointer userData) { - enableGameGenie(gtk_toggle_action_get_active(action)); + enableGameGenie (gtk_check_menu_item_get_active (item)); } -void togglePause(GtkAction *action) +void togglePause (GtkMenuItem * item, gpointer userData) { SDL_Event sdlev; int paused; - - if(isloaded) + + if (isloaded) { - paused = FCEUI_EmulationPaused(); - + paused = FCEUI_EmulationPaused (); + sdlev.type = SDL_FCEU_HOTKEY_EVENT; sdlev.user.code = HK_PAUSE; - if(SDL_PushEvent(&sdlev) < 0) + if (SDL_PushEvent (&sdlev) < 0) { - FCEU_printf("Failed to push SDL event to %s game.\n", paused ? "resume" : "pause"); + FCEU_printf ("Failed to push SDL event to %s game.\n", + paused ? "resume" : "pause"); return; } - gtk_action_set_label(action, paused ? "Pause" : "Resume"); - gtk_action_set_stock_id(action, paused ? GTK_STOCK_MEDIA_PAUSE : GTK_STOCK_MEDIA_PLAY); + 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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); + GtkWidget *fileChooser; + GtkFileFilter *filterGG; + GtkFileFilter *filterRom; + GtkFileFilter *filterNes; + GtkFileFilter *filterAll; - f2<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) + 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)); + char *filename; + + filename = + gtk_file_chooser_get_filename (GTK_FILE_CHOOSER + (fileChooser)); gtk_widget_destroy (fileChooser); - LoadGame(filename); + 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); + { + + 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 closeGame (void) { - GdkColor bg = {0, 0, 0, 0}; - gtk_widget_modify_bg(evbox, GTK_STATE_NORMAL, &bg); - CloseGame(); + //GdkColor bg = {0, 0, 0, 0}; + //gtk_widget_modify_bg(evbox, GTK_STATE_NORMAL, &bg); + CloseGame (); } -void loadGame () +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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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) + 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)); + 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); + 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); + { + + 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 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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) + 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); + 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 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, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_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); + GtkWidget *fileChooser; + GtkFileFilter *filterFcs; + GtkFileFilter *filterSav; + GtkFileFilter *filterAll; - 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) + 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); + 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 quickLoad (void) { - FCEUI_LoadState(NULL); + FCEUI_LoadState (NULL); } -void quickSave() +void quickSave (void) { - FCEUI_SaveState(NULL); + FCEUI_SaveState (NULL); } -void changeState(GtkAction *action, GtkRadioAction *current, gpointer data) +void setStateMenuItem( int i ) { - FCEUI_SelectState(gtk_radio_action_get_current_value(current), 0); + if ( (i >= 0) && (i < 10) ) + { + gtk_menu_item_activate( GTK_MENU_ITEM(stateSlot[i]) ); + } } -#if SDL_VERSION_ATLEAST(2, 0, 0) + +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_KP0 SDLK_KP_0 -#define SDLK_KP1 SDLK_KP_1 -#define SDLK_KP2 SDLK_KP_2 -#define SDLK_KP3 SDLK_KP_3 -#define SDLK_KP4 SDLK_KP_4 -#define SDLK_KP5 SDLK_KP_5 -#define SDLK_KP6 SDLK_KP_6 -#define SDLK_KP7 SDLK_KP_7 -#define SDLK_KP8 SDLK_KP_8 -#define SDLK_KP9 SDLK_KP_9 -#define SDLK_LSUPER SDLK_LGUI -#define SDLK_RSUPER SDLK_RGUI #define SDLK_LMETA 0 #define SDLK_RMETA 0 -#endif + // Adapted from Gens/GS. Converts a GDK key value into an SDL key value. -unsigned short GDKToSDLKeyval(int gdk_key) +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); - + 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)); + 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); + fprintf (stderr, "Unhandled extended key: 0x%08X\n", gdk_key); #endif return 0; } - + // Non-ASCII symbol. - static const uint16_t gdk_to_sdl_table[0x100] = - { + 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_KP5, 0x0000, 0x0000, 0x0000, + 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_KP7, SDLK_KP4, SDLK_KP8, - SDLK_KP6, SDLK_KP2, SDLK_KP9, SDLK_KP3, - SDLK_KP1, SDLK_KP5, SDLK_KP0, SDLK_KP_PERIOD, - + 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_KP0, SDLK_KP1, SDLK_KP2, SDLK_KP3, - SDLK_KP4, SDLK_KP5, SDLK_KP6, SDLK_KP7, - SDLK_KP8, SDLK_KP9, 0x0000, 0x0000, + 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_LSUPER, - SDLK_RSUPER, 0x0000, 0x0000, 0x0000, - + 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, + 0x0000, 0x0000, 0x0000, SDLK_DELETE, }; - - unsigned short sdl_key = gdk_to_sdl_table[gdk_key & 0xFF]; + + 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)); + 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]) + 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) -gint convertKeypress(GtkWidget *grab, GdkEventKey *event, gpointer user_data) +static gboolean convertKeypress (GtkWidget * grab, GdkEventKey * event, + gpointer user_data) { SDL_Event sdlev; - int keystate; -#if SDL_VERSION_ATLEAST(2, 0, 0) SDL_Keycode sdlkey; -#else - SDLKey sdlkey; -#endif + switch (event->type) { case GDK_KEY_PRESS: sdlev.type = SDL_KEYDOWN; sdlev.key.state = SDL_PRESSED; - keystate = 1; break; - + case GDK_KEY_RELEASE: sdlev.type = SDL_KEYUP; sdlev.key.state = SDL_RELEASED; - keystate = 0; break; - + default: - fprintf(stderr, "Unhandled GDK event type: %d", event->type); + fprintf (stderr, "Unhandled GDK event type: %d", + event->type); return FALSE; } - + // Convert this keypress from GDK to SDL. -#if SDL_VERSION_ATLEAST(2, 0, 0) - sdlkey = GDKToSDLKeyval(event->keyval); -#else - sdlkey = (SDLKey)GDKToSDLKeyval(event->keyval); -#endif - + sdlkey = GDKToSDLKeyval (event->keyval); + // Create an SDL event from the keypress. + sdlev.key.keysym.scancode = SDL_GetScancodeFromKey(sdlkey); sdlev.key.keysym.sym = sdlkey; - if (sdlkey != 0) + + sdlev.key.keysym.mod = 0; + + if ( event->state & GDK_SHIFT_MASK ) { - SDL_PushEvent(&sdlev); - - // Only let the emulator handle the key event if this window has the input focus. - if(keystate == 0 || gtk_window_is_active(GTK_WINDOW(MainWindow))) + 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 ) { - #if SDL_VERSION_ATLEAST(2, 0, 0) - // Not sure how to do this yet with SDL 2.0 - // TODO - SDL 2.0 - //SDL_GetKeyboardState(NULL)[SDL_GetScancodeFromKey(sdlkey)] = keystate; - #else - SDL_GetKeyState(NULL)[sdlkey] = keystate; - #endif + return FALSE; } } - + + if (sdlkey != 0) + { + SDL_PushEvent (&sdlev); + } + // Allow GTK+ to process this key. return FALSE; } -// Our menu, in the XML markup format used by GtkUIManager -static char* menuXml = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " -#ifdef _S9XLUA_H - " " -#endif - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - -// Menu items, as an array of GtkActionEntry structures that define each item -static GtkActionEntry normal_entries[] = { - {"FileMenuAction", NULL, "_File"}, - {"OpenRomAction", GTK_STOCK_OPEN, "_Open ROM", "O", NULL, G_CALLBACK(loadGame)}, - {"CloseRomAction", GTK_STOCK_CLOSE, "_Close ROM", "C", NULL, G_CALLBACK(closeGame)}, - {"PlayNsfAction", GTK_STOCK_OPEN, "_Play NSF", "N", NULL, G_CALLBACK(loadNSF)}, - {"LoadStateFromAction", GTK_STOCK_OPEN, "Load State _From", "", NULL, G_CALLBACK(loadStateFrom)}, - {"SaveStateAsAction", GTK_STOCK_SAVE_AS, "Save State _As", NULL, NULL, G_CALLBACK(saveStateAs)}, - {"QuickLoadAction", "go-jump", "Quick _Load", "F7", NULL, G_CALLBACK(quickLoad)}, - {"QuickSaveAction", GTK_STOCK_SAVE, "Qu_ick Save", "F5", NULL, G_CALLBACK(quickSave)}, - {"ChangeStateMenuAction", NULL, "C_hange State"}, -#ifdef _S9XLUA_H - {"LoadLuaScriptAction", GTK_STOCK_OPEN, "Load L_ua Script", "", NULL, G_CALLBACK(loadLua)}, -#endif - {"ScreenshotAction", NULL, "_Screenshot", "F12", NULL, G_CALLBACK(FCEUI_SaveSnapshot)}, - {"QuitAction", GTK_STOCK_QUIT, "_Quit", "Q", NULL, G_CALLBACK(quit)}, - - {"OptionsMenuAction", NULL, "_Options"}, -#if GTK_MAJOR_VERSION == 3 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24) - {"GamepadConfigAction", "input-gaming", "_Gamepad Config", NULL, NULL, G_CALLBACK(openGamepadConfig)}, -#endif - {"HotkeyConfigAction", "input", "_Hotkey Config", NULL, NULL, G_CALLBACK(openHotkeyConfig)}, - {"SoundConfigAction", "audio-x-generic", "_Sound Config", NULL, NULL, G_CALLBACK(openSoundConfig)}, - {"VideoConfigAction", "video-display", "_Video Config", NULL, NULL, G_CALLBACK(openVideoConfig)}, - {"PaletteConfigAction", GTK_STOCK_SELECT_COLOR, "_Palette Config", NULL, NULL, G_CALLBACK(openPaletteConfig)}, - {"NetworkConfigAction", GTK_STOCK_NETWORK, "_Network Config", NULL, NULL, G_CALLBACK(openNetworkConfig)}, - {"FullscreenAction", GTK_STOCK_FULLSCREEN, "_Fullscreen", "Return", NULL, G_CALLBACK(enableFullscreen)}, - {"EmulationMenuAction", NULL, "_Emulation"}, - {"PowerAction", NULL, "P_ower", NULL, NULL, G_CALLBACK(FCEUI_PowerNES)}, - {"SoftResetAction", GTK_STOCK_REFRESH, "_Soft Reset", NULL, NULL, G_CALLBACK(emuReset)}, - {"ResetAction", GTK_STOCK_REFRESH, "_Reset", NULL, NULL, G_CALLBACK(hardReset)}, - {"PauseToggleAction", GTK_STOCK_MEDIA_PAUSE, "_Pause", "Pause", NULL, G_CALLBACK(togglePause)}, - {"FdsMenuAction", GTK_STOCK_FLOPPY, "_FDS"}, - {"SwitchDiskAction", "go-jump", "_Switch Disk", NULL, NULL, G_CALLBACK(FCEU_FDSSelect)}, - {"EjectDiskAction", "media-eject", "_Eject Disk", NULL, NULL, G_CALLBACK(FCEU_FDSInsert)}, - {"LoadBiosAction", GTK_STOCK_OPEN, "Load _BIOS File", "", NULL, G_CALLBACK(loadFdsBios)}, - {"LoadGameGenieAction", GTK_STOCK_OPEN, "_Load Game Genie ROM", "", NULL, G_CALLBACK(loadGameGenie)}, - {"InsertCoinAction", NULL, "_Insert Coin", NULL, NULL, G_CALLBACK(FCEUI_VSUniCoin)}, - - {"MovieMenuAction", NULL, "_Movie"}, - {"OpenMovieAction", GTK_STOCK_OPEN, "_Open", "F7", NULL, G_CALLBACK(loadMovie)}, - {"StopMovieAction", GTK_STOCK_MEDIA_STOP, "S_top", NULL, NULL, G_CALLBACK(FCEUI_StopMovie)}, - {"RecordMovieAction", GTK_STOCK_MEDIA_RECORD, "_Record", "F5", NULL, G_CALLBACK(recordMovie)}, - {"RecordMovieAsAction", NULL, "Record _As", NULL, NULL, G_CALLBACK(recordMovieAs)}, - - {"HelpMenuAction", NULL, "_Help"}, - {"AboutAction", GTK_STOCK_ABOUT, "_About", NULL, NULL, G_CALLBACK(openAbout)}, -}; - -// Menu items with a check box that can be toggled on or off -static GtkToggleActionEntry toggle_entries[] = { - {"GameGenieToggleAction", NULL, "Enable Game _Genie", NULL, NULL, G_CALLBACK(toggleGameGenie), FALSE}, - {"AutoResumeAction", NULL, "Auto-Resume Play", NULL, NULL, G_CALLBACK(toggleAutoResume), FALSE}, - {"ToggleMenuAction", NULL, "Toggle Menubar (alt)", NULL, NULL, G_CALLBACK(toggleMenuToggling), FALSE}, -}; - -// Menu items for selecting a save state slot using radio buttons -static GtkRadioActionEntry radio_entries[] = { - {"State0Action", NULL, "0", NULL, NULL, 0}, - {"State1Action", NULL, "1", NULL, NULL, 1}, - {"State2Action", NULL, "2", NULL, NULL, 2}, - {"State3Action", NULL, "3", NULL, NULL, 3}, - {"State4Action", NULL, "4", NULL, NULL, 4}, - {"State5Action", NULL, "5", NULL, NULL, 5}, - {"State6Action", NULL, "6", NULL, NULL, 6}, - {"State7Action", NULL, "7", NULL, NULL, 7}, - {"State8Action", NULL, "8", NULL, NULL, 8}, - {"State9Action", NULL, "9", NULL, NULL, 9}, -}; - -static GtkWidget* CreateMenubar( GtkWidget* window) +static GtkWidget *CreateMenubar (GtkWidget * window) { - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkAccelGroup* accel_group; - GError *error = NULL; - GtkAction* state; + 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 (); - /* Make an UIManager (which makes a menubar). */ - ui_manager = gtk_ui_manager_new (); - - /* Add the menu items to the UIManager as a GtkActionGroup. */ - action_group = gtk_action_group_new ("MenubarActions"); - gtk_action_group_add_actions (action_group, normal_entries, G_N_ELEMENTS (normal_entries), NULL); - gtk_action_group_add_toggle_actions (action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), NULL); - gtk_action_group_add_radio_actions (action_group, radio_entries, G_N_ELEMENTS (radio_entries), 0, G_CALLBACK(changeState), NULL); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - - /* Read the menu layout from the XML markup. */ - gtk_ui_manager_add_ui_from_string (ui_manager, menuXml, -1, &error); - if (error) - { - fprintf (stderr, "Unable to create menu bar: %s\n", error->message); - g_error_free (error); - } - - /* Attach the new accelerator group to the window. */ - accel_group = gtk_ui_manager_get_accel_group (ui_manager); gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - - /* Get an action that can be used to change the active state slot selection. */ - state = gtk_action_group_get_action (action_group, "State0Action"); - if (state && GTK_IS_RADIO_ACTION (state)) - stateSlot = GTK_RADIO_ACTION (state); - /* Set the autoResume checkbox */ - GtkCheckMenuItem* auto_resume_chk = (GtkCheckMenuItem*) gtk_ui_manager_get_widget ( ui_manager, "/Menubar/OptionsMenuAction/AutoResumeAction"); - gtk_check_menu_item_set_active (auto_resume_chk, (bool)AutoResumePlay); - - /* Finally, return the actual menu bar created by the UIManager. */ - return gtk_ui_manager_get_widget (ui_manager, "/Menubar"); + //--------------------------------------- + // 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 (quit), 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) +void pushOutputToGTK (const char *str) { // we don't really do anything with the output right now return; } -void showGui(bool b) +void showGui (bool b) { - if(b) - gtk_widget_show_all(MainWindow); + 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 (MainWindow); + //gtk_widget_hide (Menubar); + //gtk_window_maximize( GTK_WINDOW(MainWindow) ); + gtk_window_fullscreen( GTK_WINDOW(MainWindow) ); + } } -gint handleKeyRelease(GtkWidget* w, GdkEvent* event, gpointer cb_data) +void toggleMenuVis(void) { - if(menuTogglingEnabled) + if (menuTogglingEnabled) { - static bool menuShown = true; - if(((GdkEventKey*)event)->keyval == GDK_KEY_Alt_L || ((GdkEventKey*)event)->keyval == GDK_KEY_Alt_R) + if ( gtk_widget_get_visible(Menubar) ) { - if(menuShown) - { - gtk_widget_hide(Menubar); - menuShown = false; - } - else - { - gtk_widget_show(Menubar); - menuShown = true; - } + gtk_widget_hide (Menubar); + } + else + { + gtk_widget_show (Menubar); } } - return 0; }; -int GtkMouseData[3] = {0,0,0}; +int GtkMouseData[3] = { 0, 0, 0 }; -gint handleMouseClick(GtkWidget* widget, GdkEvent *event, gpointer callback_data) +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[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) + if (button == 1) GtkMouseData[2] |= 0x1; - if(button == 3) + 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_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); + */ - SDL_PushEvent(&sdlev); - */ - return 0; } -// NES resolution = 256x240 -const int NES_WIDTH=256; -const int NES_HEIGHT=240; -void handle_resize(GtkWindow* win, GdkEvent* event, gpointer data) +union cairo_pixel_t { - // TODO this is a stub atm - // this should handle resizing so the emulation takes up as much + 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; ypixbuf; + + //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++; + + if ( useCairoDraw ) + { + transferPix2CairoSurface(); + } + else + { + gtk3_glx_render(); + } + + 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; ipixbuf; +// +// 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; yncol; + 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 ury) ) + { + for (x=0; 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(); + + return 0; +} + +int init_gui_video( int use_openGL ) +{ + drawAreaGL = use_openGL; + useCairoDraw = !drawAreaGL; + + if ( use_openGL ) + { + 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; + + destroy_cairo_screen(); + init_gtk3_GLXContext( flags ); + } + else + { + destroy_gtk3_GLXContext(); + init_cairo_screen(); + } + 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; + int width, height, winsize_changed = 0; + width = event->configure.width; height = event->configure.height; - printf("DEBUG: new window size: %dx%d\n", width, 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; + double xscale = width / (double) NES_WIDTH; + double yscale = height / (double) NES_HEIGHT; + + //printf("DRAW: %ix%i MenuY: %i \n", draw_width, draw_height, gtk_win_menu_ysize ); + + 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) + if (xscale > yscale) xscale = yscale; - if(yscale > xscale) + if (yscale > xscale) yscale = xscale; - //TODO if openGL make these integers - g_config->setOption("SDL.XScale", xscale); - g_config->setOption("SDL.YScale", yscale); - //gtk_widget_realize(evbox); - flushGtkEvents(); - if(GameInfo != 0) + if ( useCairoDraw && winsize_changed ) { - KillVideo(); - InitVideo(GameInfo); + cairo_handle_resize(); } - gtk_widget_set_size_request(evbox, (int)(NES_WIDTH*xscale), (int)(NES_HEIGHT*yscale)); - // Currently unused; unsure why - /* GdkColor black; - black.red = 0; - black.green = 0; - black.blue = 0; - gtk_widget_modify_bg(GTK_WIDGET(win), GTK_STATE_NORMAL, &black);*/ + //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); + //} - printf("DEBUG: new xscale: %f yscale: %f\n", xscale, yscale); + gtk_widget_queue_draw( evbox ); - return; + //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; } -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_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(MainWindow), vbox); - - Menubar = CreateMenubar(MainWindow); - // turn of game genie by default, since its off by default in the menu - enableGameGenie(0); +// 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; + + if ( useCairoDraw ) + { + cairo_draw_cb( widget, cr, data ); + } + else + { + gtk3_glx_render(); + } + + return FALSE; +} + +static void +drawAreaRealizeCB (GtkWidget *widget, + gpointer user_data) +{ + printf("Draw Area Realize\n"); + + init_gui_video( drawAreaGL ); +} + + +int InitGTKSubsystem (int argc, char **argv) +{ + + int s_useOpenGL=0; + 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); - 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 + // 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 @@ -2514,44 +3648,63 @@ int InitGTKSubsystem(int argc, char** argv) // 1/24/11 // // prg - Bryan Cain, you are the man! - - evbox = gtk_event_box_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); - 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); - - GdkColor bg = {0, 0, 0, 0}; - gtk_widget_modify_bg(evbox, GTK_STATE_NORMAL, &bg); - + #ifdef OPENGL + g_config->getOption("SDL.OpenGL", &s_useOpenGL); + #endif + + drawAreaGL = s_useOpenGL; + useCairoDraw = !drawAreaGL; + + 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); + //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); + 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); - g_signal_connect(G_OBJECT(MainWindow), "key-release-event", G_CALLBACK(handleKeyRelease), NULL); - // signal handlers - g_signal_connect(MainWindow, "delete-event", quit, NULL); - g_signal_connect(MainWindow, "destroy-event", quit, NULL); - // resize handler -// g_signal_connect(MainWindow, "configure-event", G_CALLBACK(handle_resize), NULL); - - gtk_widget_show_all(MainWindow); - + g_signal_connect (MainWindow, "delete-event", quit, NULL); + g_signal_connect (MainWindow, "destroy-event", quit, 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_size_request(GTK_WIDGET(MainWindow), &req); - gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); + 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; } - diff --git a/src/drivers/sdl/gui.h b/src/drivers/sdl/gui.h index 35b5bdbf..e824d4a2 100644 --- a/src/drivers/sdl/gui.h +++ b/src/drivers/sdl/gui.h @@ -27,13 +27,13 @@ #endif extern GtkWidget* MainWindow; extern GtkWidget* evbox; -extern GtkRadioAction* stateSlot; extern int GtkMouseData[3]; extern bool gtkIsStarted; int InitGTKSubsystem(int argc, char** argv); void pushOutputToGTK(const char* str); void showGui(bool b); +void toggleMenuVis(void); bool checkGTKVersion(int major_required, int minor_required); @@ -55,6 +55,8 @@ void setGl(GtkWidget* w, gpointer p); void setDoubleBuffering(GtkWidget* w, gpointer p); #endif +void setStateMenuItem( int i ); + void openVideoConfig(); void openSoundConfig(); void quit (); @@ -82,7 +84,15 @@ void saveStateAs(); void loadStateFrom(); void quickLoad(); void quickSave(); -unsigned short GDKToSDLKeyval(int gdk_key); +unsigned int GDKToSDLKeyval(int gdk_key); int InitGTKSubsystem(int argc, char** argv); +uint32_t *getGuiPixelBuffer( int *w, int *h, int *s ); +int guiPixelBufferReDraw(void); + +int init_gui_video( int use_openGL ); +int destroy_gui_video( void ); +void init_cairo_screen(void); +void destroy_cairo_screen(void); + #endif // ifndef FCEUX_GUI_H diff --git a/src/drivers/sdl/input.cpp b/src/drivers/sdl/input.cpp index 3cf13b3c..f4246e96 100644 --- a/src/drivers/sdl/input.cpp +++ b/src/drivers/sdl/input.cpp @@ -31,6 +31,7 @@ #include "../../movie.h" #include "../../fceu.h" #include "../../driver.h" +#include "../../state.h" #include "../../utils/xstring.h" #ifdef _S9XLUA_H #include "../../fceulua.h" @@ -48,7 +49,7 @@ #include /** GLOBALS **/ -int NoWaiting = 1; +int NoWaiting = 0; extern Config *g_config; extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; @@ -136,32 +137,50 @@ DoCheatSeq () } #include "keyscan.h" -static uint8 *g_keyState = 0; +static uint8 g_keyState[SDL_NUM_SCANCODES]; static int DIPS = 0; -static uint8 keyonce[MKK_COUNT]; +static uint8 keyonce[SDL_NUM_SCANCODES]; #define KEY(__a) g_keyState[MKK(__a)] +int getKeyState( int k ) +{ + if ( (k >= 0) && (k < SDL_NUM_SCANCODES) ) + { + return g_keyState[k]; + } + return 0; +} + static int _keyonly (int a) { - // check for valid key - if (a > SDLK_LAST + 1 || a < 0) - return 0; -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (g_keyState[SDL_GetScancodeFromKey (a)]) -#else - if (g_keyState[a]) -#endif + int sc; + + if ( a < 0 ) { - if (!keyonce[a]) + return 0; + } + + sc = SDL_GetScancodeFromKey(a); + + // check for valid key + if (sc >= SDL_NUM_SCANCODES || sc < 0) + { + return 0; + } + + if (g_keyState[sc]) + { + if (!keyonce[sc]) { - keyonce[a] = 1; + keyonce[sc] = 1; return 1; } } - else { - keyonce[a] = 0; + else + { + keyonce[sc] = 0; } return 0; } @@ -177,12 +196,12 @@ int Hotkeys[HK_MAX] = { 0 }; // on every cycle of keyboardinput() void -setHotKeys () +setHotKeys (void) { std::string prefix = "SDL.Hotkeys."; for (int i = 0; i < HK_MAX; i++) { - g_config->getOption (prefix + HotkeyStrings[i], &Hotkeys[i]); + g_config->getOption (prefix + getHotkeyString(i), &Hotkeys[i]); } return; } @@ -201,24 +220,6 @@ TogglePause () int fullscreen; g_config->getOption ("SDL.Fullscreen", &fullscreen); - // Don't touch grab when in windowed mode - if(fullscreen == 0) - return; - -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - if (FCEUI_EmulationPaused () == 0) - { - SDL_WM_GrabInput (SDL_GRAB_ON); - if(no_cursor) - SDL_ShowCursor (0); - } - else { - SDL_WM_GrabInput (SDL_GRAB_OFF); - SDL_ShowCursor (1); - } -#endif return; } @@ -281,16 +282,16 @@ std::string GetFilename (const char *title, bool save, const char *filter) if (save) fileChooser = gtk_file_chooser_dialog_new ("Save as", NULL, GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, + "_Cancel", GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE_AS, + "_Save", GTK_RESPONSE_ACCEPT, NULL); else fileChooser = gtk_file_chooser_dialog_new ("Open", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, + "_Cancel", GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, + "_Open", GTK_RESPONSE_ACCEPT, NULL); // TODO: make file filters case insensitive @@ -432,88 +433,53 @@ void FCEUD_LoadStateFrom () unsigned int *GetKeyboard(void) { int size = 256; -#if SDL_VERSION_ATLEAST(2, 0, 0) + Uint8* keystate = (Uint8*)SDL_GetKeyboardState(&size); -#else - Uint8* keystate = SDL_GetKeyState(&size); -#endif + return (unsigned int*)(keystate); } /** * Parse keyboard commands and execute accordingly. */ -static void KeyboardCommands () +static void KeyboardCommands (void) { int is_shift, is_alt; - char *movie_fname = ""; // get the keyboard input -#if SDL_VERSION_ATLEAST(1, 3, 0) - g_keyState = (Uint8*)SDL_GetKeyboardState (NULL); -#else - g_keyState = SDL_GetKeyState (NULL); -#endif // check if the family keyboard is enabled if (CurInputType[2] == SIFC_FKB) { -#if SDL_VERSION_ATLEAST(1, 3, 0) - // TODO - SDL2 - if (0) -#else - if (keyonly (SCROLLLOCK)) -#endif - { - g_fkbEnabled ^= 1; - FCEUI_DispMessage ("Family Keyboard %sabled.", 0, - g_fkbEnabled ? "en" : "dis"); - } -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - SDL_WM_GrabInput (g_fkbEnabled ? SDL_GRAB_ON : SDL_GRAB_OFF); -#endif + if ( g_keyState[SDL_SCANCODE_SCROLLLOCK] ) + { + g_fkbEnabled ^= 1; + FCEUI_DispMessage ("Family Keyboard %sabled.", 0, + g_fkbEnabled ? "en" : "dis"); + } if (g_fkbEnabled) { return; } } -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (g_keyState[SDL_GetScancodeFromKey (SDLK_LSHIFT)] - || g_keyState[SDL_GetScancodeFromKey (SDLK_RSHIFT)]) -#else - if (g_keyState[SDLK_LSHIFT] || g_keyState[SDLK_RSHIFT]) -#endif - is_shift = 1; - else - is_shift = 0; -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (g_keyState[SDL_GetScancodeFromKey (SDLK_LALT)] - || g_keyState[SDL_GetScancodeFromKey (SDLK_RALT)]) -#else - if (g_keyState[SDLK_LALT] || g_keyState[SDLK_RALT]) -#endif + if (g_keyState[SDL_SCANCODE_LSHIFT] || g_keyState[SDL_SCANCODE_RSHIFT]) { - is_alt = 1; -#if !SDL_VERSION_ATLEAST(2, 0, 0) - // workaround for GDK->SDL in GTK problems where ALT release is never - // getting sent - // I know this is sort of an ugly hack to fix this, but the bug is - // rather annoying - // prg318 10/23/11 - int fullscreen; - g_config->getOption ("SDL.Fullscreen", &fullscreen); - if (!fullscreen) - { - g_keyState[SDLK_LALT] = 0; - g_keyState[SDLK_RALT] = 0; - } -#endif + is_shift = 1; } else + { + is_shift = 0; + } + + if (g_keyState[SDL_SCANCODE_LALT] || g_keyState[SDL_SCANCODE_RALT]) + { + is_alt = 1; + } + else + { is_alt = 0; + } if (_keyonly (Hotkeys[HK_TOGGLE_BG])) @@ -529,37 +495,50 @@ static void KeyboardCommands () } // Alt-Enter to toggle full-screen - if (keyonly (ENTER) && is_alt) + // This is already handled by GTK Accelerator + //if (keyonly (ENTER) && is_alt) + //{ + // ToggleFS (); + //} + // + + // Alt-M to toggle Main Menu Visibility + if ( is_alt ) { - ToggleFS (); + if (keyonly (M)) + { + toggleMenuVis(); + } } - - // Toggle Movie auto-backup - if (keyonly (M) && is_shift) + if ( is_shift ) { - autoMovieBackup ^= 1; - FCEUI_DispMessage ("Automatic movie backup %sabled.", 0, - autoMovieBackup ? "en" : "dis"); + if (keyonly (M)) + { + autoMovieBackup ^= 1; + FCEUI_DispMessage ("Automatic movie backup %sabled.", 0, + autoMovieBackup ? "en" : "dis"); + } } - // Start recording an FM2 movie on Alt+R - if (keyonly (R) && is_alt) + if ( is_alt ) { - FCEUD_MovieRecordTo (); - } - - // Save a state from a file - if (keyonly (S) && is_alt) - { - FCEUD_SaveStateAs (); - } - - // Load a state from a file - if (keyonly (L) && is_alt) - { - FCEUD_LoadStateFrom (); + // Start recording an FM2 movie on Alt+R + if (keyonly (R)) + { + FCEUD_MovieRecordTo (); + } + // Save a state from a file + if (keyonly (S)) + { + FCEUD_SaveStateAs (); + } + // Load a state from a file + if (keyonly (L)) + { + FCEUD_LoadStateFrom (); + } } // Famicom disk-system games @@ -593,10 +572,9 @@ static void KeyboardCommands () { if (is_shift) { - movie_fname = - const_cast (FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0).c_str ()); - FCEUI_printf ("Recording movie to %s\n", movie_fname); - FCEUI_SaveMovie (movie_fname, MOVIE_FLAG_NONE, L""); + std::string movie_fname = FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0); + FCEUI_printf ("Recording movie to %s\n", movie_fname.c_str() ); + FCEUI_SaveMovie(movie_fname.c_str() , MOVIE_FLAG_NONE, L""); } else { @@ -682,14 +660,14 @@ static void KeyboardCommands () } // Toggle throttling - NoWaiting &= ~1; - if (g_keyState[Hotkeys[HK_TURBO]]) + if ( _keyonly(Hotkeys[HK_TURBO]) ) { - NoWaiting |= 1; + NoWaiting ^= 1; + //printf("NoWaiting: 0x%04x\n", NoWaiting ); } static bool frameAdvancing = false; - if (g_keyState[Hotkeys[HK_FRAME_ADVANCE]]) + if ( _keyonly(Hotkeys[HK_FRAME_ADVANCE])) { if (frameAdvancing == false) { @@ -739,22 +717,30 @@ static void KeyboardCommands () #endif for (int i = 0; i < 10; i++) + { if (_keyonly (Hotkeys[HK_SELECT_STATE_0 + i])) { #ifdef _GTK - gtk_radio_action_set_current_value (stateSlot, i); + setStateMenuItem(i); #endif FCEUI_SelectState (i, 1); } + } if (_keyonly (Hotkeys[HK_SELECT_STATE_NEXT])) { FCEUI_SelectStateNext (1); +#ifdef _GTK + setStateMenuItem( CurrentState ); +#endif } if (_keyonly (Hotkeys[HK_SELECT_STATE_PREV])) { FCEUI_SelectStateNext (-1); +#ifdef _GTK + setStateMenuItem( CurrentState ); +#endif } if (_keyonly (Hotkeys[HK_BIND_STATE])) @@ -959,6 +945,10 @@ void GetMouseRelative (int32 (&d)[3]) d[2] = md[2]; // buttons } +//static void checkKeyBoardState( int scanCode ) +//{ +// printf("Key State is: %i \n", g_keyState[ scanCode ] ); +//} /** * Handles outstanding SDL events. */ @@ -986,6 +976,15 @@ UpdatePhysicalInput () FCEU_printf ("Warning: unknown hotkey event %d\n", event.user.code); } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + //printf("SDL_Event.type: %i Keysym: %i ScanCode: %i\n", + // event.type, event.key.keysym.sym, event.key.keysym.scancode ); + + g_keyState[ event.key.keysym.scancode ] = (event.type == SDL_KEYDOWN) ? 1 : 0; + //checkKeyBoardState( event.key.keysym.scancode ); + break; default: break; } @@ -1010,62 +1009,20 @@ int ButtonConfigBegin () g_config->getOption ("SDL.NoGUI", &noGui); if (noGui == 1) { - SDL_QuitSubSystem (SDL_INIT_VIDEO); + //SDL_QuitSubSystem (SDL_INIT_VIDEO); bcpv = KillVideo (); } #else // XXX soules - why are we doing this right before KillVideo()? - SDL_QuitSubSystem (SDL_INIT_VIDEO); + //SDL_QuitSubSystem (SDL_INIT_VIDEO); // shut down the video and joystick subsystems bcpv = KillVideo (); #endif - SDL_Surface *screen; + //SDL_Surface *screen; bcpj = KillJoysticks (); - // reactivate the video subsystem - if (!SDL_WasInit (SDL_INIT_VIDEO)) - { - if (!bcpv) - { - InitVideo (GameInfo); - } - else - { -#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) - if (noGui == 0) - { - while (gtk_events_pending ()) - gtk_main_iteration_do (FALSE); - - char SDL_windowhack[128]; - if (gtk_widget_get_window (evbox)) - sprintf (SDL_windowhack, "SDL_WINDOWID=%u", - (unsigned int) GDK_WINDOW_XID (gtk_widget_get_window (evbox))); -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - SDL_putenv (SDL_windowhack); -#endif - } -#endif - if (SDL_InitSubSystem (SDL_INIT_VIDEO) == -1) - { - FCEUD_Message (SDL_GetError ()); - return 0; - } - - // set the screen and notify the user of button configuration -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - screen = SDL_SetVideoMode (420, 200, 8, 0); - SDL_WM_SetCaption ("Button Config", 0); -#endif - } - } - // XXX soules - why did we shut this down? // initialize the joystick subsystem InitJoysticks (); @@ -1107,13 +1064,8 @@ DTestButton (ButtConfig * bc) { if (bc->ButtType[x] == BUTTC_KEYBOARD) { -#if SDL_VERSION_ATLEAST(2, 0, 0) if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum[x])]) { -#else - if (g_keyState[bc->ButtonNum[x]]) - { -#endif return 1; } } @@ -1124,8 +1076,8 @@ DTestButton (ButtConfig * bc) return 1; } } - } - return 0; + } + return 0; } @@ -1135,15 +1087,9 @@ DTestButton (ButtConfig * bc) #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} ButtConfig GamePadConfig[4][10] = { -#if SDL_VERSION_ATLEAST(2, 0, 0) /* Gamepad 1 */ {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, -#else - /* Gamepad 1 */ - {MK (KP3), MK (KP2), MK (SLASH), MK (ENTER), - MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, -#endif /* Gamepad 2 */ GPZ (), @@ -1187,6 +1133,7 @@ UpdateGamepad(void) { if (DTestButton (&GamePadConfig[wg][x])) { + //printf("GamePad%i Button Hit: %i \n", wg, x ); if(opposite_dirs == 0) { // test for left+right and up+down @@ -1413,6 +1360,8 @@ void InitInputInterface () int x; int attrib; + memset( g_keyState, 0, sizeof(g_keyState) ); + for (t = 0, x = 0; x < 2; x++) { attrib = 0; @@ -1658,12 +1607,10 @@ const char * ButtonName (const ButtConfig * bc, int which) switch (bc->ButtType[which]) { case BUTTC_KEYBOARD: -#if SDL_VERSION_ATLEAST(2,0,0) return SDL_GetKeyName (bc->ButtonNum[which]); -#else - return SDL_GetKeyName ((SDLKey) bc->ButtonNum[which]); -#endif + break; case BUTTC_JOYSTICK: + { int joyNum, inputNum; const char *inputType, *inputDirection; @@ -1685,13 +1632,13 @@ const char * ButtonName (const ButtConfig * bc, int which) inputValue = bc->ButtonNum[which] & 0xF; if (inputValue & SDL_HAT_UP) - strncat (direction, "Up ", sizeof (direction)); + strncat (direction, "Up ", sizeof (direction)-1); if (inputValue & SDL_HAT_DOWN) - strncat (direction, "Down ", sizeof (direction)); + strncat (direction, "Down ", sizeof (direction)-1); if (inputValue & SDL_HAT_LEFT) - strncat (direction, "Left ", sizeof (direction)); + strncat (direction, "Left ", sizeof (direction)-1); if (inputValue & SDL_HAT_RIGHT) - strncat (direction, "Right ", sizeof (direction)); + strncat (direction, "Right ", sizeof (direction)-1); if (direction[0]) inputDirection = direction; @@ -1704,6 +1651,9 @@ const char * ButtonName (const ButtConfig * bc, int which) inputNum = bc->ButtonNum[which]; inputDirection = ""; } + sprintf( name, "js%i:%s%i%s", joyNum, inputType, inputNum, inputDirection ); + } + break; } return name; @@ -1713,7 +1663,7 @@ const char * ButtonName (const ButtConfig * bc, int which) * Waits for a button input and returns the information as to which * button was pressed. Used in button configuration. */ -int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) +int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigStatus ) { SDL_Event event; static int32 LastAx[64][64]; @@ -1723,11 +1673,8 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) { std::string title = "Press a key for "; title += (const char *) text; -#if SDL_VERSION_ATLEAST(2,0,0) // TODO - SDL2 -#else - SDL_WM_SetCaption (title.c_str (), 0); -#endif + //SDL_WM_SetCaption (title.c_str (), 0); puts ((const char *) text); } @@ -1807,6 +1754,16 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) } if (done) break; + + // If the button config window is Closed, + // get out of loop. + if ( buttonConfigStatus != NULL ) + { + if ( *buttonConfigStatus == 0 ) + { + break; + } + } } return (0); @@ -1828,7 +1785,7 @@ ConfigButton (char *text, ButtConfig * bc) for (wc = 0; wc < MAXBUTTCONFIG; wc++) { sprintf ((char *) buf, "%s (%d)", text, wc + 1); - DWaitButton (buf, bc, wc); + DWaitButton (buf, bc, wc, NULL); if (wc && bc->ButtType[wc] == bc->ButtType[wc - 1] && @@ -2041,7 +1998,7 @@ UpdateInput (Config * config) for (unsigned int i = 0; i < 3; i++) { - snprintf (buf, 64, "SDL.Input.%d", i); + snprintf (buf, 64, "SDL.Input.%u", i); config->getOption (buf, &device); if (device == "None") @@ -2127,7 +2084,7 @@ UpdateInput (Config * config) for (unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) { char buf[64]; - snprintf (buf, 20, "SDL.Input.GamePad.%d.", i); + snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%u.", i); prefix = buf; config->getOption (prefix + "DeviceType", &device); @@ -2160,7 +2117,7 @@ UpdateInput (Config * config) for (unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) { char buf[64]; - snprintf (buf, 20, "SDL.Input.PowerPad.%d.", i); + snprintf (buf, 32, "SDL.Input.PowerPad.%u.", i); prefix = buf; config->getOption (prefix + "DeviceType", &device); diff --git a/src/drivers/sdl/input.h b/src/drivers/sdl/input.h index bd3d4994..2a1a2d85 100644 --- a/src/drivers/sdl/input.h +++ b/src/drivers/sdl/input.h @@ -7,7 +7,8 @@ typedef struct { uint8 ButtType[MAXBUTTCONFIG]; uint8 DeviceNum[MAXBUTTCONFIG]; - uint16 ButtonNum[MAXBUTTCONFIG]; + //uint16 ButtonNum[MAXBUTTCONFIG]; + int ButtonNum[MAXBUTTCONFIG]; uint32 NumC; //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ } ButtConfig; @@ -19,10 +20,11 @@ extern ARGPSTRUCT InputArgs[]; extern int Hotkeys[]; void ParseGIInput(FCEUGI *GI); void setHotKeys(); +int getKeyState( int k ); int ButtonConfigBegin(); void ButtonConfigEnd(); void ConfigButton(char *text, ButtConfig *bc); -int DWaitButton(const uint8 *text, ButtConfig *bc, int wb); +int DWaitButton(const uint8 *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL); #define BUTTC_KEYBOARD 0x00 #define BUTTC_JOYSTICK 0x01 diff --git a/src/drivers/sdl/keyscan.h b/src/drivers/sdl/keyscan.h index 0a73804b..b3973c20 100644 --- a/src/drivers/sdl/keyscan.h +++ b/src/drivers/sdl/keyscan.h @@ -42,7 +42,3 @@ #define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */ #define SDLK_GRAVE SDLK_BACKQUOTE #define MKK(k) SDLK_##k -#if SDL_VERSION_ATLEAST(2, 0, 0) -#define SDLK_LAST SDL_NUM_SCANCODES -#endif -#define MKK_COUNT (SDLK_LAST+1) diff --git a/src/drivers/sdl/memview.cpp b/src/drivers/sdl/memview.cpp new file mode 100644 index 00000000..c89dbf3c --- /dev/null +++ b/src/drivers/sdl/memview.cpp @@ -0,0 +1,1627 @@ +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#ifdef _GTK3 +#include +#endif + +#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 "../../cart.h" +#include "../../ines.h" +#include "../common/configSys.h" + +#include "sdl.h" +#include "gui.h" +#include "dface.h" +#include "input.h" +#include "config.h" +#include "memview.h" + +extern Config *g_config; + +#define HIGHLIGHT_ACTIVITY_NUM_COLORS 16 + +static unsigned int highlightActivityColors[HIGHLIGHT_ACTIVITY_NUM_COLORS] = +{ + 0x000000, 0x004035, 0x185218, 0x5e5c34, + 0x804c00, 0xba0300, 0xd10038, 0xb21272, + 0xba00ab, 0x6f00b0, 0x3700c2, 0x000cba, + 0x002cc9, 0x0053bf, 0x0072cf, 0x3c8bc7 +}; + +struct memByte_t +{ + unsigned char data; + unsigned char color; + unsigned char actv; + unsigned char draw; +}; +//******************************************************************************************************* +// Memory View (Hex Editor) Window +//******************************************************************************************************* +// +static int getRAM( unsigned int i ) +{ + return GetMem(i); +} +static int getPPU( unsigned int i ) +{ + i &= 0x3FFF; + if (i < 0x2000)return VPage[(i) >> 10][(i)]; + //NSF PPU Viewer crash here (UGETAB) (Also disabled by 'MaxSize = 0x2000') + if (GameInfo->type == GIT_NSF) + return 0; + else + { + if (i < 0x3F00) + return vnapage[(i >> 10) & 0x3][i & 0x3FF]; + return READPAL_MOTHEROFALL(i & 0x1F); + } + return 0; +} +static int getOAM( unsigned int i ) +{ + return SPRAM[i & 0xFF]; +} +static int getROM( unsigned int offset) +{ + if (offset < 16) + { + return *((unsigned char *)&head+offset); + } + else if (offset < (16+PRGsize[0]) ) + { + return PRGptr[0][offset-16]; + } + else if (offset < (16+PRGsize[0]+CHRsize[0]) ) + { + return CHRptr[0][offset-16-PRGsize[0]]; + } + return -1; +} + +static void PalettePoke(uint32 addr, uint8 data) +{ + data = data & 0x3F; + addr = addr & 0x1F; + if ((addr & 3) == 0) + { + addr = (addr & 0xC) >> 2; + if (addr == 0) + { + PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = data; + } + else + { + UPALRAM[addr-1] = UPALRAM[0x10|(addr-1)] = data; + } + } + else + { + PALRAM[addr] = data; + } +} + +// +struct memViewWin_t +{ + GtkWidget *win; + GtkWidget *ivbar; + GtkWidget *selCellLabel; + GtkWidget *addr_entry; + GtkWidget *memSelRadioItem[4]; + GtkTextView *textview; + GtkTextBuffer *textbuf; + GtkCssProvider *cssProvider; + int selAddr; + int selRomAddr; + int jumpAddr; + int jumpDelay; + int dialog_op; + int mode; + int evntSrcID; + int numLines; + int numCharsPerLine; + struct memByte_t *mbuf; + int mbuf_size; + GtkCellRenderer *hexByte_renderer[16]; + bool redraw; + bool useActivityColors; + bool actv_color_reverse_video; + int (*memAccessFunc)( unsigned int offset); + uint64 total_instructions_lp; + + GdkRGBA bgColor; + GdkRGBA fgColor; + + std::vector colorList; + + enum { + MODE_NES_RAM = 0, + MODE_NES_PPU, + MODE_NES_OAM, + MODE_NES_ROM + }; + + memViewWin_t(void) + { + win = NULL; + textview = NULL; + textbuf = NULL; + addr_entry = NULL; + selCellLabel = NULL; + ivbar = NULL; + selAddr = 0; + selRomAddr = -1; + jumpAddr = -1; + jumpDelay = 0; + dialog_op = 0; + mode = MODE_NES_RAM; + mbuf = NULL; + mbuf_size = 0; + numLines = 0; + evntSrcID = 0; + numCharsPerLine = 90; + redraw = 1; + memAccessFunc = getRAM; + useActivityColors = 1; + total_instructions_lp = 0; + cssProvider = NULL; + actv_color_reverse_video = 1; + + bgColor.red = 1.0; + bgColor.green = 1.0; + bgColor.blue = 1.0; + bgColor.alpha = 1.0; + + fgColor.red = 0.0; + fgColor.green = 0.0; + fgColor.blue = 0.0; + fgColor.alpha = 1.0; + + for (int i=0; i<4; i++) + { + memSelRadioItem[i] = NULL; + } + for (int i=0; i<16; i++) + { + hexByte_renderer[i] = NULL; + } + } + + ~memViewWin_t(void) + { + if ( mbuf != NULL ) + { + free(mbuf); mbuf = NULL; + } + } + + void setMode(int new_mode) + { + if ( mode != new_mode ) + { + showMemViewResults(1); + } + mode = new_mode; + } + + int writeMem( unsigned int addr, int value ) + { + value = value & 0x000000ff; + + switch ( mode ) + { + default: + case MODE_NES_RAM: + { + if ( addr < 0x8000 ) + { + writefunc wfunc; + + wfunc = GetWriteHandler (addr); + + if (wfunc) + { + wfunc ((uint32) addr, + (uint8) (value & 0x000000ff)); + } + } + else + { + fprintf( stdout, "Error: Writing into RAM addresses >= 0x8000 is unsafe. Operation Denied.\n"); + } + } + break; + case MODE_NES_PPU: + { + addr &= 0x3FFF; + if (addr < 0x2000) + { + VPage[addr >> 10][addr] = value; //todo: detect if this is vrom and turn it red if so + } + if ((addr >= 0x2000) && (addr < 0x3F00)) + { + vnapage[(addr >> 10) & 0x3][addr & 0x3FF] = value; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? + } + if ((addr >= 0x3F00) && (addr < 0x3FFF)) + { + PalettePoke(addr, value); + } + } + break; + case MODE_NES_OAM: + { + addr &= 0xFF; + SPRAM[addr] = value; + } + break; + case MODE_NES_ROM: + { + if (addr < 16) + { + fprintf( stdout, "You can't edit ROM header here, however you can use iNES Header Editor to edit the header if it's an iNES format file."); + } + else if ( (addr >= 16) && (addr < PRGsize[0]+16) ) + { + *(uint8 *)(GetNesPRGPointer(addr-16)) = value; + } + else if ( (addr >= PRGsize[0]+16) && (addr < CHRsize[0]+PRGsize[0]+16) ) + { + *(uint8 *)(GetNesCHRPointer(addr-16-PRGsize[0])) = value; + } + } + break; + } + return 0; + } + + int gotoLocation( int addr ); + void showMemViewResults (int reset); + int calcVisibleRange( int *start_out, int *end_out, int *center_out ); + int getAddrFromCursor( int CursorTextOffset = -1 ); + int checkMemActivity(void); + void initMem(void); + int upDateTextViewStyle(void); + void initColors(void); + +}; + +static int conv2xchar( int i ) +{ + int c = 0; + + if ( (i >= 0) && (i < 10) ) + { + c = i + '0'; + } + else if ( i < 16 ) + { + c = (i - 10) + 'A'; + } + return c; +} + +void memViewWin_t::initMem(void) +{ + + for (int i=0; i 0 ) + { + mbuf[i].draw = 1; + mbuf[i].actv--; + } + } + } + total_instructions_lp = total_instructions; + + return 0; +} + +int memViewWin_t::getAddrFromCursor( int CursorTextOffset ) +{ + int line, offs, byte0, byte, bcol, addr = -1; + + if ( CursorTextOffset < 0 ) + { + gint cpos; + g_object_get( textbuf, "cursor-position", &cpos, NULL ); + CursorTextOffset = cpos; + } + line = CursorTextOffset / numCharsPerLine; + offs = CursorTextOffset % numCharsPerLine; + + if ( offs < 10 ) + { + return addr; + } + else if ( offs < 73 ) + { + byte0 = (offs - 10); + + byte = byte0 / 4; + bcol = byte0 % 4; + + if ( byte < 16 ) + { + if (bcol < 2) + { + addr = (line*16) + byte; + } + } + } + else + { + if ( (offs >= 73) && (offs < 89) ) + { + addr = (line*16) + (offs-73); + } + } + + return addr; +} + +void memViewWin_t::showMemViewResults (int reset) +{ + int addr, memSize = 0; + int lineAddr = 0, c, un, ln; + int i, row, row_start, row_end, totalChars; + gint cpos, textview_lines_allocated; + char addrStr[128], valStr[16][8], ascii[18]; + char addrChg, valChg[16], activityColoringOn, colorEnable; + GtkTextIter iter, next_iter; //, start_iter, end_iter; + + if ( redraw ) + { + reset = 1; + redraw = 0; + } + + switch ( mode ) + { + default: + case MODE_NES_RAM: + memAccessFunc = getRAM; + memSize = 0x10000; + break; + case MODE_NES_PPU: + memAccessFunc = getPPU; + memSize = (GameInfo->type == GIT_NSF ? 0x2000 : 0x4000); + break; + case MODE_NES_OAM: + memAccessFunc = getOAM; + memSize = 0x100; + break; + case MODE_NES_ROM: + + if ( GameInfo != NULL ) + { + memAccessFunc = getROM; + memSize = 16 + CHRsize[0] + PRGsize[0]; + } + else + { // No Game Loaded!!! Get out of Function + memAccessFunc = NULL; + memSize = 0; + if ( mbuf ) + { + free(mbuf); mbuf = NULL; + } + mbuf_size = 0; + redraw = 1; + gtk_text_buffer_set_text( textbuf, "No ROM Loaded", -1 ); + return; + } + break; + } + numLines = memSize / 16; + + if ( (mbuf == NULL) || (mbuf_size != memSize) ) + { + printf("Mode: %i MemSize:%i 0x%08x\n", mode, memSize, (unsigned int)memSize ); + reset = 1; + + if ( mbuf ) + { + free(mbuf); mbuf = NULL; + } + mbuf = (struct memByte_t *)malloc( memSize * sizeof(struct memByte_t) ); + + if ( mbuf ) + { + mbuf_size = memSize; + initMem(); + } + else + { + printf("Error: Failed to allocate memview buffer size\n"); + mbuf_size = 0; + return; + } + } + + g_object_get( textbuf, "cursor-position", &cpos, NULL ); + + selAddr = getAddrFromCursor( cpos ); + + //printf("CPOS: %i \n", cpos ); + + if ( reset ) + { + //gtk_text_buffer_get_bounds( textbuf, &start_iter, &end_iter ); + + //gtk_text_buffer_delete( textbuf, &start_iter, &end_iter ); + gtk_text_buffer_set_text( textbuf, "", -1 ); + + row_start = 0; + row_end = numLines; + + gtk_text_buffer_get_iter_at_offset( textbuf, &iter, 0 ); + } + else + { + calcVisibleRange( &row_start, &row_end, NULL ); + + gtk_text_buffer_get_iter_at_line( textbuf, &iter, row_start ); + } + + activityColoringOn = useActivityColors && (mode != MODE_NES_ROM); + + colorEnable = activityColoringOn; + + checkMemActivity(); + + //gtk_text_buffer_get_iter_at_offset( textbuf, &iter, 0 ); + + totalChars = row_start * numCharsPerLine; + + textview_lines_allocated = gtk_text_buffer_get_line_count( textbuf ) - 1; + + for (row=row_start; row= textview_lines_allocated ) + { + reset = 1; + } + + addrChg = reset; + + lineAddr = (row*16); + + if ( addrChg ) + { + next_iter = iter; + gtk_text_iter_forward_chars( &next_iter, 9 ); + + sprintf( addrStr, "%08X ", lineAddr ); + + if ( !reset ) + { + gtk_text_buffer_delete( textbuf, &iter, &next_iter ); + } + gtk_text_buffer_insert( textbuf, &iter, addrStr, -1 ); + } + else + { + gtk_text_iter_forward_chars( &iter, 9 ); + } + + for (i=0; i<16; i++) + { + valChg[i] = reset; + + addr = lineAddr+i; + + c = memAccessFunc(addr); + + if ( mbuf[addr].draw ) + { + mbuf[addr].draw = 0; + valChg[i] = 1; + } + + un = ( c & 0x00f0 ) >> 4; + ln = ( c & 0x000f ); + + valStr[i][0] = ' '; + valStr[i][1] = conv2xchar(un); + valStr[i][2] = conv2xchar(ln); + valStr[i][3] = ' '; + valStr[i][4] = 0; + + if ( isprint(c) ) + { + ascii[i] = c; + } + else + { + ascii[i] = '.'; + } + + next_iter = iter; + + if ( valChg[i] ) + { + if ( !reset ) + { + next_iter = iter; + gtk_text_iter_forward_chars( &next_iter, 4 ); + + gtk_text_buffer_delete( textbuf, &iter, &next_iter ); + } + if ( colorEnable ) + { + if ( activityColoringOn ) + { + if ( mbuf[addr].actv > 0 ) + { + if ( actv_color_reverse_video ) + { + gtk_text_buffer_insert_with_tags( textbuf, &iter, valStr[i], -1, colorList[ mbuf[addr].actv + HIGHLIGHT_ACTIVITY_NUM_COLORS ], NULL ); + } + else + { + gtk_text_buffer_insert_with_tags( textbuf, &iter, valStr[i], -1, colorList[ mbuf[addr].actv ], NULL ); + } + } + else + { + gtk_text_buffer_insert( textbuf, &iter, valStr[i], -1 ); + } + } + else + { + gtk_text_buffer_insert_with_tags( textbuf, &iter, valStr[i], -1, colorList[ mbuf[addr].color ], NULL ); + } + } + else + { // No Color Options Active, other than regular fore/back ground coloring. + gtk_text_buffer_insert( textbuf, &iter, valStr[i], -1 ); + } + } + else + { + //if ( !reset ) + //{ + // next_iter = iter; + + // if ( gtk_text_iter_forward_chars( &next_iter, 4 ) == FALSE ) + // { + // return; + // } + + // //gtk_text_buffer_remove_all_tags( textbuf, &iter, &next_iter ); + // //gtk_text_buffer_delete( textbuf, &iter, &next_iter ); + + // //gtk_text_buffer_insert( textbuf, &iter, valStr[i], -1 ); + //} + if ( gtk_text_iter_forward_chars( &iter, 4 ) == FALSE) + { + return; + } + } + } + ascii[16] = 0; + + for (i=0; i<16; i++) + { + if ( valChg[i] ) + { + if ( !reset ) + { + next_iter = iter; + + if ( gtk_text_iter_forward_chars( &next_iter, 1 ) == FALSE ) + { + return; + } + gtk_text_buffer_delete( textbuf, &iter, &next_iter ); + } + gtk_text_buffer_insert( textbuf, &iter, &ascii[i], 1 ); + } + else + { + if ( gtk_text_iter_forward_chars( &iter, 1 ) == FALSE ) + { + return; + } + } + } + + numCharsPerLine = 9 + (4*16) + 16 + 1; + + if ( reset ) + { + gtk_text_buffer_insert ( textbuf, &iter, "\n", -1 ); + } + else + { + gtk_text_iter_forward_chars( &iter, 1 ); + } + + totalChars += numCharsPerLine; + } + + // Put cursor back where it was + gtk_text_buffer_get_iter_at_offset( textbuf, &iter, cpos ); + gtk_text_buffer_place_cursor( textbuf, &iter ); + + // Check if a Jump Delay is set. + if ( jumpDelay <= 0 ) + { + if ( jumpAddr >= 0 ) + { + gotoLocation( jumpAddr ); + jumpAddr = -1; + } + jumpDelay = 0; + } + else + { + jumpDelay--; + } + + if ( selAddr >= 0 ) + { + sprintf( addrStr, "Selected Addr: 0x%08X", selAddr ); + } + else + { + addrStr[0] = 0; + } + gtk_label_set_text( GTK_LABEL(selCellLabel), addrStr ); + +} + +int memViewWin_t::calcVisibleRange( int *start_out, int *end_out, int *center_out ) +{ + //GtkAdjustment *ivadj; + //double v, l, u, r; + int start, end, center; + GdkRectangle rect; + GtkTextIter iter; + + gtk_text_view_get_visible_rect( textview, &rect ); + + gtk_text_view_get_line_at_y( textview, &iter, rect.y, NULL ); + start = gtk_text_iter_get_line( &iter ) - 1; + + gtk_text_view_get_line_at_y( textview, &iter, rect.y+rect.height, NULL ); + end = gtk_text_iter_get_line( &iter ) + 1; + + if ( start < 0 ) start = 0; + + if ( end > (start+32) ) + { + end = start + 32; + } + if ( end > numLines ) + { + end = numLines; + } + + center = start + (end - start)/2; + + if ( start_out ) *start_out = start; + if ( end_out ) *end_out = end; + if ( center_out ) *center_out = center; + + //printf("Start:%i End:%i StartADDR:%08X EndADDR:%08X Rect: X:%i Y:%i W:%i H:%i \n", + // start, end, start*16, end*16, rect.x, rect.y, rect.width, rect.height ); + + return 0; +} + +int memViewWin_t::gotoLocation( int addr ) +{ + int linenum, bytenum, cpos; + GtkTextIter iter; + + linenum = addr / 16; + bytenum = addr % 16; + + cpos = (linenum*numCharsPerLine) + (bytenum*4) + 10; + + //printf("Line:%i Byte:%i CPOS:%i \n", linenum, bytenum, cpos ); + + gtk_text_buffer_get_iter_at_offset( textbuf, &iter, cpos ); + + gtk_text_view_scroll_to_iter ( textview, &iter, 0.0, 1, 0.0, 0.25 ); + gtk_text_buffer_place_cursor( textbuf, &iter ); + + return 0; +} + +static void gdkColorConv( GdkRGBA *in, int *out ) +{ + *out = 0; + *out |= ( (int)( (in->red * 255.0) ) & 0x00ff) << 16; + *out |= ( (int)( (in->green * 255.0) ) & 0x00ff) << 8; + *out |= ( (int)( (in->blue * 255.0) ) & 0x00ff); +} + +void memViewWin_t::initColors(void) +{ + GdkRGBA color, ivcolor; + GtkTextTag *tag; + float avg, grayScale; + + // Normal Activity Colors + for (int i=0; i> 8; + b = (highlightActivityColors[i] & 0x00ff0000) >> 16; + + color.red = (double)r / 255.0f; + color.green = (double)g / 255.0f; + color.blue = (double)b / 255.0f; + color.alpha = 1.0; + + tag = gtk_text_buffer_create_tag( textbuf, stmp, + "foreground-rgba", &color, NULL ); + + colorList.push_back( tag ); + } + + // Reverse Video Activity Colors + for (int i=0; i> 8; + b = (highlightActivityColors[i] & 0x00ff0000) >> 16; + + color.red = (double)r / 255.0f; + color.green = (double)g / 255.0f; + color.blue = (double)b / 255.0f; + color.alpha = 1.0; + + avg = (color.red + color.green + color.blue) / 3.0; + + if ( avg >= 0.5 ) + { + grayScale = 0.0; + } + else + { + grayScale = 1.0; + } + + ivcolor.red = grayScale; + ivcolor.green = grayScale; + ivcolor.blue = grayScale; + ivcolor.alpha = 1.0; + + //printf("%i R:%f G:%f B:%f \n", i, color.red, color.green, color.blue ); + + tag = gtk_text_buffer_create_tag( textbuf, stmp, + "background-rgba", &color, "foreground-rgba", &ivcolor, NULL ); + + colorList.push_back( tag ); + } + return; +} + +int memViewWin_t::upDateTextViewStyle(void) +{ + char styleString[512]; + int fg, bg; + + gdkColorConv( &bgColor, &bg ); + gdkColorConv( &fgColor, &fg ); + + sprintf( styleString, +"#hex_editor text \ +{\ + color: #%06X;\ + background-color: #%06X; \ +}", fg, bg ); + + //printf("Style: %s\n", styleString ); + + gtk_css_provider_load_from_data(cssProvider, styleString, -1, NULL); + + return 0; +} + +static int memViewEvntSrcID = 0; +static std::list memViewWinList; + +static void changeModeRAM (GtkRadioMenuItem * radiomenuitem, memViewWin_t *mv) +{ + printf("Changing Mode RAM \n"); + mv->setMode( memViewWin_t::MODE_NES_RAM ); +} +static void changeModePPU (GtkRadioMenuItem * radiomenuitem, memViewWin_t *mv) +{ + printf("Changing Mode PPU \n"); + mv->setMode( memViewWin_t::MODE_NES_PPU ); +} +static void changeModeOAM (GtkRadioMenuItem * radiomenuitem, memViewWin_t *mv) +{ + printf("Changing Mode OAM \n"); + mv->setMode( memViewWin_t::MODE_NES_OAM ); +} +static void changeModeROM (GtkRadioMenuItem * radiomenuitem, memViewWin_t *mv) +{ + printf("Changing Mode ROM \n"); + mv->setMode( memViewWin_t::MODE_NES_ROM ); +} + +static void colorPickCB (GtkDialog *dialog, + gint response_id, + memViewWin_t *mv) +{ + GdkRGBA color; + const char *title; + + gtk_color_chooser_get_rgba ( GTK_COLOR_CHOOSER( dialog ), &color ); + + title = gtk_window_get_title( GTK_WINDOW(dialog) ); + + //printf("Response: %s %i R:%f G:%f B:%f\n", + // gtk_window_get_title( GTK_WINDOW(dialog) ), + // response_id, color.red, color.green, color.blue ); + + if ( GTK_RESPONSE_OK == response_id ) + { + if ( strstr( title, "Background" ) ) + { + mv->bgColor = color; + mv->upDateTextViewStyle(); + } + else if ( strstr( title, "Foreground" ) ) + { + mv->fgColor = color; + mv->upDateTextViewStyle(); + } + } + + gtk_widget_destroy ( GTK_WIDGET(dialog) ); +} + +static void openColorPicker (memViewWin_t *mv, int mode) +{ + GtkWidget *w; + char title[256]; + + //printf("Open Color Picker \n"); + + if ( mode ) + { + strcpy( title, "Pick Background Color"); + } + else + { + strcpy( title, "Pick Foreground Color"); + } + + w = gtk_color_chooser_dialog_new( title, GTK_WINDOW(mv->win) ); + + g_signal_connect (w, "response", G_CALLBACK (colorPickCB), + (gpointer) mv); + + gtk_widget_show_all (w); +} + +static void openColorPicker_FG_CB (GtkMenuItem * item, memViewWin_t *mv) +{ + openColorPicker (mv,0); +} +static void openColorPicker_BG_CB (GtkMenuItem * item, memViewWin_t *mv) +{ + openColorPicker (mv,1); +} + +static void toggleActivityHighlight (GtkCheckMenuItem * item, memViewWin_t *mv) +{ + mv->useActivityColors = gtk_check_menu_item_get_active (item); + + //printf("ToggleMenu: %i\n", (int)toggleMenu); + //g_config->setOption ("SDL.ToggleMenu", (int) toggleMenu); +} + +static void toggleActivityReverseVideo (GtkCheckMenuItem * item, memViewWin_t *mv) +{ + mv->actv_color_reverse_video = gtk_check_menu_item_get_active (item); + + //printf("ToggleMenu: %i\n", (int)toggleMenu); + //g_config->setOption ("SDL.ToggleMenu", (int) toggleMenu); +} + +static GtkWidget *CreateMemViewMenubar (memViewWin_t * mv) +{ + GtkWidget *menubar, *menu, *item; + GSList *radioGroup; + + menubar = gtk_menu_bar_new (); + + item = gtk_menu_item_new_with_label ("View"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item); + + menu = gtk_menu_new (); + + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu); + + //-View --> RAM ------------------ + radioGroup = NULL; + + mv->memSelRadioItem[0] = gtk_radio_menu_item_new_with_label (radioGroup, "RAM"); + + radioGroup = + gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM(mv->memSelRadioItem[0])); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mv->memSelRadioItem[0]); + + g_signal_connect (mv->memSelRadioItem[0], "activate", G_CALLBACK (changeModeRAM), + (gpointer) mv); + + //-View --> PPU ------------------ + mv->memSelRadioItem[1] = gtk_radio_menu_item_new_with_label (radioGroup, "PPU"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mv->memSelRadioItem[1]); + + g_signal_connect (mv->memSelRadioItem[1], "activate", G_CALLBACK (changeModePPU), + (gpointer) mv); + + //-View --> OAM ------------------ + mv->memSelRadioItem[2] = gtk_radio_menu_item_new_with_label (radioGroup, "OAM"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mv->memSelRadioItem[2]); + + g_signal_connect (mv->memSelRadioItem[2], "activate", G_CALLBACK (changeModeOAM), + (gpointer) mv); + + //-View --> ROM ------------------ + mv->memSelRadioItem[3] = gtk_radio_menu_item_new_with_label (radioGroup, "ROM"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mv->memSelRadioItem[3]); + + g_signal_connect (mv->memSelRadioItem[3], "activate", G_CALLBACK (changeModeROM), + (gpointer) mv); + + //-Color ------------------ + item = gtk_menu_item_new_with_label ("Colors"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item); + + menu = gtk_menu_new (); + + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu); + + //-Color --> Set Foreground ------------------ + item = gtk_menu_item_new_with_label ("Set Foreground"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item ); + + g_signal_connect (item, "activate", G_CALLBACK (openColorPicker_FG_CB), + (gpointer) mv); + + //-Color --> Set Background ------------------ + item = gtk_menu_item_new_with_label ("Set Background"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item ); + + g_signal_connect (item, "activate", G_CALLBACK (openColorPicker_BG_CB), + (gpointer) mv); + + //-HighLight ------------------ + item = gtk_menu_item_new_with_label ("Highlight"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menubar), item); + + menu = gtk_menu_new (); + + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu); + + //-HighLight --> Activity ------------------ + item = gtk_check_menu_item_new_with_label ("Activity"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item ); + + g_signal_connect (item, "activate", G_CALLBACK (toggleActivityHighlight), + (gpointer) mv); + + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), mv->useActivityColors ); + + //-HighLight --> Reverse Video ------------------ + item = gtk_check_menu_item_new_with_label ("Reverse Video"); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item ); + + g_signal_connect (item, "activate", G_CALLBACK (toggleActivityReverseVideo), + (gpointer) mv); + + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), mv->actv_color_reverse_video ); + + // Finally, return the actual menu bar created + return menubar; +} + + +static void closeMemoryViewWindow (GtkWidget * w, GdkEvent * e, memViewWin_t * mv) +{ + std::list < memViewWin_t * >::iterator it; + + for (it = memViewWinList.begin (); it != memViewWinList.end (); it++) + { + if (mv == *it) + { + //printf("Removing MemView Window %p from List\n", cw); + memViewWinList.erase (it); + break; + } + } + + delete mv; + + gtk_widget_destroy (w); +} + +static void +textview_string_insert (GtkTextView *text_view, + gchar *string, + memViewWin_t * mv ) +{ + printf("String: '%s'\n", string ); + +} + +static gboolean textbuffer_string_insert (GtkWidget * grab, GdkEventKey * event, memViewWin_t * mv) +{ + int addr, line, offs, byte0, byte, bcol, c, d; + gint cpos; + gboolean stopKeyPropagate = TRUE; + + g_object_get( mv->textbuf, "cursor-position", &cpos, NULL ); + + line = cpos / mv->numCharsPerLine; + offs = cpos % mv->numCharsPerLine; + + byte0 = (offs - 10); + + byte = byte0 / 4; + bcol = byte0 % 4; + + addr = (line*16) + byte; + + //printf("Line: %i Offset: %i Byte:%i Bcol:%i\n", line, offs, byte, bcol ); + + d = event->keyval; + + //printf("Key: %i '%c' \n", d, d ); + + stopKeyPropagate = (d != GDK_KEY_Up ) && + (d != GDK_KEY_Down ) && + (d != GDK_KEY_Left ) && + (d != GDK_KEY_Right ) && + (d != GDK_KEY_Page_Up ) && + (d != GDK_KEY_Page_Down); + + if ( !isascii( d ) ) + { + return stopKeyPropagate; + } + + if ( offs > (9 + (16*4)) ) + { // ASCII Text Area + byte = (offs - 73); + + if ( (byte < 0) || (byte >= 16) ) + { + return stopKeyPropagate; + } + addr = (line*16) + byte; + + c = d; + } + else + { // Hex Text Area + if ( !isxdigit( d ) ) + { + return stopKeyPropagate; + } + byte0 = (offs - 10); + + byte = byte0 / 4; + bcol = byte0 % 4; + + addr = (line*16) + byte; + + if ( (d >= '0') && (d <= '9') ) + { + d = d - '0'; + } + else if ( (d >= 'a') && (d <= 'f') ) + { + d = d - 'a' + 10; + } + else + { + d = d - 'A' + 10; + } + + c = mv->memAccessFunc( addr ); + + //printf("Changing Addr:0x%08x from:0x%02x ", addr, c ); + + if ( bcol == 0 ) + { + c = c & 0x0f; + c = c | (d << 4); + } + else if ( bcol == 1 ) + { + c = c & 0xf0; + c = c | d; + } + } + //printf(" to:0x%02x \n", c ); + + mv->writeMem( addr, c ); + + // Return wether to allow GTK+ to process this key. + return stopKeyPropagate; +} + +static void +textview_backspace_cb (GtkTextView *text_view, + memViewWin_t * mv) +{ + //printf("BackSpace:\n"); + mv->redraw = 1; +} + +static void handleDialogResponse (GtkWidget * w, gint response_id, memViewWin_t * mv) +{ + //printf("Response %i\n", response_id ); + + if ( response_id == GTK_RESPONSE_OK ) + { + const char *txt; + + //printf("Reponse OK\n"); + + txt = gtk_entry_get_text( GTK_ENTRY( mv->addr_entry ) ); + + if ( txt != NULL ) + { + //printf("Text: '%s'\n", txt ); + switch (mv->dialog_op) + { + case 1: + if ( isxdigit(txt[0]) ) + { // Address is always treated as hex number + mv->gotoLocation( strtol( txt, NULL, 16 ) ); + } + break; + case 2: + if ( isdigit(txt[0]) ) + { // Value is numerical + mv->writeMem( mv->selAddr, strtol( txt, NULL, 0 ) ); + } + else if ( (txt[0] == '\'') && (txt[2] == '\'') ) + { // Byte to be written is expressed as ASCII character + mv->writeMem( mv->selAddr, txt[1] ); + } + break; + } + } + } + //else if ( response_id == GTK_RESPONSE_CANCEL ) + //{ + // printf("Reponse Cancel\n"); + //} + gtk_widget_destroy (w); + + mv->addr_entry = NULL; +} + +static void closeDialogWindow (GtkWidget * w, GdkEvent * e, memViewWin_t * mv) +{ + gtk_widget_destroy (w); + + mv->addr_entry = NULL; +} + +static void +gotoLocationCB (GtkMenuItem *menuitem, + memViewWin_t * mv) +{ + GtkWidget *win; + GtkWidget *vbox; + + mv->dialog_op = 1; + + win = gtk_dialog_new_with_buttons ("Goto Address", + GTK_WINDOW (mv->win), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Cancel", GTK_RESPONSE_CANCEL, + "_Goto", GTK_RESPONSE_OK, NULL); + + gtk_dialog_set_default_response( GTK_DIALOG(win), GTK_RESPONSE_OK ); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); + + mv->addr_entry = gtk_entry_new (); + + gtk_entry_set_activates_default( GTK_ENTRY (mv->addr_entry), TRUE ); + + gtk_entry_set_text (GTK_ENTRY (mv->addr_entry), "0x0"); + + gtk_box_pack_start (GTK_BOX (vbox), mv->addr_entry, TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (win))), vbox, TRUE, TRUE, 1); + + gtk_widget_show_all (win); + + g_signal_connect (win, "delete-event", + G_CALLBACK (closeDialogWindow), mv); + g_signal_connect (win, "response", + G_CALLBACK (handleDialogResponse), mv); + +} + +static void +setValueCB (GtkMenuItem *menuitem, + memViewWin_t * mv) +{ + GtkWidget *win; + GtkWidget *vbox; + char stmp[256]; + + mv->dialog_op = 2; + + sprintf( stmp, "Poke Address 0x%08x", mv->selAddr ); + + win = gtk_dialog_new_with_buttons ( stmp, + GTK_WINDOW (mv->win), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Cancel", GTK_RESPONSE_CANCEL, + "_Write", GTK_RESPONSE_OK, NULL); + + gtk_dialog_set_default_response( GTK_DIALOG(win), GTK_RESPONSE_OK ); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); + + mv->addr_entry = gtk_entry_new (); + + gtk_entry_set_text (GTK_ENTRY (mv->addr_entry), "0x0"); + + gtk_entry_set_activates_default( GTK_ENTRY (mv->addr_entry), TRUE ); + + gtk_box_pack_start (GTK_BOX (vbox), mv->addr_entry, TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (win))), vbox, TRUE, TRUE, 1); + + gtk_widget_show_all (win); + + g_signal_connect (win, "delete-event", + G_CALLBACK (closeDialogWindow), mv); + g_signal_connect (win, "response", + G_CALLBACK (handleDialogResponse), mv); + +} + +static void +gotoRomLocationCB (GtkMenuItem *menuitem, + memViewWin_t * mv) +{ + gtk_menu_item_activate( GTK_MENU_ITEM(mv->memSelRadioItem[3]) ); + + mv->setMode( memViewWin_t::MODE_NES_ROM ); + + mv->showMemViewResults(1); + + mv->jumpAddr = mv->selRomAddr; + mv->jumpDelay = 10; + +} + +static gboolean +populate_context_menu (GtkWidget *popup, + memViewWin_t * mv ) +{ + GtkWidget *menu = NULL; + GtkWidget *item; + char stmp[256]; + + //printf("Context Menu\n"); + + menu = gtk_menu_new (); + + item = gtk_menu_item_new_with_label("Goto Address..."); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (gotoLocationCB), mv); + + switch ( mv->mode ) + { + case memViewWin_t::MODE_NES_RAM: + { + if ( mv->selAddr >= 0x0000 ) + { + sprintf( stmp, "Poke RAM 0x%04X", mv->selAddr ); + + item = gtk_menu_item_new_with_label(stmp); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (setValueCB), mv); + } + if ( mv->selAddr >= 0x6000 ) + { + mv->selRomAddr = GetNesFileAddress(mv->selAddr); + + if ( mv->selRomAddr >= 0 ) + { + sprintf( stmp, "Goto ROM 0x%08X", mv->selRomAddr ); + + item = gtk_menu_item_new_with_label(stmp); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (gotoRomLocationCB), mv); + } + } + } + break; + case memViewWin_t::MODE_NES_PPU: + { + if ( mv->selAddr >= 0x0000 ) + { + sprintf( stmp, "Poke PPU 0x%08X", mv->selAddr ); + + item = gtk_menu_item_new_with_label(stmp); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (setValueCB), mv); + } + } + break; + case memViewWin_t::MODE_NES_OAM: + { + if ( mv->selAddr >= 0x0000 ) + { + sprintf( stmp, "Poke OAM 0x%08X", mv->selAddr ); + + item = gtk_menu_item_new_with_label(stmp); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (setValueCB), mv); + } + } + break; + case memViewWin_t::MODE_NES_ROM: + { + if ( mv->selAddr >= 0x0000 ) + { + sprintf( stmp, "Poke ROM 0x%08X", mv->selAddr ); + + item = gtk_menu_item_new_with_label(stmp); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + g_signal_connect (item, "activate", + G_CALLBACK (setValueCB), mv); + } + } + break; + } + + gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL ); + //gtk_widget_show_all (popup); + gtk_widget_show_all (menu); + + return TRUE; +} + +static gboolean +textview_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + memViewWin_t * mv ) +{ + gboolean ret = FALSE; + //printf("Press Button %i %u\n", event->type, event->button ); + + if ( event->button == 3 ) + { + ret = populate_context_menu( widget, mv ); + } + + return ret; +} + +static gint updateMemViewTree (void *userData) +{ + std::list ::iterator it; + + for (it=memViewWinList.begin(); it != memViewWinList.end(); it++) + { + (*it)->showMemViewResults(0); + } + return 1; +} + +void openMemoryViewWindow (void) +{ + GtkWidget *main_vbox; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *scroll; + GtkWidget *menubar; + memViewWin_t *mv; + + mv = new memViewWin_t; + + memViewWinList.push_back (mv); + + mv->win = gtk_dialog_new_with_buttons ("Memory View", + GTK_WINDOW (MainWindow), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Close", GTK_RESPONSE_OK, + NULL); + + gtk_window_set_default_size (GTK_WINDOW (mv->win), 800, 600); + + main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); + + menubar = CreateMemViewMenubar(mv); + + gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0); + + mv->textview = (GtkTextView*) gtk_text_view_new(); + + gtk_widget_set_name( GTK_WIDGET(mv->textview), "hex_editor"); + gtk_text_view_set_monospace( mv->textview, TRUE ); + gtk_text_view_set_overwrite( mv->textview, TRUE ); + gtk_text_view_set_editable( mv->textview, TRUE ); + gtk_text_view_set_wrap_mode( mv->textview, GTK_WRAP_NONE ); + gtk_text_view_set_cursor_visible( mv->textview, TRUE ); + + g_signal_connect (mv->textview, "insert-at-cursor", + G_CALLBACK (textview_string_insert), mv); + g_signal_connect (mv->textview, "preedit-changed", + G_CALLBACK (textview_string_insert), mv); + g_signal_connect (mv->textview, "backspace", + G_CALLBACK (textview_backspace_cb), mv); + g_signal_connect (mv->textview, "popup-menu", + G_CALLBACK (populate_context_menu), mv); + g_signal_connect (mv->textview, "button-press-event", + G_CALLBACK (textview_button_press_cb), mv); + + mv->textbuf = gtk_text_view_get_buffer( mv->textview ); + + g_signal_connect (G_OBJECT (mv->textview), "key-press-event", + G_CALLBACK (textbuffer_string_insert), mv); + + mv->initColors(); + + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS); + gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET(mv->textview) ); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); + gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 2); + + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 5); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + + mv->selCellLabel = gtk_label_new(""); + //g_object_set (mv->selCellLabel, "family", "MonoSpace", NULL); + gtk_box_pack_start (GTK_BOX (hbox), mv->selCellLabel, FALSE, FALSE, 5); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 5); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (mv->win))), main_vbox, TRUE, TRUE, + 0); + + mv->ivbar = gtk_scrolled_window_get_vscrollbar( GTK_SCROLLED_WINDOW(scroll) ); + + g_signal_connect (mv->win, "delete-event", + G_CALLBACK (closeMemoryViewWindow), mv); + g_signal_connect (mv->win, "response", + G_CALLBACK (closeMemoryViewWindow), mv); + + mv->cssProvider = gtk_css_provider_new(); + + mv->upDateTextViewStyle(); + + gtk_style_context_add_provider( gtk_widget_get_style_context( GTK_WIDGET(mv->textview) ), + GTK_STYLE_PROVIDER(mv->cssProvider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + + gtk_widget_show_all (mv->win); + + mv->showMemViewResults(1); + + if (memViewEvntSrcID == 0) + { + memViewEvntSrcID = + g_timeout_add (100, updateMemViewTree, mv); + } + +} diff --git a/src/drivers/sdl/memview.h b/src/drivers/sdl/memview.h new file mode 100644 index 00000000..aa149af3 --- /dev/null +++ b/src/drivers/sdl/memview.h @@ -0,0 +1,4 @@ +// memview.h +// + +void openMemoryViewWindow (void); diff --git a/src/drivers/sdl/ramwatch.cpp b/src/drivers/sdl/ramwatch.cpp new file mode 100644 index 00000000..9683ce92 --- /dev/null +++ b/src/drivers/sdl/ramwatch.cpp @@ -0,0 +1,1235 @@ +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#ifdef _GTK3 +#include +#endif + +#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" + +extern Config *g_config; + +//******************************************************************************************************* +// Ram Watch Window +//******************************************************************************************************* +// +struct ramWatch_t +{ + std::string name; + int addr; + int type; + int size; + + union + { + int8_t i8; + uint8_t u8; + int16_t i16; + uint16_t u16; + } val; + + ramWatch_t (void) + { + addr = 0; + type = 0; + size = 0; + val.u16 = 0; + }; + + void updateMem (void) + { + if (size == 1) + { + val.u8 = GetMem (addr); + } + else if (size == 2) + { + val.u16 = GetMem (addr) | (GetMem (addr + 1) << 8); + } + else + { + val.u8 = GetMem (addr); + } + } +}; + +struct ramWatchList_t +{ + + std::list < ramWatch_t * >ls; + + ramWatchList_t (void) + { + + } + + ~ramWatchList_t (void) + { + ramWatch_t *rw; + + while (!ls.empty ()) + { + rw = ls.front (); + + delete rw; + + ls.pop_front (); + } + } + + size_t size (void) + { + return ls.size (); + }; + + void add_entry (const char *name, int addr, int type, int size) + { + ramWatch_t *rw = new ramWatch_t; + + rw->name.assign (name); + rw->addr = addr; + rw->type = type; + rw->size = size; + ls.push_back (rw); + } + + void updateMemoryValues (void) + { + ramWatch_t *rw; + std::list < ramWatch_t * >::iterator it; + + for (it = ls.begin (); it != ls.end (); it++) + { + rw = *it; + + rw->updateMem (); + } + } + + ramWatch_t *getIndex (size_t idx) + { + size_t i = 0; + std::list < ramWatch_t * >::iterator it; + + for (it = ls.begin (); it != ls.end (); it++) + { + if (i == idx) + { + return *it; + } + i++; + } + return NULL; + } + + int deleteIndex (size_t idx) + { + size_t i = 0; + std::list < ramWatch_t * >::iterator it; + + for (it = ls.begin (); it != ls.end (); it++) + { + if (i == idx) + { + delete *it; + ls.erase (it); + return 0; + } + i++; + } + return -1; + } +}; + +static ramWatchList_t ramWatchList; + +struct ramWatchWin_t; + +struct ramWatchEntryWin_t +{ + GtkWidget *win; + GtkWidget *chkbox; + GtkWidget *button1, *button2, *button4; + GtkWidget *txt_entry_name; + GtkWidget *txt_entry_addr; + ramWatchWin_t *rww; + int idx; + + ramWatchEntryWin_t (void) + { + win = NULL; + chkbox = NULL; + button1 = NULL; + button2 = NULL; + button4 = NULL; + txt_entry_name = NULL; + txt_entry_addr = NULL; + rww = NULL; + idx = -1; + } +}; + +struct ramWatchWin_t +{ + + GtkWidget *win; + GtkWidget *tree; + GtkTreeStore *ram_watch_store; + bool ramWatchWinOpen; + int ramWatchEditRowIdx; + int ramWatchEditColIdx; + + ramWatchWin_t (void) + { + win = NULL; + tree = NULL; + ram_watch_store = NULL; + ramWatchWinOpen = false; + ramWatchEditRowIdx = -1; + ramWatchEditColIdx = -1; + } + + void showRamWatchResults (int reset); +}; + +static gint ramWatchEvntSrcID = 0; + +void ramWatchWin_t::showRamWatchResults (int reset) +{ + int row = 0; + std::list < ramWatch_t * >::iterator it; + GtkTreeIter iter; + char addrStr[32], valStr1[16], valStr2[16]; + ramWatch_t *rw; + + //if ( !reset ) + //{ + // if ( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(ram_watch_store), &iter ) ) + // { + // size_t treeSize = 1; + + // while ( gtk_tree_model_iter_next( GTK_TREE_MODEL(ram_watch_store), &iter ) ) + // { + // treeSize++; + // } + // if ( treeSize != ramWatchList.size() ) + // { + // reset = 1; + // } + // //printf(" TreeSize: %zi RamWatchList.size: %zi \n", treeSize, ramWatchList.size() ); + // } + //} + + if (reset) + { + gtk_tree_store_clear (ram_watch_store); + } + else + { + if (!gtk_tree_model_get_iter_first + (GTK_TREE_MODEL (ram_watch_store), &iter)) + { + gtk_tree_store_append (ram_watch_store, &iter, NULL); // aquire iter + } + } + + for (it = ramWatchList.ls.begin (); it != ramWatchList.ls.end (); it++) + { + rw = *it; + sprintf (addrStr, "0x%04X", rw->addr); + + if (reset) + { + gtk_tree_store_append (ram_watch_store, &iter, NULL); // aquire iter + } + + rw->updateMem (); + + if (rw->size == 2) + { + if (rw->type) + { + sprintf (valStr1, "%6u", rw->val.u16); + } + else + { + sprintf (valStr1, "%6i", rw->val.i16); + } + sprintf (valStr2, "0x%04X", rw->val.u16); + } + else + { + if (rw->type) + { + sprintf (valStr1, "%6u", rw->val.u8); + } + else + { + sprintf (valStr1, "%6i", rw->val.i8); + } + sprintf (valStr2, "0x%02X", rw->val.u8); + } + + if (row != ramWatchEditRowIdx) + { + gtk_tree_store_set (ram_watch_store, &iter, + 0, addrStr, 1, valStr1, 2, valStr2, + 3, rw->name.c_str (), -1); + } + else + { + //if ( ramWatchEditColIdx != 0 ) + //{ + // gtk_tree_store_set(ram_watch_store, &iter, 0, addrStr, -1 ); + //} + + //if ( ramWatchEditColIdx != 1 ) + //{ + // gtk_tree_store_set(ram_watch_store, &iter, 1, valStr1, -1 ); + //} + + //if ( ramWatchEditColIdx != 2 ) + //{ + // gtk_tree_store_set(ram_watch_store, &iter, 2, valStr2, -1 ); + //} + + //if ( ramWatchEditColIdx != 3 ) + //{ + // gtk_tree_store_set(ram_watch_store, &iter, 3, rw->name.c_str(), -1 ); + //} + } + + if (!reset) + { + if (!gtk_tree_model_iter_next + (GTK_TREE_MODEL (ram_watch_store), &iter)) + { + gtk_tree_store_append (ram_watch_store, &iter, NULL); // aquire iter + } + } + row++; + } +} + +static std::list < ramWatchWin_t * >ramWatchWinList; + +void showAllRamWatchResults (int reset) +{ + std::list < ramWatchWin_t * >::iterator it; + + for (it = ramWatchWinList.begin (); it != ramWatchWinList.end (); it++) + { + (*it)->showRamWatchResults (reset); + } +} + +static void saveWatchFile (const char *filename) +{ + int i; + FILE *fp; + const char *c; + std::list < ramWatch_t * >::iterator it; + ramWatch_t *rw; + + fp = fopen (filename, "w"); + + if (fp == NULL) + { + printf ("Error: Failed to open file: %s\n", filename); + return; + } + + for (it = ramWatchList.ls.begin (); it != ramWatchList.ls.end (); it++) + { + rw = *it; + + c = rw->name.c_str (); + + fprintf (fp, "0x%04x %c%i ", rw->addr, rw->type ? 'U' : 'S', + rw->size); + + i = 0; + fprintf (fp, "\""); + while (c[i]) + { + if (c[i] == '"') + { + fprintf (fp, "\\%c", c[i]); + } + else + { + fprintf (fp, "%c", c[i]); + } + i++; + } + fprintf (fp, "\"\n"); + } + fclose (fp); + +} + +static void loadWatchFile (const char *filename) +{ + FILE *fp; + int i, j, a, t, s, literal; + char line[512], stmp[512]; + ramWatch_t *rw; + + fp = fopen (filename, "r"); + + if (fp == NULL) + { + printf ("Error: Failed to open file: %s\n", filename); + return; + } + + while (fgets (line, sizeof (line) - 1, fp) > 0) + { + a = -1; + t = -1; + s = -1; + // Check for Comments + i = 0; + while (line[i] != 0) + { + if (literal) + { + literal = 0; + } + else + { + if (line[i] == '#') + { + line[i] = 0; + break; + } + else if (line[i] == '\\') + { + literal = 1; + } + } + i++; + } + + i = 0; + j = 0; + while (isspace (line[i])) i++; + + if ((line[i] == '0') && (tolower (line[i + 1]) == 'x')) + { + stmp[j] = '0'; + j++; + i++; + stmp[j] = 'x'; + j++; + i++; + + while (isxdigit (line[i])) + { + stmp[j] = line[i]; + i++; + j++; + } + } + else + { + while (isxdigit (line[i])) + { + stmp[j] = line[i]; + i++; + j++; + } + } + stmp[j] = 0; + + if (j == 0) continue; + + a = strtol (stmp, NULL, 0); + + while (isspace (line[i])) i++; + + t = line[i]; + i++; + s = line[i]; + i++; + + if ((t != 'U') && (t != 'S')) + { + printf ("Error: Invalid RAM Watch Byte Type: %c", t); + continue; + } + if (!isdigit (s)) + { + printf ("Error: Invalid RAM Watch Byte Size: %c", s); + continue; + } + s = s - '0'; + + if ((s != 1) && (s != 2) && (s != 4)) + { + printf ("Error: Invalid RAM Watch Byte Size: %i", s); + continue; + } + + while (isspace (line[i])) i++; + + if (line[i] == '"') + { + i++; + j = 0; + literal = 0; + while ((line[i] != 0)) + { + if (literal) + { + literal = 0; + } + else + { + if (line[i] == '"') + { + break; + } + else if (line[i] == '\\') + { + literal = 1; + } + } + if (!literal) + { + stmp[j] = line[i]; + j++; + } + i++; + } + stmp[j] = 0; + } + rw = new ramWatch_t; + + rw->addr = a; + rw->type = (t == 'U') ? 1 : 0; + rw->size = s; + rw->name.assign (stmp); + + ramWatchList.ls.push_back (rw); + } + + fclose (fp); + + showAllRamWatchResults (1); +} + +static void openWatchFile (int mode) +{ + GtkWidget *fileChooser; + GtkFileFilter *filterWch; + GtkFileFilter *filterAll; + + filterWch = gtk_file_filter_new (); + gtk_file_filter_add_pattern (filterWch, "*.wch"); + gtk_file_filter_add_pattern (filterWch, "*.WCH"); + gtk_file_filter_set_name (filterWch, "Watch 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); + + + if (mode) + { + fileChooser = + gtk_file_chooser_dialog_new ("Save Watch File", + GTK_WINDOW (MainWindow), + GTK_FILE_CHOOSER_ACTION_SAVE, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Save", + GTK_RESPONSE_ACCEPT, NULL); + } + else + { + fileChooser = + gtk_file_chooser_dialog_new ("Load Watch File", + 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), last_dir); + + //gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(fileChooser), ".wch"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (fileChooser), filterWch); + 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); + if (filename) + { + if (mode) + { + saveWatchFile (filename); + } + else + { + loadWatchFile (filename); + } + g_free (filename); + } + } + gtk_widget_destroy (fileChooser); +} + +static void loadRamWatchCB (GtkMenuItem * menuitem, gpointer user_data) +{ + openWatchFile (0); +} + +static void saveRamWatchCB (GtkMenuItem * menuitem, gpointer user_data) +{ + openWatchFile (1); +} + +static GtkWidget *CreateRamWatchMenubar (GtkWidget * window) +{ + GtkWidget *menubar, *menu, *item; + + menubar = gtk_menu_bar_new (); + + 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); + + item = gtk_menu_item_new_with_label ("Load Watch"); + + g_signal_connect (item, "activate", G_CALLBACK (loadRamWatchCB), NULL); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + item = gtk_menu_item_new_with_label ("Save Watch"); + + g_signal_connect (item, "activate", G_CALLBACK (saveRamWatchCB), NULL); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + // Finally, return the actual menu bar created + return menubar; +} + +//void closeMemoryWatchEntryWindow(GtkWidget* w, GdkEvent* e, ramWatchEntryWin_t *ew) +//{ +// +//// strcpy( name, gtk_entry_get_text ( GTK_ENTRY(ew->txt_entry_name) ) ); +// +////*addr = strtol( gtk_entry_get_text ( GTK_ENTRY(ew->txt_entry_addr) ), NULL, 16 ); +// +////*type = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ew->chkbox) ); +// +//// if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ew->button4) ) ) +//// { +//// *size = 4; +//// } +//// else if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ew->button2) ) ) +//// { +//// *size = 2; +//// } +//// else +//// { +//// *size = 1; +//// } +// +// delete ew; +// +// gtk_widget_destroy(w); +//} + +static int openRamWatchEntryDialog (ramWatchWin_t * rww, std::string * name, + int *addr, int *type, int *size, int idx) +{ + int retval; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + ramWatchEntryWin_t *ew; + char stmp[32]; + + ew = new ramWatchEntryWin_t; + + //printf("RAM Entry At Index %i \n", idx ); + + ew->rww = rww; + ew->idx = idx; + + ew->win = gtk_dialog_new_with_buttons ("RAM Watch Entry", + GTK_WINDOW (rww->win), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Close", GTK_RESPONSE_OK, NULL); + gtk_window_set_default_size (GTK_WINDOW (ew->win), 400, 200); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + + label = gtk_label_new ("Name:"); + ew->txt_entry_name = gtk_entry_new (); + + if (name->size () > 0) + { + gtk_entry_set_text (GTK_ENTRY (ew->txt_entry_name), + name->c_str ()); + } + + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), ew->txt_entry_name, FALSE, TRUE, 0); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + label = gtk_label_new ("Hex Address:"); + ew->txt_entry_addr = gtk_entry_new (); + + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + label = gtk_label_new ("0x"); + sprintf (stmp, "%04x", *addr); + gtk_entry_set_max_length (GTK_ENTRY (ew->txt_entry_addr), 4); + gtk_entry_set_width_chars (GTK_ENTRY (ew->txt_entry_addr), 4); + gtk_entry_set_text (GTK_ENTRY (ew->txt_entry_addr), stmp); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), ew->txt_entry_addr, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); + + ew->chkbox = gtk_check_button_new_with_label ("Value is Unsigned"); + gtk_box_pack_start (GTK_BOX (vbox), ew->chkbox, FALSE, FALSE, 0); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); + label = gtk_label_new ("Size in Bytes:"); + ew->button1 = gtk_radio_button_new_with_label (NULL, "1"); + //gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 1); + gtk_box_pack_start (GTK_BOX (hbox), ew->button1, TRUE, FALSE, 1); + + ew->button2 = + gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON + (ew->button1), + "2"); + gtk_box_pack_start (GTK_BOX (hbox), ew->button2, TRUE, FALSE, 1); + + ew->button4 = + gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON + (ew->button1), + "4"); + gtk_box_pack_start (GTK_BOX (hbox), ew->button4, TRUE, FALSE, 1); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ew->button1), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ew->button2), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ew->button4), FALSE); + + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 1); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (ew->win))), vbox, TRUE, TRUE, 1); + + gtk_widget_show_all (ew->win); + + retval = gtk_dialog_run (GTK_DIALOG (ew->win)); + + printf ("retval %i\n", retval); + // + if (retval == GTK_RESPONSE_OK) + { + // FIXME - what error checking should be done here + + name->assign (gtk_entry_get_text + (GTK_ENTRY (ew->txt_entry_name))); + + *addr = strtol (gtk_entry_get_text + (GTK_ENTRY (ew->txt_entry_addr)), NULL, 16); + + *type = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON + (ew->chkbox)); + + if (gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (ew->button4))) + { + *size = 4; + } + else if (gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (ew->button2))) + { + *size = 2; + } + else + { + *size = 1; + } + } + + //g_signal_connect(ew->win, "delete-event", G_CALLBACK(closeMemoryWatchEntryWindow), ew); + //g_signal_connect(ew->win, "response", G_CALLBACK(closeMemoryWatchEntryWindow), ew); + + gtk_widget_destroy (ew->win); + + delete ew; + + return (retval == GTK_RESPONSE_OK); +} + +static void editRamWatch (GtkButton * button, ramWatchWin_t * rww) +{ + GtkTreeModel *model = NULL; + GtkTreeSelection *treeSel; + int numListRows; + GList *selListRows, *tmpList; + + treeSel = gtk_tree_view_get_selection (GTK_TREE_VIEW (rww->tree)); + + numListRows = gtk_tree_selection_count_selected_rows (treeSel); + + if (numListRows == 0) + { + return; + } + + 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) + { + ramWatch_t *rw = ramWatchList.getIndex (indexArray[0]); + + if (rw != NULL) + { + openRamWatchEntryDialog (rww, &rw->name, + &rw->addr, &rw->type, + &rw->size, + indexArray[0]); + showAllRamWatchResults (0); + } + } + tmpList = tmpList->next; + } + + g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free); + +} + +static void removeRamWatch (GtkButton * button, ramWatchWin_t * rww) +{ + GtkTreeModel *model = NULL; + GtkTreeSelection *treeSel; + int numListRows; + GList *selListRows, *tmpList; + + treeSel = gtk_tree_view_get_selection (GTK_TREE_VIEW (rww->tree)); + + numListRows = gtk_tree_selection_count_selected_rows (treeSel); + + if (numListRows == 0) + { + return; + } + + 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) + { + ramWatchList.deleteIndex (indexArray[0]); + showAllRamWatchResults (1); + } + tmpList = tmpList->next; + } + + g_list_free_full (selListRows, (GDestroyNotify) gtk_tree_path_free); +} + +static void newRamWatch (GtkButton * button, ramWatchWin_t * rww) +{ + std::string name; + int addr = 0, type = 0, size = 0; + + if (openRamWatchEntryDialog (rww, &name, &addr, &type, &size, -1)) + { + ramWatchList.add_entry (name.c_str (), addr, type, size); + } + + showAllRamWatchResults (1); +} + +static gint updateRamWatchTree (void *userData) +{ + //static uint32_t c = 0; + //printf("RamWatch: %u\n", c++ ); + showAllRamWatchResults (0); + return 1; +} + +static void ramWatch_cell_edited_cb (GtkCellRendererText * cell, + gchar * path_string, + gchar * new_text, ramWatchWin_t * rww) +{ + ramWatch_t *rw; + //printf("Ram Watch Edited: %i:%i\n", ramWatchEditRowIdx, ramWatchEditColIdx); + + rw = ramWatchList.getIndex (rww->ramWatchEditRowIdx); + + if ( rw == NULL ) + { + rww->ramWatchEditRowIdx = -1; + rww->ramWatchEditColIdx = -1; + return; + } + + switch (rww->ramWatchEditColIdx) + { + case 0: + rw->addr = strtol (new_text, NULL, 0); + break; + case 1: + case 2: + { + if ( (rw->addr >= 0) && (rw->addr < 0x8000) ) + { + writefunc wfunc; + + if (rw->size == 2) + { + if (rw->type) + { + rw->val.u16 = + strtol (new_text, NULL, 0); + } + else + { + rw->val.i16 = + strtol (new_text, NULL, 0); + } + wfunc = GetWriteHandler (rw->addr); + + if (wfunc) + { + wfunc ((uint32) rw->addr, + (uint8) (rw->val.u16 & 0x00ff)); + } + + wfunc = GetWriteHandler (rw->addr + 1); + + if (wfunc) + { + wfunc ((uint32) rw->addr + 1, + (uint8) ((rw->val. + u16 & 0xff00) >> 8)); + } + } + else + { + if (rw->type) + { + rw->val.u8 = strtol (new_text, NULL, 0); + } + else + { + rw->val.i8 = strtol (new_text, NULL, 0); + } + wfunc = GetWriteHandler (rw->addr); + + if (wfunc) + { + wfunc ((uint32) rw->addr, + (uint8) rw->val.u8); + } + } + } + } + break; + case 3: + rw->name.assign (new_text); + break; + default: + + break; + } + + rww->ramWatchEditRowIdx = -1; + rww->ramWatchEditColIdx = -1; +} + +static void ramWatch_cell_edited_start_cb0 (GtkCellRenderer * renderer, + GtkCellEditable * editable, + gchar * path, ramWatchWin_t * rww) +{ + //printf("Ram Watch Edit Start: '%s':%li\n", path, (long)user_data); + rww->ramWatchEditRowIdx = atoi (path); + rww->ramWatchEditColIdx = 0; +} + +static void ramWatch_cell_edited_start_cb1 (GtkCellRenderer * renderer, + GtkCellEditable * editable, + gchar * path, ramWatchWin_t * rww) +{ + //printf("Ram Watch Edit Start: '%s':%li\n", path, (long)user_data); + rww->ramWatchEditRowIdx = atoi (path); + rww->ramWatchEditColIdx = 1; +} + +static void ramWatch_cell_edited_start_cb2 (GtkCellRenderer * renderer, + GtkCellEditable * editable, + gchar * path, ramWatchWin_t * rww) +{ + //printf("Ram Watch Edit Start: '%s':%li\n", path, (long)user_data); + rww->ramWatchEditRowIdx = atoi (path); + rww->ramWatchEditColIdx = 2; +} + +static void ramWatch_cell_edited_start_cb3 (GtkCellRenderer * renderer, + GtkCellEditable * editable, + gchar * path, ramWatchWin_t * rww) +{ + //printf("Ram Watch Edit Start: '%s':%li\n", path, (long)user_data); + rww->ramWatchEditRowIdx = atoi (path); + rww->ramWatchEditColIdx = 3; +} + +static void ramWatch_cell_edited_cancel_cb (GtkCellRenderer * renderer, + ramWatchWin_t * rww) +{ + //printf("Ram Watch Edit Cancel:%li\n", (long)user_data); + rww->ramWatchEditRowIdx = -1; + rww->ramWatchEditColIdx = -1; +} + +void closeMemoryWatchWindow (GtkWidget * w, GdkEvent * e, ramWatchWin_t * rww) +{ + std::list < ramWatchWin_t * >::iterator it; + + for (it = ramWatchWinList.begin (); it != ramWatchWinList.end (); it++) + { + if (rww == *it) + { + //printf("Removing RamWatch Window %p from List\n", cw); + ramWatchWinList.erase (it); + break; + } + } + + delete rww; + + gtk_widget_destroy (w); +} + +// creates and opens cheats window +void openMemoryWatchWindow (void) +{ + GtkWidget *main_vbox; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *button; + GtkWidget *scroll; + GtkWidget *menubar; + ramWatchWin_t *rww; + + rww = new ramWatchWin_t; + + ramWatchWinList.push_back (rww); + + rww->win = gtk_dialog_new_with_buttons ("RAM Watch", + GTK_WINDOW (MainWindow), + (GtkDialogFlags) + (GTK_DIALOG_DESTROY_WITH_PARENT), + "_Close", GTK_RESPONSE_OK, + NULL); + + gtk_window_set_default_size (GTK_WINDOW (rww->win), 600, 600); + + main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1); + + menubar = CreateRamWatchMenubar (rww->win); + + gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + + rww->ram_watch_store = + gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING); + + rww->tree = + gtk_tree_view_new_with_model (GTK_TREE_MODEL + (rww->ram_watch_store)); + + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (rww->tree), + GTK_TREE_VIEW_GRID_LINES_VERTICAL); + + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", + (GCallback) ramWatch_cell_edited_cb, (gpointer) rww); + g_signal_connect (renderer, "editing-started", + (GCallback) ramWatch_cell_edited_start_cb0, + (gpointer) rww); + g_signal_connect (renderer, "editing-canceled", + (GCallback) ramWatch_cell_edited_cancel_cb, + (gpointer) rww); + column = gtk_tree_view_column_new_with_attributes ("Addr", renderer, + "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (rww->tree), column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", + (GCallback) ramWatch_cell_edited_cb, (gpointer) rww); + g_signal_connect (renderer, "editing-started", + (GCallback) ramWatch_cell_edited_start_cb1, + (gpointer) rww); + g_signal_connect (renderer, "editing-canceled", + (GCallback) ramWatch_cell_edited_cancel_cb, + (gpointer) rww); + column = gtk_tree_view_column_new_with_attributes ("Value Dec", + renderer, "text", 1, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (rww->tree), column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "family", "MonoSpace", NULL); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", + (GCallback) ramWatch_cell_edited_cb, (gpointer) rww); + g_signal_connect (renderer, "editing-started", + (GCallback) ramWatch_cell_edited_start_cb2, + (gpointer) rww); + g_signal_connect (renderer, "editing-canceled", + (GCallback) ramWatch_cell_edited_cancel_cb, + (gpointer) rww); + column = gtk_tree_view_column_new_with_attributes ("Value Hex", + renderer, "text", 2, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (rww->tree), column); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (renderer, "editable", TRUE, NULL); + g_signal_connect (renderer, "edited", + (GCallback) ramWatch_cell_edited_cb, (gpointer) rww); + g_signal_connect (renderer, "editing-started", + (GCallback) ramWatch_cell_edited_start_cb3, + (gpointer) rww); + g_signal_connect (renderer, "editing-canceled", + (GCallback) ramWatch_cell_edited_cancel_cb, + (gpointer) rww); + column = gtk_tree_view_column_new_with_attributes ("Notes", renderer, + "text", 3, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (rww->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), rww->tree); + gtk_box_pack_start (GTK_BOX (hbox), scroll, TRUE, TRUE, 5); + + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 5); + + showAllRamWatchResults (1); + + if (ramWatchEvntSrcID == 0) + { + ramWatchEvntSrcID = + g_timeout_add (100, updateRamWatchTree, NULL); + } + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); + + button = gtk_button_new_with_label ("Edit"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 5); + g_signal_connect (button, "clicked", + G_CALLBACK (editRamWatch), (gpointer) rww); + + button = gtk_button_new_with_label ("Remove"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 5); + g_signal_connect (button, "clicked", + G_CALLBACK (removeRamWatch), (gpointer) rww); + + button = gtk_button_new_with_label ("New"); + gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 5); + g_signal_connect (button, "clicked", + G_CALLBACK (newRamWatch), (gpointer) rww); + + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 5); + + gtk_box_pack_start (GTK_BOX + (gtk_dialog_get_content_area + (GTK_DIALOG (rww->win))), main_vbox, TRUE, TRUE, + 0); + + g_signal_connect (rww->win, "delete-event", + G_CALLBACK (closeMemoryWatchWindow), rww); + g_signal_connect (rww->win, "response", + G_CALLBACK (closeMemoryWatchWindow), rww); + + gtk_widget_show_all (rww->win); + +} diff --git a/src/drivers/sdl/ramwatch.h b/src/drivers/sdl/ramwatch.h new file mode 100644 index 00000000..6776a765 --- /dev/null +++ b/src/drivers/sdl/ramwatch.h @@ -0,0 +1,3 @@ +// ramwatch.h + +void openMemoryWatchWindow(void); diff --git a/src/drivers/sdl/sdl-netplay.cpp b/src/drivers/sdl/sdl-netplay.cpp index 52a9e25e..093ff7e9 100644 --- a/src/drivers/sdl/sdl-netplay.cpp +++ b/src/drivers/sdl/sdl-netplay.cpp @@ -216,7 +216,7 @@ int FCEUD_GetDataFromServer(uint8 *data) } } - if(SDLNet_SocketReady(UDPSocket) + if(SDLNet_SocketReady(UDPSocket)) { diff --git a/src/drivers/sdl/sdl-opengl.cpp b/src/drivers/sdl/sdl-opengl.cpp deleted file mode 100644 index ce8562fc..00000000 --- a/src/drivers/sdl/sdl-opengl.cpp +++ /dev/null @@ -1,251 +0,0 @@ -#define GL_GLEXT_LEGACY - -#include "sdl.h" -#include "sdl-opengl.h" -#include "../common/vidblit.h" -#include "../../utils/memory.h" - -#ifdef APPLEOPENGL -#include -#include -#include -#else -#include -#include -#include -#endif -#include -#include - -#ifndef APIENTRY -#define APIENTRY -#endif - -static GLuint textures[2]={0,0}; // Normal image, scanline overlay. - -static int left,right,top,bottom; // right and bottom are not inclusive. -static int scanlines; -static void *HiBuffer; - -typedef void APIENTRY (*glColorTableEXT_Func)(GLenum target, - GLenum internalformat, GLsizei width, GLenum format, GLenum type, - const GLvoid *table); -glColorTableEXT_Func p_glColorTableEXT; - -void -SetOpenGLPalette(uint8 *data) -{ - if(!HiBuffer) { - glBindTexture(GL_TEXTURE_2D, textures[0]); - p_glColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else { - SetPaletteBlitToHigh((uint8*)data); - } -} - -void -BlitOpenGL(uint8 *buf) -{ - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, textures[0]); - - if(HiBuffer) { - Blit8ToHigh(buf, (uint8*)HiBuffer, 256, 240, 256*4, 1, 1); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, - GL_RGBA, GL_UNSIGNED_BYTE, HiBuffer); - } - else { - //glPixelStorei(GL_UNPACK_ROW_LENGTH, 256); - glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0, - GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf); - } - - glBegin(GL_QUADS); - glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of picture. - glVertex2f(-1.0f, -1.0f); // Bottom left of target. - - glTexCoord2f(1.0f*right/256, 1.0f*bottom/256);// Bottom right of picture. - glVertex2f( 1.0f, -1.0f); // Bottom right of target. - - glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture. - glVertex2f( 1.0f, 1.0f); // Top right of target. - - glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture. - glVertex2f(-1.0f, 1.0f); // Top left of target. - glEnd(); - - //glDisable(GL_BLEND); - if(scanlines) { - glEnable(GL_BLEND); - - glBindTexture(GL_TEXTURE_2D, textures[1]); - glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); - - glBegin(GL_QUADS); - - glTexCoord2f(1.0f*left/256, - 1.0f*bottom/256); // Bottom left of our picture. - glVertex2f(-1.0f, -1.0f); // Bottom left of target. - - glTexCoord2f(1.0f*right/256, - 1.0f*bottom/256); // Bottom right of our picture. - glVertex2f( 1.0f, -1.0f); // Bottom right of target. - - glTexCoord2f(1.0f*right/256, - 1.0f*top/256); // Top right of our picture. - glVertex2f( 1.0f, 1.0f); // Top right of target. - - glTexCoord2f(1.0f*left/256, - 1.0f*top/256); // Top left of our picture. - glVertex2f(-1.0f, 1.0f); // Top left of target. - - glEnd(); - glDisable(GL_BLEND); - } - SDL_GL_SwapBuffers(); -} - -void -KillOpenGL(void) -{ - if(textures[0]) { - glDeleteTextures(2, &textures[0]); - } - textures[0]=0; - if(HiBuffer) { - free(HiBuffer); - HiBuffer=0; - } -} -/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */ - -int -InitOpenGL(int l, - int r, - int t, - int b, - double xscale, - double yscale, - int efx, - int ipolate, - int stretchx, - int stretchy, - SDL_Surface *screen) -{ - const char *extensions; - -#define LFG(x) if(!(##x = (x##_Func) SDL_GL_GetProcAddress(#x))) return(0); - -#define LFGN(x) p_##x = (x##_Func) SDL_GL_GetProcAddress(#x) - -// LFG(glBindTexture); - LFGN(glColorTableEXT); -// LFG(glTexImage2D); -// LFG(glBegin); -// LFG(glVertex2f); -// LFG(glTexCoord2f); -// LFG(glEnd); -// LFG(glEnable); -// LFG(glBlendFunc); -// LFG(glGetString); -// LFG(glViewport); -// LFG(glGenTextures); -// LFG(glDeleteTextures); -// LFG(glTexParameteri); -// LFG(glClearColor); -// LFG(glLoadIdentity); -// LFG(glClear); -// LFG(glMatrixMode); -// LFG(glDisable); - - left=l; - right=r; - top=t; - bottom=b; - - HiBuffer=0; - - extensions=(const char*)glGetString(GL_EXTENSIONS); - - if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture")) - { - if(!(efx&2)) // Don't want to print out a warning message in this case... - FCEU_printf("Paletted texture extension not found. Using slower texture format...\n"); - HiBuffer=FCEU_malloc(4*256*256); - memset(HiBuffer,0x00,4*256*256); - #ifndef LSB_FIRST - InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0,0); - #else - InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0,0); - #endif - } - - if(screen->flags & SDL_FULLSCREEN) - { - xscale=(double)screen->w / (double)(r-l); - yscale=(double)screen->h / (double)(b-t); - if(xscalew-rw)/2; // Start x - int sy=(screen->h-rh)/2; // Start y - - if(stretchx) { sx=0; rw=screen->w; } - if(stretchy) { sy=0; rh=screen->h; } - glViewport(sx, sy, rw, rh); - } - glGenTextures(2, &textures[0]); - scanlines=0; - - if(efx&1) - { - uint8 *buf; - int x,y; - - scanlines=1; - - glBindTexture(GL_TEXTURE_2D, textures[1]); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - - buf=(uint8*)FCEU_dmalloc(256*(256*2)*4); - - for(y=0;y<(256*2);y++) - for(x=0;x<256;x++) - { - buf[y*256*4+x*4]=0; - buf[y*256*4+x*4+1]=0; - buf[y*256*4+x*4+2]=0; - buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty - //buf[y*256+x]=(y&1)?0x00:0xFF; - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0, - GL_RGBA,GL_UNSIGNED_BYTE,buf); - FCEU_dfree(buf); - } - glBindTexture(GL_TEXTURE_2D, textures[0]); - - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); - glEnable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // In a double buffered setup with page flipping, be sure to clear both buffers. - glClear(GL_COLOR_BUFFER_BIT); - SDL_GL_SwapBuffers(); - glClear(GL_COLOR_BUFFER_BIT); - SDL_GL_SwapBuffers(); - - return 1; -} diff --git a/src/drivers/sdl/sdl-opengl.h b/src/drivers/sdl/sdl-opengl.h deleted file mode 100644 index 0e88900f..00000000 --- a/src/drivers/sdl/sdl-opengl.h +++ /dev/null @@ -1,6 +0,0 @@ -void SetOpenGLPalette(uint8 *data); -void BlitOpenGL(uint8 *buf); -void KillOpenGL(void); -int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate, - int stretchx, int stretchy, SDL_Surface *screen); - diff --git a/src/drivers/sdl/sdl-sound.cpp b/src/drivers/sdl/sdl-sound.cpp index 36830ca3..00b7c9a6 100644 --- a/src/drivers/sdl/sdl-sound.cpp +++ b/src/drivers/sdl/sdl-sound.cpp @@ -75,25 +75,21 @@ InitSound() { int sound, soundrate, soundbufsize, soundvolume, soundtrianglevolume, soundsquare1volume, soundsquare2volume, soundnoisevolume, soundpcmvolume, soundq; SDL_AudioSpec spec; + const char *driverName; g_config->getOption("SDL.Sound", &sound); - if(!sound) { + if (!sound) + { return 0; } memset(&spec, 0, sizeof(spec)); - if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) + { puts(SDL_GetError()); KillSound(); return 0; } - char driverName[8]; -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL 2 -#else - SDL_AudioDriverName(driverName, 8); - fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName); -#endif // load configuration variables g_config->getOption("SDL.Sound.Rate", &soundrate); @@ -117,21 +113,33 @@ InitSound() // For safety, set a bare minimum: if (s_BufferSize < spec.samples * 2) - s_BufferSize = spec.samples * 2; + { + s_BufferSize = spec.samples * 2; + } s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize); + if (!s_Buffer) + { return 0; + } s_BufferRead = s_BufferWrite = s_BufferIn = 0; - if(SDL_OpenAudio(&spec, 0) < 0) + if (SDL_OpenAudio(&spec, 0) < 0) { puts(SDL_GetError()); KillSound(); return 0; - } + } SDL_PauseAudio(0); + driverName = SDL_GetCurrentAudioDriver(); + + if ( driverName ) + { + fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName); + } + FCEUI_SetSoundVolume(soundvolume); FCEUI_SetSoundQuality(soundq); FCEUI_Sound(soundrate); diff --git a/src/drivers/sdl/sdl-throttle.cpp b/src/drivers/sdl/sdl-throttle.cpp index 6832f954..498d4fe7 100644 --- a/src/drivers/sdl/sdl-throttle.cpp +++ b/src/drivers/sdl/sdl-throttle.cpp @@ -75,9 +75,13 @@ SpeedThrottle() else InFrame = 0; - /*fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n", - time_left, InFrame?"no":"yes");*/ - SDL_Delay(time_left); + //fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n", + // time_left, InFrame?"no":"yes"); + + if ( time_left > 0 ) + { + SDL_Delay(time_left); + } if(!InFrame) { diff --git a/src/drivers/sdl/sdl-video.cpp b/src/drivers/sdl/sdl-video.cpp index ea69ebfa..2b5e44f2 100644 --- a/src/drivers/sdl/sdl-video.cpp +++ b/src/drivers/sdl/sdl-video.cpp @@ -22,7 +22,7 @@ /// \brief Handles the graphical game display for the SDL implementation. #include "sdl.h" -#include "sdl-opengl.h" +#include "glxwin.h" #include "../common/vidblit.h" #include "../../fceu.h" #include "../../version.h" @@ -55,34 +55,30 @@ extern Config *g_config; // STATIC GLOBALS -extern SDL_Surface *s_screen; - -static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits. -static SDL_Surface *s_IconSurface = NULL; - -static int s_curbpp; +static int s_curbpp = 0; static int s_srendline, s_erendline; static int s_tlines; -static int s_inited; +static int s_inited = 0; #ifdef OPENGL -static int s_useOpenGL; +static int s_useOpenGL = 0; #endif -static double s_exs, s_eys; -static int s_eefx; -static int s_clipSides; -static int s_fullscreen; -static int noframe; -static int s_nativeWidth = -1; -static int s_nativeHeight = -1; +static double s_exs = 1.0, s_eys = 1.0; +static int s_eefx = 0; +static int s_clipSides = 0; +static int s_fullscreen = 0; +static int noframe = 0; +static int initBlitToHighDone = 0; #define NWIDTH (256 - (s_clipSides ? 16 : 0)) #define NOFFSET (s_clipSides ? 8 : 0) -static int s_paletterefresh; +static int s_paletterefresh = 1; extern bool MaxSpeed; +extern unsigned int gtk_draw_area_width; +extern unsigned int gtk_draw_area_height; /** * Attempts to destroy the graphical video display. Returns 0 on * success, -1 on failure. @@ -97,29 +93,29 @@ bool FCEUD_ShouldDrawInputAids() int KillVideo() { - // if the IconSurface has been initialized, destroy it - if(s_IconSurface) { - SDL_FreeSurface(s_IconSurface); - s_IconSurface=0; + //printf("Killing Video\n"); + + if ( glx_shm != NULL ) + { + glx_shm->clear_pixbuf(); } - // return failure if the video system was not initialized - if(s_inited == 0) - return -1; - - // if the rest of the system has been initialized, shut it down -#ifdef OPENGL - // check for OpenGL and shut it down - if(s_useOpenGL) - KillOpenGL(); - else -#endif - // shut down the system that converts from 8 to 16/32 bpp - if(s_curbpp > 8) - KillBlitToHigh(); + destroy_gui_video(); + // return failure if the video system was not initialized + if (s_inited == 0) + return -1; + + // if the rest of the system has been initialized, shut it down +// // shut down the system that converts from 8 to 16/32 bpp +// if (s_curbpp > 8) +// { +// KillBlitToHigh(); +// } + + // SDL Video system is not used. // shut down the SDL video sub-system - SDL_QuitSubSystem(SDL_INIT_VIDEO); + //SDL_QuitSubSystem(SDL_INIT_VIDEO); s_inited = 0; return 0; @@ -127,7 +123,7 @@ KillVideo() // this variable contains information about the special scaling filters -static int s_sponge; +static int s_sponge = 0; /** * These functions determine an appropriate scale factor for fullscreen/ @@ -150,24 +146,8 @@ void FCEUD_VideoChanged() PAL = 0; // NTSC and Dendy } -#if SDL_VERSION_ATLEAST(2, 0, 0) int InitVideo(FCEUGI *gi) { - // This is a big TODO. Stubbing this off into its own function, - // as the SDL surface routines have changed drastically in SDL2 - // TODO - SDL2 -} -#else -/** - * Attempts to initialize the graphical video display. Returns 0 on - * success, -1 on failure. - */ -int -InitVideo(FCEUGI *gi) -{ - // XXX soules - const? is this necessary? - const SDL_VideoInfo *vinf; - int error, flags = 0; int doublebuf, xstretch, ystretch, xres, yres, show_fps; FCEUI_printf("Initializing video..."); @@ -178,350 +158,94 @@ InitVideo(FCEUGI *gi) #ifdef OPENGL g_config->getOption("SDL.OpenGL", &s_useOpenGL); #endif - g_config->getOption("SDL.SpecialFilter", &s_sponge); + //g_config->getOption("SDL.SpecialFilter", &s_sponge); g_config->getOption("SDL.XStretch", &xstretch); g_config->getOption("SDL.YStretch", &ystretch); - g_config->getOption("SDL.LastXRes", &xres); - g_config->getOption("SDL.LastYRes", &yres); + //g_config->getOption("SDL.LastXRes", &xres); + //g_config->getOption("SDL.LastYRes", &yres); g_config->getOption("SDL.ClipSides", &s_clipSides); g_config->getOption("SDL.NoFrame", &noframe); g_config->getOption("SDL.ShowFPS", &show_fps); + //g_config->getOption("SDL.XScale", &s_exs); + //g_config->getOption("SDL.YScale", &s_eys); + uint32_t rmask, gmask, bmask; + s_sponge = 0; + s_exs = 1.0; + s_eys = 1.0; + xres = gtk_draw_area_width; + yres = gtk_draw_area_height; // check the starting, ending, and total scan lines + FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline); s_tlines = s_erendline - s_srendline + 1; - // check if we should auto-set x/y resolution + init_gui_video( s_useOpenGL ); - // check for OpenGL and set the global flags -#ifdef OPENGL - if(s_useOpenGL && !s_sponge) { - flags = SDL_OPENGL; - } -#endif - - // initialize the SDL video subsystem if it is not already active - if(!SDL_WasInit(SDL_INIT_VIDEO)) { - error = SDL_InitSubSystem(SDL_INIT_VIDEO); - if(error) { - FCEUD_PrintError(SDL_GetError()); - return -1; - } - } s_inited = 1; - // shows the cursor within the display window - SDL_ShowCursor(1); - - // determine if we can allocate the display on the video card - vinf = SDL_GetVideoInfo(); - if(vinf->hw_available) { - flags |= SDL_HWSURFACE; - } - - // get the monitor's current resolution if we do not already have it - if(s_nativeWidth < 0) { - s_nativeWidth = vinf->current_w; - } - if(s_nativeHeight < 0) { - s_nativeHeight = vinf->current_h; - } - // check to see if we are showing FPS FCEUI_SetShowFPS(show_fps); - - // check if we are rendering fullscreen - if(s_fullscreen) { - int no_cursor; - g_config->getOption("SDL.NoFullscreenCursor", &no_cursor); - flags |= SDL_FULLSCREEN; - SDL_ShowCursor(!no_cursor); - } - else { - SDL_ShowCursor(1); - } - - if(noframe) { - flags |= SDL_NOFRAME; - } - // gives the SDL exclusive palette control... ensures the requested colors - flags |= SDL_HWPALETTE; - - // enable double buffering if requested and we have hardware support -#ifdef OPENGL - if(s_useOpenGL) { - FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n"); - if(doublebuf) { - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - } - } else -#endif - if(doublebuf && (flags & SDL_HWSURFACE)) { - flags |= SDL_DOUBLEBUF; - } - - if(s_fullscreen) { - int desbpp, autoscale; - g_config->getOption("SDL.BitsPerPixel", &desbpp); - g_config->getOption("SDL.AutoScale", &autoscale); - if (autoscale) - { - double auto_xscale = GetXScale(xres); - double auto_yscale = GetYScale(yres); - double native_ratio = ((double)NWIDTH) / s_tlines; - double screen_ratio = ((double)xres) / yres; - int keep_ratio; - - g_config->getOption("SDL.KeepRatio", &keep_ratio); - - // Try to choose resolution - if (screen_ratio < native_ratio) - { - // The screen is narrower than the original. Maximizing width will not clip - auto_xscale = auto_yscale = GetXScale(xres); - if (keep_ratio) - auto_yscale = GetYScale(yres); - } - else - { - auto_yscale = auto_xscale = GetYScale(yres); - if (keep_ratio) - auto_xscale = GetXScale(xres); - } - s_exs = auto_xscale; - s_eys = auto_yscale; - } - else - { - g_config->getOption("SDL.XScale", &s_exs); - g_config->getOption("SDL.YScale", &s_eys); - } - g_config->getOption("SDL.SpecialFX", &s_eefx); - -#ifdef OPENGL - if(!s_useOpenGL) { - s_exs = (int)s_exs; - s_eys = (int)s_eys; - } else { - desbpp = 0; - } - - - if((s_useOpenGL && !xstretch) || !s_useOpenGL) -#endif - if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) { - FCEUD_PrintError("xscale out of bounds."); - KillVideo(); - return -1; - } - -#ifdef OPENGL - if((s_useOpenGL && !ystretch) || !s_useOpenGL) -#endif - if(yres < int(s_tlines * s_eys) || s_eys <= 0.01) { - FCEUD_PrintError("yscale out of bounds."); - KillVideo(); - return -1; - } - -#ifdef OPENGL - s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres, - s_useOpenGL ? s_nativeHeight : yres, - desbpp, flags); +#ifdef LSB_FIRST + rmask = 0x000000FF; + gmask = 0x0000FF00; + bmask = 0x00FF0000; #else - s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags); + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; #endif - if(!s_screen) { - FCEUD_PrintError(SDL_GetError()); - return -1; - } - } else { - int desbpp; - g_config->getOption("SDL.BitsPerPixel", &desbpp); - - g_config->getOption("SDL.XScale", &s_exs); - g_config->getOption("SDL.YScale", &s_eys); - g_config->getOption("SDL.SpecialFX", &s_eefx); - - // -Video Modes Tag- - if(s_sponge) { - if(s_sponge <= 3 && s_sponge >= 1) - { - s_exs = s_eys = 2; - } else if (s_sponge >=4 && s_sponge <= 5) - { - s_exs = s_eys = 3; - } else if (s_sponge >= 6 && s_sponge <= 8) - { - s_exs = s_eys = s_sponge - 4; - } - else if(s_sponge == 9) - { - s_exs = s_eys = 3; - } - else - { - s_exs = s_eys = 1; - } - if(s_sponge == 3) { - xres = 301 * s_exs; - } - s_eefx = 0; - if(s_sponge == 1 || s_sponge == 4) { - desbpp = 32; - } - } - - int scrw = NWIDTH * s_exs; - if(s_sponge == 3) { - scrw = 301 * s_exs; - } - -#ifdef OPENGL - if(!s_useOpenGL) { - s_exs = (int)s_exs; - s_eys = (int)s_eys; - } - if(s_exs <= 0.01) { - FCEUD_PrintError("xscale out of bounds."); - KillVideo(); - return -1; - } - if(s_eys <= 0.01) { - FCEUD_PrintError("yscale out of bounds."); - KillVideo(); - return -1; - } - if(s_sponge && s_useOpenGL) { - FCEUD_PrintError("scalers not compatible with openGL mode."); - KillVideo(); - return -1; - } -#endif - -#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) && defined(GDK_WINDOWING_X11) - if(noGui == 0) - { - while (gtk_events_pending()) - gtk_main_iteration_do(FALSE); - - char SDL_windowhack[128]; - sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox))); - SDL_putenv(SDL_windowhack); - - // init SDL video - if (SDL_WasInit(SDL_INIT_VIDEO)) - SDL_QuitSubSystem(SDL_INIT_VIDEO); - if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) - { - fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError()); - gtk_main_quit(); - } - } -#endif - - s_screen = SDL_SetVideoMode(scrw, (int)(s_tlines * s_eys), - desbpp, flags); - if(!s_screen) { - FCEUD_PrintError(SDL_GetError()); - return -1; - } - -#ifdef _GTK - if(noGui == 0) - { - GtkRequisition req; - gtk_widget_size_request(GTK_WIDGET(MainWindow), &req); - gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); - } -#endif - } - s_curbpp = s_screen->format->BitsPerPixel; - if(!s_screen) { - FCEUD_PrintError(SDL_GetError()); - KillVideo(); - return -1; - } - -#if 0 - // XXX soules - this would be creating a surface on the video - // card, but was commented out for some reason... - s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240, - s_screen->format->BitsPerPixel, - s_screen->format->Rmask, - s_screen->format->Gmask, - s_screen->format->Bmask, 0); -#endif + s_curbpp = 32; // Bits per pixel is always 32 FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n", - s_screen->w, s_screen->h, s_screen->format->BitsPerPixel, + xres, yres, s_curbpp, s_fullscreen ? "full screen" : ""); - if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) { + if (s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) + { FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp); KillVideo(); return -1; } - // if the game being run has a name, set it as the window name - if(gi) - { - if(gi->name) { - SDL_WM_SetCaption((const char *)gi->name, (const char *)gi->name); - } else { - SDL_WM_SetCaption(FCEU_NAME_AND_VERSION,"FCE Ultra"); - } - } - - // create the surface for displaying graphical messages -#ifdef LSB_FIRST - s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, - 32, 32, 24, 32 * 3, - 0xFF, 0xFF00, 0xFF0000, 0x00); -#else - s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, - 32, 32, 24, 32 * 3, - 0xFF0000, 0xFF00, 0xFF, 0x00); -#endif - SDL_WM_SetIcon(s_IconSurface,0); - s_paletterefresh = 1; - - // XXX soules - can't SDL do this for us? - // if using more than 8bpp, initialize the conversion routines - if(s_curbpp > 8) { - InitBlitToHigh(s_curbpp >> 3, - s_screen->format->Rmask, - s_screen->format->Gmask, - s_screen->format->Bmask, - s_eefx, s_sponge, 0); #ifdef OPENGL - if(s_useOpenGL) - { - int openGLip; - g_config->getOption("SDL.OpenGLip", &openGLip); - - if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0), - s_srendline, s_erendline + 1, - s_exs, s_eys, s_eefx, - openGLip, xstretch, ystretch, s_screen)) - { - FCEUD_PrintError("Error initializing OpenGL."); - KillVideo(); - return -1; - } - } -#endif + if(s_exs <= 0.01) { + FCEUD_PrintError("xscale out of bounds."); + KillVideo(); + return -1; } + if(s_eys <= 0.01) { + FCEUD_PrintError("yscale out of bounds."); + KillVideo(); + return -1; + } + if(s_sponge && s_useOpenGL) { + FCEUD_PrintError("scalers not compatible with openGL mode."); + KillVideo(); + return -1; + } +#endif + + if ( !initBlitToHighDone ) + { + InitBlitToHigh(s_curbpp >> 3, + rmask, + gmask, + bmask, + s_eefx, s_sponge, 0); + + initBlitToHighDone = 1; + } + return 0; } -#endif /** * Toggles the full-screen display. */ -void ToggleFS() +void ToggleFS(void) { // pause while we we are making the switch bool paused = FCEUI_EmulationPaused(); @@ -539,7 +263,7 @@ void ToggleFS() if(noGui == 0) { if(!fullscreen) - showGui(0); + showGui(0); else showGui(1); } @@ -593,23 +317,10 @@ FCEUD_GetPalette(uint8 index, */ static void RedoPalette() { -#ifdef OPENGL - if(s_useOpenGL) - SetOpenGLPalette((uint8*)s_psdl); - else -#endif + if (s_curbpp > 8) { - if(s_curbpp > 8) { - SetPaletteBlitToHigh((uint8*)s_psdl); - } else - { -#if SDL_VERSION_ATLEAST(2, 0, 0) - //TODO - SDL2 -#else - SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256); -#endif - } - } + SetPaletteBlitToHigh((uint8*)s_psdl); + } } // XXX soules - console lock/unlock unimplemented? @@ -625,126 +336,32 @@ void UnlockConsole(){} void BlitScreen(uint8 *XBuf) { - SDL_Surface *TmpScreen; uint8 *dest; - int xo = 0, yo = 0; - - if(!s_screen) { - return; - } + int w, h, pitch; // refresh the palette if required - if(s_paletterefresh) { + if (s_paletterefresh) + { RedoPalette(); s_paletterefresh = 0; } -#ifdef OPENGL - // OpenGL is handled separately - if(s_useOpenGL) { - BlitOpenGL(XBuf); - return; - } -#endif - // XXX soules - not entirely sure why this is being done yet XBuf += s_srendline * 256; - if(s_BlitBuf) { - TmpScreen = s_BlitBuf; - } else { - TmpScreen = s_screen; - } + dest = (uint8*)getGuiPixelBuffer( &w, &h, &pitch ); - // lock the display, if necessary - if(SDL_MUSTLOCK(TmpScreen)) { - if(SDL_LockSurface(TmpScreen) < 0) { - return; - } - } + glx_shm->ncol = NWIDTH; + glx_shm->nrow = s_tlines; + glx_shm->pitch = pitch; - dest = (uint8*)TmpScreen->pixels; + if ( dest == NULL ) return; - if(s_fullscreen) { - xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2); - dest += xo * (s_curbpp >> 3); - if(TmpScreen->h > (s_tlines * s_eys)) { - yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2); - dest += yo * TmpScreen->pitch; - } - } + Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1); - // XXX soules - again, I'm surprised SDL can't handle this - // perform the blit, converting bpp if necessary - if(s_curbpp > 8) { - if(s_BlitBuf) { - Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, 1, 1); - } else { - Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, (int)s_exs, (int)s_eys); - } - } else { - if(s_BlitBuf) { - Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, 1, 1, 0, s_sponge); - } else { - Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, (int)s_exs, (int)s_eys, - s_eefx, s_sponge); - } - } - - // unlock the display, if necessary - if(SDL_MUSTLOCK(TmpScreen)) { - SDL_UnlockSurface(TmpScreen); - } - - int scrw; - if(s_sponge == 3) { // NTSC 2x - scrw = 301; - } else { - scrw = NWIDTH; - } - - // if we have a hardware video buffer, do a fast video->video copy - if(s_BlitBuf) { - SDL_Rect srect; - SDL_Rect drect; - - srect.x = 0; - srect.y = 0; - srect.w = scrw; - srect.h = s_tlines; - - drect.x = 0; - drect.y = 0; - drect.w = (Uint16)(s_exs * scrw); - drect.h = (Uint16)(s_eys * s_tlines); - - SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect); - } - - // ensure that the display is updated -#if SDL_VERSION_ATLEAST(2, 0, 0) - //TODO - SDL2 -#else - SDL_UpdateRect(s_screen, xo, yo, - (Uint32)(scrw * s_exs), (Uint32)(s_tlines * s_eys)); -#endif + guiPixelBufferReDraw(); #ifdef CREATE_AVI -#if 0 /* PAL INTO NTSC HACK */ - { int fps = FCEUI_GetDesiredFPS(); - if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711; - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); - if(FCEUI_GetDesiredFPS() == 838977920) - { - static unsigned dup=0; - if(++dup==5) { dup=0; - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); } - } } -#else { int fps = FCEUI_GetDesiredFPS(); static unsigned char* result = NULL; static unsigned resultsize = 0; @@ -774,10 +391,10 @@ BlitScreen(uint8 *XBuf) break; #endif default: - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); + NESVideoLoggingVideo( dest, width,height, fps, s_curbpp); } } -#endif +#endif // CREATE_AVI #if REALTIME_LOGGING { @@ -804,17 +421,8 @@ BlitScreen(uint8 *XBuf) } memcpy(&last_time, &cur_time, sizeof(last_time)); } -#endif -#endif +#endif // REALTIME_LOGGING -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO -#else - // have to flip the displayed buffer in the case of double buffering - if(s_screen->flags & SDL_DOUBLEBUF) { - SDL_Flip(s_screen); - } -#endif } /** diff --git a/src/drivers/sdl/sdl-video.h b/src/drivers/sdl/sdl-video.h index ef6c30d5..82ac15f7 100644 --- a/src/drivers/sdl/sdl-video.h +++ b/src/drivers/sdl/sdl-video.h @@ -9,7 +9,6 @@ uint32 PtoV(uint16 x, uint16 y); bool FCEUD_ShouldDrawInputAids(); bool FCEUI_AviDisableMovieMessages(); -static SDL_Surface *s_screen; bool FCEUI_AviEnableHUDrecording(); void FCEUI_SetAviEnableHUDrecording(bool enable); bool FCEUI_AviDisableMovieMessages(); diff --git a/src/drivers/sdl/sdl.cpp b/src/drivers/sdl/sdl.cpp index a4f7c5d8..fb421832 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -16,6 +16,7 @@ #include "sdl.h" #include "sdl-video.h" #include "unix-netplay.h" +#include "glxwin.h" #include "../common/configSys.h" #include "../../oldmovie.h" @@ -171,13 +172,9 @@ static void ShowUsage(char *prog) #endif puts(""); printf("Compiled with SDL version %d.%d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL ); -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_version* v; - SDL_GetVersion(v); -#else - const SDL_version* v = SDL_Linked_Version(); -#endif - printf("Linked with SDL version %d.%d.%d\n", v->major, v->minor, v->patch); + SDL_version v; + SDL_GetVersion(&v); + printf("Linked with SDL version %d.%d.%d\n", v.major, v.minor, v.patch); #ifdef GTK printf("Compiled with GTK version %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION ); //printf("Linked with GTK version %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION ); @@ -193,9 +190,9 @@ static void ShowUsage(char *prog) */ int LoadGame(const char *path) { - if (isloaded){ - CloseGame(); - } + if (isloaded){ + CloseGame(); + } if(!FCEUI_LoadGame(path, 1)) { return 0; } @@ -560,9 +557,9 @@ int main(int argc, char *argv[]) return(-1); } -#ifdef OPENGL - SDL_GL_LoadLibrary(0); -#endif +//#ifdef OPENGL +// SDL_GL_LoadLibrary(0); +//#endif // Initialize the configuration system g_config = InitConfig(); @@ -614,8 +611,8 @@ int main(int argc, char *argv[]) g_config->getOption("SDL.InputCfg", &s); if(s.size() != 0) { - InitVideo(GameInfo); - InputCfg(s); + InitVideo(GameInfo); + InputCfg(s); } // set the FAMICOM PAD 2 Mic thing { @@ -679,41 +676,6 @@ int main(int argc, char *argv[]) int yres, xres; g_config->getOption("SDL.XResolution", &xres); g_config->getOption("SDL.YResolution", &yres); -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO _ SDL 2.0 -#else - const SDL_VideoInfo* vid_info = SDL_GetVideoInfo(); - if(xres == 0) - { - if(vid_info != NULL) - { - g_config->setOption("SDL.LastXRes", vid_info->current_w); - } - else - { - g_config->setOption("SDL.LastXRes", 512); - } - } - else - { - g_config->setOption("SDL.LastXRes", xres); - } - if(yres == 0) - { - if(vid_info != NULL) - { - g_config->setOption("SDL.LastYRes", vid_info->current_h); - } - else - { - g_config->setOption("SDL.LastYRes", 448); - } - } - else - { - g_config->setOption("SDL.LastYRes", yres); - } -#endif int autoResume; g_config->getOption("SDL.AutoResume", &autoResume); @@ -857,14 +819,20 @@ int main(int argc, char *argv[]) #ifdef _GTK if(noGui == 0) { + spawn_glxwin(0); // even though it is not spawning a window, still needed for shared memory segment. gtk_init(&argc, &argv); InitGTKSubsystem(argc, argv); while(gtk_events_pending()) gtk_main_iteration_do(FALSE); + // Ensure that the GUI has fully initialized. + // Give the X-server a small amount of time to init. + usleep(100000); + while(gtk_events_pending()) + gtk_main_iteration_do(FALSE); } #endif - if(romIndex >= 0) + if(romIndex >= 0) { // load the specified game error = LoadGame(argv[romIndex]); @@ -915,6 +883,15 @@ int main(int argc, char *argv[]) g_config->setOption("SDL.LuaScript", ""); if (s != "") { +#ifdef __linux + // Resolve absolute path to file + char fullpath[2048]; + if ( realpath( s.c_str(), fullpath ) != NULL ) + { + //printf("Fullpath: '%s'\n", fullpath ); + s.assign( fullpath ); + } +#endif FCEU_LoadLuaCode(s.c_str()); } #endif @@ -934,11 +911,18 @@ int main(int argc, char *argv[]) while(1) { if(GameInfo) + { DoFun(frameskip, periodic_saves); + } else + { SDL_Delay(1); + } + while(gtk_events_pending()) - gtk_main_iteration_do(FALSE); + { + gtk_main_iteration_do(FALSE); + } } } else diff --git a/src/emufile.cpp b/src/emufile.cpp index 162e8df0..e0e83115 100644 --- a/src/emufile.cpp +++ b/src/emufile.cpp @@ -133,7 +133,7 @@ void EMUFILE::write64le(u64 val) size_t EMUFILE::read64le(u64 *Bufo) { - u64 buf; + u64 buf=0; if(fread((char*)&buf,8) != 8) return 0; #ifndef LOCAL_BE @@ -174,7 +174,7 @@ size_t EMUFILE::read32le(s32* Bufo) { return read32le((u32*)Bufo); } size_t EMUFILE::read32le(u32* Bufo) { - u32 buf; + u32 buf=0; if(fread(&buf,4)<4) return 0; #ifndef LOCAL_BE @@ -213,7 +213,7 @@ size_t EMUFILE::read16le(s16* Bufo) { return read16le((u16*)Bufo); } size_t EMUFILE::read16le(u16* Bufo) { - u32 buf; + u32 buf=0; if(fread(&buf,2)<2) return 0; #ifndef LOCAL_BE diff --git a/src/file.cpp b/src/file.cpp index 9860d87e..dfbba02e 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -104,12 +104,14 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp) if((offset+size)>(uint32)fp->size) { // Probably a little slow. - buf=(char *)realloc(buf,offset+size); - if(!buf) + char *newbuf=(char *)realloc(buf,offset+size); + if(!newbuf) { + free(buf); buf=NULL; FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count); goto end; } + buf=newbuf; memset(buf+fp->size,0,offset+size-fp->size); fp->size=offset+size; } @@ -127,12 +129,14 @@ void ApplyIPS(FILE *ips, FCEUFILE* fp) if((offset+size)>(uint32)fp->size) { // Probably a little slow. - buf=(char *)realloc(buf,offset+size); - if(!buf) + char *newbuf=(char *)realloc(buf,offset+size); + if(!newbuf) { + free(buf); buf=NULL; FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count); goto end; } + buf=newbuf; memset(buf+fp->size,0,offset+size-fp->size); } fread(buf+offset,1,size,ips); @@ -475,9 +479,9 @@ void FCEUI_SetDirOverride(int which, char *n) va_list ap; int ret; - va_start(ap,fmt); if(!(*strp=(char*)FCEU_dmalloc(2048))) //mbg merge 7/17/06 cast to char* return(0); + va_start(ap,fmt); ret=vsnprintf(*strp,2048,fmt,ap); va_end(ap); return(ret); diff --git a/src/ppu.cpp b/src/ppu.cpp index 56466383..ca2ee0e7 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -1375,7 +1375,9 @@ static void DoLine(void) { GameHBIRQHook(); } +#ifdef WIN32 DEBUG(FCEUD_UpdateNTView(scanline, 0)); +#endif if (SpriteON) RefreshSprites(); @@ -1852,7 +1854,9 @@ int FCEUPPU_Loop(int skip) { for (scanline = 0; scanline < totalscanlines; ) { //scanline is incremented in DoLine. Evil. :/ deempcnt[deemp]++; if (scanline < 240) +#ifdef WIN32 DEBUG(FCEUD_UpdatePPUView(scanline, 1)); +#endif DoLine(); if (scanline < normalscanlines || scanline == totalscanlines) @@ -2145,8 +2149,10 @@ int FCEUX_PPU_Loop(int skip) { ppuphase = PPUPHASE_BG; if (sl != 0 && sl < 241) { // ignore the invisible +#ifdef WIN32 DEBUG(FCEUD_UpdatePPUView(scanline = yp, 1)); DEBUG(FCEUD_UpdateNTView(scanline = yp, 1)); +#endif } //hack to fix SDF ship intro screen with split. is it right? diff --git a/src/utils/endian.cpp b/src/utils/endian.cpp index 71732ff1..56704d41 100644 --- a/src/utils/endian.cpp +++ b/src/utils/endian.cpp @@ -275,7 +275,7 @@ int write64le(uint64 b, EMUFILE* os) int read32le(uint32 *Bufo, EMUFILE *fp) { - uint32 buf; + uint32 buf=0; if(fp->_fread(&buf,4)<4) return 0; #ifdef LOCAL_LE @@ -288,7 +288,7 @@ int read32le(uint32 *Bufo, EMUFILE *fp) int read16le(u16 *Bufo, EMUFILE *is) { - u16 buf; + u16 buf=0; if(is->_fread((char*)&buf,2) != 2) return 0; #ifdef LOCAL_LE @@ -301,7 +301,7 @@ int read16le(u16 *Bufo, EMUFILE *is) int read64le(uint64 *Bufo, EMUFILE *is) { - uint64 buf; + uint64 buf=0; if(is->_fread((char*)&buf,8) != 8) return 0; #ifdef LOCAL_LE diff --git a/src/utils/general.cpp b/src/utils/general.cpp index c84d9e70..9f49a19b 100644 --- a/src/utils/general.cpp +++ b/src/utils/general.cpp @@ -28,10 +28,10 @@ uint32 uppow2(uint32 n) int x; for(x=31;x>=0;x--) - if(n&(1<